P / 04 · Pare-feu intelligent · Machine learning
ML WAF
Un pare-feu applicatif intelligent : un modèle LightGBM placé dans un proxy inverse démasque les charges obfusquées, évalue chaque valeur de requête pour l’injection SQL et le XSS, et explique chaque verdict en direct.
Démo fonctionnelle · Quatre couches de tests
Explorer le dépôt- Python
- LightGBM
- scikit-learn
- FastAPI
- SQLite
- Docker
Console du pare-feu : requêtes autorisées et attaques bloquées.
Source de l’imageBesoin & utilisateurs
Les WAF à règles ratent les charges encodées ou obfusquées, et les WAF ML naïfs apprennent la mauvaise chose : une première version bloquait /users/42/profile et laissait passer 1' OR 1=1--, car ses données lui avaient appris du vocabulaire plutôt que des attaques. L’objectif : un pare-feu qui reconnaît la forme d’une injection sur n’importe quel site et sait justifier sa décision.
Réalisation
Chaque requête est d’abord normalisée : décodage URL récursif, entités HTML, échappements JS, URI data en base64, repli Unicode, suppression des commentaires SQL et littéraux hexadécimaux ou CHAR(). Elle est ensuite découpée en chemin et valeurs de paramètres, chacune transformée en n-grammes de caractères et 25 indicateurs numériques, puis classée par LightGBM en bénin, SQLi ou XSS. Un scoreur rapide contourne le pipeline sklearn pour tenir en ligne, avec des scores identiques. La console diffuse les décisions en SSE avec la trace de décodage et la contribution de chaque indicateur, permet de simuler un nouveau seuil sur le trafic récent et renvoie les faux positifs directement au format d’entraînement.
Choix technique
Évaluer chaque valeur isolément et bloquer sur la pire, pour qu’aucun contexte bénin ne dilue une attaque et que le vocabulaire du site ne compte pas. Entraîner sur des traces réelles où les mêmes chemins portent les deux étiquettes. Mode détection par défaut et ouverture en cas d’erreur, avec un plafond de 64 valeurs et 180 ms pour qu’un modèle défaillant ne cause jamais de panne.
En pratique
Sur des jeux indépendants, le modèle bloque 96 % des injections SQL et 100 % des XSS et contournements obfusqués, avec 0 % de faux positifs sur le trafic réel de la NASA et moins de 1 % sur un site inconnu. L’entraînement sur traces réelles a divisé les faux positifs par 38. Dans la démo Docker, sqlmap trouve l’injection d’OWASP Juice Shop en direct mais est refusé à travers le pare-feu. Quatre couches de tests couvrent le pipeline du modèle, le proxy et le plan de contrôle, le durcissement adversarial et l’endurance sous charge.
Essayez · dans votre navigateur
Ce que voit le modèle
Le vrai pipeline de normalisation du pare-feu, porté en JavaScript : chaque requête est décodée couche par couche puis découpée en valeurs évaluées séparément. Le score LightGBM exige le modèle entraîné ; les signaux ci-dessous sont des indices lisibles, pas le verdict.
- 1Choisissez un exemple ou tapez une URL
- 2Chaque valeur est décodée couche par couche
- 3La valeur la plus suspecte est surlignée
- Survolez ? pour les détails
IdéeL’apostrophe est encodée deux fois : un filtre qui décode une seule fois ne la voit pas.
- pathLe chemin de l’URL est évalué seul, séparément de chaque paramètre.profondeur 0Nombre de passes de décodage pour obtenir le texte brut. Le trafic normal en demande 0 ou 1 ; au-delà, c’est suspect.
/itemaucun signal - idChaque valeur de paramètre est évaluée seule. Son nom est ignoré pour que le vocabulaire du site n’influence pas le modèle.profondeur 2Nombre de passes de décodage pour obtenir le texte brut. Le trafic normal en demande 0 ou 1 ; au-delà, c’est suspect. · ← signaléeLe pare-feu décide sur la valeur la plus suspecte : les paramètres inoffensifs autour ne peuvent pas diluer l’attaque.
1%2527%2520OR%25201%253D1--- decode round 1Décodage URL, entités HTML et échappements JavaScript, répétés jusqu’à stabilité (5 passes maximum).
1%27%20OR%201%3D1-- - decode round 2Décodage URL, entités HTML et échappements JavaScript, répétés jusqu’à stabilité (5 passes maximum).
1' OR 1=1-- - lowercaseLa casse est supprimée : UNION et union sont identiques pour le modèle.
1' or 1=1--
signauxIndices lisibles pour cette démo. La vraie décision est un score LightGBM sur des n-grammes de caractères et 25 indicateurs numériques.quoteUne apostrophe peut fermer une chaîne SQL ou un attribut HTML.boolean tautologyUne condition toujours vraie comme OR 1=1, utilisée pour contourner un WHERE.sql comment-- ou # coupe la fin de la requête d’origine. - decode round 1Décodage URL, entités HTML et échappements JavaScript, répétés jusqu’à stabilité (5 passes maximum).
- sortChaque valeur de paramètre est évaluée seule. Son nom est ignoré pour que le vocabulaire du site n’influence pas le modèle.profondeur 0Nombre de passes de décodage pour obtenir le texte brut. Le trafic normal en demande 0 ou 1 ; au-delà, c’est suspect.
priceaucun signal
Limites actuelles
- La détection couvre uniquement l’injection SQL et le XSS, sans analyse de session entre requêtes. Les charges très courtes comme admin'# peuvent passer, et les valeurs au-delà de 64 ne sont pas évaluées.
- Les erreurs et délais dépassés laissent passer le trafic par choix. Le cache et le flux de la console sont propres à chaque processus.
Sur GitHub
- Jupyter Notebook
- 0 étoiles
- Mise à jour


