干貨 | SSRF的防御與繞過
SSRF漏洞形成的原因主要是服務器端所提供的接口中包含了所要請求的內容的URL參數,并且未對客戶端所傳輸過來的URL參數進行過濾
一般的防御措施是對URL參數進行過濾,或者使得URL參數用戶不可控,但當過濾方法不當時,就存在Bypass的不同方式
@繞過
http://www.baidu.com@10.10.10.10與http://10.10.10.10請求是相同的
該請求得到的內容都是10.10.10.10的內容,此繞過同樣在URL跳轉繞過中適用。
原理如下:
利用解析URL時的規則問題。
一般情況下利用URL解析導致SSRF過濾被繞過基本上都是因為后端通過不正確的正則表達式對URL進行了解析。而在2017年的Blackhat大會上,Orange Thai 在blackhat中發表的演講《A New Era of SSRF - Exploiting URL Parser in Trending Programming Languages! 》中介紹了SSRF攻擊的一個新的角度———利用不同編程語言對URL的處理標準來繞過SSRF過濾,從而實施攻擊。該方式主要是利用URL解析器和URL請求器之間的差異性發起攻擊,由于不同的編程語言實現URL解析和請求是不一樣的,所以很難驗證一個URL是否合法。
很難驗證一個URL是否合法的原因在于:
1.在 RFC2396/RFC3986 中進行了說明,但是也僅僅是說明。
2.WHATWG(網頁超文本應用技術工作小組)定義了一個基于RFC協議的具體實現,但是不同的編程語言仍然使用他們自己的實現。
下圖展示了cURL請求函數與其他語言解析函數結合使用時,由于差異性造成的漏洞。

可以得知,NodeJS url、Perl URI、Go net/url、PHP parser_url以及Ruby addressable解析函數與cURL libcurl請求函數差異性都可能造成漏洞的產生
下圖的實例中,我們看到上述所述編程語言的解析函數得到的IP是google.com,而cURL請求得到的卻是evil.com:80

點分割符號替換
在瀏覽器中可以使用不同的分割符號來代替域名中的.分割,可以使用。、?、.來代替:
http://www。qq。com http://www?qq?com http://www.qq.com
本地回環地址
127.0.0.1,通常被稱為本地回環地址(Loopback Address),指本機的虛擬接口,一些表示方法如下(ipv6的地址使用http訪問需要加[]):
http://127.0.0.1 http://localhost http://127.255.255.254 127.0.0.1 - 127.255.255.254 http://[::1] http://[::ffff:7f00:1] http://[::ffff:127.0.0.1] http://127.1 http://127.0.1 http://0:80

IP的進制轉換
IP地址是一個32位的二進制數,通常被分割為4個8位二進制數。通常用“點分十進制”表示成(a.b.c.d)的形式,所以IP地址的每一段可以用其他進制來轉換。 IPFuscator 工具可實現IP地址的進制轉換,包括了八進制、十進制、十六進制、混合進制。在這個工具的基礎上添加了IPV6的轉換和版本輸出的優化。
在腳本對IP進行八進制轉換時,一些情況下會在字符串末尾多加一個L。

封閉式字母數字 (Enclosed Alphanumerics)字符
封閉式字母數字是一個由字母數字組成的Unicode印刷符號塊,使用這些符號塊替換域名中的字母也可以被瀏覽器接受。在瀏覽器測試中只有下列單圓圈的字符可用:
List: ① ② ③ ④ ⑤ ⑥ ⑦ ⑧ ⑨ ⑩ ? ? ? ? ? ? ? ? ? ? ⑴ ⑵ ⑶ ⑷ ⑸ ⑹ ⑺ ⑻ ⑼ ⑽ ⑾ ⑿ ⒀ ⒁ ⒂ ⒃ ⒄ ⒅ ⒆ ⒇ ⒈ ⒉ ⒊ ⒋ ⒌ ⒍ ⒎ ⒏ ⒐ ⒑ ⒒ ⒓ ⒔ ⒕ ⒖ ⒗ ⒘ ⒙ ⒚ ⒛ ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?
瀏覽器訪問時會自動識別成拉丁英文字符:
???????.??? >>> example.com
URL十六進制編碼
URL十六進制編碼可被瀏覽器正常識別,編碼腳本:
#-*- coding:utf-8 -*-
data = "www.qq.com";
alist = []
for x in data:
for i in range(0, len(x), 2):
alist.append((x[i:i+2]).encode('hex'))
print "http://%"+'%'.join(alist)

利用網址縮短
網上有很多將網址轉換未短網址的網站。
?https://www.985.so/
?https://www.urlc.cn/

