Documentation
¶
Overview ¶
Package redis decodes Redis RESP (REdis Serialization Protocol) v2 + v3 messages per the Redis documentation. Runs on TCP/6379 (default Redis), TCP/6380 + TCP/6381 (Sentinel), TCP/16379 + TCP/26379 (Cluster bus). The third-largest open-source database pentest target after MySQL + PostgreSQL — every modern web-app stack uses Redis for caching / sessions / queues / pub-sub. Deployed everywhere from cloud-managed Redis (AWS ElastiCache / MemoryDB / Google Cloud Memorystore / Azure Cache / Upstash / Redis Enterprise Cloud) to bare-metal to containerized side- cars.
Operationally, Redis is the **canonical "exposed-to-the- internet without auth" pentest target** because:
**Default deployments have NO authentication** — `requirepass` is unset by default; the only protection is the `protected-mode` flag (introduced in 3.2) which refuses connections from non-localhost when no password is set. Disabling protected-mode + binding to 0.0.0.0 = unauthenticated Redis exposed to the internet. Shodan finds 100,000+ unauthenticated Redis instances on TCP/6379 globally.
**Multiple RCE primitives** — even when AUTH is required, successful authentication often grants enough power to achieve RCE:
`CONFIG SET dir /home/<user>/.ssh` + `CONFIG SET dbfilename authorized_keys` + `SET <random> "ssh-rsa ..."` + `SAVE` — writes an SSH authorized_keys file via Redis persistence. The canonical Redis-to-shell.
`MODULE LOAD /path/to/evil.so` — load arbitrary native code (Redis 4.0+) as a module. Direct RCE.
`SCRIPT LOAD` / `EVAL` — Lua scripting; CVE-2022-0543 (Debian Redis Lua sandbox escape) allowed RCE via `package.loadlib`.
`SLAVEOF` / `REPLICAOF` an attacker-controlled host coerces the victim into restoring an attacker-crafted RDB file (which can contain a malicious module).
**Cleartext password on the wire** — `AUTH <password>` sends the password as a Bulk String over TCP/6379 in cleartext (Redis 6+ supports TLS but it's opt-in and uncommon in legacy deployments). The decoder surfaces the AUTH command but reports `password_bytes` LENGTH only (privacy-preserving — never the password itself).
**Brute-force-friendly auth** — when `requirepass` is set, AUTH responses are `+OK\r\n` for success or `-WRONGPASS invalid username-password pair\r\n` for failure. Default Redis has no rate limiting (Redis 6.2+ adds optional ACL-based limits).
The wire format leaks:
- **AUTH with cleartext password** — `*2\r\n$4\r\nAUTH\r\n $N\r\n<password>\r\n`. Surfaces `is_auth_command` boolean + `password_bytes` length only.
- **HELLO with embedded AUTH** — `HELLO 3 AUTH <user> <password> SETNAME <name>` — RESP3 protocol negotiation with optional inline credentials.
- **Dangerous command detection** — flags CONFIG / DEBUG / MODULE / SCRIPT / EVAL / SLAVEOF / REPLICAOF / SHUTDOWN / FLUSHDB / FLUSHALL / CLIENT KILL with the attack-vector classification.
- **Brute-force feedback via error responses** — `-NOAUTH` (server requires AUTH — pre-auth signal), `-WRONGPASS` (canonical wrong-password — password- spray feedback), `-PERMISSION` (ACL denied), `-MOVED` / `-ASK` (Cluster slot redirection), `-LOADING` (server warming), `-BUSY` (script running).
Wrap-vs-native judgement
Native. RESP is publicly documented; it's a simple text protocol with five primary types (Simple String / Error / Integer / Bulk String / Array) plus eight RESP3 additions. Frame parsing is a CRLF-walker with length-prefixed bulk strings + count-prefixed arrays. RDB persistence format, AOF format, Cluster slot map, module command IDLs, and RediSearch / RedisJSON / RedisTimeSeries module-specific command semantics are out of scope.
What this package covers
**5-entry RESP2 type discrimination** by first byte: `+` Simple String / `-` Error / `:` Integer / `$` Bulk String / `*` Array.
**8-entry RESP3 type discrimination** (in addition to RESP2): `%` Map / `~` Set / `,` Double / `(` Big Number / `#` Boolean / `_` Null / `=` Verbatim String / `>` Push.
**CRLF frame walker** — each value is `\r\n`-terminated; Bulk Strings have a `$N\r\n<N bytes>\r\n` length- prefixed form (N=-1 indicates null); Arrays have a `*N\r\n` count-prefixed form (N=-1 indicates null array).
**Top-level Array of Bulk Strings detection** — the canonical client→server command shape. Surfaces `command` (first element, uppercased) + `argument_count` + `arguments` (subsequent elements, up to 16 — each truncated to 256 bytes for surfacing).
**Command classification + dangerous-command flagging** against a 13-entry table: AUTH / HELLO / CONFIG / DEBUG / MODULE / SCRIPT / EVAL / EVALSHA / SLAVEOF / REPLICAOF / SHUTDOWN / FLUSHDB / FLUSHALL / CLIENT.
**AUTH command password-length surfacing** — for `AUTH <password>` (one-arg) surfaces `password_bytes`; for `AUTH <user> <password>` (two-arg, Redis 6 ACL) surfaces both `auth_username` cleartext and `password_bytes` length.
**HELLO inline-AUTH detection** — scans HELLO arguments for an `AUTH` keyword followed by user + password; surfaces the same fields as AUTH.
**Error response classification** — for `-` Error frames: NOAUTH (pre-auth signal!) / WRONGPASS (canonical brute-force feedback!) / PERMISSION (ACL denied) / MOVED + ASK (Cluster redirection) / LOADING (server warming) / BUSY (script running) / MASTERDOWN
CLUSTERDOWN (failover) / READONLY (replica write) / ERR (generic).
What this package does NOT cover (deliberately out of scope)
- **RDB persistence file format** — the binary snapshot Redis writes via `BGSAVE` / `SAVE`; separate dissector concern.
- **AOF (Append-Only File) format** — the on-disk command write-ahead log.
- **Cluster slot map binary encoding** — `CLUSTER SLOTS` / `CLUSTER SHARDS` response format and the gossip protocol on TCP/16379+.
- **Module command IDLs** — RediSearch (FT.*), RedisJSON (JSON.*), RedisGraph (GRAPH.*), RedisTimeSeries (TS.*), RedisBloom (BF.* / CF.* / TDIGEST.*) follow standard RESP framing but their argument semantics are module- specific; surfaced as ordinary commands.
- **Sub-array deep recursion** — top-level Array parsed; nested Arrays inside arguments parsed only enough to find boundaries.
- **TLS handshake** — Redis 6+ supports TLS; handle the TLS strip first.
- **RESP3 attribute prefix** (`|N\r\n`) — detected but contents not surfaced.
- **Client tracking** push invalidation messages.
- **Full key-value content** — surfaces command shape + key argument; value arguments surfaced as length only for SET / SETEX / MSET / HSET / etc.
Index ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type Result ¶
type Result struct {
TotalBytes int `json:"total_bytes"`
FrameType string `json:"frame_type"`
FrameTypeName string `json:"frame_type_name"`
// Command-detection (top-level Array of Bulk Strings)
IsCommand bool `json:"is_command"`
Command string `json:"command,omitempty"`
ArgumentCount int `json:"argument_count,omitempty"`
Arguments []string `json:"arguments,omitempty"`
// Command classification
IsAuthCommand bool `json:"is_auth_command"`
IsHelloCommand bool `json:"is_hello_command"`
IsDangerousCommand bool `json:"is_dangerous_command"`
DangerousCommandFlag string `json:"dangerous_command_flag,omitempty"`
// AUTH command field surfacing
AuthUsername string `json:"auth_username,omitempty"`
PasswordBytes int `json:"password_bytes,omitempty"`
// Error response classification
IsError bool `json:"is_error"`
ErrorText string `json:"error_text,omitempty"`
ErrorCategory string `json:"error_category,omitempty"`
// Simple value surfacing
SimpleString string `json:"simple_string,omitempty"`
Integer int64 `json:"integer,omitempty"`
}
Result is the structured decode of a Redis RESP message.