La haute sécurité informatique en question !

La sécurité informatique est un domaine très complexe et de nombreux clients souhaitent que nos services lancent des offres d’hébergement de très haute sécurité. Redondance sur deux datacenter, interlan, reverse proxy filtrant, firewall ultra stricts, redondance des éléments physiques, logiques et des connexions, hardening des OS, supervision et IDS etc…

Arriver à un niveau très élevé est un chantier très important. NBS System se lance dans ce chemin particulier avec pour but de lancer les premières offres de très haute sécurité sur le marché. Dans ce chemin, nos équipes étudient actuellement toutes les possibilités et outils.

Plusieurs post seront donc consacrés à ces études, à l’explication du chemin que nous prenons et le premier de cette série concerne ModSecurity. Bonne lecture et à bientôt pour d’autres articles sur le sujet.

Qu’est ce que ModSecurity ?

ModSecurity est un WAF (pare-feu applicatif) qui se présente sous la forme d’un module pour le serveur Web Apache (httpd). Le rôle d’un WAF est de protéger le serveur Web des attaques applicatives en filtrant en amont les requêtes dangereuses.

Fonctionnement global de ModSecurity

ModSecurity dispose de cinq phases de traitement qui correspondent chacune à une étape clé. Pour chaque transaction, les phases sont exécutées séquentiellement de la phase 1 à la phase 5. Une transaction correspond à une requête d’un client et la réponse renvoyée par le serveur.

Phase 1 : Traitement des en-têtes de la requête

Cette phase permet notamment d’inspecter les arguments passés dans l’URL dans le cas d’une requête en GET ainsi que de vérifier les cookies ou le UserAgent.

Phase 2 : Traitement du corps de la requête

L’analyse de corps de la requête permet d’inspecter les arguments dans le cas d’une requête en POST

Phase 3 : Traitement des en-têtes de la réponse

Les en-têtes de la réponse du serveur Web, sont observés par ModSecurity afin de décider s’il est nécessaire où non d’inspecter le corps de la réponse.

Phase 4 : Traitement du corps de la réponse

Cette phase est identique à la phase 2 sauf qu’elle traite la réponse fournie par le serveur. Elle permet notamment de prévenir la fuite d’informations via des messages d’erreur.

Phase 5 : La journalisation

Cette phase permet la journalisation des requêtes, elle permet de définir comment la transaction doit être journalisée. Cette phase intervenant en dernier, le traitement de la transaction est déjà effectué. On ne peut donc pas bloquer une transaction lors de cette phase.

Les phases 1 et 2 permettent d’interrompre une requête avant qu’elle n’arrive au serveur. Les phases 3 et 4 permettent elles d’interrompre une réponse avant qu’elle n’arrive au client.

Configuration de ModSecurity

Nous allons nous intéresser à quelques éléments importants du fichier de configuration. Le fichier de configuration de ModSecurity n’existe pas par défaut et il doit être crée par l’administrateur.

Voici le fichier de configuration que j’ai utilisé pour les tests :

SecServerSignature « w00t server 😉 »# Basic configuration optionsSecRuleEngine On
SecRequestBodyAccess On
SecResponseBodyAccess Off
SecDataDir /var/log/modsec_data# Handling of file uploadsSecUploadDir /var/tmp/modsec_upload
SecUploadFileMode 0600
SecUploadKeepFiles RelevantOnly# Debug log

SecDebugLog /var/log/apache2/modsec_debug.log
SecDebugLogLevel 0

# Serial audit log

SecAuditEngine RelevantOnly
SecAuditLogRelevantStatus ^5
SecAuditLogParts ABIFHKZ
SecAuditLogType Serial
SecAuditLog /var/log/apache2/modsec_audit.log

# Maximum request body size we will
# accept for buffering

SecRequestBodyLimit 131072

# Store up to 128 KB in memory
SecRequestBodyInMemoryLimit 131072

# Buffer response bodies of up to # 512 KB in length
SecResponseBodyLimit 524288

# Include the rules that we use for testing
Include /etc/apache2/modsecurity-test/test.conf

 

 

Je vais détailler certains paramètres afin de clarifier les options de configuration.

SecServerSignature

Permet de donner un nom personnalisé au serveur Web. Voici la réponse affichée pour une requête sur notre serveur :

SecRuleEngine

Permet d’activer ou de désactiver ModSecurity

SecRequestBodyAccess

Permet de spécifier à ModSecurity d’inspecter ou non le corps des requêtes

SecResponseBodyAccess