利用30X重定向
可以使用重定向來讓服務器訪問目標地址,可用于重定向的HTTP狀態碼:300、301、302、303、305、307、308。
需要一個vps,把302轉換的代碼部署到vps上,然后去訪問,就可跳轉到內網中
服務端代碼如下:
header("Location: http://192.168.1.10");
exit();
?>
DNS解析
配置域名的DNS解析到目標地址(A、cname等),這里有幾個配置解析到任意的地址的域名:
nslookup 127.0.0.1.nip.io nslookup owasp.org.127.0.0.1.nip.io
xip.io
xip.io是一個開源泛域名服務。它會把如下的域名解析到特定的地址,其實和dns解析繞過一個道理。
http://10.0.0.1.xip.io = 10.0.0.1 www.10.0.0.1.xip.io= 10.0.0.1 http://mysite.10.0.0.1.xip.io = 10.0.0.1 foo.http://bar.10.0.0.1.xip.io = 10.0.0.1 10.0.0.1.xip.name resolves to 10.0.0.1 www.10.0.0.2.xip.name resolves to 10.0.0.2 foo.10.0.0.3.xip.name resolves to 10.0.0.3 bar.baz.10.0.0.4.xip.name resolves to 10.0.0.4
DNS重綁定

Untitled Diagram.drawio (3)
根據流程圖:對于用戶請求的URL參數,首先服務器端會對其進行DNS解析,然后對于DNS服務器返回的IP地址進行判斷,如果在黑名單中,就pass掉。
但是在整個過程中,第一次去請求DNS服務進行域名解析到第二次服務端去請求URL之間存在一個時間差,利用這個時間差,我們可以進行DNS 重綁定攻擊。我們利用DNS Rebinding技術,在第一次校驗IP的時候返回一個合法的IP,在真實發起請求的時候,返回我們真正想要訪問的內網IP即可。
要完成DNS重綁定攻擊,我們需要一個域名,并且將這個域名的解析指定到我們自己的DNS Server,在我們的可控的DNS Server上編寫解析服務,設置TTL(TTL表示DNS記錄在DNS服務器上緩存時間)時間為0,這是為了防止有DNS服務器對第一次的解析結果進行緩存。
完整的DNS重綁定攻擊流程為:
1.服務器端獲得URL參數,進行第一次DNS解析,獲得了一個非內網的IP
2.對于獲得的IP進行判斷,發現為指定范圍IP,則通過驗證
3.接下來服務器端對URL進行訪問,由于DNS服務器設置的TTL為0,所以再次進行DNS解析,這一次DNS服務器返回的是內網地址
4.由于已經繞過驗證,所以服務器端返回訪問內網資源的內容

在這里插入圖片描述
比如在把同一個域名綁定兩個不同的地址,也就是兩條A記錄,去碰這個概率,要的情況是第一次為外網地址,然而TTL為0,第二次請求的時候要為內網地址。
上面這種情況的話,每次解析的結果隨機,所以要達到上面這樣情況有1/4的機率,是這樣算的吧。所以去碰這個概率,碰到了就能成功,但這種方法不穩定。
需要一個更好的方法:

在這里插入圖片描述
所以需要 添加一條A記錄和一條NS記錄
ns記錄表示域名test.bendawang.site這個子域名指定由ns.bendawang.site這個域名服務器來解析,然后a記錄表示我的這個ns.bendawang.site的位置在ip地址104.160.43.154上。
這樣的話第一解析test.bendawang.site時為ns.bendawang.site這個地址,能通過,
然后第二次解析ns.bendawang.site的時候,就為配置的內網地址了。
這里推薦一個在線的實現URL重綁定的工具(雖然只能實現上述的第一種方式,碰運氣去解析):
https://lock.cmpxchg8b.com/rebinder.html

有關DNS重綁定的具體實現可以參考如下文章:
http://www.bendawang.site/2017/05/31/%E5%85%B3%E4%BA%8EDNS-rebinding%E7%9A%84%E6%80%BB%E7%BB%93/
SSRF的測試工具
SSRFmap
SSRFmap-master - 可以在一個請求包中指定SSRF的位置,工具根據模塊來發送EXP,支持了下列漏洞的利用:

幫助說明如下:

SSRF-Testing
SSRF-Testing-master - 常用的SSRF繞過測試

redis-over-gopher
redis-over-gopher - 將請求轉換為gopher協議格式

SSRF的加固
?禁止302跳轉,或者每跳轉一次都進行校驗目的地址是否為內網地址或合法地址。
?過濾返回信息,驗證遠程服務器對請求的返回結果,是否合法。
?禁用高危協議,例如:gopher、dict、ftp、file等,只允許http/https
?設置URL白名單或者限制內網IP
?限制請求的端口為http的常用端口,或者根據業務需要治開放遠程調用服務的端口
?catch錯誤信息,做統一錯誤信息,避免黑客通過錯誤信息判斷端口對應的服務