How to use Azure to crack API auth tokens

Broken user authentication is one of the most common ways we as attackers can compromise a web API. In fact, it ranks #2 on the OWASP API Security Top 10 list. From password spraying to credential stuffing, an API that puts up little defense is a prime target during our API security testing.

But let me show you an even easier way to breach an API without brute forcing weak passwords of your users. With a little luck and some help from high-performance computing in Microsoft Azure, let me show you how to crack an existing JSON Web Token (JWT) captured from API traffic to recover the signing key. Then, with a bit of magic, you can forge your own tokens to privesc into other accounts in the API to access sensitive data, or give yourself additional permissions to gain extra access within your own.

Ready for some fun? Let’s get at it!!

What the heck is a JWT token?

GitHub - Hitman666/AngularGoJWT: JWT authentication in an Angular  application with a Go backend

A JWT token is a JSON object that is used to transmit information between two parties, usually in the form of authentication tokens. The token is composed of three parts: the header, the payload, and the signature. This token comes by many names like auth token, bearer token, or access token. It is typically stored in a session cookie or in the Authorization header.

Understanding each part will let us approach cracking the JWT token to recover the signing key.

The JWT Header

The header typically consists of two parts: the type of the token, which is JWT, and the hashing algorithm being used, such as HMAC SHA256 or RSA.

For the scenario I will demonstrate today, we are going to be testing for a weak symmetric signing key against our favorite target, crAPI. To make this more realistic, I am going to leverage Azure’s GPU-enabled virtual machines to crack this token in just a few minutes.

The JWT Payload

The second part of the token is the payload, which contains claims. Claims are statements about an entity (typically, the user) and additional data and metadata.

There are three types of claims: registered, public, and private claims:

  • Registered claims are a set of predefined claims which are not mandatory but recommended, to provide a set of useful, interoperable claims. Some of the registered claims are is (issuer), exp (expiration time), sub (subject), aud (audience), and others.
  • Public claims can be defined at will by those using JWTs. Some common public claims are name, username, website, and email.
  • Private claims are the custom claims created to share information between parties that agree on using them. An example of a private claim would be user_id.

The JWT Signature

The last part of the token is the signature, which is used to verify that the sender of the JWT is who it says it is, and to ensure that the message wasn’t changed along the way. This helps in access management as it makes the JWT token somewhat tamper-resistant. Without the right secret key, attackers can’t modify the payload without breaking the digital signature.

The signature part of the token is created using the header and payload parts, a secret key, and the algorithm specified in the header. For example, if you’re using HMAC SHA256 to create the signature, you need to use the same algorithm when validating it.

That’s all there is to it! Now that we know the basics, let’s get our hands dirty and implement a way to brute force crack a JWT token!

Cracking your first JWT

So to crack JWT tokens, we need to determine if they are digitally signed with an acceptable symmetric key algorithm. We can easily check this in the header data of the token.

During your recon of crAPI, you should have captured the JWT during login with valid credentials.

If you didn’t record the JWT during sign in, you can extract it from the local reducer map that was saved in local storage (You can find this in the browser devtools under Local Storage in the Application tab).

Once you have a valid JWT from the web app, you can head over to and decode it. It might look something like this:

So let’s see if we can crack the token with hashcat.

An introduction to using hashcat

Learn How To Crack Passwords With Hashcat - DZone Security

Hashcat is a powerful open-source password cracking tool. It can be used to crack passwords, recover lost passwords, and perform other security-related tasks. It is a great JWT cracker. Hashcat is available for Windows, macOS, and Linux, and supports a wide range of hashing algorithms.

One of the attack modes hashcat supports is cracking JWTs that are digitally signed with HS256, HS384, or HS512 algorithms. As we can tell from the previous screenshot, crAPI uses HS512, so we are good there.

Here is the command line you can type to try to crack the JWT through brute forcing:

hashcat -a 3 -m 16500 jwt.txt -w 3 ?a?a?a?a?a?a?a?a -i

Let me break down the usage information of all the parameters for you:

  • -a 3 : This tells hashcat you will be using attack-mode 3, which is brute-force.
  • -m 16500 : This tells hashcat to use hash-mode 16500, which is JWT.
  • jwt.txt : This is the file that you saved the bearer token to. You should have saved this during login to crAPI.
  • -w 3 : This tells hashcat to use the Workload Profile of 3, which is High demand. This may make your desktop somewhat unresponsive. As I typically crack with a cloud VM it doesn’t really matter much, but it squeezes out a bit more performance (more on this later)
  • ?a?a?a?a?a?a?a?a : This is the pattern mask. I have set it to use up to 8 alpha, numeric, and symbols chars. (More on this in a moment)
  • -i : This tells hashcat to increment its guess. So it will start by cracking 1 char, then 2, etc until the pattern has been completed, which in our case is 8 chars.

