QUALS_NDH 2k15 | UPDATOR EXPLOIT 200 [WRITEUP]

This task is an exploit task worth 200 points from the Nuit du Hack qualifications.
We are given a website with a login form, and a link to an other page : update.py
Thxer’s first idea was to look for pyc files.
We then decompiled update.pyc with uncompyle:

# 2015.04.04 01:50:48 CEST
import config
import sys
KEY = config.KEY

def xor(*args):
    if len(args) < 2:
        sys.exit(0)
    length = len(args[0])
    for arg in args:
        if len(arg) != length:
            sys.exit(0)
        length = len(arg)

    cipher = args[0]
    for arg in args[1:]:
        cipher = ''.join([ chr(ord(arg[i]) ^ ord(cipher[i])) for i in range(len(arg)) ])

    return cipher



class Crypto:

    @staticmethod
    def encrypt(file):
        with open(file, 'r') as fd:
            content = fd.read()
        content = content.ljust(len(content) + (8 - len(content) % 8), '0')
        blocks = [ content[(i * 8):((i + 1) * 8)] for i in range(len(content) / 8) ]
        with open('%s.encrypted' % file, 'w') as fd:
            encrypted = []
            for i in range(len(blocks)):
                if i == 0:
                    encrypted.append(xor(KEY, blocks[i]))
                else:
                    encrypted.append(xor(KEY, blocks[i], encrypted[(i - 1)]))

            fd.write(''.join(encrypted))



    @staticmethod
    def decrypt(file):
        with open(file, 'r') as fd:
            content = fd.read()
        blocks = [ content[(i * 8):((i + 1) * 8)] for i in range(len(content) / 8) ]
        with open('.'.join(file.split('.')[:-1]), 'w') as fd:
            plain = []
            for i in range(len(blocks)):
                if i == 0:
                    plain.append(xor(KEY, blocks[i]))
                else:
                    plain.append(xor(KEY, blocks[i], blocks[(i - 1)]))

            fd.write(''.join(plain).rstrip('0'))



print 'Content-Type: text/html'
print '\n<!DOCTYPE html>\n<html>\n  <head>\n    <meta charset="UTF-8">\n    <title>Updator - Update system</title>\n    <link rel="stylesheet" href="static/font-awesome/css/font-awesome.css">\n    <link rel="stylesheet" href="static/css/style.css">\n  </head>\n  <body>\n    <div id="info">\n      The update managing system is still under construction but will be available soon.\n    </div>\n  </body>\n</html>\n'

You know what is fun in challenges ? Guessing for directories.

By guessing the /temp directory, you can find a file, log.py.encrypted.
Since we know the encryption routine, we made a quick script to make a known-plaintext attack.

<?php
$file = 'log.py.encrypted';
$bin  = file_get_contents($file);

function xorStr($a, $b)
{
    $c = '';
    
    $na = strlen($a);
    $nb = strlen($b);
    
    for($i = 0; $i < max($na, $nb); $i++)
        $c .= chr(ord($a[$i % $na]) ^ ord($b[$i % $nb]));
    
    return $c;
}

// Finding the key : 
$b       = strlen($bin) / 8;
$block   = array();
$block[] = substr($bin, 0, 8);

for($i = 1; $i < $b; $i++)
    $block[$i] = xorStr($block[$i - 1], substr($bin, $i * 8, 8));

$bin2  = implode('', $block);
$known = "import ";
$key   = substr(xorStr($bin2, $known), 0, strlen($known));


for($i = 0; $i < 8; $i++) {
	printf("Key     : %s\n", $key);
	printf("Padding : %d\n", $i);
	printf("Code\n%s\n", xorStr($bin2, $key . str_repeat("\0", $i)));
	printf("------------------------\n");
}

// At this point, we realize that the code starts with import datetime.
// We then managed to retrieve the key since there is a repetition with
// $known = "import datetime".

$key   = '6[@dq"&s';
$plain = xorStr($key, substr($bin, 0, 8));

for($i = 1; $i < $b; $i++)
    $plain .= xorStr(xorStr($key, substr($bin, $i * 8, 8)), substr($bin, ($i - 1) * 8, 8));

var_dump($plain);

Decrypted code is :

import datetime

LOG_DIR = 'logs'

class Logger():

    @staticmethod
    def log(username, password):
        basename = '%s/%s_%s' % (LOG_DIR, str(datetime.date.today()), username)
        with open(basename, 'a+') as fd:
            fd.write('[%s] Login with password %s\n' % (str(datetime.datetime.today()), password))

By reading file /logs/2015-04-04_admin, we see the following connection attempts :

[2015-04-04 18:49:48.839448] Login with password Mpt2P4sse2Ouf
[2015-04-04 18:49:54.044382] Login with password Mot2P4sse2Ouf

If you log in with admin:Mot2P4sse2Ouf, you get the following message :
Well played, here is your flag : zEpbiUFt5p7m84cxOxN6

Flag: zEpbiUFt5p7m84cxOxN6.

Thanks to
Thxer,

XeR

2 réflexions au sujet de « QUALS_NDH 2k15 | UPDATOR EXPLOIT 200 [WRITEUP] »

  1. You didn’t need to guess the directory, it was referenced in robots.txt.

    Thank you for all the writeups!!

Votre commentaire

Entrez vos coordonnées ci-dessous ou cliquez sur une icône pour vous connecter:

Logo WordPress.com

Vous commentez à l’aide de votre compte WordPress.com. Déconnexion /  Changer )

Photo Facebook

Vous commentez à l’aide de votre compte Facebook. Déconnexion /  Changer )

Connexion à %s