Home Write-Up Advent of CTF 2020 Challenge 4
Post
Cancel

Write-Up Advent of CTF 2020 Challenge 4

Overview

The NOVI University Of Applied Sciences is offering an Advent CTF challenge for December 2020. The CTF is created by our community member of the Hackdewereld.nl and Chief Lecturer for Cyber Security at the NOVI University, Arjen Wiersma. If you want to participate in these CTF challenges, you can create an account on the website https://www.adventofctf.com/.

Challenge 4

  • This challenge description: There are people who think you can hide important things by making it hard to read.
  • 400 Points

Let’s start this challenge! For me, this was a tough one. It had taken me some time to get out of a rabbit hole and solve this challenge.

Let’s start this challenge by visiting the URL https://04.adventofctf.com. I got redirected this page.

advent-of-ctf-challenge-4

It seems that we have a session as User 0. According to the message, this user does not have access to the flag. In the URL bar, there is a token visible. The token value: eyJ1c2VyaWQiOjB9.1074. Think that this token is Base64 encoded, so let’s decode this value and see what’s in it. For the decoding part, I removed the value after the dot. So I got left with eyJ1c2VyaWQiOjB9.

1
2
~$ eyJ1c2VyaWQiOjB9" | base64 -d
{"userid":0}

Well, this is the value. This value corresponds with the users’ number displayed on the webpage. I first had tried to change this to {"userid":1} and encoded to base64, but that’s not gonna work.

Let’s check the source code of this webpage.

advent-of-ctf-challenge-4-source-code

After reading the source code, I noticed the login.js in line 62. Let’s analyze this piece of code.

Analyzing login.js

After a quick look, I coming to the conclusion that this script is calculating a key. This key got’s stored in the Local Storage of the internet browser and got’s reflected in the token variable in the website URL. Some pieces of this code are obfuscated.

For me, this was the difficult part. I was totally lost in this script and give it a rest for a couple of hours to come back at a later time. Later on, I was understanding that there is no need to understand everything in the script. That’s the part I’ve also learned from this CTF challenge.

Let’s analyze this script. I will place comments in the code so that the code is easier to read.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
// This function is getting the key from the Local Storage
function startup() {
    key = localStorage.getItem('key');

    // When there is no key, the userid:0 will be stored.
    if (key === null) {
        localStorage.setItem('key', 'eyJ1c2VyaWQiOjB9.1074');
    }
}

// Blackbox, unreadable piece of script. No need to understand, let's skip this one.
var _0x1fde=['charCodeAt'];
(function(_0x93ff3a,_0x1fded8){
    var _0x39b47b=function(_0x54f1d3){
        while(--_0x54f1d3){
            _0x93ff3a['push'](_0x93ff3a['shift']());
        }};
    _0x39b47b(++_0x1fded8);
}(_0x1fde,0x192));
var _0x39b4=function(_0x93ff3a,_0x1fded8){
    _0x93ff3a=_0x93ff3a-0x0;
    var _0x39b47b=_0x1fde[_0x93ff3a];
    return _0x39b47b;
};

// Calculation of the text part (piece in the URL, before the .) 
function calculate(_0x54f1d3){
    var _0x58628b=_0x39b4,_0xc289d4=0x0;
    for(let _0x19ddf3 in text){
        _0xc289d4+=text[_0x58628b('0x0')](_0x19ddf3);
    }return _0xc289d4;
}

// Function to read the key
function check() {
    key = localStorage.getItem('key');
    hash = window.location.search.split('?')[1];
    
    // If the key and hash are not empty
    if (key !== null && hash != 'token='+key) {

        // Split the URL on the dot
        parts = key.split('.');

        // After the split, the first part got's base64 decoded
        text = atob(parts[0]);

        // Second part of the split becomes the checksum as an integer
        checksum = parseInt(parts[1]);
        
        // Calculation of the count (integer behind the .) based on the base64 encoded text
        count = calculate(text);
        
        // If count is equal to checksum 
        if (count == checksum) {

            // Execute this funtion every 5000ms (5sec)
            setTimeout(function(){
                window.location="index.php?token=" + key;
            }, 5000);
        }
    }
}

// Execution of the functions
startup();
check();

After done analyzing this script, let’s take the next step in this challenge. It now seems as if the analysis of the script was simple, but this was my rabbit hole. I had gotten stuck in the piece of obfuscate code and I was convinced that I had to decipher that piece 😉

Putting pieces together

As I already know. User 0 does not have access to the flag. I already tried with the {"userid":1}, but after analyzing the script, I know that there has to be a calculation. First, let’s encrypt the userid to base64.

Base64 encoding of the userid

Second, use the Developer Tools to calculate the count, based on the base64 encoded text.

advent-of-ctf-challenge-4-calculation

Now, I got the counter. The final URL will be: https://04.adventofctf.com/index.php?token=eyJ1c2VyaWQi0jF9.1075. After filling in this URL and refreshing the page, I got the flag!! The flag: NOVI{0bfusc@t3_all_U_w@n7}.

The flag

Thanks for reading!

This post is licensed under CC BY 4.0 by the author.