Attack pattern masks

So hashcat supports several types of character masks. The easiest way I can break it down is to show you the built-in character sets :

  • ?l = abcdefghijklmnopqrstuvwxyz
  • ?d = 0123456789
  • ?s = !”#$%&'()*+,-./:;<=>[email protected][\]^_`{|}~
  • ?a = ?l?u?d?s
  • ?b = 0x00 – 0xff

As you can see, using ?a allows us to check lowercase, uppercase, digits and symbols, which is the largest possible set we can test in a reasonable manner.

Incremental offsetting

Although I am not using it here, there are other optional parameters of increment-min and increment-max that allow you to control the depth of the mask checks. As an example, if we knew that the secret key was between 4 and 6 chars long, we could use increment-min=4 and increment-max=6 to scope the cracking accordingly as we look for broken user authentication.

I sometimes use this when I do an initial cracking pass of 4 or 5 characters, and then want to come back later to crack 6 or more chars as time permits and I determine it might be worth it.

Cracking a JWT in the real world

OK, so now for a bit of a reality check. Brute-force cracking is time and CPU intensive. So you won’t typically want to actually do this on your desktop. Our goal is to invest a reasonable amount of time (and cost) for the possible returns of recovering the signing key and allowing us to forge our own JWT tokens.

The typical desktop or laptop computer you will be using to conduct your API security testing probably isn’t beefy enough to crack the JWT tokens. Chances are, it doesn’t even have a decent GPU.

GPUs are special kinds of computer chips that are used for graphics, video processing, and intensive mathematical computations. They can be used to improve the performance of certain tasks, like cracking passwords. This is why you should leverage cloud computing that supports GPUs to do this task.

As a Microsoft Security MVP, I’ve been using Azure for this task for many years. You can just as easily find GPU-enabled VMs in Google GCP or Amazon AWS if that’s your preferred stack. In any case, let me show you how best to crack JWT tokens in Azure.

Deploying a GPU-optimized Azure Virtual Machine

To deploy an Azure VM with the right hardware characteristics, you will want to select a NCv3-series virtual machine. NCv3-series VMs are powered by NVIDIA Tesla V100 GPUs, which gives you the optimal cost/performance ratio for cloud cracking.

There are really two options to consider:

  • Standard_NC6s_v3 – This includes 6 vCPUs along with 1 GPU, and 112 GB ram. The pay-as-you-go (PAYG) cost is about ~$3/hour.
  • Standard_NC24s_v3 – This includes 24 vCPUs along with 4 GPUs, and 448 GB ram. The PAYG cost is about ~$14/hour.

Depending on your subscription in Azure, you will probably NOT have any quota authorized for this high-performance compute. You can easily request it in the Azure portal under the Quotas blade. I recommend you request a quota increase of 24 so you can spin up either VM.

To make your life easier, I have written an Azure CLI script that can deploy and configure a disposable NCv3-series VM to leverage the CUDA cores in Azure to maximize your cracking capabilities. The script will:

  • Setup a dedicated resource group for the deployment
  • Deploy a 4 GPU-enabled Standard_NC24s_v3 instance
  • Install an optimized (and minimal) Ubuntu 22.04 server image
  • Set up SSH keys for direct connection to the VM from your Azure CloudShell instance without needing to maintain credentials to log in.
  • Install the latest NVIDIA platform drivers, including CUDA service
  • Install tools to help you crack your JWT tokens (ie: hashcat, vim, tmux, etc)

In the package, I also include a script to de-provision the resource group and destroy the VM. This allows you to set up and tear down the cracking sessions in minutes to keep your costs down.

You can download the script package here.

NOTE: GPU-enabled VMs are in very limited supply. So make your request early in the region closest to you. If you get declined, select the next closest region and continue making requests until you find one that fits your needs.

Cost-saving trick

You can significantly reduce your cracking costs if you look at Azure SPOT Instances. Where the larger 4 GPU system is about $14/hour for PAYG, it’s only ~5/hour for a SPOT instance. The trick is understanding the risk factors of using a SPOT instance, namely:

  • Azure doesn’t offer any SLA for Spot VMs
  • Termination can occur with only a 30-second warning
  • Spot VMs are terminated based on capacity availability and your configured price maximum
  • Available capacity varies based on region, size, and time of day

Just make sure that you research hashcat sessions and restores and make sure the .restore and .potfile are saved to external storage so you don’t lose all your work if an instance is swiped from under ya. That’s beyond the scope of this article but is an option if you crack a lot of JWTs.

