Skip to content
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

Open
wants to merge 9 commits into
base: master
Choose a base branch
from

Conversation

leiberbertel
Copy link

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

@preetkaran20 preetkaran20 self-requested a review August 19, 2024 17:19
public ResponseEntity<GenericVulnerabilityResponseBean<String>> getHeaderInjectionVulnerability(
HttpServletRequest request) {
String headerValue = request.getHeader("User-Defined-Header");
if (headerValue != null && headerValue.contains("malicious")) {
Copy link
Member

@preetkaran20 preetkaran20 Aug 24, 2024

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.

Copy link
Author

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) {
Copy link
Member

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'
Copy link
Member

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,

Copy link
Author

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.

Copy link
Member

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'
Copy link
Member

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?

Copy link
Author

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?

Copy link
Member

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

Copy link
Author

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.

Copy link
Member

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.

Copy link
Author

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;

/**
Copy link
Member

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.

Copy link
Author

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

Copy link
Member

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.

Copy link
Author

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 ")) {
Copy link
Member

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.

Copy link
Author

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
Copy link
Member

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.

Copy link
Author

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")
Copy link
Member

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.

Copy link
Author

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(
Copy link
Member

@preetkaran20 preetkaran20 Sep 29, 2024

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 ?

Copy link
Member

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.

Copy link
Author

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:).

@leiberbertel
Copy link
Author

@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.

@preetkaran20
Copy link
Member

@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.

@leiberbertel
Copy link
Author

leiberbertel commented Nov 10, 2024

@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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants