HTB Cyber Apocalypse 2024 (LockTalk) Writeup
I solved LockTalk web challenge from HTB CyberApocalypse 2024 and here is the writeup for it.
Challenge:
We are given a page showing different endpoints.
Our endgoal is to access /api/v1/flag endpoint with administrator JWT token. Let us now look at the source code of challenge.
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
from flask import jsonify, current_app
import python_jwt as jwt, datetime
import json
import os
from app.middleware.middleware import *
from . import api_blueprint
JSON_DIR = os.path.join(os.path.dirname(__file__), 'json')
@api_blueprint.route('/get_ticket', methods=['GET'])
def get_ticket():
claims = {
"role": "guest",
"user": "guest_user"
}
token = jwt.generate_jwt(claims, current_app.config.get('JWT_SECRET_KEY'), 'PS256', datetime.timedelta(minutes=60))
return jsonify({'ticket: ': token})
@api_blueprint.route('/chat/<int:chat_id>', methods=['GET'])
@authorize_roles(['guest', 'administrator'])
def chat(chat_id):
json_file_path = os.path.join(JSON_DIR, f"{chat_id}.json")
if os.path.exists(json_file_path):
with open(json_file_path, 'r') as f:
chat_data = json.load(f)
chat_id = chat_data.get('chat_id', None)
return jsonify({'chat_id': chat_id, 'messages': chat_data['messages']})
else:
return jsonify({'error': 'Chat not found'}), 404
@api_blueprint.route('/flag', methods=['GET'])
@authorize_roles(['administrator'])
def flag():
return jsonify({'message': current_app.config.get('FLAG')}), 200
Ok, checking requirement.txt file, we see that version 3.3.3 of python_jwt is used by the app. Upon researching, we come to know that it is vulnerable to CVE-2022-39227. By exploiting this, we can modify claims of JWT token. We can use this exploit for our use. https://github.com/user0x1337/CVE-2022-39227
But before this exploit, we need a JWT generated by the application. In source code, we see an endpoint “/api/v1/get_ticket” which will generate a JWT for us.
Here comes the second part. When we try to access this endpoint, we see that this endpoint is forbidden by HAPROXY. Let us see the content of haproxy.cfg file.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
global
daemon
maxconn 256
defaults
mode http
timeout connect 5000ms
timeout client 50000ms
timeout server 50000ms
frontend haproxy
bind 0.0.0.0:1337
default_backend backend
http-request deny if { path_beg,url_dec -i /api/v1/get_ticket }
backend backend
balance roundrobin
server s1 0.0.0.0:5000 maxconn 32 check
So basically, haproxy is checking the string “/api/v1/get_ticket” in the beginning of the URL. We can bypass it using double backslash “//” in the beginning of the URL.
1
2
<IP>:<PORT>/api/v1/get_ticket -> forbidden
<IP>:<PORT>//api/v1/get_ticket -> bypassed
Accessing this endpoint, application generated a JWT token for us.
Now we can pass this token to our exploit. As “/api/v1/flag” endpoint is only accessible through “administrator”, we modify the value of “role” in our exploit from “guest” to “administrator”. Exploit will then generate a JWT token with modified claims. Accessing the “/api/v1/flag” with generated JWT gives you the flag.
Thankyou for Reading