This post spoils a CTF challenge … Don’t read if you want to try it !
Sogeti CTF was a qualifier for the Sogeti Cyber E-Scape. I could not find a team to participate in this event, so I played alone and finally managed to find a team for the final :)
[+] Presentation
The Game - You need to be admin to have the flag
Here’s the source code.
nc quals.shadow-league.org 5001
[+] Finding the bug
The file name is an hint : uaf stands for Use-After-Free, a well known type of vulnerability.
So basically, a use after free situation occurs when memory referenced by a pointer has been freed, but this pointer has not been set to NULL.
If you try dereferencing this pointer, it will not throw an error, but the value pointed by the pointer won’t be the expected one : it can be anything, since this memory portion is considered as “free” (understand not used by a variable).
In order to exploit this vulnerability, we need to create a pointer and allocate some memory space to it, then free this memory and find a way to write what we want at this previously occupied place.
Let’s read the code !
It’s a simple program which accept several commands :
- set <name> : free the current player if there is one, and create a new player called <name>
- del : free the current player if there is one
WITHOUT SETTING POINTER TO NULL
- title : change the game title
- login : show the flag
IF YOU ARE AN ADMIN
- exit : well… it leaves the program
As an example :
[+] Exploitation
The player structure is the following :
typedef struct player {
char name[MAX_NAME_SIZE];
int64_t isAdmin;
} player_t;
The ‘set’ command allocate a new player structure, give it our name and set isAdmin
to 0.
The ‘del’ command free the pointer holding our player structure, but don’t set it to NULL.
We need to exploit this uaf vulnerability to set current player’s isAdmin
value to any value different than 0, and then login to retrieve the flag.
Here’s the simplified heap layout after ‘set aaaaaa’ command :
Here’s the same memory region, but after ‘del’ command :
If we could to allocate a new heap block with the content we want, we would be able to overwrite the “current player” pointed.
Basically, we can just use the ‘title a…a’ to allocate a new heap block with controlled value, because the ‘title’ commmand uses the strndup
function, which returns a new heap block pointing to the string we want to duplicate.
We will just try several title size until our player structure is overwritten.
Here’s the same memory region, but after ‘title aaaaaaaaaaaaaaaaaaaaaaa’ command :
The player structure has been overwritten, and isAdmin
value is not 0 anymore : we can now login and grab the flag !
Here’s my final solution script.
Flag : SCE{Th1s_wasnt_f0r_fr3e_r1ght?}
[+] Bye
Feel free to tell me what you think about this post :)