Hack The Box – Invite Challenge and Python Requests

I’ve been meaning to give www.hackthebox.eu a go for a while now, and finally got time to sit down today and attempt the obligatory invite challenge (you have to “hack” the registration page to generate an invite code to join the site).

There’s plenty of guides out there on how to do this, but I thought I’d detail my solution since I came across a Python quirk that I couldn’t find documented elsewhere. Of course it goes without saying, don’t use this guide unless you’re absolutely 100% mindbogglingly stuck.

I’ll also preface this by saying I’m an absolute noob when it comes to Javascript, which this introductory challenge is heavily based on, so some of the terms I use here may not be 100% correct.

So from the registration page at https://www.hackthebox.eu/invite, you’re invited to “Hack this page to get your invite code”:

First stop is your browser’s Developer Tools (F12 in Chrome), where you’ll see a couple of scripts in the body:

One of these scripts, calm.js, writes to the console the first step of the challenge, which you can view in all its glory by clicking into the Console:

Going to Sources in your Dev Tools and expanding www.hackthebox.eu -> js, it’s pretty obvious which script is the “interesting” one, and to make it extra obvious it’s commented “This javascript code looks strange…is it obfuscated???”!

//This javascript code looks strange…is it obfuscated???eval(function(p,a,c,k,e,r){e=function(c){return c.toString(a)};if(!''.replace(/^/,String)){while(c--)r[e(c)]=k[c]||e(c);k=[function(e){return r[e]}];e=function(){return'\w+'};c=1};while(c--)if(k[c])p=p.replace(new RegExp('\b'+e(c)+'\b','g'),k[c]);return p}('0 3(){$.4({5:"6",7:"8",9:\'/b/c/d/e/f\',g:0(a){1.2(a)},h:0(a){1.2(a)}})}',18,18,'function|console|log|makeInviteCode|ajax|type|POST|dataType|json|url||api|invite|how|to|generate|success|error'.split('|'),0,{}))

So to make this function more readable and see what it does, I popped it into http://deobfuscatejavascript.com/ , which gave me the below function:

function makeInviteCode() {
    $.ajax({
        type: "POST",
        dataType: "json",
        url: '/api/invite/how/to/generate',
        success: function(a) {
            console.log(a)
        },
        error: function(a) {
            console.log(a)
        }
    })
}

So we now know there’s a script on this page that “makes an invite code”. So we call the function makeInviteCode() from the Dev Tools console, receiving the below:

As the ever helpful hints suggest, we have an encrypted string, of type BASE64. A quick Google of ‘BASE64 decode’ brings me to https://www.base64decode.org/ where I enter the above string. The resulting decoded string is yet another hint: “In order to generate the invite code, make a POST request to /api/invite/generate

So, we need to make a POST request to https://www.hackthebox.eu/api/invite/generate. Simple enough, but this is where I ran into problems, essentially because I was adamant on using Python. The code I was using below gave me 404 errors, and no amount of tinkering seemed to work:

import requests
import json

url = 'https://www.hackthebox.eu/api/invite/generate'
headers = {'Content-type': 'application/json; charset=utf-8', 'Accept': 'text/json'}
payload = {'key': 'value'}

r = requests.post(url, data=json.dumps(payload), headers=headers)

print(r.status_code)    # 404

After much frustration, I decided to use a web-based POST requester instead, which led me to www.redbin.com. On simply entering the API URL, this worked instantly!

I didn’t want to give up on the Python code, because I couldn’t see any reason the request wouldn’t work. Turns out, not specifying the ‘User-Agent’ field in the requests header and leaving it to the default results in a 404. Specifying the ‘User-Agent’, to literally anything or even a blank string, results in a successful request. Below is the working Python code:

import requests
import json

url = 'https://www.hackthebox.eu/api/invite/generate'
headers = {'Content-type': 'application/json; charset=utf-8', 'Accept': 'text/json', 'user-agent' : 'anything!'}
payload = {'key': 'value'}

r = requests.post(url, data=json.dumps(payload), headers=headers)

print(r.status_code)    # 200

The generated code is still encoded, so we pop it back into the BASE64 decoder and get the final result, which we enter into the Invite Code field:

And we’re in!

I’m looking forward to exploring Hack The Box. Any kind of web-based exploitation is completely out of my comfort zone, but the result was having to research JavaScript, Browser Dev Tools, POST requests, BASE64…I even went down a rabbit hole researching CORS, which ended up being a complete red herring. Frustrating in ways, but ultimately rewarding, and a great way to learn about something that wouldn’t normally be on my radar.

I’m certainly looking forward to using Hack The Box to explore security issues that are a little close to home for me, such as vulnerability scanning and server exploitation. Hopefully I’ll be documenting a few of these in the future.

Leave a Reply

Your email address will not be published. Required fields are marked *