Write-up
  • WhoAmI
  • Web Cache Poisoning
  • Came looking for SSRF and found XSS
  • Phishing Attack using Machine Learning model
  • JWT Attacks
  • OAuth - Mechanism and Attacks
  • Upgrade plan from Free to Paid via Response Manipulation
  • XSS IN SOQL Console
  • A Journey from Automated Discovery to Manual Exploitation
Powered by GitBook
On this page
  • Why JWT ?
  • Format :
  • Payload:
  • Signature:
  • JWT Attacks:
  • Accepting Arbitrary Signatures:
  • Accepting Tokens With No Signature
  • Brute-Forcing Secret Keys:
  • JWK :
  • JWT header parameter(JOSE headers):
  • JWK Basic Attack:
  • JWKS Spoofing:
  • Injecting self-signed JWTs via the kid parameter:
  • Exploit :
  • Algorithm(key) confusion attacks:
  • EXPLOIT :
  • Quick Notes:

JWT Attacks

PreviousPhishing Attack using Machine Learning modelNextOAuth - Mechanism and Attacks

Last updated 2 years ago

JSON web tokens (JWTs) are a standardized format for sending cryptographically signed JSON data between systems.

They can theoretically contain any kind of data, but are most commonly used to send information ("claims") about users as part of authentication, session handling, and access control mechanisms.

Why JWT ?

Unlike with classic session tokens, all of the data that a server needs is stored client-side within the JWT itself. This makes JWTs a popular choice for highly distributed websites where users need to interact seamlessly with multiple back-end servers.

Format :

header.payload.signature

Example :

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9
.eyJzdWIiOiJqd3Qtbm90ZXMiLCJuYW1lIjoiSWJyYVJhZGkiLCJpYXQiOjl9.
8VEC8jgazxAGx0-Q-3hrWyXTaND81EFQVCtWEvDre3Q

Header :

The header is a base64 encoded json data which typically consists of two parts:

  • The type of the token, which is JWT,

  • The signing algorithm being used , such as HMAC SHA256 or RSA.

{
  "alg": "HS256",
  "typ": "JWT"
}

Payload:

The payload is also a base64 encoded json data,This data is usually a user info used for Authorization.

{
  "sub": "1234567890",
  "name": "John Doe",
  "admin": true
} 

πŸ“Œ The data in the payload is readable,but it’s protected against tampering.

Signature:

To create the signature you have to take the encoded header, the encoded payload, a secret.

,the algorithm specified in the header, and sign that in the next form:

TheUsedAlgorithm(
  base64UrlEncode(header) + "." +
  base64UrlEncode(payload),
  secret)

πŸ“Œ **The Signature is used as a part of the security validation on that JWT,to make sure no one tampers the data unless he owns a secret key.**




A JWT is usually either a JWS(JSON Web Signature) or JWE(JSON Web Encryption) token.

When people use the term "JWT", they almost always mean a JWS token. JWEs are very similar, except that the actual contents of the token are encrypted rather than just encoded.



JWT Attacks:

"Target" : "modifying the content of the JWT",
"Impact" : "Breaking Access Control and Authentication",

"Main Causes"  : 
{
"Flexible" : "many implementation details",
"misconfiguration" : "The signature of the JWT is not verified",
"Leaks" : "Secret key is leaked , can be guessed or brute-forced",
"Lake Of Validations" : "servers any information about the JWTs that they issue"
  ,"The Token is an entirely self-contained entity."
}

Accepting Arbitrary Signatures:

JWT libraries typically provide one method for verifying tokens and another that just decodes them. For example, the Node.js library jsonwebtoken has verify() and decode()

πŸ“Œ The mistake that the developers might do is passing the incoming tokens to the `decode()` Method With out verifying them.

Exploit :

πŸ“Œ Just edit the jwt to what ever content you want and it’s accepted.


Accepting Tokens With No Signature

The alg parameter in the header is used to tell the server which algorithm was used to sign the token which he uses while verifying the signature.

{
    "alg": "HS256",
    "typ": "JWT"
}

πŸ“Œ JWT Can be left unsigned. In this case, the `alg` parameter is set to `none`.It’s called unsecured JWT β€”> JWS without a signature

