[DevCTF 2022] FlagAuction
Yay !!! The Flag is on sale !!!! But are you okay with paying the "Gold Price" or will you pay the "Iron Price" ?
https://web.ctf.devclub.in/web/4/
Of course, this looks like a standard shopping page. If we click on Add to Cart
the URL changes to https://web.ctf.devclub.in/web/4/buy/<product_name>.
Clearly, the URL parameter is rendered on the front end. The URL parameter is an untrusted user input, and rendering it on the front end without any sanity checks could indicate a vulnerability here. Let’s try the standard SSTI vulnerability check add {{7*7}}
as the URL parameter. Well the number 49 is rendered. This is a proof of SSTI vulnerability.
Let’s try to push our limits and see where we could reach. We have established that we can execute arbitrary python code on the system. If only we could access the various modules like os, exec
we could get an RCE on the server machine.
This involves messing around with python variables. You see, everything in python is an object of class <'object'>
. To get access to a random module we can first reach to this class and enumerate all its subclasses.
Whoops! That’s a lot of classes. Maybe we can find some interesting class that would allow us to execute any code that we might like. Now, there could be multiple ways to reach the desired goal. Here is one of them, find thepopen
class and its index 367
in the list. Using this class we can reach to the os
module by accessing the globals.
The first place to check for any sensitive information are the environment variables. This comes as a surprise to many newbies as they have no idea where to find the flag. The motivation behind env vars is inspired from real world deployments where all deployment configurations and secrets for a web-app are stored in environment variables instead of files on the local system.
"foo".__class__.__base__.__subclasses__()[367].__init__.__globals__['os'].environ
The above payload lists the environment variables of the web app where a variable FLAG_DIR
is located. The user just needs to enumerate the contents of the directory and read a file called required_file
in this directory, and get access to the flag. The final payload is
{{ "foo".__class__.__base__.__subclasses__()[367].__init__.__globals__['sys'].modules['os'].popen("cat /srv/http/app2/src/required_file").read() }}
Here we go,