More from Insomnia

Check back to read more Insomnia blogs in the coming months.

April 16, 2020

Ben Knight Senior Security Consultant

JSON Web Token Validation Bypass in Auth0 Authentication API

Ben discusses a JSON Web Token validation bypass issue disclosed to Auth0 in their Authentication API.

During a client engagement last year, I discovered a JSON Web Token (JWT) validation bypass issue in Auth0's Authentication API. The following outlines how I found the vulnerability that led to our advisory.

The Authentication API did not adequately validate a user’s JWT, allowing an attacker to forge a JWT for any user by creating a JWT with an algorithm of none and no signature. The Authentication API prevented the use of alg: none with a case sensitive filter. This means that simply capitalising any letter e.g. alg: nonE, allowed tokens to be forged.

Insomnia Security disclosed the vulnerability through Auth0's Responsible Disclosure Program. Auth0's public platform was quickly patched and they rolled out patches to their private platform over time. Overall, the response from Auth0 was swift and pleasant. They quickly remediated the issue and appreciated the vulnerability report.

Discovering the vulnerability

Thanks to the JSON Web Token Attacker (JOSEPH) Burp Suite plugin, working with JWTs is relatively straightforward, as they're just base64 encoded JSON. The JOSEPH plugin saves you time and has a number of common JWT attacks built-in. One of the attacks is a 'signature exclusion' attack which includes different capitalisation variations of the word 'none' and strips the signature from the original token. This leads me to think the same bug has been found in other applications, so case sensitive filtering is well-worth checking for if you're reviewing an application that uses JWTs.

This bug is a great lesson in complacency and being methodical when doing security reviews. After I noticed I was receiving 200 responses from the /userinfo endpoint with requests containing a forged token, I was left staring at my screen a bit dumbfounded. I called over my colleagues and went through the process of forging a token, step by step, expecting somewhere along the way there must be something I missed. A session cookie in the request, some caching, whitelisting, anything. We came to conclusion it was definitely the capitalisation of characters in the word 'none' that allowed the signature checking to be bypassed. I began evaluating the impact of the vulnerability. What details of a victim's account do you need? Could you fully bypass authentication in any application using Auth0? What other functionality does the Authentication API have?

What was the impact?

Auth0's Authentication API is reasonably limited in functionality, likely by design to limit the attack surface of the API. There were two scenarios in which forging tokens for the API could be useful for an attacker. To bypass multi-factor authentication (MFA) when enabled on the user's account, and fully bypassing authentication in instances where the client application does not independently validate the token itself.

The customer's application I was reviewing at the time did independently validate the user's token, so was not vulnerable to full authentication bypass. However, accepting a 200 response from the /userinfo token introspection endpoint is an acceptable method of validating a user's token, and certainly the most straightforward for a developer integrating the service. It was considered likely a large number of applications were vulnerable at the time of discovery.

In the case of Multi-Factor Authentication (MFA) bypass, an attacker already knows the username and password of the victim's account and uses the vulnerability to bypass MFA on the user's account. An attacker could enroll and activate a new Time-based One-Time Password (TOTP) MFA device. The attacker then logs in to the victim's account with the known credentials and completes the authentication process with the MFA second factor they control.

In both scenarios, the attacker would need to know the victim user's Auth0 userid, which some applications may disclose. The userid is a unique value, such as auth0|5d3e…<truncated>, so is not predictable or easily guessed.

Other Auth0 APIs - such as the Management API - were reviewed for the same vulnerability but were found to not be vulnerable.

Alg "none" strikes again

You may be thinking this seems awfully familiar, and you'd be right. The vulnerability is very similar to the JWT implementation flaws relating to the use of the none algorithm, written up on Auth0’s own blog by external researcher Tim McLean in 2015.

The JWT standard supports insecure JWT algorithms for scenarios where encryption and a signature are not suitable, such as trusted server-to-server communication. In these scenarios, the none algorithm is specified in the JWT header. The none alg type should never be used for untrusted user-supplied tokens.

