Level 1 – getadmin

Level 1 – getadmin

The getadmin contest show us the danger of enabling the register_globals directive in PHP. Looking into the source code, you can see that it is a simple form:


source

The url doesn’t points to any file, so I can guess that the file name is index.php (trying that page confirms it). The password field is passed by the POST method to index.php again due to the action attribute of the form tag.

Trying some known weakness, I found a backup copy of index.php, called index.php~. When requesting this file it isn’t processed by PHP in the server side, and the file is served as is to the client: our browser, so I can see the source code that processes the form:

<?php

$admin_pass="old password";
/**
 * function to emulate the register_globals setting in PHP
 * @author Ruquay K Calloway
 * @param string $order order in which to register the globals, e.g. 'egpcs' for default
 */
function register_globals($order = 'egpcs')
{
    // define a subroutine
    if(!function_exists('register_global_array'))
    {
        function register_global_array(array $superglobal)
        {
            foreach($superglobal as $varname => $value)
            {
                global $$varname;
                $$varname = $value;
            }
        }
    }

    $order = explode("\r\n", trim(chunk_split($order, 1)));
    foreach($order as $k)
    {
        switch(strtolower($k))
        {
            case 'e':    register_global_array($_ENV);        break;
            case 'g':    register_global_array($_GET);        break;
            case 'p':    register_global_array($_POST);        break;
            case 'c':    register_global_array($_COOKIE);    break;
            case 's':    register_global_array($_SERVER);    break;
        }
    }
}


if($_GET["is_administrator"] or $_POST["is_administrator"]) {
    die("hacking attempt!");
}

register_globals();

if ($pass) {
     if($pass== $admin_pass ) {
         $is_administrator=1;
     }

     if($is_administrator) {
         print "Correct! Password validated: $admin_pass";
     } else {
         print "Incorrect password";
     }
} else {
?>
    <form action="<?echo $PHP_SELF;?>">
     Password: <input type="password" name="pass" length="20">
     <input type="submit" name="lere" value="go" length="20">
    </form>
<?
}
?>

The code is simple. Defines the variable $admin_pass, which is the one we’re looking for (the Flag) but not the right value ;-), a function that emulates the register_globals setting in PHP and compares the password we’ve entered in the form field against the $admin_pass defined. If both of them are the same, the variable $is_administrator is set to 1 and show us the correct password message along with the value of the $admin_pass variable.
As you must know, when register_globals directive is enabled all variables defined in the superglobals arrays: $_ENV, $_GET, $_POST, $_COOKIE and $_SERVER becomes a valid variable in our code preserving its value. So, if we could pass the $is_administrator variable set to 1, we’re done! but passing that variable by GET or POST methods are forbidden.

My solution: create a cookie with that variable set to 1. The result:solution

The Flag captured: t00easy_f0r_31337_l1k3_y0u

The web admin made two fatal mistakes:

  1. Enabled register_globals directive.
  2. Forgot a backup copy of the source code left in the server.

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

Antes de enviar el formulario: