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 password
. Once
there, confirm the old password correctly. Modify the $PATH
such that python
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 strlen
function
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
here
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
it again: for (i = 0; i <= 16; ++i)
. This means that we have an index out of
bounds error. 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
stack. See
this question
for reference. Thus digits[16]
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 python
to python2
so that we used the real python to
inject input into obo.
watch_your_bounds