# 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 * ![內網中的服務使用的不同的lib,可能會有不同的解讀](https://i.imgur.com/zhwF8q5.png) 例如: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 ![](https://i.imgur.com/OgaleLo.png) > 將攻擊payload 放在SSL SNI中 hello message 中 sni 的 extension 如果我們能在 hostname 插一些奇怪的字元 在這個例子中黃色框框是一個空白 這個空白非常重要,因為能讓我們有機會塞一些奇怪的東西,但他還是能正常連上 這邊用到的 trick 在 linux 的 glibc 中 (//先記住,晚點說) 剛剛是用 16 進位的方式來看封包 現在用人類方式來看(?) ![](https://i.imgur.com/KlFqxjq.png) ## Make SSRF Great Again: 4 methods URL Parsing Issues: URL parser and requester 對同一個網址有不同解釋 * checking URL is defficult because WHATWG的RFC3986 只有定義規格無定義實作。以人魚為例,spec 是半人半魚,但不知道哪一半是人哪一半是魚啊!實作成品會出乎意料之外。 ![URL Components (RFC3968)](https://i.imgur.com/5lJi8vc.png) - 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 ![今天會涵蓋的漏洞列表](https://i.imgur.com/M7fdgMC.png) 這段 php code 只有 7 行 ![A php code for read a file](https://i.imgur.com/GmupdP4.png) programmers use parse_url(php內建的) method to check port & host are legal or not; However, RFC 只定義冒號(分隔 port&host) spec,但有的 parser 會從帽號前面來解釋,有的 parser 會從冒號後面來解釋 ![Example1: Different parseres have different result](https://i.imgur.com/SujkMSw.png) ![Example2: Different parseres have different result](https://i.imgur.com/M0fptNm.png) // PHP parse_url讀前面 PHP readfile讀後面 **How about CURL(?)** Curl(A lib) 很大量的人用,用於抓取資源。內建 http lib很爛,故幾乎都改用 Curl,但給 Curl 更新之後,後續用一個空白一樣可以打穿這個弱點。 開發團隊回覆:無法過濾來源網址,請程式設計師自行檢查,只能用文件提醒大家… ((誰會看文件啊 XD ![Example3: Different parseres have different result](https://i.imgur.com/Ugjbf5q.png) ![Example4: Different parseres have different result](https://i.imgur.com/AQfkuDA.png) ##### Attack NodeJS by Unicode ![A Nodejs code](https://i.imgur.com/A2Oeviw.png) - 使用者同名目錄當成加目錄,會檢查..以外的字(為了防止什麼攻擊?)-> 無法存取sandbox 以外的目錄: - 假設現在有個密碼檔在根目錄下,如何繞過此限制存取到該檔案?-> 用 Unicode 全型字母 N。 **JavaScript 內部使用UCS2實作來處理全型字母** - UCS2 處理全型字串->轉為十六進位->N = \xFF\x2E (Differences between UCS-2 and UTF-16: https://mathiasbynens.be/notes/javascript-encoding) ![JavaScript UCS2 處理全型字母前之URL](https://i.imgur.com/wP1IZPM.png) ![JavaScript UCS2 處理全型字母後之URL1](https://i.imgur.com/IobWtQn.png) Moreover, NodeJs(C++實作,以byte為單位) bufferString will discard the fist byte when encoding conversion. ![JavaScript UCS2 處理全型字母後之URL2](https://i.imgur.com/tGoQDLK.png) . = \x2E ![JavaScript UCS2 處理全型字母後之URL3](https://i.imgur.com/ctxoqn6.png) **若插換行呢?** 可以用剛剛這個 unicode 的特性 U+FF0D, U+FF0A 繞過這個保護(when BufferString, FF會被拿掉->變換行符號) #### GLibc NSS 的特性 ![GLibc sourcecode](https://i.imgur.com/y4WZAyA.png) - RFC1035: DNS 支援十進位的轉換。 or\097nge = orange - 反斜線後面若非數字,會把反斜線直接拿掉->用一堆反斜線來混淆host name域名。(python@linux). For example, \o\r\a\n\g\e.\o\r\g - Getaddressinfo(): 合法IP address+空白字元後面的東西給過濾掉![linux'll return 127.0.0.1](https://i.imgur.com/Cy7qyYN.png) \o\r\a\n\g\e.\o\r\g = orange.org #### 攻擊URL parsing (\t encoding 問題)32:40 ![](https://i.imgur.com/s23miFF.png) ![](https://i.imgur.com/LS0qDHF.png) 換行 & 可以用相同的 Host 塞奇怪的東西進來,以"換行"參雜其他協定。(繞過相同的Host,傳送至其他的Request) **Attacks by Glibc NSS feature** - HTTP 1.1 要求 a Host header; 網址 host name will put in request host header. 34:00 - .......(?) ![參雜radis protocol(?)](https://i.imgur.com/kfBmOGw.png) SET foo 0 60 5\r\n:443/ ![\t](https://i.imgur.com/gra14xi.png) ![\t URL encode](https://i.imgur.com/Om6rYdS.png) ![\t URL double encode](https://i.imgur.com/sbVARLt.png) 感謝 Redis 跟 memcached 用前面的空白去繞過亦可。 (用於多一個空白,可用於最新版本的python) #### Attack IDNA - IDNA => 定義Unicode的標準 //複雜的排版上是否為合法之類的標準 - IDNA standars 目前常用的標準有兩個 2003, 2008 過渡期:2003+UTS46->如果 URL 的 parser 跟 url requester 用不同標準就會有問題 ![](https://i.imgur.com/o48d5nr.png) - 拉丁字母 ß (德母的字母沒有相對應的大寫字母,就會轉成兩個大寫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 ![三者對SSRF的防禦方法](https://i.imgur.com/YNeEavM.png) - URL parser: 檢查網址是否在白名單內 - DNS checker:確保IP不再黑名單內 - URL requstster:存取網址(此時會再產生一次DNS query)並抓回內容 BUT!!!!若檢查時狀態與使用時狀態不同!! ![TOCTTOU問題之精髓(?)41:00](https://i.imgur.com/E2c3lVr.png) 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(?)的方式包起來 ![完全不懂(?)](https://i.imgur.com/igtt4Qj.png) #### 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