PicoCTF 2014 Write-ups

OBO - 90 (Miscellaneous)

Writeup by Gladius Maximus

Created: 2014-11-08 01:19:48

Last modified: 2014-11-10 00:09:35

Problem

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.

Hint

Can you figure out the error the programmer mentioned in the comments?

Note

This problem fits well under the Binary Exploitation category, so we put a copy there as well.

Answer

Overview

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.

Details

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.

Flag

watch_your_bounds