← Back to Feed CACHED · 2026-10-20 17:54:48 · CACHE_KEY CVE-2026-25243
CVE-2026-25243 · CWE-122 · Disclosed 2026-05-05

Redis RESTORE command heap double-free via zipmap desynchronization and stream NACK duplicate leading to RCE

ASSESSED — NOISGATE
Vendor
—
—
—
Reassessed
—
—
—
Verdict: —
Do you agree?
01 · The Real Story

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.

"Auth-gated RCE in Redis RESTORE now exploited in the wild; default configs wide open"
02 · The Attack Path

6 steps from start to impact.

STEP 01

Gain network access to Redis

The attacker needs TCP connectivity to the Redis port (default 6379). In exposed-internet scenarios, Shodan/Censys currently index ~40,000–60,000 unauthenticated Redis instances. In enterprise environments, the attacker needs internal network access — either from a compromised host, a misconfigured cloud security group, or an overly permissive VPN.
Conditions required:
  • TCP access to Redis port (6379 or custom)
Where this breaks in practice:
  • 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
Detection/coverage: Shodan/Censys/FOFA scans detect internet-exposed instances. Internal exposure requires asset inventory audits.
STEP 02

Authenticate to Redis

The exploit requires at minimum 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.
Conditions required:
  • Valid credentials or unauthenticated access
Where this breaks in practice:
  • Enterprises with Redis ACLs and strong per-user passwords are materially harder to exploit
  • Redis Cloud (managed) enforces authentication by default
Detection/coverage: Redis AUTH failures logged in slowlog. Monitor for brute-force attempts on port 6379.
STEP 03

Execute crafted RESTORE payload (double-free)

The attacker sends a malformed serialized payload to 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.
Conditions required:
  • RESTORE command permission (default: granted to all users)
  • Target Redis is an affected version
Where this breaks in practice:
  • ACL rule -RESTORE on non-admin users completely blocks this step
  • Some Redis forks (KeyDB, Dragonfly) may not share the same code path
Detection/coverage: Redis crash logs with stack traces originating from rdbLoadObject or ziplistConvert. Anomalous RESTORE commands in slowlog or MONITOR output.
STEP 04

Heap spray and overlap detection

Post-double-free, the exploit sprays Redis keys with unique marker strings to identify which two live objects share the same freed heap chunk. It then deletes one object, reclaims the chunk with a crafted 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.
Conditions required:
  • Heap layout must be semi-predictable (fresh or low-load instance improves reliability)
Where this breaks in practice:
  • High-throughput production instances with fragmented heaps reduce exploit reliability
  • jemalloc thread caches and arena randomization add noise
Detection/coverage: Sudden creation of many small keys followed by rapid deletion is anomalous. Memory usage spikes without corresponding client activity.
STEP 05

ASLR bypass via Lua heap probing

The exploit moves probing logic into server-side Lua (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.
Conditions required:
  • EVAL command permission (default: granted)
  • Lua scripting enabled (default: yes)
Where this breaks in practice:
  • ACL rule -EVAL blocks this step but also breaks many legitimate workloads
  • Redis 7.0+ lua-replicate-commands changes can affect script behavior
Detection/coverage: Long-running Lua scripts trigger BUSY warnings. Monitor for EVAL calls from unexpected clients.
STEP 06

Code execution via DEBUG CRASH-AND-RECOVER

The exploit patches 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.
Conditions required:
  • Arbitrary write primitive from step 4
  • Knowledge of redisServer struct layout from step 5
Where this breaks in practice:
  • Running Redis as non-root with seccomp/AppArmor/SELinux limits post-exploitation impact
  • Containers with read-only root filesystems constrain persistence
Detection/coverage: Process execution under the redis-server PID tree. EDR/auditd alerts on execve from redis-server. Redis process crash + immediate child shell spawn is highly anomalous.
03 · Compensating Control

1
HIGH 7.8→LOW 3.1
SEVERITY REDUCED
ACL-block RESTORE and DEBUG for non-admin users — Run 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.
2
HIGH 7.8→MEDIUM 5.5
SEVERITY REDUCED
Enable authentication and per-user ACLs — Set 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.
3
HIGH 7.8→HIGH 6.8
Network-segment Redis to application-tier VLAN only — Bind Redis to internal interfaces only (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.
4
HIGH 7.8→HIGH 7.0
Run Redis as non-root with seccomp/AppArmor/SELinux — Ensure 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.
5
HIGH 7.8→IGNORE 0.0
SEVERITY REDUCED
Patch to fixed Redis version — Upgrade to the fixed release for your version line: 6.2.22, 7.2.14, 7.4.9, 8.2.6, 8.4.3, or 8.6.3. For distro packages, apply your vendor's backport (e.g., Ubuntu 24.04: 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.
What doesn't work
  • 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.
04 · Intelligence Metadata

The supporting signals.

In-the-wild exploitationConfirmed. 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-conceptMultiple 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.
EPSS0.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 statusNot listed as of 2026-10-21. Given confirmed wild exploitation, KEV addition is plausible in coming weeks.
CVSS vectorCVSS: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 versionsAll 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 versionsUpstream: 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 dataShodan 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 timelineDisclosed 2026-05-05 via coordinated advisory covering five CVEs. Patches shipped same day. ~5.5 months elapsed to first confirmed exploitation (Oct 16–17).
ResearchersDouble-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.

  1. Redis Security Advisory (official)
  2. Wiz ZeroDay.Cloud deep-dive: CVE-2026-25243
  3. SecurityOnline — Redis RESTORE CVE-2026-25243 exploited in the wild
  4. dinosn/CVE-2026-25243 PoC (GitHub)
  5. Red Hat CVE page
  6. Ubuntu OSV advisory
  7. SentinelOne vulnerability database
  8. FIRST EPSS API
05 · The Call

Final Verdict
= UNCHANGED to HIGH (7.8/10)

Why this verdict

  • Authentication barrier is real but thin. The CVSS PR:L is technically correct, but default Redis ships with no requirepass and protected-mode only 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.

06 · Verification

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.

noisgate-verify.sh
BASHREAD-ONLYSAFE
#!/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