Like leaving your vault door locked but the combination taped to the frame — Redis RESTORE's heap corruption chain bypasses ASLR and achieves RCE, and most deployments never changed the default key
CVE-2026-25243 is a heap-based memory corruption vulnerability in the Redis RESTORE command, encompassing two independent bugs: a zipmap length-encoding desynchronization that triggers a double-free on 256-byte SDS chunks, and a stream consumer group NACK double-free on 32–48-byte streamNACK allocations. An authenticated attacker sends a crafted serialized payload to RESTORE, exploits the double-free to create heap overlap, then chains into an arbitrary read/write primitive via SDS header corruption. The exploit culminates in patching server.executable and server.exec_argv in redisServer memory and issuing DEBUG CRASH-AND-RECOVER to execute execve("/bin/sh", …). Full ASLR bypass is achieved server-side using Lua scripting. All Redis OSS/CE versions through 6.2.21, 7.2.13, 7.4.8, 8.2.5, 8.4.2, and 8.6.2 are affected.
The NVD assigned CVSS 3.1 base 8.8 (HIGH) while Redis's own CVSSv4 assessment came in at 7.7 (HIGH). The NVD score of 8.8 is slightly generous for most enterprise deployments: it accurately reflects PR:L (authenticated), but doesn't capture that Redis should never face the internet and that ACL restriction of RESTORE is a one-command mitigation. However, the 7.7 vendor self-score slightly *understates* real-world risk because default Redis ships with no authentication and grants the default user access to every command including RESTORE. With exploitation now confirmed in the wild via honeypots (October 16–17, 2026) and multiple public PoCs achieving reliable RCE with ASLR on, the practical severity sits between the two vendor numbers — but the active exploitation tilts the urgency sharply upward.
6 steps from start to impact.
Gain network access to Redis
- TCP access to Redis port (6379 or custom)
- Redis should never be internet-exposed; well-managed enterprises keep it behind firewalls on internal VLANs
- Cloud providers (AWS ElastiCache, Azure Cache) default to VPC-only access
Authenticate to Redis
PR:L — a valid session. Default Redis ships with protected-mode on but no requirepass, meaning localhost connections are unauthenticated. Remote connections without auth are rejected only by protected-mode, which many operators disable. Where auth exists, it is typically a single shared password (requirepass), not per-user credentials. ACLs (Redis 6.0+) are available but adoption is low.- Valid credentials or unauthenticated access
- Enterprises with Redis ACLs and strong per-user passwords are materially harder to exploit
- Redis Cloud (managed) enforces authentication by default
AUTH failures logged in slowlog. Monitor for brute-force attempts on port 6379.Execute crafted RESTORE payload (double-free)
RESTORE that exploits either the zipmap length-encoding desync or the stream consumer group NACK duplicate rawid path. Both trigger a double-free: the zipmap variant frees a 256-byte SDS chunk twice via dictRelease() + explicit sdsfree(field); the NACK variant frees a 32–48-byte streamNACK twice via the error path and subsequent stream cleanup. Public PoCs from dinosn/CVE-2026-25243 (Python 3, 13 stars) and berabuddies/redis-poc (Python 3 + C, KitPloit) automate this step.- RESTORE command permission (default: granted to all users)
- Target Redis is an affected version
- ACL rule
-RESTOREon non-admin users completely blocks this step - Some Redis forks (KeyDB, Dragonfly) may not share the same code path
rdbLoadObject or ziplistConvert. Anomalous RESTORE commands in slowlog or MONITOR output.Heap spray and overlap detection
RESTORE intset payload containing attacker-controlled bytes, and overwrites the SDS header of the surviving object. This creates a 64KB read/write view that is expanded to ~1MB via chained SDS header corruption.- Heap layout must be semi-predictable (fresh or low-load instance improves reliability)
- High-throughput production instances with fragmented heaps reduce exploit reliability
- jemalloc thread caches and arena randomization add noise
ASLR bypass via Lua heap probing
redis.call) to scan backward from a known heap address, locate function pointers into the Redis binary, and discover the redisServer struct by matching its distinctive field pattern (valid PID, heap-like pointers, small positive hz values). This eliminates network round-trips and completes in seconds.- EVAL command permission (default: granted)
- Lua scripting enabled (default: yes)
- ACL rule
-EVALblocks this step but also breaks many legitimate workloads - Redis 7.0+
lua-replicate-commandschanges can affect script behavior
BUSY warnings. Monitor for EVAL calls from unexpected clients.Code execution via DEBUG CRASH-AND-RECOVER
enable_debug_cmd in redisServer memory, constructs a fake argv array pointing to /bin/sh -c <command> in the memview key, overwrites server.executable and server.exec_argv, and sends DEBUG CRASH-AND-RECOVER. Redis calls restartServer() → execve("/bin/sh", …), executing arbitrary commands as the Redis process user — often root in containerized deployments or redis on bare metal.- Arbitrary write primitive from step 4
- Knowledge of redisServer struct layout from step 5
- Running Redis as non-root with seccomp/AppArmor/SELinux limits post-exploitation impact
- Containers with read-only root filesystems constrain persistence
ACL SETUSER default -RESTORE -DEBUG on every Redis instance (or add to redis.conf / ACL file). This completely breaks the exploit chain at step 3 — the attacker cannot trigger the double-free without RESTORE permission, and cannot achieve code execution without DEBUG even if they obtain arbitrary write. Deploy within hours given active exploitation — the noisgate mitigation SLA for active exploitation overrides the standard 30-day HIGH window. This change is non-breaking for the vast majority of workloads; only migration/replication tooling and debugging scripts use RESTORE directly.requirepass <strong-random> at minimum; better, configure per-user ACLs with least-privilege command sets (ACL SETUSER appuser on >password ~app:* +GET +SET +DEL -RESTORE -DEBUG -EVAL). This raises the bar from 'any TCP connection' to 'must possess valid credentials with RESTORE permission.' Deploy within 30 days per the noisgate mitigation SLA for HIGH severity. Does not fully eliminate the risk if an admin user is compromised but drastically narrows the attack surface.bind 127.0.0.1 <app-tier-subnet>), enforce firewall rules blocking port 6379 from all non-application hosts, and remove any internet-facing exposure. This eliminates the remote attack vector for external attackers and limits internal attackers to those already on the application tier. Deploy within 30 days. Reduces attacker pool but does not prevent exploitation from a compromised application server.redis-server runs as a dedicated redis user (never root), apply a seccomp profile restricting execve, fork, clone syscalls, and enable SELinux/AppArmor confinement. This does not prevent the heap corruption or initial code execution but constrains post-exploitation impact — the attacker's shell inherits limited privileges and cannot easily escalate or persist. Deploy within 30 days. Residual severity remains HIGH because code execution still occurs.redis 5:7.0.15-1ubuntu0.24.04.5). This is the definitive remediation. Per the noisgate remediation SLA for HIGH severity, complete within 180 days — but given active exploitation, accelerate to within 30 days alongside the ACL mitigation above.- TLS encryption for Redis traffic — protects data in transit and prevents credential sniffing, but does nothing against an authenticated attacker who already has a valid session. The exploit payload is delivered over the normal Redis protocol regardless of TLS.
- Redis Sentinel or Cluster high-availability — provides failover and replication, but a compromised primary propagates the attacker's access to replicas. Worse, replication internally uses RESTORE-like serialization, making clusters no harder to exploit.
- Rate-limiting Redis commands — the exploit requires only a handful of RESTORE calls (single-digit) to achieve RCE. Throughput limiting would need to be set impractically low to interfere.
- Upgrading to Redis 7.0+ for ACL support alone without configuring ACLs — having ACL capability means nothing if the default user retains
+@all(all commands). The ACL must be explicitly configured to remove RESTORE.
The supporting signals.
| In-the-wild exploitation | Confirmed. Defused honeypots captured scripted exploitation attempts on October 16–17, 2026 — one attacker hit a decoy five times on a timer with identical payloads. SecurityOnline reports this as the first documented wild exploitation. No CISA KEV listing yet. |
|---|---|
| Proof-of-concept | Multiple public PoCs. dinosn/CVE-2026-25243 (Python 3, 13 stars, achieves RCE with ASLR enabled, no libc offsets needed). berabuddies/redis-poc via KitPloit (Python 3 + C, published July 22 2026, version-specific variants through Oct 2026). Both target stock Redis configs. |
| EPSS | 0.03663 (3.66%) probability of exploitation in next 30 days, 89.52nd percentile. This places it in the top ~10% of all scored CVEs — consistent with authenticated RCE + public PoC + confirmed exploitation. |
| KEV status | Not listed as of 2026-10-21. Given confirmed wild exploitation, KEV addition is plausible in coming weeks. |
| CVSS vector | CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H → 8.8 (NVD) / 7.7 (Redis CVSSv4). The PR:L (low privilege required) is the sole friction in the vector. AC:L is accurate — the PoC is reliable. S:U means impact is confined to the Redis host, though lateral movement extends the blast radius in practice. |
| Affected versions | All Redis OSS/CE releases: 6.2.0–6.2.21, 7.2.0–7.2.13, 7.4.0–7.4.8, 8.2.0–8.2.5, 8.4.0–8.4.2, 8.6.0–8.6.2, plus all unmaintained lines (5.x, 6.0, 6.1, 7.0, 7.1, 7.3, 8.0, 8.1, 8.3, 8.5). Redis Software up to 8.0.6. |
| Fixed versions | Upstream: 6.2.22, 7.2.14, 7.4.9, 8.2.6, 8.4.3, 8.6.3. Redis Software: 8.0.10-64, 7.22.2-79, 7.8.6-253, 7.4.6-279, 7.2.4-153. Ubuntu backports: 7.0.15-1ubuntu0.24.04.5 (24.04), 8.0.5-1ubuntu0.1 (26.04), 8.0.6-3 (26.10). Redis Cloud: already patched. |
| Exposure data | Shodan indexes ~43,000 Redis services on port 6379. Censys found ~39,400 unauthenticated Redis instances (~11% of internet-facing). Wiz's 2025 sweep: ~330,000 exposed, ~60,000 requiring no auth. Most enterprise Redis is internal-only, but misconfigured cloud security groups are a recurring finding. |
| Disclosure timeline | Disclosed 2026-05-05 via coordinated advisory covering five CVEs. Patches shipped same day. ~5.5 months elapsed to first confirmed exploitation (Oct 16–17). |
| Researchers | Double-free discovered by Emil Lerner (@emil_lerner). VectorSets integer overflow and OOB read by Joseph Surin. Reported through Redis's security disclosure process and Wiz ZeroDay.Cloud platform. |
Sources.
Why this verdict
- Authentication barrier is real but thin. The CVSS
PR:Lis technically correct, but default Redis ships with norequirepassandprotected-modeonly blocks non-localhost. ACL adoption is low. In enterprise environments with proper auth, this is a meaningful friction point — but the default-insecure posture means a significant fraction of real deployments have no effective auth gate. Net effect: -0.3 from baseline. - Internal-only deployment norm narrows reachable population. Redis should never be internet-facing. Well-managed enterprises expose Redis only on internal VLANs. While ~40K–60K instances are internet-exposed, this is a small fraction of the millions of Redis deployments. For the average 10K-host enterprise, Redis attack surface is post-initial-access only (attacker already inside). Net effect: -0.5 from baseline.
- ACL mitigation is trivial and fully effective. A single command (
ACL SETUSER default -RESTORE) completely eliminates the attack vector without breaking most workloads. This is a rare case where a one-line config change is a complete compensating control. Net effect: -0.2 from baseline (availability of mitigation, not current deployment state). - Role multiplier: Production database engine on data tiers. Redis is canonically deployed as a production data store (cache, session store, message broker) in >30% of its installed base. RCE on a production Redis instance yields: full access to all cached data (sessions, tokens, PII), pivot point into the application tier, and potential supply-chain impact when Redis backs CI/CD job queues (Sidekiq, Celery, Bull). Blast radius is host → tenant → potential data breach. This floor-sets the verdict at HIGH.
- Role multiplier: CI/CD broker role. In ~5–10% of deployments, Redis serves as the job queue backend for CI/CD pipelines. Compromise here can inject malicious jobs, pivot to build infrastructure, and achieve supply-chain impact. The chain succeeds identically in this role (RESTORE is used by replication and migration tooling). Blast radius: host → supply chain. Reinforces HIGH floor.
- Active exploitation overrides calendar-based urgency. Defused honeypots confirmed scripted exploitation on Oct 16–17, 2026 — 4 days ago. Multiple public PoCs achieve reliable RCE with ASLR bypass via Lua. EPSS at 89.52nd percentile corroborates elevated risk. This doesn't change the severity score but demands immediate mitigation action.
Why not higher?
CRITICAL would require either pre-authentication access or a canonical infrastructure-tier target (domain controller, hypervisor, identity provider, certificate authority). Redis requires authenticated access (PR:L), and while that barrier is often absent in practice, it is architecturally present. Redis is not an identity or infrastructure-control-plane component — compromising a Redis instance does not directly yield domain admin, fleet-wide code execution, or certificate authority compromise. The blast radius, while serious (data exfiltration, session hijacking, lateral movement), is bounded to the host and its data tier rather than propagating automatically across the domain.
Why not lower?
MEDIUM would understate the risk given three converging factors: (1) active exploitation confirmed in the wild just days ago, (2) multiple public PoCs achieve reliable RCE with full ASLR bypass using only default Redis permissions, and (3) Redis is a production data store in >30% of deployments where compromise yields immediate access to sensitive data and lateral movement capability. The default-insecure configuration (no auth, RESTORE accessible to all) means the PR:L friction in the CVSS vector overstates the real barrier for a large fraction of the installed base.
Crowdsourced verification payload.
Run from any Linux/macOS host with redis-cli installed and network access to the target Redis instance. Usage: bash check_cve_2026_25243.sh <host> [port] [password]. No elevated privileges required — uses standard Redis client commands only.
#!/usr/bin/env bash
# CVE-2026-25243 — Redis RESTORE heap corruption vulnerability checker
# Outputs: VULNERABLE / PATCHED / UNKNOWN
# Exit: 1 = VULNERABLE, 0 = PATCHED, 2 = UNKNOWN
set -uo pipefail
HOST="${1:?Usage: $0 <host> [port] [password]}"
PORT="${2:-6379}"
PASS="${3:-}"
AUTH_FLAG=""
[ -n "$PASS" ] && AUTH_FLAG="-a $PASS --no-auth-warning"
# shellcheck disable=SC2086
info=$(redis-cli -h "$HOST" -p "$PORT" $AUTH_FLAG INFO server 2>&1) || {
echo "UNKNOWN — cannot connect to Redis at $HOST:$PORT"; exit 2
}
ver=$(echo "$info" | grep -oP 'redis_version:\K[0-9]+\.[0-9]+\.[0-9]+' | head -1)
[ -z "$ver" ] && { echo "UNKNOWN — could not parse Redis version"; exit 2; }
IFS='.' read -r maj min pat <<< "$ver"
echo "[*] Redis $ver detected at $HOST:$PORT"
# --- Version check against fixed releases ---
# Fixed: 6.2.22, 7.2.14, 7.4.9, 8.2.6, 8.4.3, 8.6.3
# All unmaintained lines (5.x, 6.0, 6.1, 7.0, 7.1, 7.3, 8.0, 8.1, 8.3, 8.5) are vulnerable.
vuln=2 # 0=patched, 1=vulnerable, 2=unknown
case "$maj.$min" in
6.2) [ "$pat" -ge 22 ] && vuln=0 || vuln=1 ;;
7.2) [ "$pat" -ge 14 ] && vuln=0 || vuln=1 ;;
7.4) [ "$pat" -ge 9 ] && vuln=0 || vuln=1 ;;
8.2) [ "$pat" -ge 6 ] && vuln=0 || vuln=1 ;;
8.4) [ "$pat" -ge 3 ] && vuln=0 || vuln=1 ;;
8.6) [ "$pat" -ge 3 ] && vuln=0 || vuln=1 ;;
*)
# Anything above 8.6.x is assumed patched
if [ "$maj" -gt 8 ] || { [ "$maj" -eq 8 ] && [ "$min" -gt 6 ]; }; then
vuln=0
else
# Unmaintained or older lines — all vulnerable, no fix available on this line
vuln=1
fi
;;
esac
# --- RESTORE command ACL check ---
# shellcheck disable=SC2086
restore_test=$(redis-cli -h "$HOST" -p "$PORT" $AUTH_FLAG \
RESTORE __cve2026_25243_check__ 0 "\x00" REPLACE 2>&1 || true)
restore_blocked="no"
if echo "$restore_test" | grep -qi "NOPERM"; then
restore_blocked="yes"
echo "[+] RESTORE command is ACL-blocked for current user"
else
echo "[!] RESTORE command is accessible to current user"
fi
# --- Final verdict ---
case "$vuln" in
0)
echo "PATCHED — Redis $ver includes the fix for CVE-2026-25243"
exit 0
;;
1)
if [ "$restore_blocked" = "yes" ]; then
echo "VULNERABLE (mitigated) — Redis $ver is affected but RESTORE is ACL-blocked"
else
echo "VULNERABLE — Redis $ver is affected and RESTORE is accessible"
fi
exit 1
;;
*)
echo "UNKNOWN — cannot determine patch status for Redis $ver"
exit 2
;;
esac