maxuru ~ % cat memcached/exposed-to-the-internet
Memcached exposed to the internet
An exposed memcached is two distinct incidents that happen to share a port number. Most write-ups cover one and skip the other.
One: everything in the cache is readable
Section titled “One: everything in the cache is readable”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:
printf 'stats items\r\n' | nc target 11211 # which slabs hold keysprintf 'stats cachedump 1 100\r\n' | nc target 11211 # actual key namesprintf 'get session:9f2a...\r\n' | nc target 11211 # the valueWhat 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.
Two: the reflector
Section titled “Two: the reflector”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.
What it is not
Section titled “What it is not”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.
How they find you
Section titled “How they find you”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.
Closing it
Section titled “Closing it”In order, and the first one is usually the whole job:
- 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.
- Firewall the port as well — binding and filtering fail differently, and this is a case worth having both.
- Check the version for the reflector half.
- Add authentication if your build supports it, for the day the network boundary turns out to be wrong.
Related
Section titled “Related”- Bind Memcached to localhost — the fix, and the first thing to do.
- Memcached UDP is already off — the version line that decides the reflector half.