Fusion 3

Hello boyz and girlz. Today I will solve fusion 3. But I must go play Sattelers of Catan with friends later so let’s make it quick 😀

There is an old saying that goes something like: “Fast is slow, slow is fast, do it once and do it right.” So we will try to work in baby steps in order to finish this post and exploit fast… btw remember it next time you play an escape room.

First thing we do is go and read the code of Fusion-3. Take as much time as we need to understand what it should do..

Here is what I understood:

It is some kind of web server.

It allows us to post articles after authentication.

Every connection is forked and therefore has the same address space of the parent process. Which means infinite number of times we can crash the program in our solution.

Game plan:

Read the code and find the vulnerability.

Write a working client for this server.

Find the address of libc

Use the legitimate code flow to store a string in one of the 2 globals that can store strings (gContents or gTitle) *

Call system on this string

Win this game of Catan with friends

* I read the code again and we can’t do it. These globals are just pointers, the actual strings will be malloced I would have to deference them to make it work. Let’s find libc and then decide how to continue

Crashing the program

To find the vulnerability I search for ‘[‘ in the code, because I am looking for arrays. Specifically looking for bugs in handling of arrays. Pretty fast I understand that the arrays I can work with are either title or content in the function handle_request, and that the bug must be in decode string.

If you look carefully at the loop in the function. If somehow we manage to increase dest so that dest > end when the condition is tested we get can overflow the buffer and stop at /0. I bealive that we found an overflow. But we will have to test it.

Consider the loop condition

Our next job is to write a working client…

Because the program do not print it’s errors, I connect with ssh to the VM that runs the machine, and using gdb I place a breakpoint on the function errx, every time my client fails I try to understand why.

Basically we need to send a request that looks like this:

// TOKEN{json}

But the request must also match a certain hash function. The first 2 bytes of the hmac-sha1 hash of the entire request must be 0. I do it by adding a comment at the end of the request and brute forcing values. I work on my client until I get the error message “Unable to parse request”, fair error for a request of “a”* 128 :D. Anyway it means that my request passed the hash test. Which is what I was going for. I change the json body to something that should trigger the function decode_string, make sure it triggers decode_string with a debugger. and then save it up as a working client.

I write the code to overflow the buffer in decode_string. I chose the title buffer because it’s the first variable in the function which means It should be closest to the return address of the function. I had some small bugs in my code my code is perfect on the first try!

leaking the info

Now we need to figure out what can we do with it… excuse me. I meant to say: Now we need to figure out how do we find libc with what we have. On a personal note, this is the part I like the most in this kind of work. Because it is like solving a giant complicated Sudoku puzzle.

Well the trick with printing stuff we did in fusion 2 will not work here. The reason it won’t work is that the program closed stdin, stdout and stderror. So we will not get any output from printing them.

What can we do? We can use any function in the import table of the main binary. And we can use any function inside the binary (Because this is not compiled as Position Independent code), the load address of the binary is static. And we can use any constant we need as a function argument.

This is pretty much all of the external functions we can use. Take your time and try to think if you know how can we get the address of libc.

After thinking about it I figured out we can build an absolute read primitive from what we have by doing this:

Pass serverip as our ip address,

Pass a contents with whatever length we want to read. Just to set gContents_len with the length of the data we want to read.

Rop into memcpy(gContents, address_to_read, 4) and then post_blog_article. This will cause the program to copy from whatever address we want into the global gContent, and then read from this address and send it to our IP address in HTTP format! We will read the address of a function in .got.plt and will calculate the offset of libc.

I code this up and it works! Now we have the address of libc and we can read any address we would like in the program’s address space. Just needs to find the address of a buffer we control

Hammm now that I can memory read whatever I want*, we need to figure out how to use it to get the address of a buffer we can control. Well I can do the rop-exploition-with-adddress-of-libc-only. But I am keeping this ace for some later exercise in this series. And besides, I am feeling adventurous.

* If you think about it, we don’t exactly have the ability to read wherever we want yet, we have a memory read primitive that recives a pointer to a pointer to the data we want to read, (instead of a pointer to that data). Which is not ideal. But for now it will do because we know a place which has a pointer to a pointer to imported functions and we can find libc with it..

Some more primitives in libc

My first thought was I must be able to somehow read the address of a heap data structure to predict the next(actually previous) heap allocation – This program relies heavily on heap allocations and I am sure I can find one of my buffers on the heap. The problem with it is that my memory read requires 2 level of pointing, kind of like calling printf(“%x”, *pointer_to_pointer_to_data). Which is kind of lame… I Couldn’t find this pointer to pointer to my address I was looking for. And besides, I want to practice my ropping skills..

After running ropgadget on libc I found the following 3 gadgets (short sequence of opcodes):

We will run them in the order they are written in. But let’s consider them backwards to understand what they are doing.

Number 3, allows us to write whatever we want wherever we want, (As long as we control $edx and $ecx).

Number 2, lets us control $edx and $ecx. We can write whatever we want where ever we want (yay!).

Number 1, allows us to use the stack pointer as a part of our rop by pushing it and jumping to an address (as opposed to pushing it and returning into it.)

This allows me to write the address of $esp into anywhere I want. What If I will write it into gContents? When the program will try to print gContents it will print the contents of the stack instead!

I wrote it and it works. After getting the address of the stack, by reading the stack and searching for a pointer to a stack variable on it, I found one with constant distance from a buffer on the stack I control, (char title[128]). Wrote the simple POC exploit we all love: return into system(“touch /tmp/a”)

Post navigation

About Me

Hey, my name is Nadav Claude Cohen and this is my blog. Around here you can read some of my thoughts and work in the information security field. I am currently working as a Team Lead at ACE labs. Feel free to follow me on twitter.