Permet de spécifier à ModSecurity d’inspecter ou non le corps des réponses

SecDataDir

Spécifie le répertoire permettant à ModSecurity de stocker des informations. Ce répertoire est nécessaire notamment pour pouvoir utiliser les variables persistantes dans les règles. Il doit être inscriptible avec les droits www-data pour pouvoir fonctionner. Un exemple d’utilisation des variables persistante est fourni dans la suite de cet article.

SecDebugLogLevel

Cette option fixe la verbosité des logs de ModSecurity. Les différents niveaux sont les suivants :

Niveau de log Détail
0 Pas de logs
1 Les erreurs (ex : transactions bloquées)
2 Les Avertissements (règles non bloquantes)
3 Remarques (ex : erreurs non fatales)
4 Informatif
5 Détaillé
9 Tout

 

Pour déboguer des règles on pourra régler le paramètre au niveau 5 mais il est impératif de le mettre à 0 dans un contexte de production.

SecAuditEngine

Indique à ModSecurity ce qu’il doit journaliser lors de son fonctionnement. Les trois options sont On, Off et RelevantOnly. Cette dernière permet de ne journaliser que les requêtes ayant remonté une alerte.

SecAuditLogRelevantStatus

Précise quels statuts doivent être journalisés. Par exemple ^[45] permet de journaliser que les erreurs 4XX et 5XX du serveur.

SecAuditLogParts

Indique quelles parties de la requête doivent être journalisés par ModSecurity. Les différentes valeurs sont les suivantes :

Lettre Correspondance
A En –tête du log d’audit (obligatoire)
B En-têtes de la requête
C Corps de la requête
D Réservé
E Corps de la réponse intermédiaire
F En tête de la réponse
G Réservé
H Fin du log d’audit (contient des infos sup.)
I Corps de la requête compact (exclut les fichiers)
J Réservé
K Contient la liste des règles ayant été déclenchées par la transaction
Z Marqueur de fin de requête (obligatoire)

Tous les paramètres et leur description sont disponibles sur le site de ModSecurity :

http://www.modsecurity.org/documentation/modsecurity-apache/2.1.3/html-multipage/03-configuration-directives.html

Analyse d’une règle ModSecurity

Une règle ModSecurity se compose des éléments suivants :

SecRule VARIABLES OPERATEUR [FONCTIONS_DE_TRANSFORMATION, ACTIONS]

Les variables

La directive « variables » précise à ModSecurity sur quelles parties doivent porter l’analyse.

Les variables les plus utilisées sont ARGS, REQUEST_HEADERS et REQUEST_BODY. Le listes des variables est disponible ici : http://www.modsecurity.org/documentation/modsecurity-apache/2.1.3/html-multipage/05-variables.html

Les opérateurs

Les opérateurs commencent avec un @ et sont toujours suivis d’un espace. Voici quelques un des opérateurs utilisables :

Quelques opérateurs portant sur les chaînes de caractères :

Opérateur Signification
@beginsWith la chaîne commence par …
@contains la chaîne contient …
@endsWith la chaîne se fini par …
@rx mode expression régulière
@pm mode de correspondance parallèle (permet de tester plusieurs valeurs)

Opérateurs portant sur les valeurs numériques :

Opérateur Signification
@eq Egal
@ge supérieur ou égal
@gt strictement supérieur
@le inférieur ou égal
@lt strictement inférieur

 

Il est à noter que par défaut c’est l’opérateur @rx (expression régulière) qui est utilisé par ModSecurity. Dès qu’une règle ne contient pas d’opérateur c’est @rx qui est utilisé.

La liste des opérateurs est disponible ici : http://www.modsecurity.org/documentation/modsecurity-apache/2.1.3/html-multipage/08-operators.html

Les fonctions de transformation

Le rôle des fonctions de transformation est de normaliser les données avant de rechercher des traces d’attaques connues. Par exemple « t :urlDecode, t :lowercase » permet de décoder l’URL puis de mettre les données en minuscule. Il est à noter que l’ordre des fonctions de transformation est très important pour ne pas permettre à un attaquant de pouvoir échapper à une détection.

La liste des fonctions de transformation est disponible ici : http://www.modsecurity.org/documentation/modsecurity-apache/2.1.3/html-multipage/06-transformation-functions.html

Les actions

Les actions de la règle ne seront appelées que si une correspondance a été trouvée. On peut distinguer cinq grands types d’actions.

Les actions perturbatrices

Ces actions vont avoir un effet direct sur la suite du traitement. Voici les différentes actions disponibles :

