JWT authentication bypass via algorithm confusion
Description
This lab uses a JWT-based mechanism for handling sessions. It uses a robust RSA key pair to sign and verify tokens. However, due to implementation flaws, this mechanism is vulnerable to algorithm confusion attacks.
Reproduction and proof of concept
Obtain the server’s public key
In Burp, load the JWT Editor extension from the BApp store.
In the lab, log in to your own account and send the post-login
GET /my-account
request to Burp Repeater.In Burp Repeater, change the path to
/admin
and send the request. Observe that the admin panel is only accessible when logged in as the administrator user.In the browser, go to the standard endpoint
/jwks.json
and observe that the server exposes aJWK Set
containing a single public key.
{"keys":[{"kty":"RSA","e":"AQAB","use":"sig","kid":"755ba25e-ab8d-4c0f-bf55-37c8e00df45c","alg":"RS256","n":"ij8YJYUP37-rqoUJ9dzghcG8HaghpWB4oTmSEN509W4ArQBh19P72F271eRgrFxePIqqW7FhY3H04tOw8ybPOhqys56GCnFzM4NI8q-FA_QKr6hwyZJmm135lkBN_SyEx9r-UV4qOe0KmWBhL1k6jUAuITT5K5sy_YEEsLF3xgfA-suuz7Y3y0fswJgwnfsQz3zn3cKdbh3n2U7Cp5nX4G6im_SAjcaIhwKsA0sDPGUBwc7SY-_aFHcdni8vZPhrBw2qQAekK4nFpTfSl5_GzOWrapkle8ac88VVjjO0P9AWtJZhUb8mJn9MaBZJOEloLd9H6jGen0rnnN5h2iNX-w"}]}
Copy the JWK object from inside the keys array. Make sure that you don’t accidentally copy any characters from the surrounding array.
{"kty":"RSA","e":"AQAB","use":"sig","kid":"755ba25e-ab8d-4c0f-bf55-37c8e00df45c","alg":"RS256","n":"ij8YJYUP37-rqoUJ9dzghcG8HaghpWB4oTmSEN509W4ArQBh19P72F271eRgrFxePIqqW7FhY3H04tOw8ybPOhqys56GCnFzM4NI8q-FA_QKr6hwyZJmm135lkBN_SyEx9r-UV4qOe0KmWBhL1k6jUAuITT5K5sy_YEEsLF3xgfA-suuz7Y3y0fswJgwnfsQz3zn3cKdbh3n2U7Cp5nX4G6im_SAjcaIhwKsA0sDPGUBwc7SY-_aFHcdni8vZPhrBw2qQAekK4nFpTfSl5_GzOWrapkle8ac88VVjjO0P9AWtJZhUb8mJn9MaBZJOEloLd9H6jGen0rnnN5h2iNX-w"}
Generate a malicious signing key
In Burp, go to the JWT Editor Keys tab in Burp’s main tab bar.
Click New RSA Key.
In the dialog, make sure that the
JWK
option is selected, then paste theJWK
that you just copied. Click OK to save the key.Right-click on the entry for the key that you just created, then select Copy Public Key as PEM.
-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAij8YJYUP37+rqoUJ9dzg
hcG8HaghpWB4oTmSEN509W4ArQBh19P72F271eRgrFxePIqqW7FhY3H04tOw8ybP
Ohqys56GCnFzM4NI8q+FA/QKr6hwyZJmm135lkBN/SyEx9r+UV4qOe0KmWBhL1k6
jUAuITT5K5sy/YEEsLF3xgfA+suuz7Y3y0fswJgwnfsQz3zn3cKdbh3n2U7Cp5nX
4G6im/SAjcaIhwKsA0sDPGUBwc7SY+/aFHcdni8vZPhrBw2qQAekK4nFpTfSl5/G
zOWrapkle8ac88VVjjO0P9AWtJZhUb8mJn9MaBZJOEloLd9H6jGen0rnnN5h2iNX
+wIDAQAB
-----END PUBLIC KEY-----
Use the Decoder tab to Base64 encode this PEM key, then copy the resulting string.
LS0tLS1CRUdJTiBQVUJMSUMgS0VZLS0tLS0KTUlJQklqQU5CZ2txaGtpRzl3MEJBUUVGQUFPQ0FROEFNSUlCQ2dLQ0FRRUFpajhZSllVUDM3K3Jxb1VKOWR6ZwpoY0c4SGFnaHBXQjRvVG1TRU41MDlXNEFyUUJoMTlQNzJGMjcxZVJnckZ4ZVBJcXFXN0ZoWTNIMDR0T3c4eWJQCk9ocXlzNTZHQ25Gek00Tkk4cStGQS9RS3I2aHd5WkptbTEzNWxrQk4vU3lFeDlyK1VWNHFPZTBLbVdCaEwxazYKalVBdUlUVDVLNXN5L1lFRXNMRjN4Z2ZBK3N1dXo3WTN5MGZzd0pnd25mc1F6M3puM2NLZGJoM24yVTdDcDVuWAo0RzZpbS9TQWpjYUlod0tzQTBzRFBHVUJ3YzdTWSsvYUZIY2RuaTh2WlBockJ3MnFRQWVrSzRuRnBUZlNsNS9HCnpPV3JhcGtsZThhYzg4VlZqak8wUDlBV3RKWmhVYjhtSm45TWFCWkpPRWxvTGQ5SDZqR2VuMHJubk41aDJpTlgKK3dJREFRQUIKLS0tLS1FTkQgUFVCTElDIEtFWS0tLS0tCg==
Go back to the JWT Editor Keys tab in Burp’s main tab bar.
Click New Symmetric Key. In the dialog, click Generate to generate a new key in JWK format. Note that you don’t need to select a key size as this will automatically be updated later.
Replace the generated value for the
k
property with a Base64-encoded PEM that you just created.
{
"kty": "oct",
"kid": "f3010916-1cdf-490e-972c-bac83f450fcc",
"k": "LS0tLS1CRUdJTiBQVUJMSUMgS0VZLS0tLS0KTUlJQklqQU5CZ2txaGtpRzl3MEJBUUVGQUFPQ0FROEFNSUlCQ2dLQ0FRRUFpajhZSllVUDM3K3Jxb1VKOWR6ZwpoY0c4SGFnaHBXQjRvVG1TRU41MDlXNEFyUUJoMTlQNzJGMjcxZVJnckZ4ZVBJcXFXN0ZoWTNIMDR0T3c4eWJQCk9ocXlzNTZHQ25Gek00Tkk4cStGQS9RS3I2aHd5WkptbTEzNWxrQk4vU3lFeDlyK1VWNHFPZTBLbVdCaEwxazYKalVBdUlUVDVLNXN5L1lFRXNMRjN4Z2ZBK3N1dXo3WTN5MGZzd0pnd25mc1F6M3puM2NLZGJoM24yVTdDcDVuWAo0RzZpbS9TQWpjYUlod0tzQTBzRFBHVUJ3YzdTWSsvYUZIY2RuaTh2WlBockJ3MnFRQWVrSzRuRnBUZlNsNS9HCnpPV3JhcGtsZThhYzg4VlZqak8wUDlBV3RKWmhVYjhtSm45TWFCWkpPRWxvTGQ5SDZqR2VuMHJubk41aDJpTlgKK3dJREFRQUIKLS0tLS1FTkQgUFVCTElDIEtFWS0tLS0tCg=="
}
Save the key.
Modify and sign the token
Go back to the
GET /admin
request in Burp Repeater and switch to the extension-generated JSON Web Token tab.In the header of the JWT, change the value of the
alg
parameter toHS256
.In the payload, change the value of the
sub
claim toadministrator
.At the bottom of the tab, click Sign, then select the symmetric key that you generated in the previous section.
Make sure that the
Don't modify header
option is selected, then click OK. The modified token is now signed using the server’s public key as the secret key.Send the request and observe that you have successfully accessed the admin panel.
In the response, find the URL for deleting Carlos (
/admin/delete?username=carlos
). Send the request to this endpoint to solve the lab.
Exploitability
An attacker will need to log in to wiener:peter
; obtain the server’s public key. (exposed via a standard endpoint); use this key to sign a modified session token that gives access to the admin panel at /admin
; then delete the user carlos
.