[Web] Journey Through Hashland (Incomplete)

As the title states, we did not manage to find the flag and only managed to exploit the Hash Length Extension attack.
We’re given with the link https://globe-express-finals.pwndemanila.ph
lol it didn't load
Viewing the source code, we have this:
lol it didn't load
It’s noticeable the 3 links in the source code. A request to /get.php with path parameter accepting base64 input and the hash parameter accepting some kind of hash hex string. We checked out the first one and we got the source code below. It only redirects us to https://www.google.com/maps.
lol it didn't load
Changing even one character in the hash will return integrity error:
lol it didn't load
We also checked out the actual string behind the base64:
lol it didn't load
We wanted to know as well what hash type it is and if we can replicate the hash from the base64 decoded values.
lol it didn't load
We tried getting the sha1sum of destinations and it doesn’t match to the ones in the website. This means that additional data is being padded, appended, or prepended to page decoded parameter.
lol it didn't load
So we tried to look for similar challenges online to have an idea what kind of exploit we can use against this kind of setup. We found the one from SANS about Hash Length Extensions attack. Basically, you can create a new valid hash and append some data from the original data provided.
lol it didn't load
This means if Hash Length Extension attack works, we can attempt to do Path Traversal + Local File Inclusion (LFI) and try to load data. This would very well work against the forbidden flag.php page.
lol it didn't load
Upon reading the SANS writeup page, we found out we can use hash_extender to create a new valid hash with also a new malicious appended data.
lol it didn't load
lol it didn't load
The nightmare doesn’t end there and this is where we spent most of our time trying to solve this since each time we used the hash_extender to forge new data and hash, the integrity error message is still being returned. WE DON”T KNOW THE FORMAT OF DATA WE SHOULD INPUT ON THE HASH EXTENDER We banged our head here and there, tried applying hash_extender against the base64 instead, tried it with the equals sign present, tried double hashing it and so on. What eventually worked is that:

  1. Set data to hash_extender with the “.php” on the base64 decoded data. e.g. “destinations” becomes “destinations.php”
  2. The appended data should also have the “.php” in the end.
  3. The resulting new data will have a “.php” in the end of it. REMOVE IT WHEN SUBMITTING TO get.php


The reason why this is needed is because in the backend, this is what’s roughly happening when it tries to do some integrity checks:

...
$final_hash = sha1($secret . base64_decode($_GET['page']) . ".php" );

if ($final_hash !== $_GET['hash']) {
    echo "Don't fat finger my site!";
}
...


Therefore, you always remove the “.php” from the appended data when submitting because the backend does it already for you.
This is and example of a working hash_extender command that we have:
lol it didn't load
Below is the extraction of the new appended data and noting the new hash.
lol it didn't load
We just have to convert the new data to base64 and we put everything to together and submit the request to /get.php
lol it didn't load
We automated this whole process by creating the following bash script below:

#!/bin/bash

original_data=$1
original_hash=$2
to_append=$3

./hash_extender -d "$1.php" --secret 32 --append "$3.php" --signature $original_hash --format sha1 --out-data-format raw --table > hash_extender_output.txt

new_hash=$(head -n 1 hash_extender_output.txt | awk '{ print $2 }')
echo "[*] new hash: " $new_hash
cat hash_extender_output.txt | awk -F"$new_hash " '{ print $2 }' > urls.txt

new_b64=$(cat urls.txt | sed -z "s/\n//g" | sed "s/.php\$//g" | base64 -w 0)

new_url=$(echo -n "https://globe-express-finals.pwndemanila.ph/get.php?page=$new_b64&hash=$new_hash")

echo "New url: [*] $new_url"
curl $new_url


An example of usage of the script:
lol it didn't load
We tried accessing the /flag.php but there’s no flag in there:
lol it didn't load
We then targeted the phpinfo.php. This is also a forbidden page.
lol it didn't load
The PHP info page…
lol it didn't load
It also has the secret key used by the sha1 function in the backend:
lol it didn't load
We can now forge new payloads for the page without the hash_extender. Example of the “destinations” page forgery below:
lol it didn't load
lol it didn't load
And this our progress ends sadly. What we did next is that we tried to forge new payloads where we used PHP Filters, data, and some other payloads so that we can execute code or read arbitary files but no payloads have been working.
The challenge author (Motoh4ck3r) mentioned that the flag real directory should be through one of the server variables but the PHP Info output that we got doesn’t have it. There are other payloads we can use but since the “.php” extension appending done by the backend, it may restrict our payloads. We have to do some more bypasses where we simply don’t have time during the competition.