URL parse Bypass (SSRF)
How various libraries parse urls differently
Introduction
최근 url parser를 이용한 SSRF 문제를 풀게 되면서 \ 등을 이용해서 localhost 체크를 넘어가는 것들을 종종 보게 되었다. 그래서 이런 것들은 쭉 정리할 필요가 있어보여서 관련 자료를 조사한 것을 정리한다.
상당수의 내용은 Orange Tsai가 발표한 A New Era of SSRF - Exploiting URL Parser in Trending Programming Languages를 참고했으며, OWASP의 SSRF Bible 또한 참조했다.
Fun fact
이번 글에서 다룰 내용을 가장 단적으로 보여주는 사진인 것 같다.
| Libraries/Vulns | CR-LF Injection | URL Parsing | ||||
|---|---|---|---|---|---|---|
| Path | Host | SNI | Port Injection | Host Injection | Path Injection | |
| Python httplib | ☠️ | ☠️ | ☠️ | |||
| Python urllib | ☠️ | ☠️ | ☠️ | |||
| Python urllib2 | ☠️ | ☠️ | ||||
| Ruby Net::HTTP | ☠️ | ☠️ | ☠️ | |||
| Java net.URL | ☠️ | ☠️ | ||||
| Perl LWP | ☠️ | ☠️ | ||||
| NodeJS http | ☠️ | ☠️ | ||||
| PHP http_wrapper | ☠️ | ☠️ | ☠️ | |||
| Wget | ☠️ | ☠️ | ||||
| cURL | ☠️ | ☠️ |
위 표는 2017년 자료라 현재는 패치된 것도 많을 것이라고 생각한다.
Overview
URL의 SPEC은 여러군데에서 정의되었고, 그것을 구현하는 방식은 언어마다 그리고 paser마다 모두 다르다. 그렇기에 parser가 host라고 생각한 것이 요청을 보내는 라이브러리에서 다르게 해석될 여지가 있다. 따라서 이러한 불일치는 parsing 후에 발생하는 server side request가 변조될 가능성을 열어둔다.
sonar의 블로그에서 이를 정리한 표를 찾을 수 있었다.
Common Mismatch
1. Abuse of special chars : @ # //
가장 흔한 예시가 예약문자를 이용한 방식이다. 예를 들어
1
https://127.0.0.1#@google.com:3000/
위와 같은 url의 host가 google.com으로 해석되는 것이다. (CVE-2016-10397)
그리고 공백( )이나 역슬래쉬(\)도 bypass에 쓰일 여지가 있다.
2. Unicode decoding
유니코드를 지원하는 parser과 그렇지 않은 것들이 있다. 그리고 (a) 지원 유무에 따른 차이를 이용하거나 (b) 지원한다면 blacklist bypass가 시도되는 상황을 생각해 볼 수 있다.
예를 들어 nodejs의 경우 기본적으로 \n\r은 urlencode를 통해서 escape 처리를 한다. 그러나 U+FF0D, U+FF0A를 이용하면, \n\r이 들어가기도 한다. 이유는 이렇다:
1
2
3
4
https://example.com/*-
https://example.com/\FF\0A\FF\0D
https://example.com/\0A\0D
=> \n\r
동일한 이유도 ../ 같은 금지된 문자들도 U+FF2E를 이용하여 통과할 수 있다.
특히 CRLF는 protocol smuggling에도 사용될 수 있기에 연쇄적으로 SSRF를 발생시킬 수 있다.
3. IP address confusion
IPv4와 IPv6를 이용한 방법들이다. 이것들은 payload만 작성하였다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# basics
localhost
127.0.0.1
::1
# IPv4 alias
127.1
127.000.000.001
0177.0.0.1
0x7f.0x00.0x00.0x01
2130706433
127.0x0.1
# IPv6 <-> IPv4
::ffff:127.0.0.1
::ffff:7f00:1
# Others
localhost.
DNS rebinding is also a useful tool
Use https://lock.cmpxchg8b.com/rebinder.html
Conclusion
여기끼지가 내가 알고 있는 SSRF 관련 내용들이다.
이 외에도 추가적인 방법을 찾고 싶다면 직접 라이브러리 소스코드를 봐서 찾아보는 방법밖에 없다.
아직은 보안 공부를 한지 얼마 안 되기도 하고, 웹은 시스템 다음 순위로 공부하는 분야라 아는 내용이 생길때마다 여기에 추가할 예정이다.