Action Effet
allow Arrête l’analyse et autorise la transaction à circuler
block Indique que la règle souhaite bloquer la transaction
deny Bloque la transaction avec une page d’erreur
drop Ferme la connexion réseau
pass Ne bloque pas la transaction et continue l’analyse
proxy Proxifie la requite
redirect Redirige la requête sur un autre serveur Web

Les actions de flux

Ces actions vont modifier le flux de vérification.

Action Effet
chain Agrège plusieurs règles en une seule
skip Permet de sauter une ou plusieurs règles
skipAfter Permet de sauter toutes les règles jusqu’au label précisé

Les actions permettant d’assigner des métas données

Ces actions permettent d’attribuer des informations à la règle tels qu’un identifiant unique. Les actions disponibles sont :

Action Effet
id Identifiant de la règle (doit être unique)
phase Phase durant laquelle s’applique la règle (1 à 5)
msg Message qui sera reporté dans les logs (aide à la compréhension)
rev Version de la règle
severity Sévérité de la menace
tag Tag permettant de classer la menace

 

Les actions permettant d’assigner des variables

ModSecurity offre la possibilité d’assigner des variables. Plusieurs actions permettent de gérer ces variables :

Action Effet
capture Capture les résultats dans une ou plusieurs variables
deprecatevar Diminue la valeur numérique d’une variable dans le temps
expirevar Supprime une variable après une période donnée
initcol Initialise une collection persistante
setenv Affecte ou supprime une variable d’environnement
setuid Associe la transaction courante avec le nom d’utilisateur de l’application
setsid Associe la transaction courante avec l’ID de session de l’application

 

Les actions de journalisation

Ces actions modifient la façon dont va être journalisé la transaction :

Action Effet
auditlog Journalise la transaction dans le journal d’audit
log Journalise la transaction dans le log Apache et ModSecurity
noauditlog Ne journalise pas la transaction
sanitiseArg Enlève un des paramètres de la transaction avant de journaliser
sanitiseMatched Enlève certains paramètres de la transaction avant journalisation
sanitiseRequestHeader Enlève l’en-tête de la requête avant journalisation
sanitiseResponseHeader Enlève l’en-tête de la réponse avant journalisation

Le détail des actions est disponible ici: http://www.modsecurity.org/documentation/modsecurity-apache/2.1.3/html-multipage/07-actions.html

Créer des règles pour ModSecurity

Nous allons maintenant créer nos propres règles pour ModSecurity. Le but est de protéger un site vulnérable sans changer le code source de l’application. Notre site de test consiste en un simple formulaire d’authentification. Si le login et le mot de passe sont valides, des informations sur l’utilisateur sont affichées.

Voici le formulaire d’authentification :

Si un utilisateur s’authentifie correctement, il obtient l’affichage suivant (ici pour l’utilisateur admin):

En revanche, si l’utilisateur n’existe pas ou que le mot de passe n’est pas correct, on obtient l’affichage suivant :

La page comporte comme vulnérabilités des failles de types Cross Site Scripting et d’injection SQL.

Pour le login «
//
// ]]>

» on obtient le résultat suivant :

Pour le login « peu_importe’ or ‘1’=’1′ # » et n’importe quel mot de passe, on obtient l’affichage suivant :

Sans changer au code source, nous allons sécuriser cette page afin d’empêcher l’exploitation de ces failles. Il existe deux principales approches : l’approche par liste noire et l’approche par liste blanche.

L’approche par liste noire

Dans l’approche par liste noire, nous allons chercher à bloquer l’attaque XSS et l’injection SQL.

#Injection SQL

SecRule REQUEST_FILENAME « ^/test_modsec/index.php$ » « msg:’Virtual Patch SQL violation’,
tag:’WEB_ATTACK/ATTACK_SQL’,chain,block,log,capture,multiMatch,t:none,t:cssDecode,
t:jsDecode,t:htmlEntityDecode,t:replaceComments,t:compressWhiteSpace »

