If an application requires you to log in, it must use some form of authentication to verify who you are. Depending on the authentication method an application is using, there could be several types of attacks used to compromise the authentication process.
Compromising the authentication process will typically lead to Account Takeover (ATO) vulnerabilities, and depending on the accounts you take over, it could also lead to privilege escalation (gaining higher access permissions than intended). The following sections discuss some of the most common authentication methods and their pitfalls.
HTTP Basic Authentication
This is probably the most basic and easy to implement type of authentication. You can identify HTTP Basic Auth by the pop-up it displays in web browsers asking for a username and password.
The Pitfall: Base64 Encoding
After typing in your username and password, the authentication details are stored in an Authorization header as shown below:
Authorization: Basic dXNlcm5hbWU6cGFzc3dvcmQ=
Note that the authorization header is just a Base64 encoded string of the username and password. Base64 is an encoding scheme used to represent binary data in an ASCII string format; it is not encryption.
If you were to decode the string dXNlcm5hbWU6cGFzc3dvcmQ= you would get:
username:password
That’s one of the biggest downfalls of using HTTP Basic Auth. Each time you send a request, your clear-text username and password are sent as a Base64 encoded authentication header, making it very susceptible to eavesdropping attacks if the connection is not secured with HTTPS.
JSON Web Token (JWT)
JSON Web Tokens (JWTs) are extremely popular among API endpoints as they are easy to implement and understand.
When a user attempts to log in, the system sends its credentials to the back-end API. The backend verifies the credentials and, if they are correct, it generates a JWT token. This token is then sent back to the user. After that, any subsequent request sent to the API will include this JWT token to prove the user’s identity.
A JWT token is made up of three parts separated by dots (.):
[HEADER]. [PAYLOAD] . [SIGNATURE]
Example Token:
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c
The token can easily be decoded using a Base64 decoder. Security professionals often use tools like jwt.io to inspect these tokens.
Anatomy of a JWT
- Header: The first part of the token is the header. This is where you specify the algorithm (
alg) used to generate the signature (e.g.,HS256,RS256). - Payload: The second part of the token is the payload. This is where you specify the information used for access control (e.g., user ID, roles, expiry time). In the example above, the payload section has a variable called
name, which is used to determine who the user is when authenticating. - Signature: The last part of the token is the signature. This value is used to ensure the token has not been modified or tampered with. The signature is created by concatenating the Base64-encoded Header and Payload sections (separated by a dot) and then signing this value using the algorithm specified in the header, along with a secret key.
If an attacker were able to sign their own key, they would be able to impersonate any user on the system since the backend will trust whatever information is in the payload section. There are several different attacks which attempt to achieve this, as shown in the below sections.
JWT Attack Methodologies
1. Deleted Signature (Signature Stripping)
Without a signature, anyone could modify the payload section, completely bypassing the authentication process. If you remove the signature from a JWT token and the modified token is still accepted by the server, you have successfully bypassed the verification process. This means you can modify the payload section to anything you want (e.g., changing the name value from john doe to admin) and it will be accepted by the backend, potentially signing you in as the admin user.
2. “None” Algorithm Attack
If you can tamper with the algorithm used to sign the token, you might be able to break the signature verification process. JWT supports a none algorithm (intended originally for debugging purposes). If the header is modified to specify the none algorithm, any JWT token will be valid as long as the signature is missing or empty.
Modified Header (Base64 decoded):
{"alg":"none","typ":"JWT"}
This attack essentially tells the server, “Don’t verify the signature.” This attack can be done manually or by using a Burp plugin such as “JSON Web Token Attacker.”
3. Brute Force Secret Key
JWT tokens will either use an HMAC (Symmetric) or RSA (Asymmetric) algorithm to verify the signature.
If the application is using an HMAC algorithm (like HS256), it uses a single secret key when generating the signature. If you can guess this secret key, you will be able to generate signatures, allowing you to forge your own tokens. This is often successful if the key is weak or common. There are several open-source projects that can be used to crack these keys, often by using dictionary attacks (list goes on for days, just search GitHub for the words jwt cracker):
- https://github.com/AresS31/jwtcat
- https://github.com/lmammino/jwt-cracker
- https://github.com/mazen160/jwt-pwn
4. RSA to HMAC Algorithm Confusion
This is a more sophisticated attack against JWTs that use RSA (Asymmetric) signature verification.
- RSA (e.g., RS256): Uses a private key to generate the signature and a separate public key for verification. The public key is typically available to the public.
- HMAC (e.g., HS256): Uses the same secret key for both signing and verifying the signature.
The Attack: An attacker changes the JWT header’s algorithm from an RSA type (e.g., RS256) to the symmetric HMAC type (e.g., HS256).
- The attacker changes the
algin the header fromRS256toHS256. - The attacker uses the server’s public key (which is public information) as the secret key to sign their forged token.
- When the server receives the token, the backend code reads the header and attempts to verify the token using the
HS256algorithm. - Because the server’s code was originally configured for RSA, during verification, it retrieves the public key (which is publicly known) to use for the verification process.
- Since the attacker signed the token with the public key, and the server attempts to verify it with the public key (as a symmetric key), the token passes the verification check. The attacker has successfully impersonated any user.
The original header used the RS256 algorithm, but the attacker changed it to use HS256. Next, the attacker changed their username to admin and signed the token using the server’s public key. When this is sent to the server, it will use the HS256 algorithm to verify the token instead of RS256. Since the backend code was set up to use a public/private key, the public key will be used during the verification process, and the attacker’s forged token will pass.
Summary
JSON Web Tokens (JWTs) are a relatively new way to handle authentication and are relatively simple compared to older methods. However, even with this simplicity, there are several vulnerabilities that impact JWTs. If an attacker is able to forge their own token, it’s game over. This is why most of the attacks revolve around this methodology of token forgery.