diff --git a/src/main/java/burp/intruder/JWSPayloadProcessor.java b/src/main/java/burp/intruder/JWSPayloadProcessor.java index 11cda73..706772e 100644 --- a/src/main/java/burp/intruder/JWSPayloadProcessor.java +++ b/src/main/java/burp/intruder/JWSPayloadProcessor.java @@ -80,17 +80,18 @@ public String displayName() { // Creates a JWS object from the given attributes. Signs the JWS if possible (i.e., available key selected in Intruder settings) private JWS createJWS(Base64URL header, Base64URL payload, Base64URL originalSignature) { - return this.loadKey().flatMap(key -> { - Optional result = Optional.empty(); - - try { - // TODO - update alg within header - result = Optional.of(JWSFactory.sign(key, intruderConfig.signingAlgorithm(), header, payload)); - } catch (SigningException ex) { - logging.logToError("Failed to sign JWS: " + ex); - } - - return result; - }).orElseGet(() -> JWSFactory.jwsFromParts(header, payload, originalSignature)); + return loadKey() + .flatMap(key -> { + try { + // TODO - update alg within header + return Optional.of(JWSFactory.sign(key, intruderConfig.signingAlgorithm(), header, payload)); + } catch (SigningException ex) { + logging.logToError("Failed to sign JWS: " + ex); + return Optional.empty(); + } + }) + .orElseGet( + () -> JWSFactory.jwsFromParts(header, payload, originalSignature) + ); } } diff --git a/src/test/java/burp/intruder/IntruderConfigBuilder.java b/src/test/java/burp/intruder/IntruderConfigBuilder.java index 7dc40d9..741849f 100644 --- a/src/test/java/burp/intruder/IntruderConfigBuilder.java +++ b/src/test/java/burp/intruder/IntruderConfigBuilder.java @@ -1,5 +1,7 @@ package burp.intruder; +import com.nimbusds.jose.JWSAlgorithm; + class IntruderConfigBuilder { private final IntruderConfig config; @@ -17,6 +19,21 @@ IntruderConfigBuilder withFuzzParameter(String parameterName) { return this; } + IntruderConfigBuilder withSigningKeyId(String signingId) { + config.setSigningKeyId(signingId); + return this; + } + + IntruderConfigBuilder withSigningAlgorithm(JWSAlgorithm algorithm) { + config.setSigningAlgorithm(algorithm); + return this; + } + + IntruderConfigBuilder withResigning(boolean resign) { + config.setResign(resign); + return this; + } + IntruderConfig build() { return config; } diff --git a/src/test/java/burp/intruder/JWSPayloadProcessorTest.java b/src/test/java/burp/intruder/JWSPayloadProcessorTest.java index 79e9126..c600a67 100644 --- a/src/test/java/burp/intruder/JWSPayloadProcessorTest.java +++ b/src/test/java/burp/intruder/JWSPayloadProcessorTest.java @@ -21,6 +21,8 @@ import static burp.intruder.FuzzLocation.PAYLOAD; import static burp.intruder.IntruderConfigBuilder.intruderConfig; import static com.blackberry.jwteditor.KeysModelBuilder.keysModel; +import static com.nimbusds.jose.JWSAlgorithm.RS512; +import static data.PemData.RSA1024Private; import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyString; @@ -29,6 +31,7 @@ @ExtendWith(MontoyaExtension.class) class JWSPayloadProcessorTest { private static final KeysModel EMPTY_KEYS_MODEL = keysModel().build(); + private static final String KEY_ID = "id"; @BeforeEach void configureMocks() { @@ -105,4 +108,63 @@ void givenBaseValueJWSAndFuzzParameterPresentInPayload_whenPayloadProcessed_then assertThat(result.action()).isEqualTo(USE_PAYLOAD); assertThat(result.processedPayload().toString()).isEqualTo("eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6ImVtYW5vbiIsImlhdCI6MTUxNjIzOTAyMn0.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c"); } + + @Test + void givenBaseValueJWSAndFuzzParameterPresentInPayload_whenSigningKeyLoadedButResignOff_thenPayloadModifiedButNotResigned() { + String baseValue = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c"; + PayloadData payloadData = payloadData().withBaseValue(baseValue).withCurrentPayload("emanon").build(); + KeysModel keysModel = keysModel().withRSAKey(RSA1024Private, KEY_ID).build(); + IntruderConfig intruderConfig = intruderConfig() + .withFuzzParameter("name") + .withFuzzLocation(PAYLOAD) + .withSigningKeyId(KEY_ID) + .withSigningAlgorithm(RS512) + .build(); + + JWSPayloadProcessor processor = new JWSPayloadProcessor(intruderConfig, LOGGING, keysModel); + PayloadProcessingResult result = processor.processPayload(payloadData); + + assertThat(result.action()).isEqualTo(USE_PAYLOAD); + assertThat(result.processedPayload().toString()).isEqualTo("eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6ImVtYW5vbiIsImlhdCI6MTUxNjIzOTAyMn0.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c"); + } + + @Test + void givenBaseValueJWSAndFuzzParameterPresentInPayload_whenResignOnButUnknownSigningKeyConfigured_thenPayloadModifiedButNotResigned() { + String baseValue = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c"; + PayloadData payloadData = payloadData().withBaseValue(baseValue).withCurrentPayload("emanon").build(); + KeysModel keysModel = keysModel().withRSAKey(RSA1024Private, KEY_ID).build(); + IntruderConfig intruderConfig = intruderConfig() + .withFuzzParameter("name") + .withFuzzLocation(PAYLOAD) + .withSigningKeyId("rogue") + .withSigningAlgorithm(RS512) + .withResigning(true) + .build(); + + JWSPayloadProcessor processor = new JWSPayloadProcessor(intruderConfig, LOGGING, keysModel); + PayloadProcessingResult result = processor.processPayload(payloadData); + + assertThat(result.action()).isEqualTo(USE_PAYLOAD); + assertThat(result.processedPayload().toString()).isEqualTo("eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6ImVtYW5vbiIsImlhdCI6MTUxNjIzOTAyMn0.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c"); + } + + @Test + void givenBaseValueJWSAndFuzzParameterPresentInPayload_whenResignOnAndSigningKeyPresentAndAlgorithmUnchanged_thenPayloadModifiedAndResignedButAlgUnchanged() { + String baseValue = "eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzUxMiJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.LX5A6Hu00jlQ2n8s1SoVL4BEPjMiF1zrEs3qRtV08sbmsqxXV8bc8LarGm8YZj2OuXWL7aOkdBc9ezOBi5bjxsrtiUmwo5VWlU5Y6PXqGwH5v7w0kpRckdd0IA3nbrR2SyLQ1L1pQJk2PzoCvEpspBPMxtIyrK5MTep3Yx1Xn3aiw3aE1cHzOwK0xBIg-RW5qK5PwPa4H8T7eOOSMytS6N4AiZbeiIVHBWxmjrdp8AuC_fmfM1TQA_O8gK_1QkK3jPWkmbbtb48ut6dxz3H_gvPkPzsRE96nQ1qcOlbJjN0URcR2Tc1ACwZO4VpY4gujo_LwTsLiKQcmq0glFA3SIw"; + PayloadData payloadData = payloadData().withBaseValue(baseValue).withCurrentPayload("emanon").build(); + KeysModel keysModel = keysModel().withRSAKey(RSA1024Private, KEY_ID).build(); + IntruderConfig intruderConfig = intruderConfig() + .withFuzzParameter("name") + .withFuzzLocation(PAYLOAD) + .withSigningKeyId(KEY_ID) + .withSigningAlgorithm(RS512) + .withResigning(true) + .build(); + + JWSPayloadProcessor processor = new JWSPayloadProcessor(intruderConfig, LOGGING, keysModel); + PayloadProcessingResult result = processor.processPayload(payloadData); + + assertThat(result.action()).isEqualTo(USE_PAYLOAD); + assertThat(result.processedPayload().toString()).isEqualTo("eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzUxMiJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6ImVtYW5vbiIsImlhdCI6MTUxNjIzOTAyMn0.poPOxqjqp-CnC2b7eaf2QvfvAfawzp6k-P1QECIHN7KCTnFIlQbiJC4ZtLPH_0-o3HQcUGZbib3m1CVWeY21FIUTVUmOyjU8XuBohtBXRlXoaKXVWibrm5YiLC3yNQz5uAF-gdBB8ybvsmetK7JIZ8UvQdJ3mdvlAAW-3xFv8fs"); + } } \ No newline at end of file diff --git a/src/test/java/com/blackberry/jwteditor/KeysModelBuilder.java b/src/test/java/com/blackberry/jwteditor/KeysModelBuilder.java index b017ac1..5f80128 100644 --- a/src/test/java/com/blackberry/jwteditor/KeysModelBuilder.java +++ b/src/test/java/com/blackberry/jwteditor/KeysModelBuilder.java @@ -30,17 +30,29 @@ public class KeysModelBuilder { private final KeysModel model = new KeysModel(); public KeysModelBuilder withECKey(String pem) { - model.addKey(loadECKey(pem, nextKeyId())); + return withECKey(pem, nextKeyId()); + } + + public KeysModelBuilder withECKey(String pem, String keyId) { + model.addKey(loadECKey(pem, keyId)); return this; } public KeysModelBuilder withRSAKey(String pem) { - model.addKey(loadRSAKey(pem, nextKeyId())); + return withRSAKey(pem, nextKeyId()); + } + + public KeysModelBuilder withRSAKey(String pem, String keyId) { + model.addKey(loadRSAKey(pem, keyId)); return this; } public KeysModelBuilder withOKPKey(String pem) { - model.addKey(loadOKPKey(pem, nextKeyId())); + return withOKPKey(pem, nextKeyId()); + } + + public KeysModelBuilder withOKPKey(String pem, String keyId) { + model.addKey(loadOKPKey(pem, keyId)); return this; }