Created: 2014-11-08 01:19:48
Last modified: 2014-11-10 00:09:35
This password changing program was written by an inexperienced C programmer. Can you some find bugs and exploit them to get the flag? The problem can be found at /home/obo/ on the shell server, and the source code can be downloaded here.
Can you figure out the error the programmer mentioned in the comments?
This problem fits well under the Binary Exploitation category, so we put a copy there as well.
The programmer used
<= instead of
< on line 77, so you can write to the
variable on the stack after
digits, which happens to be
there, confirm the old password correctly. Modify the
$PATH such that
points to a program that prints the flag.
All strings in C are terminated with a null byte. This is how programs know
that the string is terminated in memory. For example, the
just counts how many bytes there are until the next null byte. This, in theory,
should be the length of the string. Read more about null terminated strings
On line 68, we see
for (i = 0; i <= strlen(new_password); ++i). This is
problematic because the programmer used
<= instead of
<. This means it reads the null
terminator at the end of the string and then looks up the value of the null byte (ascii value of 0) in the hex table. If the hex table does not contain ascii value 0, the program gives
Invalid character:. If the programmer adds line 30 in, then the hex table does contain ascii
value 0 and the program works as expected.
That isn't the only place the programmer made that mistake. On line 70, we see
for (i = 0; i <= 16; ++i). This means that we have an index out of
digits[i] is only defined for
i < 16. Index out of bounds
behavior in C is undefined. Usually it writes to whatever is next on the
for reference. Thus
digits writes into the next thing on the stack, which
is the variable declared immediately after digits was declared, which is
password. It writes a 1 to that position. Therefore the new password is
ascii 1. We can inject this character using a line of python.
python -c "print 'abcdefg123456789\n\1'"| /home/obo/obo
Now that should say
New password: Confirm old password: Password
changed!. Now let us make the program read the flag. Calling
system() on any
user input is dangerous. Fortunately (for us) that is exactly what the
programmer does. We can hijack the
python command do do our bidding. When you
type in a command from a terminal or from
system(), the shell will look in
each folder in
$PATH starting left to right for an executable with the same
name as the one you typed. Normally
$PATH contains a colon separated list of
folders. Read more about the path here.
We can write to the path. Make a script called
python in your home folder,
that contains these lines
#!/bin/sh cat /home/obo/flag.txt
The first line tells the computer how to run this file (with /bin/sh interpreter). The second one gets the flag. Now type in this from the shell
chmod +x python export PATH=/home_users/pico89244:$PATH
Now lets do the hack on obo again. This time, instead of calling the real python, it will call our hijacked python.
python2 -c "print 'abcdefg123456789\n\1'"| /home/obo/obo
Notice I changed
python2 so that we used the real python to
inject input into obo.