NOTE: When using SPOT instances implement a process to crack your JWT tokens during a window of non-peak hours in the region of your choosing. (ie: overnight) In that scenario, it is rare for other projects to generate reprovision requests to deallocate your instance.

You can even build custom software solutions and/or scripts to generate tasks to deploy and destroy cracking resources to reduce costs and take advantage of off-peak hours to crack the keyscape you want. I’ve used Azure Function Apps to do this successfully in a few projects where broken user authentication was a primary engagement scope.

Performance results from cracking a crAPI token

OK, let’s get down to the fun part. Can you really crack a JWT in a reasonable amount of time on the Microsoft Azure platform?


Let me show you some real results.

First up, let me show you the performance characteristics of my Surface Laptop running Windows Subsystem for Linux (WSL). It has no GPU at all.

I can run hashcat in KALI Linux on Windows 11 and see the following benchmark results when trying to crack a JWT:

  • 6 chars – ~9hrs  
  • 7 chars – ~1.75 years
  • 8 chars – ~172.5 years
  • 9 chars – ~15,451 years

That device is a pretty abysmal platform for this project. Now let’s look at an Azure VM with 1 GPU:

  • 6 chars – ~45 mins  
  • 7 chars – ~2.5 days
  • 8 chars – ~294 days
  • 9 chars – ~66 years

Not too bad. I can crack a weak 6-character signing key in about 45 minutes, and it would cost under $3. But let’s amp that up with a 4 GPU VM:

  • 6 chars – ~14 min
  • 7 chars – ~1 day
  • 8 chars – ~100 days
  • 9 chars – ~23 years

So for about the same cost of just over $3, I can crack a 6-character signing key in under 15 minutes.

So, what happened with that crAPI JWT? Using the largest keyscape I could to get the most guess coverage, I found it was a weak 5-character signing key with the value of crapi. (How original)

I cracked it in under 1 minute. The overall cost was under $1.

Will this attack against API tokens really work?

So a question that could be asked is “how real is this attack”? The answer is, it depends. But for the cost/benefit perspective, checking for weaker signing keys has clear value… at least for up to 6 chars. Maybe up to 7 chars if you can use it in a kill chain to get a critical vulnerability that may pay a 4 or 5-figure bounty.

But, there is no guarantee the signing key is that weak.

I have had real success with this approach, especially on dev and test instances, where the secret keys may not be as strong as they are in production. Developers don’t usually implement strong configuration and change management in non-production environments… which leads to less secure API instances.

Once, I cracked a 7 character signing key on a staging instance of a popular SaaS app, which got me a decent 5 figure bounty for a P1 crit. My cost? Just over $200 in Azure spend. And it was cracked and recovered while I was sleeping on the first night of my engagement after I completed my recon.

YMMV of course. At the very least, spend the $3 and implement a methodology to try to crack 1 to 6-character signing keys. You just never know what you might come across in under 15 minutes of cracking.

How to use a cracked signing key to privesc

OK, so you recovered a weak signing key. Now what?

At this point, you can forge your own tokens. Check the claims in your JWT and see if you can modify them or insert additional claims to gain more privileges. (ie: add additional roles or scopes). Create a second account on the target, and see if you can mint a new token modifying the sub claim to gain access to that account.

However you modify the JWT payload, now update the Verify Signature section in with the recovered signing key. This will produce a new JWT on the left pane that is properly signed. The API will trust and accept it as its properly signed.

If the API accepts the token without validating the modified claims on the server side, you’ve just demonstrated a Broken User Authentication vulnerability. And because you were able to crack the signing key you’ve also found a Security Misconfiguration vulnerability. Depending on the privileges you can give yourself, you might be able to even push for Broken Object Level Authorization and Broken Function Level Authorization issues.

From here your attack chain can get quite interesting. I’ll leave it up to you and your imagination. Just be careful if you start minting administrator tokens. Depending on the scope of the engagement, the target may not want you to proceed that deep.


This article demonstrates the feasibility of using Azure to crack JWT tokens and shows how this can be used to find security vulnerabilities in web apps and APIs.

While the cost of this attack is not zero, it is quite low compared to other types of attacks. And the potential for finding high-value vulnerabilities is quite good. So, if you are looking for a new way to find security vulnerabilities in the APIs you are testing, give this a try.

Don’t forget, you can download my script package to automatically deploy disposable cracking resources in Azure using Azure CloudShell. You can get it here.

Interested in learning more ways to hack APIs? Make sure you download my Ultimate Guide to API Hacking Resources.

Hack Hard!

The post How to use Azure to crack API auth tokens appeared first on Dana Epp’s Blog.

*** This is a Security Bloggers Network syndicated blog from Dana Epp&#039;s Blog authored by Dana Epp. Read the original post at:

Leave a Reply

Your email address will not be published. Required fields are marked *