JSON Web Token (JWT) is the data format with bill-in signature and encryption mechanisms that are often used by modern web applications to store user sessions and application context, including authentication by SSO and meta-data.

Usually, you can find JWT tokens in an Authentication Bearer HTTP headers for authenticated API calls.

As Wikipedia says:

“The tokens are signed either using a private secret or a public/private key. For example, a server could generate a token that has the claim “logged in as admin” and provide that to a client. The client could then use that token to prove that it is logged in as admin. The tokens can be signed by one party’s private key (usually the server’s) so that the party can subsequently verify the token is legitimate.”

https://en.wikipedia.org/wiki/JSON_Web_Token

What’s wrong with JWT?

The difficult thing about JWT implementation is generating and storing private keys (for encryption), or secrets (for signatures).

More than 95% of JWT tokens we saw in the last 5 years during security audit projects were signed, but not encrypted. The signature secret is a string with no limits or restrictions implemented by design. As a result, developers often keep it blank, weak, or default. There are a lot of copy & paste secrets from public samples, code snippets, Github gists, etc. 

The second problem with JWT signatures is that attackers offline can brute-force secrets by using only the JWT sample. This means that only string secrets must be used during the JWT implementation. You can get this done by John the Ripper or Hashcat tools using GPU. You can find step-by-step instructions here.

What we did

The goal for this project was to find as many public JWT secrets as possible to help developers and DevOps identify them by traffic analysis at the Wallarm NGWAF level. We focused on Google search and GitHub dorks by using mainly two query patterns: 

  1. “jwt example +TECHNOLOGY” where the TECHNOLOGY is the language itself, such as PHP, Ruby, Rails, or framework like ExpressJS, Struts of Flask.
  2. Google BigQuery search based on 3M GitHub projects.

As a result, we found 340 unique JWT secrets, compiled a list, and made it publicly available for everyone. 

To check if your JWT implementation is vulnerable for well-known secrets, you can run the following shell command:

$ git clone https://github.com/wallarm/jwt-secrets/jwt.secrets.list
$ brew install hashcat
$ hashcat -m 16500 /tmp/jwt.hash /path/to/jwt.secrets.list

Enjoy! And don’t forget to protect your applications and APIs by modern security solutions like Wallarm.

Schedule your personal Wallarm demo today: