Skip to content

maxuru ~ % cat memcached/exposed-to-the-internet

Memcached exposed to the internet

Severity: criticalApplies to: Memcached 1.5.xApplies to: Memcached 1.6.x

An exposed memcached is two distinct incidents that happen to share a port number. Most write-ups cover one and skip the other.

No authentication in the default build means a TCP connection is a complete grant. Not a foothold to escalate from — the access itself is total:

Terminal window
printf 'stats items\r\n' | nc target 11211 # which slabs hold keys
printf 'stats cachedump 1 100\r\n' | nc target 11211 # actual key names
printf 'get session:9f2a...\r\n' | nc target 11211 # the value

What that yields depends entirely on what you cache, and the answer is usually worse than expected. Session objects mean account takeover without a password. Cached query results mean whatever those queries returned. Rendered fragments mean other users’ personal data. Caches accumulate the expensive-to-compute parts of an application, which correlates closely with the sensitive parts.

Writes are equally unauthenticated. An attacker who can set a key can poison the cache — replacing a cached permission check, a price, or a rendered template that the application will trust because it came from its own cache.

And flush_all drops everything in one command, sending full read load at the database behind it.

This is the one memcached is famous for, and it is not a risk to you — it is your host being used as a weapon.

UDP source addresses are trivially forged. An attacker sends a small request to your memcached with the victim’s address as the source, and memcached sends a much larger reply to the victim. Store a large value first and the ratio becomes enormous.

On 28 February 2018, between 17:21 and 17:30 UTC, GitHub absorbed 1.35 Tbps at 126.9 million packets per second built from exactly this — memcached on UDP 11211, with an amplification factor reported at up to 51,000×. Each byte the attacker sent produced up to 51 kilobytes at the target. It was, at the time, the largest DDoS ever recorded, and the attackers did not compromise a single one of the servers they used. They just found ones that answered.

The vulnerability is CVE-2018-1000115, and the fix shipped in memcached 1.5.6, which disabled UDP by default. Every version since is a non-participant unless somebody explicitly re-enabled it.

So the reflector half of this threat is version-gated, and the data half is not. A current memcached on an open port is still a total data compromise; it just is not also a cannon.

Worth stating plainly, because the genre inflates it and accuracy is the point.

An open memcached is not usually host compromise. There is no CONFIG SET dir equivalent to write an SSH key with, as in Redis, and no user-defined-function path as in MySQL. Memcached has no persistence, no filesystem writes, and no scripting engine. The protocol does what it says.

That places it with MongoDB and Elasticsearch: total data compromise, not usually host compromise. It is rated critical on the data alone, and there is no need to overstate it.

Not by scanning your address. Internet-wide scanners publish memcached instances continuously, and 11211 is a default that nobody changes. Exposure is measured in hours, not months — the port is found long before anyone gets around to auditing it.

Changing the port does not help. Service fingerprinting identifies memcached wherever it answers, and the same scanners record it.

In order, and the first one is usually the whole job:

  1. Bind it. Loopback if clients are local, a private address otherwise, or a Unix socket to remove the network surface entirely. This is the control that closes the exposure.
  2. Firewall the port as well — binding and filtering fail differently, and this is a case worth having both.
  3. Check the version for the reflector half.
  4. Add authentication if your build supports it, for the day the network boundary turns out to be wrong.