Memcached Unauthorized Access Defense: Cache Service Hardening Guide
Memcached has no authentication by default. An exposed port means unauthorized access: data leaks at best, UDP reflection DDoS at worst. This guide covers port confirmation, bind-to-intranet, firewall drop, SASL auth, and disabling UDP—with copy-paste hardening commands and verification.
Applicable scenarios
Memcached unauthorized-access hardening applies to Web systems that cache Session, catalog data, and similar objects in Memcached; cloud or bare-metal hosts exposed on the public internet; security-assessment and MLPS remediation that must close high-risk ports; and multi-tenant or hybrid networks that need a hard access boundary around an internal service. Memcached is fast by design and ships with no auth. Ignore port exposure and it becomes a pivot for lateral movement and DDoS reflection.
Prerequisites
- A Linux host running Memcached (Ubuntu 22.04 / Debian 12 in this article)
- root or sudo: service config and firewall rules
- Confirmed access path from the app (loopback on-box vs intranet cross-host)
How it works
Memcached listens on 11211 by default. Protocol is trivial: after connect, the client sends plaintext `stats`, `get`, `set`. No identity check. Anyone can read every key, overwrite data, or `flush_all` the cache and avalanche the app. Worse: UDP 11211 is on by default and answers spoofed-source amplification (one-byte request → hundreds of times the response). It has been used at scale for UDP reflection DDoS. Hardening model: minimize exposure (intranet only) + authentication (SASL) + kill the dangerous channel (UDP).
Procedure
1. Confirm exposure
Check listen address and whether the port is open:
# Listen address and port. 0.0.0.0:11211 = bound on all interfaces
ss -lntup | grep 11211
# External view: is the port reachable on the public internet (authorized test env only)
nmap -sU -p 11211 <server public IP>
2. Bind to an internal address
Edit the config. Change listen from `0.0.0.0` to loopback or an intranet address:
# /etc/memcached.conf: on-box app, loopback only
-l 127.0.0.1
# Cross-host intranet access: bind the intranet IP (never a public IP)
-l 10.0.0.5
# Restart to apply
systemctl restart memcached
ss -lntup | grep 11211 # confirm listen address has shrunk
3. Firewall: drop external access
# iptables: allow 11211 only from the intranet range
iptables -A INPUT -p tcp --dport 11211 -s 10.0.0.0/8 -j ACCEPT
iptables -A INPUT -p tcp --dport 11211 -j DROP
iptables -A INPUT -p udp --dport 11211 -j DROP
# Persist (Debian/Ubuntu: netfilter-persistent)
netfilter-persistent save
4. Disable UDP listen
UDP is for reflection attacks. App traffic almost never needs it. Turn it off:
# Add -U 0 to memcached startup args to disable UDP
# Append to /etc/memcached.conf:
-U 0
# After restart, UDP must no longer listen
ss -lunp | grep 11211
5. Enable SASL auth (optional extra control)
If the cache holds sensitive data and you cannot rely on network isolation alone, enable SASL. Requires a build with SASL support:
# Install SASL components
apt install -y libsasl2-dev sasl2-bin memcached
# Create the auth-db user
saslpasswd2 -a memcached -c cacheuser
# Enter and confirm the password (e.g. Strong@2026)
# Append to /etc/memcached.conf:
-S
# Restart and verify
systemctl restart memcached
printf 'stats\r\n' | nc 127.0.0.1 11211 # unauthenticated should return ERROR
6. Patch and monitor
# Upgrade to latest stable; pick up known-vuln fixes
apt update && apt upgrade memcached
# Watch connection sources and anomalous commands
memcached-tool 127.0.0.1:11211 stats | grep -E 'curr_connections|cmd_flush|total_connections'
Verification
# 1. Listen address: must show only 127.0.0.1 or an intranet IP
ss -lntup | grep 11211
# 2. UDP off: no output = success
ss -lunp | grep 11211
# 3. Firewall rules in place
iptables -L INPUT -n | grep 11211
# 4. From an external host: must not connect (timeout or refused)
nc -vz <server IP> 11211
# 5. App regression: reads/writes still work
memcached-tool 127.0.0.1:11211 stats | grep -E 'get_hits|get_misses'
Pass criteria: listen address shrunk, UDP off, externally unreachable—all hard requirements. After SASL, configure username/password on the client and re-check get_hits; hit rate must not drop materially.
FAQ
Q1: App host and cache host are on different subnets. After binding intranet, connect fails. What now?
Do not bind a public address. Bind the intranet NIC the app can reach. Firewall: allow only the app-server CIDR (e.g. `172.16.0.0/12`); DROP everything else. If you must cross the public internet: VPN or a private line, SASL on both ends.
Q2: After SASL, the client reports “authentication not supported”. What now?
Server binary was not built with SASL. Check `memcached -h | grep sasl`. No output: rebuild with `--enable-sasl`, or install the distro package that ships SASL. Client must pass username and password on connect (e.g. PHP memcached extension `setSaslAuthData`).
Summary
Memcached unauthorized access is a classic misconfiguration high-risk. Cheap to fix, high defensive value. Four layers—bind intranet, firewall allowlist, disable UDP, SASL—shrink the risk to a controllable range. Put 11211 on the daily port-scan checklist. Monitor connection count and `cmd_flush`. Alert on abnormal access. If the cache was ever exposed, check for reads and writes you did not make. Rotate sensitive cached data if needed.