# Keynote - A New Era of SSRF - Exploiting URL Parser in Trending Programming Languages!
### [R0]Keynote - A New Era of SSRF - Exploiting URL Parser in Trending Programming Languages! ###
[slide](https://www.blackhat.com/docs/us-17/thursday/us-17-Tsai-A-New-Era-Of-SSRF-Exploiting-URL-Parser-In-Trending-Programming-Languages.pdf)
[Case Study - How I Chained 4 vulnerabilities on GitHub Enterprise, From SSRF Execution Chain to RCE!](http://blog.orange.tw/2017/07/how-i-chained-4-vulnerabilities-on.html)
SSRF網頁安全的攻擊手法
* 2008被提出
* 因XXE(Attack through XML)而繁榮
SSRF漏洞一再出現在臉書和google中
- 預覽功能
- 網址上傳圖片(內網網址->無視防火牆保護去抓圖)
- http://orange/logo.gif (normal)
- http://10.0.56.254/logo.gif (abnormal)
熟悉SSRF新的攻擊手法很重要,讓SSRF重返榮耀
SSRF漏洞:繞過防火牆碰觸到內網資源,企業內網越大,攻擊力越強
如何進一步利用SSRF?(很吃基本功:對**網路架構**的了解)
SSRF仍然常見,所以了解是必要的
SSRF可繞過防火牆去取得內網資源,內網資源越多,SSRF的觸碰面越多,被攻擊面也越多
從一些有趣的案例來介紹
* SSRF bypass
* protocol smuggling
## What Is SSRF
Server Side Request Forgery
* 繞過防火牆,碰觸到內網資源
* 被戲稱為專打有錢人的漏洞, 因為有錢人的內網比較大(SSRF攻擊力道愈大)
* XSPA (Cross Site Port Attack, 概念似 side channel attack) attack:based on 時間差可知哪些port 有開,可作port scan -> 有開哪些services
* http://10.0.56.254:80 -OK
* http://10.0..56.254:81 -Timeout
* http://10.0.56.254:82 -Timeout
* 
例如:python 抓某網址之內容時,不同之內建http lib的解析會不同。
## SSRF Digging
- 常見參數?url,link, src, target, u, imageURL, host
- 從網址上傳?
- 資源 import/文章中網址?
- URL 預覽; 分享連結(since tittle or meta data needs server-side information)
- 有無存取 web server (Tool: Skull security)
- DNS 有無來存取 (Tool: Dnslogger)
- Special XML insert
- schemaLocation
- noNamespeaceSchemaLocation
- Xlnclude
- XML External Entity (XXE): XML 中,定義變數
- 特殊 SSRF 的地方(下敘為弱點)
- Oracle UTL_HTTP:?id=1 and 1=1
- ImageTragick:SSRF.gif(.mvg)
- FFMPEG:SSRF.m3u8(加字幕功能)
- HTTPoxy:HTTP request header 會被取代成環境變數 incording to CGI spec
- HTTP lib 將環境變數 http_proxy 當作 proxy 使用 e.g. CURL
- SVG to SSRF:SVG Parser implement 抓取外部資源
## Protocol Smuggling in SSRF
* Make SSRF more powerful
* HTTP based protocol: Elastic, CouchDB, MongoDB, Docker(可被攻擊的內網服務)
* Text-based protocol: FTP, SMTP
* 在原有的協議中走私其他的協議
* SMTP 的 protocol 是 line by line
* 利用 CR-LF injection 將 payload 插到 HTTP protocol 中
* 現在的SMTP Server 會阻止HTTP connection
* if SMTP connection 第一行有 HTTP pattern then close connection
* GOPHER(a protocol (?))
### HTTPS 中偽造 SMTP(:25/)
HTTPS Protocol 所有訊息都會在SSL中被加密,那如何在HTTPS中偽造SMTP? ->思考有哪些東西在SSL/HTTPS中不會被加密?->SNI(Server Name Indication)(?)
#### 對攻擊目標之:25/送 HTTPS connection -> bypass

> 將攻擊payload 放在SSL SNI中
hello message 中 sni 的 extension
如果我們能在 hostname 插一些奇怪的字元
在這個例子中黃色框框是一個空白
這個空白非常重要,因為能讓我們有機會塞一些奇怪的東西,但他還是能正常連上
這邊用到的 trick 在 linux 的 glibc 中 (//先記住,晚點說)
剛剛是用 16 進位的方式來看封包
現在用人類方式來看(?)

## Make SSRF Great Again: 4 methods
URL Parsing Issues: URL parser and requester 對同一個網址有不同解釋
* checking URL is defficult because WHATWG的RFC3986 只有定義規格無定義實作。以人魚為例,spec 是半人半魚,但不知道哪一半是人哪一半是魚啊!實作成品會出乎意料之外。

- Scheme: SSRF 攻擊面
- Authority: 是否可以SSRF攻擊
- Path: SSRF 攻擊深度
### SSRF 利用
**Local**
- Ruby's open(parans[:url])
- url: /etc/passwd
- http:/../../etc/passwd: Because there is not http://, therefore, if there is an folder named http, the url will be seems file route note url.
**Remote**
- 可使用的協議
- Gopher (萬用協議-可偽造任意TCP封包)
- 限制:需要Handshake/加密/認證,則無法利用
- Jar: 在目標伺服器製造可控的暫存檔案
- DOS
- LFY
- FTP / SMB: pwd BruteForece
- UNC Path
- Pass the Hash
- 可擁有的服務
- 攻擊內網常見的 HTTP/HTTPS service
- Struts2: Java framework
- ElasticSearch - Port 9200
- Docker - Port 2375
- Neo4j, CouchDB, MongoBD: 直接訪問API 可透過修改設定甚至導致ROC
- HeartBleed
- Tomcat Port 8005
- Zabbix Port 10050
- Radis Port 6379
- SAVE write shell
- .. SSH Key
- .. Cribtab
- SET modify value for 二次利用
- SMTP Port 25
- 內部主機寄信:test.smtp.org/
- test/smtp.org/log 記錄攻擊是否成功
- Memcached Port 11211
- SET modify value for 二次利用
- Memcached + Rails: Memcahed & Dalli lib 會經過 Marshal
- FastCGI Port 9000
#### 演練
Q1:
https://blog.ephrain.net/wp-content/uploads/2015/08/1439478873-964214684.png
http://127.0.0.1/
file://../etc/passwd

這段 php code 只有 7 行

programmers use parse_url(php內建的) method to check port & host are legal or not; However, RFC 只定義冒號(分隔 port&host) spec,但有的 parser 會從帽號前面來解釋,有的 parser 會從冒號後面來解釋


// PHP parse_url讀前面 PHP readfile讀後面
**How about CURL(?)**
Curl(A lib) 很大量的人用,用於抓取資源。內建 http lib很爛,故幾乎都改用 Curl,但給 Curl 更新之後,後續用一個空白一樣可以打穿這個弱點。
開發團隊回覆:無法過濾來源網址,請程式設計師自行檢查,只能用文件提醒大家… ((誰會看文件啊 XD


##### Attack NodeJS by Unicode

- 使用者同名目錄當成加目錄,會檢查..以外的字(為了防止什麼攻擊?)-> 無法存取sandbox 以外的目錄:
- 假設現在有個密碼檔在根目錄下,如何繞過此限制存取到該檔案?-> 用 Unicode 全型字母 N。
**JavaScript 內部使用UCS2實作來處理全型字母**
- UCS2 處理全型字串->轉為十六進位->N = \xFF\x2E
(Differences between UCS-2 and UTF-16: https://mathiasbynens.be/notes/javascript-encoding)


Moreover, NodeJs(C++實作,以byte為單位) bufferString will discard the fist byte when encoding conversion.

. = \x2E

**若插換行呢?**
可以用剛剛這個 unicode 的特性 U+FF0D, U+FF0A 繞過這個保護(when BufferString, FF會被拿掉->變換行符號)
#### GLibc NSS 的特性

- RFC1035: DNS 支援十進位的轉換。
or\097nge = orange
- 反斜線後面若非數字,會把反斜線直接拿掉->用一堆反斜線來混淆host name域名。(python@linux). For example, \o\r\a\n\g\e.\o\r\g
- Getaddressinfo(): 合法IP address+空白字元後面的東西給過濾掉
\o\r\a\n\g\e.\o\r\g = orange.org
#### 攻擊URL parsing (\t encoding 問題)32:40


換行 & 可以用相同的 Host 塞奇怪的東西進來,以"換行"參雜其他協定。(繞過相同的Host,傳送至其他的Request)
**Attacks by Glibc NSS feature**
- HTTP 1.1 要求 a Host header; 網址 host name will put in request host header. 34:00
- .......(?)

SET foo 0 60 5\r\n:443/



感謝 Redis 跟 memcached
用前面的空白去繞過亦可。 (用於多一個空白,可用於最新版本的python)
#### Attack IDNA
- IDNA => 定義Unicode的標準 //複雜的排版上是否為合法之類的標準
- IDNA standars 目前常用的標準有兩個 2003, 2008 過渡期:2003+UTS46->如果 URL 的 parser 跟 url requester 用不同標準就會有問題

- 拉丁字母 ß (德母的字母沒有相對應的大寫字母,就會轉成兩個大寫s) However, ss!=ß; 但如果用瀏覽器去開啟,會有可以繞過黑名單的洞。For example, WordPreß = WordPress -> 目前還沒修 XD
繞過 IIS 的方式:找出標準中的不一致,就可以達到繞過的方式。
### SSRF Bypass
- DNS Bypass
- 方便的host name反解提供商
- xip.io
- DNS Rebinging
- Round-Robin DNS: 使某DNS記錄可對應到哪個IP
- TTL = 1
- attack.com 第一次解析 1.2.3.4
- attack.com 第二次解析 127.0.0.1
- 網址 Bypass
- 127.0.0.1
- localhost
- 127.0.1
- 127.1
- 0.0.0.0
- 0.0
- 0
- IP 表達形式
- ping 127.2.3.4
- ping 0x7f.0x0.0x0.0x1
- ping 0177.01.01.01
- ping 0x7f000001
- .........
- IPv6 可接 interface(IP....%1, %後接的是interface)
- WordPress SSRF
- 各種 localhost 的不同表達方式
- 雜項
- 302 Rederection
- Fingerprinting: intranet 有哪些services
**檢查要檢查什麼?**
Scheme
Host
Port
### Case study: 3個繞過的方法
1. Time-of-check to time-of-use(TOCTTOU) problem

- URL parser: 檢查網址是否在白名單內
- DNS checker:確保IP不再黑名單內
- URL requstster:存取網址(此時會再產生一次DNS query)並抓回內容
BUT!!!!若檢查時狀態與使用時狀態不同!!

2. 對 IDNA 標準支援的差異
CURL 支援 Unicode 域名自動轉換但PHP之gethostbyname()不支援-> SSRF bypass
3. URL parser and URL requester 的解讀不一致-> bypass
即使 curl 7.54, PHP 後來修復了 SSRF 的問題,但是大多數專案(ex. Ubuntu 17.0.1?的 curl)沒有跟上
**空白的弱點**,curl 永遠不會修復XD
#### SSRF Execution Chain: 4個漏洞串成RCE (?)44:00
GitHub WebHuck 用了一個Ruby gem 作為黑名單保護,然而
可以用 0 輕鬆繞過。**在 linux 中 0 = localhost**->有一個SSRF
但,此SSRF有以下限制導致無法利用此漏洞做事情:
1. 只能用http/https 的 skeme&沒有302重導向跳轉(?)可以轉換成其他skeme(第一次第二次沒檢查header可能被插入location 轉去其他地方)
2. 無法控制POST header&其他內容
3. 前面介紹的CR LF injection(?)在這邊都無法做到
-> 無法做到 protocol smuggling
那,內網中的http服務中有什麼可以做利用咧?
localhost:8000 有個服務會抓GET()參數並訪問->第二個SSRF->用兩個 SSRF 結合成Chain,偽造 protocol
&url=127.0.0.1:6379/%0D%0ASET...
一個假造協定,一個假造目標(?)
為什麼Github 能存下 ruby object (?)
用marshal(?)的方式包起來

#### Prevent(Mitigation)
1. Software(Application): 唯一IP(不用再問一次DNS Server) and hostname(一個IP可能會有多個網站),不要reuse使用者提供的IP
2. Network: firewall/network policy 阻擋intranet traffics(不可以做192.168.../172.20...等內網的請求) Some library you can use like SafeCurl or Advocate