Skip to content

Commit

Permalink
Merge pull request #28 from DolphFlynn/signing_tests
Browse files Browse the repository at this point in the history
Signing tests
  • Loading branch information
DolphFlynn authored Feb 25, 2024
2 parents 1ca2c7e + 0d108d7 commit df1c7dd
Show file tree
Hide file tree
Showing 4 changed files with 151 additions and 37 deletions.
25 changes: 13 additions & 12 deletions src/main/java/burp/intruder/JWSPayloadProcessor.java
Original file line number Diff line number Diff line change
Expand Up @@ -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<JWS> 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)
);
}
}
44 changes: 44 additions & 0 deletions src/test/java/burp/intruder/IntruderConfigBuilder.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
package burp.intruder;

import com.nimbusds.jose.JWSAlgorithm;

class IntruderConfigBuilder {
private final IntruderConfig config;

private IntruderConfigBuilder() {
this.config = new IntruderConfig();
}

IntruderConfigBuilder withFuzzLocation(FuzzLocation fuzzLocation) {
config.setFuzzLocation(fuzzLocation);
return this;
}

IntruderConfigBuilder withFuzzParameter(String parameterName) {
config.setFuzzParameter(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;
}

static IntruderConfigBuilder intruderConfig() {
return new IntruderConfigBuilder();
}
}
87 changes: 72 additions & 15 deletions src/test/java/burp/intruder/JWSPayloadProcessorTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,19 @@
import static burp.api.montoya.logging.StubLogging.LOGGING;
import static burp.intruder.FuzzLocation.HEADER;
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;
import static org.mockito.Mockito.when;

@ExtendWith(MontoyaExtension.class)
class JWSPayloadProcessorTest {
private static final KeysModel EMPTY_KEYS_MODEL = keysModel().build();
private static final String KEY_ID = "id";

@BeforeEach
void configureMocks() {
Expand All @@ -42,9 +48,9 @@ void configureMocks() {
void givenBaseValueNotJWS_whenPayloadProcessed_thenPayloadLeftUnchanged() {
String baseValue = "isogeny";
PayloadData payloadData = payloadData().withBaseValue(baseValue).build();
KeysModel keysModel = new KeysModel();
JWSPayloadProcessor processor = new JWSPayloadProcessor(intruderConfig("role", PAYLOAD), LOGGING, keysModel);
IntruderConfig intruderConfig = intruderConfig().withFuzzParameter("role").withFuzzLocation(PAYLOAD).build();

JWSPayloadProcessor processor = new JWSPayloadProcessor(intruderConfig, LOGGING, EMPTY_KEYS_MODEL);
PayloadProcessingResult result = processor.processPayload(payloadData);

assertThat(result.action()).isEqualTo(USE_PAYLOAD);
Expand All @@ -55,9 +61,9 @@ void givenBaseValueNotJWS_whenPayloadProcessed_thenPayloadLeftUnchanged() {
void givenBaseValueJWSAndFuzzParameterNotPresent_whenPayloadProcessed_thenPayloadLeftUnchanged() {
String baseValue = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c";
PayloadData payloadData = payloadData().withBaseValue(baseValue).build();
KeysModel keysModel = new KeysModel();
JWSPayloadProcessor processor = new JWSPayloadProcessor(intruderConfig("role", PAYLOAD), LOGGING, keysModel);
IntruderConfig intruderConfig = intruderConfig().withFuzzParameter("role").withFuzzLocation(PAYLOAD).build();

JWSPayloadProcessor processor = new JWSPayloadProcessor(intruderConfig, LOGGING, EMPTY_KEYS_MODEL);
PayloadProcessingResult result = processor.processPayload(payloadData);

assertThat(result.action()).isEqualTo(USE_PAYLOAD);
Expand All @@ -68,9 +74,9 @@ void givenBaseValueJWSAndFuzzParameterNotPresent_whenPayloadProcessed_thenPayloa
void givenBaseValueJWSAndFuzzParameterPresentInWrongContext_whenPayloadProcessed_thenPayloadLeftUnchanged() {
String baseValue = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c";
PayloadData payloadData = payloadData().withBaseValue(baseValue).build();
KeysModel keysModel = new KeysModel();
JWSPayloadProcessor processor = new JWSPayloadProcessor(intruderConfig("alg", PAYLOAD), LOGGING, keysModel);
IntruderConfig intruderConfig = intruderConfig().withFuzzParameter("alg").withFuzzLocation(PAYLOAD).build();

JWSPayloadProcessor processor = new JWSPayloadProcessor(intruderConfig, LOGGING, EMPTY_KEYS_MODEL);
PayloadProcessingResult result = processor.processPayload(payloadData);

assertThat(result.action()).isEqualTo(USE_PAYLOAD);
Expand All @@ -81,9 +87,9 @@ void givenBaseValueJWSAndFuzzParameterPresentInWrongContext_whenPayloadProcessed
void givenBaseValueJWSAndFuzzParameterPresentInHeader_whenPayloadProcessed_thenPayloadModified() {
String baseValue = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c";
PayloadData payloadData = payloadData().withBaseValue(baseValue).withCurrentPayload("RS256").build();
KeysModel keysModel = new KeysModel();
JWSPayloadProcessor processor = new JWSPayloadProcessor(intruderConfig("alg", HEADER), LOGGING, keysModel);
IntruderConfig intruderConfig = intruderConfig().withFuzzParameter("alg").withFuzzLocation(HEADER).build();

JWSPayloadProcessor processor = new JWSPayloadProcessor(intruderConfig, LOGGING, EMPTY_KEYS_MODEL);
PayloadProcessingResult result = processor.processPayload(payloadData);

assertThat(result.action()).isEqualTo(USE_PAYLOAD);
Expand All @@ -94,20 +100,71 @@ void givenBaseValueJWSAndFuzzParameterPresentInHeader_whenPayloadProcessed_thenP
void givenBaseValueJWSAndFuzzParameterPresentInPayload_whenPayloadProcessed_thenPayloadModified() {
String baseValue = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c";
PayloadData payloadData = payloadData().withBaseValue(baseValue).withCurrentPayload("emanon").build();
KeysModel keysModel = new KeysModel();
JWSPayloadProcessor processor = new JWSPayloadProcessor(intruderConfig("name", PAYLOAD), LOGGING, keysModel);
IntruderConfig intruderConfig = intruderConfig().withFuzzParameter("name").withFuzzLocation(PAYLOAD).build();

JWSPayloadProcessor processor = new JWSPayloadProcessor(intruderConfig, LOGGING, EMPTY_KEYS_MODEL);
PayloadProcessingResult result = processor.processPayload(payloadData);

assertThat(result.action()).isEqualTo(USE_PAYLOAD);
assertThat(result.processedPayload().toString()).isEqualTo("eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6ImVtYW5vbiIsImlhdCI6MTUxNjIzOTAyMn0.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c");
}

private static IntruderConfig intruderConfig(String parameterName, FuzzLocation parameterLocation) {
IntruderConfig intruderConfig = new IntruderConfig();
intruderConfig.setFuzzParameter(parameterName);
intruderConfig.setFuzzLocation(parameterLocation);
@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");
}

return intruderConfig;
@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");
}
}
32 changes: 22 additions & 10 deletions src/test/java/com/blackberry/jwteditor/KeysModelBuilder.java
Original file line number Diff line number Diff line change
Expand Up @@ -25,39 +25,51 @@

import static com.blackberry.jwteditor.KeyLoader.*;

class KeysModelBuilder {
public class KeysModelBuilder {
private final AtomicInteger keyId = new AtomicInteger();
private final KeysModel model = new KeysModel();

KeysModelBuilder withECKey(String pem) {
model.addKey(loadECKey(pem, nextKeyId()));
public KeysModelBuilder withECKey(String pem) {
return withECKey(pem, nextKeyId());
}

public KeysModelBuilder withECKey(String pem, String keyId) {
model.addKey(loadECKey(pem, keyId));
return this;
}

KeysModelBuilder withRSAKey(String pem) {
model.addKey(loadRSAKey(pem, nextKeyId()));
public KeysModelBuilder withRSAKey(String pem) {
return withRSAKey(pem, nextKeyId());
}

public KeysModelBuilder withRSAKey(String pem, String keyId) {
model.addKey(loadRSAKey(pem, keyId));
return this;
}

KeysModelBuilder withOKPKey(String pem) {
model.addKey(loadOKPKey(pem, nextKeyId()));
public KeysModelBuilder withOKPKey(String pem) {
return withOKPKey(pem, nextKeyId());
}

public KeysModelBuilder withOKPKey(String pem, String keyId) {
model.addKey(loadOKPKey(pem, keyId));
return this;
}

KeysModelBuilder withKey(Key key) {
public KeysModelBuilder withKey(Key key) {
model.addKey(key);
return this;
}

KeysModel build() {
public KeysModel build() {
return model;
}

private String nextKeyId() {
return Integer.toString(keyId.incrementAndGet());
}

static KeysModelBuilder keysModel() {
public static KeysModelBuilder keysModel() {
return new KeysModelBuilder();
}
}

0 comments on commit df1c7dd

Please sign in to comment.