Proof of concept

In instances where a client application did not independently validate the user's token and relies on the 200 response from the /userinfo token introspection endpoint, exploitation was as easy as creating a forged token.

MFA bypass was slightly more interesting as several steps were required. The Authentication API includes all the pieces required to manage MFA of a user's account, such as the enrolling and activating of new MFA devices. As the forged token was the equivalent of being fully authenticated, it could be used to manage the MFA settings of a victim user's account.

To bypass MFA on an Auth0 account, an attacker could use a forged token to associate a new (attacker-controlled) Time based One-Time Password (TOTP) MFA device, and then use it to successfully authenticate with a known username and password. The attacker would need to know the Auth0 userid of the victim user's account to achieve this.

When a user authenticates with Auth0's Authentication API using a username and password and MFA is enabled on their account, the API returns a 403 response containing a mfa_token value.

An example request containing a mfa_token in the response is provided below:

POST /oauth/token HTTP/1.1
Host: <tenant_instance>.au.auth0.com
Content-Type: application/x-www-form-urlencoded
Connection: close
Content-Length: 129
 
grant_type=password&client_id=fL82…<removed>&username=<removed>@<removed>.com&password=<removed>
 
HTTP/1.1 403 Forbidden
...
{"error":"mfa_required","error_description":"Multifactor authentication required","mfa_token":"Fe26.2**72fdf1599abb608b56b4277d0a0dc7…<removed>…"}

Using a forged token, an attacker could associate a new TOTP MFA device that they control with the victim's account.

An example request showing the forged token being used to associate a new MFA device is provided below:

POST /mfa/associate HTTP/1.1
Host: <tenant_instance>.au.auth0.com
Content-Type: application/json
Authorization: Bearer eyJ0eXAiOiJKV1QiL<removed>
Content-Length: 92
 
{
  "client_id": "fL82…<removed>",
  "authenticator_types": ["otp"]
}
 
HTTP/1.1 200 OK
...
{"authenticator_type":"otp","secret":"N5G…<removed>","barcode_uri":"otpauth://totp/<tenant_instance>:<removed>%40<removed>.com?secret=N5G…<removed>&issuer=<tenant_instance>&algorithm=SHA1&digits=6&period=30","recovery_codes":["4KXX…<removed>"]}

Now the attacker has the two factors required to successfully authenticate - credentials and an MFA second factor device. The attacker obtains an access token for the victim user's account with the TOTP code and mfa_token value. The grant type for the request is http://auth0.com/oauth/grant-type/mfa-otp.

An example request showing successful authentication with an attacker-controlled TOTP MFA device is provided below:

POST /oauth/token HTTP/1.1
Host: <tenant_instance>.au.auth0.com
Content-Type: application/x-www-form-urlencoded
Connection: close
Content-Length: 1616
 
grant_type=http://auth0.com/oauth/grant-type/mfa-otp&client_id=fL82…<removed>&mfa_token=Fe26.2**…<removed>…&otp=026024
 
HTTP/1.1 200 OK
...
{"access_token":"QFq…<removed>”,"id_token":"eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1…<removed>","scope":"openid profile email address phone","expires_in":86400,"token_type":"Bearer"}

Our full advisory

Read the complete advisory on our website.

Attacking JSON Web Tokens

There are a number of great write-ups on attacking JWTs. The resources below cover a good introduction to JWTs, considerations for security reviews and a range of common attacks against JWTs. With the added complexity of authentication, comes an increased likelihood of something in the chain being misconfigured and introducing security vulnerabilities.

Be careful not to overlook the simple stuff and happy bug hunting!

securitum: JWT (JSON Web Token) (in)security

ncc group: JWT Attack Walk-Through

TrustFoundry: JWT Hacking 101

jwt_tool: Attack Methodology

Rudra Pratap: Hacking JSON Web Token (JWT)

Websecurify: Hacking JSON Web Tokens

To find out more