Obscure

A CTF room focused on web and binary exploitation - by Zeeshan1234

Recon

First of all we are looking for open ports using nmap with

nmap -sT -sC -sV <target's ip address>

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!

Getting initial access and 1st flag

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

python2.7 44064.py

set up a listener on 4444

nc -lnvp 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

Upgrade shell
SHELL=/bin/bash scrip -q /dev/null
STRG+Z
stty raw -echo && fg

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

Binary Exploitation for 2nd flag

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

More binary exploitation and 3rd flag

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

https://ir0nstone.gitbook.io/notes/

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.

Example for GOT.gets
payload = padding
payload += p64(rop.find_gadget(['pop rdi', 'ret'])[0])
payload += p64(binary.got.gets)
payload += p64(binary.plt.puts)
payload += p64(binary.symbols.main)

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

Exploit Locally

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

Exploit Remotely

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

Last updated