SecRule ARGS_POST:login|ARGS_POST:password »(?i:’|\ »|\de\d\d|%[a-fA-F]\d%[a-fA-F]\d|%.\d%.\d|\)|\bAND[\s]+|\bMOD[\s]+|\+[\s]*\d|%2b[\s]*\d|\-[\s]*\d|\bOR[\s]+|\bIN[\s]+[\(]|\bTABLE[\s]+|\bCREATE[\s]+|\bDELETE[\s]+[\(]|\bUNION[\s]+[\(]|\bLIKE[\s]+[\(]|\bJOIN[\s]+[\(]|\bSELECT[\s]+|\bLIMIT[\s]+|\bFROM[\s]+|%|_|\-\-|#|\/\*) »

 

Pour écrire cette règle, nous utilisons l’option chain. La première règle va s’assurer que nous sommes bien sur notre page de login et formater les données pour les rendre uniformes. Cette étape nous met à l’abri des techniques de contournement via l’utilisation d’encodage, de commentaires ou autres. Une fois cette phase effectuée, nous appelons la seconde règle qui va vérifier, via une expression régulière la présence de mots clés et de caractères étant des instructions SQL.

L’action à effectuer si nous trouvons une correspondance avec notre expression régulière est de bloquer la requête.

# XSS

SecRule REQUEST_FILENAME « ^/test_modsec/index.php$ » « msg:’Virtual Patch Cross-Site Scripting violation’,
tag:’WEB_ATTACK/CROSS-SITE_SCRIPTING’,chain,block,log,capture,multiMatch,t:none,t:cssDecode,
t:jsDecode,t:htmlEntityDecode,t:replaceComments,t:compressWhiteSpace »

SecRule ARGS_POST:login « (?i:’|\ »|<|>|\;|\bonchange[\s]*[=]|\bon(dblclick|click)[\s]*[=]|\bon(blur|focus)[\s]*[=]|\bon(submit|reset)[\s]*[=]|\bonmouse(over|out|down|up)[\s]*[=]|\bonkey(down|press|up|up)[\s]*[=]|\bon(load|unload|error|abort|move|resize|dragdrop)[\s]*[=]|\b(java|j|vb|live)script[:]||//|\/\*|\*\/) »

 

Nous utilisons la même technique pour filtrer les XSS sauf qu’on ne l’applique qu’au champ login car le champ password n’est pas affiché.

La dernière étape est d’indiquer à ModSecurity de bloquer la requête si une des règles a remonté une alerte, pour cela nous devons ajouter avant ces règles la directive suivante

SecDefaultAction phase:2,log,deny,status:500

 

Si nous retentons les mêmes requêtes que précédemment, on obtient le message d’erreur suivant.

L’approche par liste blanche

Dans l’approche par liste blanche, nous allons n’autoriser qu’un certain nombre de caractères pour notre champ de login et de password.

SecRule REQUEST_FILENAME « ^/test_modsec/index.php$ » « msg:’Virtual Patch Login Whitelisting’,
tag:’WEB_ATTACK’,chain,block,log,capture,multiMatch,t:none,t:cssDecode,
t:jsDecode,t:htmlEntityDecode,t:replaceComments,t:compressWhiteSpace »

SecRule ARGS_POST:login|ARGS_POST:password « !@rx ^[a-zA-Z0-9_]*$ »

 

Ici nous n’autorisons que les caractères alphanumériques et l’underscore. Tout autre caractère entrainera l’affichage de la page d’erreur.

Utilisation des variables persistantes :

Afficher une erreur 500 à nos utilisateurs qui ont fait une faute de frappe n’est pas forcément le choix le plus judicieux. Nous allons mettre en place une page d’erreur indiquant à l’utilisateur que celui-ci a entré des caractères invalides et le rediriger dessus en cas d’erreur. De plus, pour éviter les attaques réelles, nous bloquerons pour 60 secondes l’utilisateur au bout de trois essais infructueux.

 

Nous commençons par définir le comportement de blocage qui sera l’affichage de la page d’erreur 500.

SecDefaultAction phase:1,log,deny,status:500

SecDefaultAction phase:2,log,deny,status:500

 

La deuxième étape est de prendre un identifiant unique pour chaque utilisateur :

#crée un hash du UserAgent

SecRule REQUEST_HEADERS:User-Agent ^(.+)$ \

phase:1,pass,t:none,t:sha1,t:hexEncode,capture,setvar:tx.uaHASH=%{TX.0}

#crée un identifiant unique par client en utilisant le hash du User Agent et l’IP

SecAction phase:1,nolog,pass,initcol:ip=%{REMOTE_ADDR}_%{TX.uaHASH}

 

Ensuite nous modifions la règle qui surveille la conformité des entrées du login afin d’incrémenter un compteur en cas de correspondance.

SecRule REQUEST_FILENAME « ^/test_modsec/index.php$ » « msg:’Virtual Patch Login Whitelisting’,tag:’WEB_ATTACK’,
chain,redirect:./error.php?error=login,log,capture,multiMatch,t:none,t:cs$

SecRule ARGS_POST:login|ARGS_POST:password « !@rx ^[a-zA-Z0-9_]*$ » \

setvar:ip.error_count=+1″

 

Nous avons maintenant une variable « error_count » qui surveille le nombre de fois que l’utilisateur à envoyé des entrées non valides. Il faut maintenant créer la règle qui va bloquer l’utilisateur s’il fait plus de trois tentatives.

SecRule IP:error_ count « @gt 3 » \

« phase:1,block,msg:’Blocage !’expirevar:ip.error_count=60 »

 

Quand l’utilisateur fourni des entrées invalides, il tombe sur la page erreur.php :

ModSecurity nous permet donc de faire respecter une politique de mots de passe ou d’empêcher les attaques par force brute et cela sans modifier le code source de l’application.

Limites de la création de règles

Les modèles de sécurité par liste noire ou liste blanche ont chacun leurs avantages et leurs inconvénients.

Limites du filtrage par liste noire

La liste noire ne peut bloquer les attaques qui n’ont pas été spécifiés dans les règles du pare-feu applicatif. Pour obtenir un niveau de sécurité correct, il est possible d’utiliser les règles mises à disposition sur le site de ModSecurity intitulées « core rules set ». Ces règles permettent à un administrateur de mettre en place rapidement une protection pour son serveur Web. Le plus grand risque liée à l’installation de ces règles est la présence de faux positifs. L’administrateur doit veiller à désactiver certaines règles sur des pages précises de son site afin de ne pas entraver son fonctionnement.

Limites du filtrage par liste blanche

La stratégie de la liste blanche demande beaucoup de maintenance car chaque nouvelle page et ses champs doivent être intégrés dans le processus de vérification afin de ne pas compromettre la sécurité du site. Sur un site subissant de nombreuses modifications, la charge de travail de l’administrateur peut devenir très importante.

Il est également envisageable d’utiliser le filtrage par liste noire et par liste blanche simultanément.

Limites de ModSecurity

ModSecurity n’a aucune connaissance du comportement des langages de programmation des sites hébergés sur le serveur Apache. Le comportement laxiste de certains langages de programmation tels que le PHP peuvent permettre à un attaquant de contourner les protections mises en place.

Nous allons prendre par exemple les règles que nous avons écrites ci-dessus. Afin de contrôler les champs « login » et « password » nous avons spécifié la directive suivante à ModSecurity :

SecRule ARGS_POST:login|ARGS_POST:password [ …]

Le caractère espace se code « %20 »en HTML. Pour Apache, « ARGS_POST :login » et « ARGS_POST :%20login » sont deux champs différents. La règle que nous avons écrite ci-dessus ne va donc pas s’appliquer. Tout cela ne poserai pas de problème si PHP n’enlevait pas automatiquement les espaces par la suite pour retransformer « %20login » en « login ».

Il est donc possible en mettant des « %20 » devant le nom des variables envoyées au serveur Web de contourner nos règles sans se faire rejeter par PHP. On pourrait écrire une règle qui repère les « %20 » devant les noms de variable et génère une alerte, mais cette règle ne nous protégerai pas si une autre technique de contournement existait. Nous allons donc restreindre les valeurs que nous acceptons pour les noms de variables via la règle suivante :

SecRule ARGS_NAMES « !^[0-9a-zA-Z_-.]+$ » \

« phase:2,log,block,msg:’Invalid parameter name' »

 

Ainsi, nous pouvons être surs qu’un attaquant ne pourra pas contourner nos règles via l’ajout de caractères spéciaux dans le nom des variables.

Cet exemple nous prouve qu’il est nécessaire de bien connaître les spécificités du langage qui va traiter les requêtes soumises au serveur Apache afin de prévenir le contournement des règles mises en place.

Conclusion

Ajouter un pare-applicatif à son site internet n’est aujourd’hui plus une option pour les entreprises soucieuses de leur sécurité. Un pare-feu applicatif ne serait être en soit une protection suffisante mais il a tout à fait sa place dans une stratégie de défense en profondeur. ModSecurity, de part sa flexibilité, sa communauté et son intégration dans Apache, est un acteur de tout premier plan dans le monde des solutions WAF Open Source.

Philippe Humeau
Philippe Humeau
Philippe a co-fondé NBS System en 1999. Après s’être concentré sur la sécurité, qu’il n’a jamais abandonnée, il se découvre une passion pour le ecommerce à partir de 2008. Tour à tour pentester, CTO, CCO puis CEO, son profil touche-à-tout l’a conduit à devenir directeur marketing et stratégie d’OT Group après notre intégration dans celui-ci.