---[ Présentation de mod_security2 ]------------------------------------------ Cet article traite de l'installation et du fonctionnement de mod_security2, la nouvelle version du célèbre pare feu applicatif. --[ 1. Introduction ]--------------------------------------------------------- Mod_security2 amène de nombreuses améliorations et une nouvelle syntaxe pour la création de règles de filtrage, nous allons voir comment installer et configurer cette nouvelle version de ce firewall applicatif. À noter que cette version ne fonctionne qu'avec Apache2. Pour toute information sur le fonctionnement de mod_security et sur la mise en place de mod_security, je vous conseille la brève de Stéphane Milani : http://www.hsc.fr/ressources/breves/modsecurity.html . --[ 2. Différences avec mod_security 1 ]-------------------------------------- Cette nouvelle version de mod_security amène de nombreuses fonctionnalités par rapport à la version précédente mais ne fonctionne plus avec Apache 1.3. De plus pour l'instant mod_security2 ne peut pas être compilé comme un module statique. Cette nouvelle version apporte le support du format XML, ce qui peut permettre de mettre en place un firewall XML simple. La granularité du filtrage a aussi été grandement améliorée et on peut simplement créer des régles très précises. Là où mod_security ne gère que 2 phases (entrée/sortie), mod_security2 en gère 5. --[ 3. Installation ]--------------------------------------------------------- Cette nouvelle version étant encore récente, sa distribution n'est pas encore faite dans toutes les distributions courantes. Pour l'installer, il faut récupérer la dernière version sur le site de modsecurity : http://www.modsecurity.org/download/index.html . Il suffit ensuite de décompresser l'archive : $ tar -zxvf modsecurity-apache_$version.tar.gz Puis, il faut faire quelques modifications dans le Makefile : $ cd modsecurity-$version/apache2/ Il suffit ensuite de modifier les variables top_dir et INCLUDES (exemple pour Gentoo): top_dir = /usr/lib/apache2 INCLUDES = -I /usr/include/apache2/ -I /usr/include/libxml2 L'utilisation ou non de la libxml2 peut être décidée grâce à la ligne : DEFS = -DWITH_LIBXML2 Pour le filtrage d'un WebService, la bibliothèque XML2 est nécessaire. Enfin, on peut lancer la compilation et l'installation de mod_security2 : $ make $ sudo make install Il ne reste plus qu'à créer le fichier de configuration minimale pour indiquer à Apache de charger mod_security2 et pour tester son fonctionnement (extrait du fichier /etc/apache2/modules.d/99_mod_sec2.conf) : LoadFile /usr/lib/libxml2.so LoadModule security2_module modules/mod_security2.so LoadModule unique_id_module modules/mod_unique_id.so SecRuleEngine On SecRequestBodyAccess Off SecResponseBodyAccess Off SecServerSignature "HSC" SecDebugLog modsec2_debug.log SecDebugLogLevel 3 SecRule REQUEST_FILENAME "testhsc" log,deny,status:403,msg:'testhsc' La ligne SecServerSignature "HSC" permet de changer la bannière du serveur. La ligne SecRule REQUEST_FILENAME "testhsc" log,deny,status:403,msg:'testhsc' va permettre de faire un simple test du bon fonctionnement de mod_security2 en bloquant l'accès au fichier testhsc, toute tentative d'accès renverra une erreur 403 et sera journalisée avec le message 'testhsc'. Après rechargement du serveur Apache : $ sudo /etc/init.d/apache2 restart il est possible de tester le bon fonctionnement de mod_security2 : $ telnet localhost 80 Trying 127.0.0.1... Connected to localhost. Escape character is '^]'. GET / HTTP/1.0 HTTP/1.1 200 OK Date: Tue, 10 Apr 2007 15:28:54 GMT Server: HSC [...] La nouvelle bannière du serveur est maintenant visible. L'accès au fichier testhsc est maintenant interdit : $ telnet localhost 80 Trying 127.0.0.1... Connected to localhost. Escape character is '^]'. GET /testhsc HTTP/1.0 HTTP/1.1 403 Forbidden Date: Tue, 10 Apr 2007 15:31:05 GMT Server: HSC [...] Le résultat est visible dans les journaux de mod_security : $ sudo tail /var/log/apache2/modsec2_debug.log [...] [10/Apr/2007:17:31:05 +0200] [kinkakuji/sid#817abe0][rid#82439a0] [/testhsc][1] Access denied with code 403 (phase 2). Pattern match "testhsc" at REQUEST_FILENAME. [msg "testhsc"] --[ 4. Configuration ]-------------------------------------------------------- Voici un petit tour des options qui peuvent s'avérer utiles : * SecServerSignature permet de modifier la bannière du serveur. * SecRequestBodyLimit limite la taille du corps des requêtes. * SecRuleEngine permet d'activer le moteur de règles qui peut prendre 3 valeurs : On, Off, DetectionOnly. * SecRule pour la création de règle. Les règles peuvent être appliquées à 5 instants lors du traitement d'une requête : * après la réception de l'en-tête de la requête, le corps de la requête n'est pas encore disponible, les règles mises en place durant cette phase ne tiennent pas compte de la gestion des requêtes faite par Apache. Si une requête est bloquée durant cette phase, le serveur HTTP ne verra même pas la requête. * après la réception du corps de la requête, durant cette phase, la totalité des arguments envoyés à l'application est connue. * avant l'envoi de l'en-tête de la réponse. * avant l'envoi du corps de la réponse qui permet de modifier le corps de la réponse avant son envoi. * durant la phase de journalisation. Mod_security2 met à disposition des variables sur lesquelles ont peu simplement mettre en place des règles : * ARGS pour traiter l'ensemble des arguments, ou accéder à un argument en particulier, ou à tous les arguments sauf un, ... * AUTH_TYPE pour accéder au type d'authentification * HTTP_REFERER pour l'accès au Referer * REMOTE_ADDR et REMOTE_HOST pour connaître l'adresse IP ou le reverse DNS du client * le corps d'une requête grâce à REQUEST_BODY * l'en-tête d'une requête avec REQUEST_HEADERS * la méthode HTTP utilisée avec REQUEST_METHOD * l'ensemble de la réponse en combinant RESPONSE_BODY et RESPONSE_HEADERS Il est ainsi possible d'accéder à l'intégralité des données transférées lors d'une requête HTTP au moment de la requête et de la réponse. Mod_security donne aussi accès à des fonctions permettant d'encoder ou de décoder l'ensemble des variables que nous venons de voir. Il est ainsi possible de décoder en base64, d'enlever les espaces, de calculer une empreinte md5 ou sha1, de décoder une url, ... La validation d'une règle permet de spécifier une ou plusieurs actions, plusieurs actions sont ainsi disponibles : * auditlog pour journaliser l'action dans le fichier d'audit * capture permet de sauvegarder la transaction, 10 captures sont possibles * chain pour enchaîner plusieurs règles * ctl pour mettre à jour les règles de filtrage * deny : bloque la requête et l'interprétation des autres règles. * drop pour couper la connexion au niveau TCP * exec pour lancer un script externe (pour bloquer une adresse par exemple) * log pour journaliser la transaction * pass pour donner la main à la prochaine règle * phase pour spécifier la phase durant laquelle la règle sera mise en place * proxy pour relayer la requête vers un autre serveur (si mod_proxy est installé) * redirect pour rediriger le client * plusieurs actions de nettoyage sanitiseArg, sanitiseMatched, sanitiseRequestHeader. * severity pour spécifier le niveau d'une alerte * status pour spécifier la réponse HTTP : 403, 404, ... * ... --[ 4. Les règles génériques ]------------------------------------------------ Il est toujours possible d'utiliser les règles génériques fournies avec mod_security2, mais il est préférable de mettre en place un filtrage adapté à l'application hébergée. Les règles génériques risquent de prendre beaucoup plus de ressources que des règles spécialement mise en place pour une application donnée. Les règles génériques sont présentes dans l'archive contenant le code de mod_security2. Plusieurs fichiers sont disponibles, pour les utiliser il suffit d'utiliser la directive Apache "Include". Les jeux de règles suivants sont présents : * modsecurity_crs_10_config.conf qui est un fichier minimal d'installation de mod_security est décrit les fonctions de base. * modsecurity_crs_20_protocol_violations.conf qui permet de vérifier que les requêtes suivent bien le correctement le protocole HTTP et permet de détecter certaines anomalies : méthode GET ou HEAD avec un corps de message, méthode POST sans corps de message, blocage des requêtes utilisant Apache comme un relais. * modsecurity_crs_21_protocol_anomalies.conf permet de détecter des anomalies dans les requêtes comme l'absence d'un User-Agent ou l'absence de clause Accept. * modsecurity_crs_30_http_policy.conf permet de n'accepter que les méthodes GET, HEAD, POST et OPTIONS, de n'accepter que les requêtes dont le protocole est HTTP 0.9, 1.0 ou 1.1. * modsecurity_crs_35_bad_robots.conf bloque l'accès aux robots tel que le scanner nessus, bacunetix, ou des programmes en perl, ceci en se basant sur le User-Agent principalement. * modsecurity_crs_40_generic_attacks.conf permet de bloquer les injections SQL, les injections de fichiers, l'accès à des fichiers sensibles, l'injection de commande et les XSS. Ce filtrage se fait sur la base d'une suite d'expression régulières complexes (et donc consommatrice de ressources). * modsecurity_crs_45_trojans.conf qui tente de bloquer l'upload de chevaux de Troie connus sur la machine. * modsecurity_crs_50_outbound.conf remplace les messages d'erreurs d'une application par des réponses HTTP 501. Ceci permet de cacher les informations sensibles contenues dans les messages d'erreurs. Pour limiter la consommation de ces règles, il est important de n'utiliser que les règles correspondants aux technologies présentes sur le serveur. * modsecurity_crs_55_marketing.conf permet de journaliser le passage des robots d'indexation de Google, Yahoo et Microsoft. --[ 5. Protection d'une Application Web ]------------------------------------- Il est possible, comme avec la version précédente de protéger une application Web. Par exemple, une application présentant une injection SQL sur le champs id : http://www.hsc.fr/monapplication/index.php?id=3 Il est possible grâce à mod_security2 de faire une liste blanche des valeurs possibles pour la variable id. La variable id ne doit pouvoir qu'une valeur entière. On peut facilement vérifier que la valeur est un entier grâce à la régle : SecRule ARGS:id "!(^[0-9]*$)" log,deny,status:403 Après un rechargement d'Apache2, la page index.php renvoie un erreur 403 si id n'est pas un entier. NB: L'utilisation des directives plus petit que, plus grand que ne permet en rien de vérifier que la variable est un entier, si la variable n'est pas un entier, la régle ne sera pas appliquée. Un autre exemple, les vulnérabilités de type include : http://www.hsc.fr/monapplication/index.php?file=home.php On peut facilement vérifier que la valeur fait partie d'une liste blanche, grâce à la régle suivante (ici avec home et liens): SecRule ARGS:file "!(^(home|liens)\.php$)" log,deny,status:403 Mod_security permet ainsi de bloquer la plupart des attaques de façon simple mais pour autant ne remplacera jamais de bonnes pratiques de développement. --[ 6. Protection d'un Webservice ]------------------------------------------- Cette nouvelle version amène la possibilité de filtrer des services Web sur HTTP. Nous allons voir comment on peut simplement faire une liste blanche sur les entrées provenant d'un utilisateur. Pour cela nous allons utiliser un serveur Tomcat avec Jax-WS 2 pour la partie Webservice et le serveur Apache avec mod_security2 servira de connecteur HTTP. Une base de données Mysql est utilisée pour le stockage. ________ ________________________ __________________ | | | | | | | Client |------| Apache + mod_security2 |------| Tomcat+ Jax-WS 2 | |________| |________________________| |__________________| | _____|____ | | | Mysql | |__________| Ce webservice permet pour un numéro de département donné de récupérer le nom d'un département (stocké dans la base de données MySQL) à partir de son numéro. Tout d'abord, si la génération de code n'est pas réalisée dynamiquement à partir du wsdl du webservice. Il est possible de bloquer cette accès à partir de mod_security2. Pour cela, la règle suivante : SecRule REQUEST_URI "\?wsdl$" log,deny,status:403 permet de bloquer l'accès aux wsdl. Un intrus n'ayant pas connaissance du fonctionnement du webservice aura déjà beaucoup plus de mal à s'y attaquer. Le webservice présenté contient une injection SQL. Le message envoyé lors d'une interrogation classique du webservice ressemble à cela : 76 L'objectif de ce filtre n'est d'accepter qu'un numéro de département, il faut donc que la valeur du champs dpt soit au maximum de 3 chiffres. SecRule REQUEST_HEADERS:Content-Type "text/xml" \ phase:1,pass,ctl:requestBodyProcessor=XML,\ ctl:requestBodyAccess=On SecRule XML://dpt "!(^[0-9]{2,3}$)" phase:2,deny Cette commande permet ainsi de s'assurer de la conformité des données avec l'utilisation classique du webservice. La commande "XML://dpt" correspond à une requête XPath Pour l'instant, il n'est pas possible de réaliser des requêtes XPath plus complexe sur les messages SOAP car la gestion des namespaces ne fonctionnent pas encore (msre_action_xmlns_validate dans re_actions.c). --[ 7. Conclusion ]----------------------------------------------------------- Cette brève vous a présenté le fonctionnement de mod_security2 et comment il est simplement possible de mettre en place un filtrage en amont d'une application Web ou d'un Webservice ayant des problèmes de sécurité. Cependant, il ne faut pas oublier que la meilleure solution est tout de même d'adopter une politique de développement sécurisé dés la création de l' application en définissant clairement les types de données attendues en entrée et en pratiquant la programmation défensive. -- Louis Nyffenegger < Louis.Nyffenegger@hsc.fr > -- --[ 8. Références ]----------------------------------------------------------- - Le site du projet mod_security : http://www.modsecurity.org/ - La documentation de mod_security2 : http://www.modsecurity.org/documentation/modsecurity-apache/2.1.0/ - Brève de Stéphane Milani sur mod_security : http://www.hsc.fr/ressources/breves/modsecurity.html - Le site du projet Tomcat http://tomcat.apache.org/ - Le site du projet Apache : http://httpd.apache.org/ - Xpath : http://xmlfr.org/w3c/TR/xpath/