-
-
Notifications
You must be signed in to change notification settings - Fork 416
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat: implement header param injection handling for JWT vulnerabilities #473
base: master
Are you sure you want to change the base?
feat: implement header param injection handling for JWT vulnerabilities #473
Conversation
public ResponseEntity<GenericVulnerabilityResponseBean<String>> getHeaderInjectionVulnerability( | ||
HttpServletRequest request) { | ||
String headerValue = request.getHeader("User-Defined-Header"); | ||
if (headerValue != null && headerValue.contains("malicious")) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@leiberbertel I think this is not the right way to implement the header param injection. The real vulnerability is with optional headers like JWK or KID or JKU as implemention of library will start relying on the data provided as part of these headers for verifying signature.
Having custom/user defined headers is not wrong or considered malicious.
A simple attack is say JWT library is relying on the public key provided as part of JWK header instead of validating the public key provided with the whitelisted public key set. so attack would be a malicious user will generate key pairs and sign the jwt with its own private key and passed public key as JWK header. The backend will not validate public key against a whitelist and start relying on provided public key to validate the JWT.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hi @preetkaran20,
I really appreciate your detailed review and the points you highlighted. I completely agree that attacks via headers such as JWK, KID or JKU pose a significant threat, especially when the implementation does not properly validate public keys against a trusted set.
My intent with the current implementation was to demonstrate how user-defined headers can be manipulated, but I see that focusing on these critical headers such as JWK could provide a more realistic and educational example of common vulnerabilities in JWTs.
I will revise the implementation to incorporate these examples, ensuring that we clearly demonstrate how the lack of proper validation of public keys can be exploited.
Regards.
@@ -245,6 +245,11 @@ function doGetAjaxCall(callBack, url, isJson) { | |||
"Content-Type", | |||
isJson ? "application/json" : "text/html" | |||
); | |||
|
|||
for (const header in headers) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for this change.
@@ -150,14 +150,19 @@ dependencies { | |||
implementation group: 'org.json', name: 'json', version: '20190722' | |||
|
|||
//https://mvnrepository.com/artifact/com.nimbusds/nimbus-jose-jwt | |||
implementation group: 'com.nimbusds', name: 'nimbus-jose-jwt', version: '8.3' | |||
implementation group: 'com.nimbusds', name: 'nimbus-jose-jwt', version: '9.31' |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
please validate that it is backward compatible. Try to test other levels of JWT vulnerability,
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have validated the other JWT vulnerabilities and they work correctly, ensuring that they stay within the expected parameters.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you !!! ❤️
build.gradle
Outdated
|
||
// https://mvnrepository.com/artifact/commons-io/commons-io | ||
implementation group: 'commons-io', name: 'commons-io', version: '2.7' | ||
|
||
implementation group: 'io.github.sasanlabs', name: 'facade-schema', version: '1.0.1' | ||
|
||
implementation group: 'commons-fileupload', name: 'commons-fileupload', version: '1.5' | ||
|
||
// https://mvnrepository.com/artifact/com.auth0/java-jwt | ||
implementation group: 'com.auth0', name: 'java-jwt', version: '4.2.1' |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we need this version?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Currently, I have added java-jwt version 4.2.1 as it is compatible with the project dependencies and the version of Java 8 we are using. I have found no conflicts with other libraries, but I may upgrade to the latest 4.4.0 version to ensure we have the latest fixes and enhancements. Is it okay with you if I make the change?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we don't need this as we already have nimbus-jose-jwt
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for pointing that out, I hadn't considered that nimbus-jose-jwt already covers the functionality needed to handle JWTs. I reviewed my implementation and indeed, it looks like we can dispense with java-jwt and just use nimbus-jose-jwt. I will proceed to remove the java-jwt dependency and adjust the code to work with nimbus-jose-jwt.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please let me know once you have done the changes, we can go ahead with the merging of the PR.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
All ready, we can continue:)
import org.sasanlabs.vulnerability.types.VulnerabilityType; | ||
import org.springframework.web.bind.annotation.RequestParam; | ||
|
||
/** |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
please remove samplevulnerability related code.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks, I have already removed it
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I can still see these. can you please push the changes.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes of course, please give me a few hours and I'll upload it. Thanks
public ResponseEntity<GenericVulnerabilityResponseBean<String>> getHeaderInjectionVulnerability( | ||
HttpServletRequest request) { | ||
String jwtToken = request.getHeader("Authorization"); | ||
if (jwtToken == null || !jwtToken.startsWith("Bearer ")) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
better create a constant for "Bearer" in constants.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks, I have implemented the improvement
HttpStatus.BAD_REQUEST); | ||
} | ||
|
||
jwtToken = jwtToken.substring(7); // Remove "Bearer " prefix |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it is better to replace bearer from token instead of index substring.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks, I have implemented the improvement
|
||
@AttackVector( | ||
vulnerabilityExposed = VulnerabilityType.HEADER_INJECTION, | ||
description = "HEADER_INJECTION_VULNERABILITY_EXAMPLE") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
please update the Locale Key for description.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks, I have updated it
@VulnerableAppRequestMapping( | ||
value = LevelConstants.LEVEL_13, | ||
htmlTemplate = "LEVEL_13/HeaderInjection_Level13") | ||
public ResponseEntity<GenericVulnerabilityResponseBean<String>> getHeaderInjectionVulnerability( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry but there is a Level9 which has JWK based vulnerability.
How about converting it into a secure level as an extension of level 9 where we always validate JWK header against a set of public keys and only allow if it is part of them ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@leiberbertel it is fine to have another vulnerability with same functionality as well.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I understand, thanks for the confirmation:).
…pendency and update messages
@preetkaran20, I hope you are well, thanks for your patience! I wanted to consult you if it would be possible for me to upload some unit tests for the level I created. If so, I can create the card, or if you prefer, you could do it. I remain attentive to your answer. |
@leiberbertel It is upto you. I am fine with everything. |
@preetkaran20 Okay, in that case, I'll upload the changes. |
Added handling for header parameter injection in
JWTVulnerability.java
, addressing the missing attack vector noted in issue #413. Follows https://portswigger.net/web-security/jwt guidelines.Ref: #413