Filereader
Event | Challenge | Category | Points | Solves |
---|---|---|---|---|
ecsc2019 | filereader | pwn | 1000 | 20 |
TL;DR
We need to exploit binary which read the content of files listed in an other file. A buffer-overflow is present in one of the function and we can leak the address of libc thanks to /proc/self/map since we can read files. A onegadget is then used to pop a shell.
Recon
First we check the protections, NX and PIE are enabled which mean we won’t be able neither to execute code nor use gadgets to do a ropchain.
The binary ask for a file which should contain a list of other files. Then it will display the content of each file if the permissions are ok. I load the binary into ghidra and spot many interesting things.
First we can spot a buffer overflow in the fscanf function which doesn’t check for the size of the filename. (local_118 is a pointer to the file containing the filenames of the files to read and auStack272 is a 260 bytes long buffer)
But we have to bypass some custom stack cookies, indeed the binary is not stripped and we can see the canarie variable wich is push on the stack at the beginning of the execution :
And then checked at the end.
It’s not secure at all since the pid can be predicted and so the canarie can be forged to bypass the protection.
Exploit part1
We now have everything to start writing our exploit, I like python for pwn challenge, but the random implementation of python is different from the one used in C so I wrote a really simple program which return a random number depending of the input like in the binary.
1 |
|
Let start writing some python and see :
1 |
|
I found that the filereader binary would be launched with a pid increased by 5 from the python script. Then run it… and we don’t have the message saying Stack smashing detected! anymore, instead we have a segfault due to 0xdeadbeef address.
Exploit part2
Ok, but now what ? Where should we jump since we control rip ? As I said at the beginning no ropchain and no shellcode because of PIE and NX protections. We need to leak an address from the libc and then found a onegadget to get our shell. This is the tricky part and I stayed stuck here for some days. But wait we have a binary which read files, so we can read /proc/self/maps which contain the address of the code, the stack, the heap and the libc !
My idea was to create a file like this :
1 |
|
If there is enought /tmp/a the process will be too busy to read them and we will be able to write our payload from the first part at the end of this file.
Before we need the address of a onegadget.
Here is the final exploit :
1 |
|