Exploit :

  • Change The alg parameter value : none

  • change the payload

  • remove the signature from the payload(keep the tailed dot)

Restrictions and bypassed:

Some times it’s not allowed to send the JWT with alg : none

πŸ“Œ bypassed using classic obfuscation techniques, such as mixed capitalization and unexpected encodings.


Brute-Forcing Secret Keys:

πŸ“Œ Some signing algorithms, such as HS256 (HMAC + SHA-256), use an arbitrary, standalone string as the secret key. Just like a password, it's crucial that this secret can't be easily guessed or brute-forced by an attacker.

hashcat -a 0 -m 16500 <jwt> <wordlist>

Wordlist of Common Secret Keys :



JWK :

πŸ“Œ Two algorithms are supported for signing JWTs: **RS256** and **HS256.**RS256 generates an asymmetric signature, which means a private key must be used to sign the JWT and a different public key must be used to verify the signature.

JWT header parameter(JOSE headers):

  1. jwk (JSON Web Key) : Provides an embedded JSON object representing the key.

  2. jku (JSON Web Key Set URL): Provides a URL from which servers can fetch a set of keys containing the correct key.

  3. kid(Key ID) : Provides an ID that servers can use to identify the correct key in cases where there are multiple keys to choose from. Depending on the format of the key, this may have a matching kid parameter.



JWK Basic Attack:

public keys are used to verify the jwt,so just edit your token then Embedding your own key

would be enough for exploiting this flaw.

JWKS Spoofing:

Method:

πŸ“Œ If the token uses a β€œjku” Header claim then check out the provided URL. This should point to a URL containing the JWKS file that holds the Public Key for verifying the token. Tamper the token to point the jku value to a web service you can monitor traffic for.

Create a private Key :

openssl genrsa -out key.pem 2048

Export a public key :

import json
from jwcrypto import jwk,jwt
with open("key.pem","rb") as pemfile:
	key = jwk.JWK.from_pem(pemfile.read())
public_key = key.export()

JWKS:

jwks = {}
jwks["keys"] = [json.loads(public_key)]
print(jwks)

What’s Next :

  • Create your own jwk using the private key

  • Host your public key on your own domain

Token = jwt.JWT(
header = {
        "alg" : "RS256",
        "jku" : "link to your own public key",
	      "kid":key.key_id,                              },
claims= {"key":"value"}
)
Token.make_signed_token(key)             
print(Token.serialize())

Go and use burp :

Injecting self-signed JWTs via the kid parameter:

They might use the kid parameter to point to a particular entry in a database, or even the name of a file.

{
    "kid": "../../path/to/file",
    "typ": "JWT",
    "alg": "HS256",
    "k": "asGsADas3421-dfh9DGN-AFDFDbasfd8-anfjkvc"
}

You could theoretically do this with any file, but one of the simplest methods is to use /dev/null which is present on most Linux systems. As this is an empty file, fetching it returns null. Therefore, signing the token with a Base64-encoded null byte will result in a valid signature.

Exploit :

  • Create New Symmetric Key

  • Replace the generated value for the k property with a Base64-encoded null byte (AA==). or any value that matches the concept.

  • Set The kid parameter value to ../../../../../../../../dev/null

  • Use the new Symmetric Key to create your jwt.



Algorithm(key) confusion attacks:

