How to do Privilege Escalation with JWT

How to do Privilege Escalation with JWT

Hello everyone!! In the previous [post], we discussed about what exactly are JSON Web Tokens, its components and how it works.

In this blog post, I am gonna talk about how keeping weak secret keys could lead to privileged access rights.

With all that said, Lets get started.

RECAP

We learned in the previous [post] that JWT is of the form 

Header.payload.signature

Where header and payload are base64 encoded and signature is calculated based upon the header,payload, a secret and the signing algorithm(in the header)

Why Use a strong secret??

The funcion by which the signature is created determines the overall security of the token. A secret key(that is only known to the server)  is an essential part of signing the signature. And thats the only parameter that is hidden from any normal user. Therefore, if the server uses a weak secret, an attacker can potentially crack that secret and recreate the jwt with the malformed payload to gain privileged access.

Let’s consider a scenario!

There is a user john on an application with normal user privileges. The application also has the admin user who can perform all the administrative tasks. So, just by knowing the secret key, privileges of john can be elevated by re-signing the jwt with an obfuscated payload. 

Lets walk in step by step.

Here is the original token components of John. As a part of payload, Its clearly visible that the key “user” has the value john

{
“alg”: “HS256”,
“typ”: “JWT”
}

{
“user”: “john”
}
HMACSHA256(
base64UrlEncode(header) + “.” +
base64UrlEncode(payload),
password
)

And the token generated is:

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyIjoiam9obiJ9.kkxgkYx4559EWetAD2phOxqgSe2B-nTSRXqEmoP0nXY

The goal is to generate a token, where the key “user” has value admin.

 Here, I have used secret as password which is easily crackable. The secret key of jwt can be cracked using hashcat(as it has the module available) 

Google for hashcat example hashes, and search for jwt.

 There is only one mode available for jwt i.e.16500

So let’s save the above-generated jwt to a file and name it jwt.hash. Rockyou.txt is a huge dictionary of common passwords and can be used as a wordlist to crack passwords.

# hashcat -m 16500 jwt.hash /usr/share/wordlists/rockyou.txt --force  

Within no time, the password got cracked. 

So now that we know the secret, we can re-create the jwt, with user: admin

{
“alg”: “HS256”,
“typ”: “JWT”
}

{
“user”: “admin”
}
HMACSHA256(
base64UrlEncode(header) + “.” +
base64UrlEncode(payload),
password
)

And the newly created token is:

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyIjoiYWRtaW4ifQ.is8m3EBkfw5RqrUtrXG5mwTjjAOHhPMuxnjbpD9Fugk

Now this token can be used as a part of authorization header to gain access to application with admin privilege.

Remediations??

  1. Use a strong secret while signing the signature.
  2.  The JWT can be encrypted, so that any normal user cant even view or transform the contents of the payload.

However, it was a primitive use-case to exploit still it should not be overlooked.
Hope you enjoyed reading the post. I’ll be back with few more attack scenarios on JWT.

Until then, Happy Hunting!!

shreyapohekar

I’m Shreya Pohekar, a Senior Product Security Analyst at HackerOne. I enjoy sharing my thoughts and insights through blogging, turning complex security topics into engaging and accessible content for my readers.

Leave a Reply