WARNING: The post below contains spoilers! If you would like to solve them on your own, DO NOT continue reading!
At the urging of zwned, I decided to participate in stripe.com’s ctf. Upon finishing I few, I discovered that this might be an great opportunity to draft up a tutorial and share my so-called expertise with … uhm… however actually reads these. (Internet blog gnomes?) Anyways, to the write-up…
First, we’ll head over to https://stripe.com/blog , where we will find the following instructions under “CTF”:
You can begin Stripe’s CTF challenge by running
ssh firstname.lastname@example.org your shell and entering the password
Your goal is to read the contents of
/levels/level01, you’ll find a setuid binary owned by level02 (as well as its source code) — you will probably find it useful.
Once you have the password, you can ssh in as level02. There are six levels in all; once you’ve logged in as level06 your goal is to read the password from
Once logged in, we’ll get the following welcome banner:
Welcome to the Stripe CTF challenge! Stripe CTF is a wargame, inspired by SmashTheStack I/O. In /home/level02/.password is the SSH password for the level02 user. Your mission, should you choose to accept it, is to read that file. You may find the binary /levels/level01 and its source code /levels/level01.c useful. We've created a scratch directory for you in /tmp. There are a total of 6 levels in this CTF; if you're stuck, feel free to email email@example.com for guidance. Happy hacking, The Stripe team  http://io.smashthestack.org:84/ Please enter your preferred handle: khrash Welcome, khrash!
Given our hint, we should then check out /levels/level01.c:
#include <stdio.h>#include <stdlib.h>
int main(int argc, char **argv)
printf("Current time: ");
It appears from the source that this executable makes a system call for an executable named “date”. We were also given the hint that this executable is a setuid binary owned by level02. Looking up a few sources, notably https://www.owasp.org/index.php/Command_Injection, we find the following under Example 4:
Unlike the previous examples, the command in this example is hardcoded, so an attacker cannot control the argument passed to system(). However, since the program does not specify an absolute path for make, and does not scrub any environment variables prior to invoking the command, the attacker can modify their $PATH variable to point to a malicious binary named make and execute the CGI script from a shell prompt. And since the program has been installed setuid root, the attacker’s version of make now runs with root privileges.
LightBulb! We know we have a binary that makes a call to a binary loaded in the $PATH, so what if we add our own version of “date” and then add it to the $PATH? So what will our “date” do? Well, read level02’s password file. This should work because the binary /levels/level01 runs as level02 user, thereby anything we can get level01 (binary) to execute, it will execute as the user level02!
level01@ctf4:/tmp/khrash$ echo cat /home/level02/.password > date level01@ctf4:/tmp/khrash$ chmod 755 date
Next, we will need to ensure our directory we are currently in is in our $PATH – and order does matter. According to http://www.mediacollege.com/linux/red-hat/path-variable.html :
To see what the current path is, type…
You should get something like the following…
This means that when you try to run a program or script (eg: ping, ftp or vi etc), Redhat will look in /usr/local/bin then /bin, /usr/bin and finally in/home/myname/bin to find it.
You can change the path to suit your needs.
Meaning we will have to ensure our directory is checked first, and then /usr/local … We can ensure this by running:
level01@ctf4:/tmp/khrash$ echo $PATH
level01@ctf4:/tmp/khrash$ export PATH=/tmp/khrash:$PATH
level01@ctf4:/tmp/khrash$ echo $PATH
We should be all set for our exploit! Running the binary /levels/level01, we should see:
Current time: kxlVXUvzv
And there you have it, the password for user level02!