πŸ“Œ Force the server to verify the signature of a ([JWT](https://portswigger.net/web-security/jwt)) using a different algorithm than is intended by the website's developers.

When ?

methods rely on the alg parameter in the token's header to determine the type of verification they should perform.

EXAMPLE OF A METHOD :

function verify(token, secretOrPublicKey){
    algorithm = token.getAlgHeader();
    if(algorithm == "RS256"){
        // Use the provided key as an RSA public key
    } else if (algorithm == "HS256"){
        // Use the provided key as an HMAC secret key
    }
}

πŸ“Œ Problems arise when website developers who subsequently use this method assume that it will exclusively handle JWTs signed using an asymmetric algorithm like RS256. Due to this flawed assumption, they may always pass a fixed public key to the method

EXAMPLE OF A FLAW :

publicKey = <public-key-of-server>;
token = request.getCookie("session");
verify(token, publicKey);

The algorithm HS256 uses the secret key to sign and verify each message. The algorithm RS256 uses the private key to sign the message and uses the public key for authentication. If you change the algorithm from RS256 to HS256, the back end code uses the public key as the secret key and then uses the HS256 algorithm to verify the signature.Then, using the public key and changing RS256 to HS256 we could create a valid signature.

πŸ“Œ The public key you use to sign the token must be absolutely identical to the public key stored on the server. which in this case it’s a SECRET to a symmetric algorithm.

EXPLOIT :

  1. Obtain the server's public key

  2. Convert the public key to a suitable format

  3. Create a malicious JWT with a modified payload and the alg header set to HS256.

  4. Sign the token with HS256, using the public key as the secret.

Obtain the server's public key

  • Could be found in an endpoint or leaked somewhere in an endpoint like

    /.well-known/jwks.json

    /jwks.json

  • Deriving public keys from existing tokens

    docker run --rm -it portswigger/sig2n <token1> <token2>

    Outputs multiple JWT with the key that is being used to validate it,The JWT that works use it’s key to sing your new JWT

Convert the public key to a suitable format:

πŸ“Œ Although the server may expose their public key in JWK format, when verifying the signature of a token, it will use its own copy of the key from its local filesystem or database. This may be stored in a different format.

In order for the attack to work, the version of the key that you use to sign the JWT must be identical to the server's local copy.

Or you can just use it as it’s,but base-64 decoded ,try it .



Quick Notes:

Easy Way :

  • Run jwt_tool with mode All Tests. β€”> not always working - Nothing is that easy

Origin:

  • Check where the token originated in your proxy's request history. It should be created on the server, not the client.

Duration:

  • Check if the token lasts more than 24h... maybe it never expires. If there is a "exp" filed, check if the server is correctly handling it.

Kid Leaks Key :

  • If the claim "kid" is used in the header, check the web directory for that file or a variation of it. For example if "kid":"key/12345" then look for /key/12345 and /key/12345.pem on the web root

Kid SQL Injection:

  • In a scenario wehre the content of the "kid" is used to retreive the password from the database, you could change the payload inside the "kid" parameter to: non-existent index' UNION SELECT 'Your Secret';--

Kid OS Command Injection :

  • In a scenario where the "kid" parameter contains a path to the file with the key and this path is being used inside an executed command you could be able to obtain RCE and expose the private key with a payload like the following: /root/res/keys/secret7.key; cd /root/res/keys/ && python -m SimpleHTTPServer 1337&

The JSON Web Key Set (JWKS) is a set of keys containing the public keys used to verify any JSON Web Token (JWT) issued by the authorization server and signed using the RS256

cty(Content Type) : Sometimes used to declare a media type for the content in the JWT payload. This is usually omitted from the header, but the underlying parsing library may support it anyway. If you have found a way to bypass signature verification, you can try injecting a cty header to change the content type to text/xml or application/x-java-serialized-object, which can potentially enable new vectors for and attacks.

x5c(X.509 Certificate Chain) : Sometimes used to pass the X.509 public key certificate or certificate chain of the key used to digitally sign the JWT. This header parameter can be used to inject self-signed certificates, similar to the [jwk header injection](https://portswigger.net/web-security/jwt#injecting-self-signed-jwts-via-the-jwk-parameter) attacks discussed above. Due to the complexity of the X.509 format and its extensions, parsing these certificates can also introduce vulnerabilities. Details of these attacks are beyond the scope of these materials, but for more details, check out and

This's just a waste of time - just likes the fancy stuff

If this parameter is also vulnerable to , an attacker could potentially force the server to use an arbitrary file from its filesystem as the verification key.

This is especially dangerous if the server also supports JWTs signed using a . In this case, an attacker could potentially point the kid parameter to a predictable, static file, then sign the JWT using a secret that matches the contents of this file.

https://raw.githubusercontent.com/wallarm/jwt-secrets/master/jwt.secrets.list
signing algorithm
XXE
deserialization
CVE-2017-2800
CVE-2018-2633
John Hammond
Working with JWTs in Burp Suite | Web Security Academy
directory traversal
symmetric algorithm