Skip to content

Commit

Permalink
## [1.0.3] - 2024-04-25
Browse files Browse the repository at this point in the history
### Added

- New key derivation: Ruby Key Generator
- JSON editor for Ruby tokens

### Changed

- Ruby on rails signer was updated to support different Key Generators

Signed-off-by: d4d <[email protected]>
  • Loading branch information
d0ge committed Apr 25, 2024
1 parent 2ecb9d9 commit 88c6dc7
Show file tree
Hide file tree
Showing 18 changed files with 216 additions and 44 deletions.
11 changes: 11 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,16 @@
# Changelog

## [1.0.3] - 2024-04-25

### Added

- New key derivation: Ruby Key Generator
- JSON editor for Ruby tokens

### Changed

- Ruby on rails signer was updated to support different Key Generators

## [1.0.2] - 2024-04-04

### Changed
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ found [here](https://github.com/blackberry/jwt-editor) and [here](https://github

* Ensure that Java JDK 17 or newer is installed
* From root of project, run the command `./gradlew jar`
* This should place the JAR file `sign-saboteur-1.0.2.jar` within the `build/libs` directory
* This should place the JAR file `sign-saboteur-1.0.3.jar` within the `build/libs` directory
* This can be loaded into Burp by navigating to the `Extensions` tab, `Installed` sub-tab, clicking `Add` and loading
the JAR file
* This BApp is using the newer Montoya API, so it's best to use the latest version of Burp (try the earlier adopter
Expand Down
2 changes: 1 addition & 1 deletion build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ plugins {
}

group = 'one.d4d'
version = '1.0.2'
version = '1.0.3'
description = 'sign-saboteur'

repositories {
Expand Down
53 changes: 50 additions & 3 deletions src/main/java/one/d4d/signsaboteur/forms/EditorTab.form
Original file line number Diff line number Diff line change
Expand Up @@ -537,7 +537,7 @@
<properties/>
<border type="empty"/>
<children>
<grid id="98be0" layout-manager="GridLayoutManager" row-count="1" column-count="1" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
<grid id="98be0" layout-manager="GridLayoutManager" row-count="1" column-count="2" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
<margin top="0" left="0" bottom="0" right="0"/>
<constraints>
<grid row="0" column="0" row-span="1" col-span="1" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
Expand All @@ -549,7 +549,7 @@
<children>
<scrollpane id="4d20a" class="org.fife.ui.rtextarea.RTextScrollPane">
<constraints>
<grid row="0" column="0" row-span="1" col-span="1" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
<grid row="0" column="0" row-span="1" col-span="1" vsize-policy="7" hsize-policy="7" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
</constraints>
<properties/>
<border type="none"/>
Expand All @@ -558,10 +558,34 @@
<constraints/>
<properties>
<currentLineHighlightColor color="-1"/>
<syntaxEditingStyle resource-bundle="strings" key="text_area_syntax_label"/>
</properties>
</component>
</children>
</scrollpane>
<grid id="690de" layout-manager="GridLayoutManager" row-count="2" column-count="1" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
<margin top="0" left="0" bottom="0" right="0"/>
<constraints>
<grid row="0" column="1" row-span="1" col-span="1" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
</constraints>
<properties/>
<border type="none"/>
<children>
<component id="197e9" class="javax.swing.JCheckBox" binding="checkBoxRubyURLEncoded">
<constraints>
<grid row="0" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
</constraints>
<properties>
<text resource-bundle="strings" key="urlencoded_checkbox"/>
</properties>
</component>
<vspacer id="db73a">
<constraints>
<grid row="1" column="0" row-span="1" col-span="1" vsize-policy="6" hsize-policy="1" anchor="0" fill="2" indent="0" use-parent-layout="false"/>
</constraints>
</vspacer>
</children>
</grid>
</children>
</grid>
<grid id="8b213" layout-manager="GridLayoutManager" row-count="1" column-count="1" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
Expand Down Expand Up @@ -698,7 +722,7 @@
<properties/>
<border type="empty"/>
<children>
<grid id="77895" layout-manager="GridLayoutManager" row-count="1" column-count="1" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
<grid id="77895" layout-manager="GridLayoutManager" row-count="1" column-count="2" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
<margin top="0" left="0" bottom="0" right="0"/>
<constraints>
<grid row="0" column="0" row-span="1" col-span="1" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
Expand All @@ -723,6 +747,29 @@
</component>
</children>
</scrollpane>
<grid id="53ad8" layout-manager="GridLayoutManager" row-count="2" column-count="1" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
<margin top="0" left="0" bottom="0" right="0"/>
<constraints>
<grid row="0" column="1" row-span="1" col-span="1" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
</constraints>
<properties/>
<border type="none"/>
<children>
<component id="6f435" class="javax.swing.JCheckBox" binding="checkBoxUnknownURLEncoded">
<constraints>
<grid row="0" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
</constraints>
<properties>
<text resource-bundle="strings" key="urlencoded_checkbox"/>
</properties>
</component>
<vspacer id="8683f">
<constraints>
<grid row="1" column="0" row-span="1" col-span="1" vsize-policy="6" hsize-policy="1" anchor="0" fill="2" indent="0" use-parent-layout="false"/>
</constraints>
</vspacer>
</children>
</grid>
</children>
</grid>
<grid id="31275" layout-manager="GridLayoutManager" row-count="1" column-count="1" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
Expand Down
29 changes: 22 additions & 7 deletions src/main/java/one/d4d/signsaboteur/forms/EditorTab.java
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,8 @@ public abstract class EditorTab implements ExtensionProvidedEditor {
private JPanel panelJSONWebSeparator;
private RSyntaxTextArea textAreaJSONWebSignatureHeader;
private RSyntaxTextArea textAreaJSONWebSignaturePayload;
private JCheckBox checkBoxUnknownURLEncoded;
private JCheckBox checkBoxRubyURLEncoded;
private CodeArea codeAreaDangerousSignature;
private CodeArea codeAreaDangerousSeparator;
private CodeArea codeAreaOAuthSignature;
Expand Down Expand Up @@ -149,6 +151,8 @@ public void changedUpdate(DocumentEvent e) {
checkBoxIsJSON.addActionListener(e -> presenter.componentChanged());
checkBoxDjango.addActionListener(e -> presenter.componentChanged());
checkBoxCompress.addActionListener(e -> presenter.componentChanged());
checkBoxRubyURLEncoded.addActionListener(e -> presenter.componentChanged());
checkBoxUnknownURLEncoded.addActionListener(e -> presenter.componentChanged());

codeAreaDangerousSignature.addDataChangedListener(presenter::componentChanged);
codeAreaDangerousSeparator.addDataChangedListener(presenter::componentChanged);
Expand Down Expand Up @@ -337,6 +341,14 @@ public void setRubyMessage(String text) {
textAreaRubyMessage.setText(text);
}

public boolean getRubyIsURLEncoded() {
return checkBoxRubyURLEncoded.isSelected();
}

public void setRubyIsURLEncoded(boolean enabled) {
checkBoxRubyURLEncoded.setSelected(enabled);
}

public String getRubySignature() {
return textAreaRubySignature.getText();
}
Expand Down Expand Up @@ -392,6 +404,14 @@ public String getUnknownMessage() {
public void setUnknownMessage(String text) {
textAreaUnknownStringMessage.setText(text);
}
public boolean getUnknownIsURLEncoded() {
return checkBoxUnknownURLEncoded.isSelected();
}

public void setUnknownIsURLEncoded(boolean enabled) {
checkBoxUnknownURLEncoded.setSelected(enabled);
}


public String getUnknownSignature() {
return textAreaUnknownStringSignature.getText();
Expand Down Expand Up @@ -521,7 +541,6 @@ private void enableTabAtIndex(int index) {
public void setDangerousMode() {
mode = TAB_DANGEROUS;
enableTabAtIndex(TAB_DANGEROUS);
buttonBruteForceAttack.setEnabled(editable);
buttonAttack.setEnabled(editable);
textAreaDangerousPayload.setEditable(editable);
textAreaDangerousTimestamp.setEditable(editable);
Expand All @@ -542,7 +561,6 @@ public void setDangerousMode() {
public void setExpressMode() {
mode = TAB_EXPRESS;
enableTabAtIndex(TAB_EXPRESS);
buttonBruteForceAttack.setEnabled(editable);
buttonAttack.setEnabled(editable);
textAreaExpressParameter.setEditable(false);
textAreaExpressPayload.setEditable(editable);
Expand All @@ -552,7 +570,6 @@ public void setExpressMode() {
public void setOAuthMode() {
mode = TAB_OAUTH;
enableTabAtIndex(TAB_OAUTH);
buttonBruteForceAttack.setEnabled(editable);
buttonAttack.setEnabled(false);
textAreaOAuthParameter.setEditable(false);
textAreaOAuthPayload.setEditable(editable);
Expand All @@ -565,7 +582,6 @@ public void setOAuthMode() {
public void setTornadoMode() {
mode = TAB_TORNADO;
enableTabAtIndex(TAB_TORNADO);
buttonBruteForceAttack.setEnabled(editable);
buttonAttack.setEnabled(editable);

textAreaTornadoTimestamp.setEditable(editable);
Expand All @@ -579,7 +595,7 @@ public void setTornadoMode() {
public void setRubyMode() {
mode = TAB_RUBY;
enableTabAtIndex(TAB_RUBY);
buttonBruteForceAttack.setEnabled(editable);
checkBoxRubyURLEncoded.setEnabled(editable);
buttonAttack.setEnabled(editable);

textAreaRubyMessage.setEditable(editable);
Expand All @@ -592,7 +608,6 @@ public void setRubyMode() {
public void setJWTMode() {
mode = TAB_JWT;
enableTabAtIndex(TAB_JWT);
buttonBruteForceAttack.setEnabled(editable);
buttonAttack.setEnabled(editable);

textAreaJSONWebSignatureHeader.setEditable(editable);
Expand All @@ -606,7 +621,7 @@ public void setJWTMode() {
public void setUnknownMode() {
mode = TAB_UNKNOWN;
enableTabAtIndex(TAB_UNKNOWN);
buttonBruteForceAttack.setEnabled(editable);
checkBoxUnknownURLEncoded.setEnabled(editable);
buttonAttack.setEnabled(editable);

textAreaUnknownStringMessage.setEditable(editable);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,17 +67,14 @@ public boolean isEnabledFor(HttpRequestResponse requestResponse) {
MimeType.IMAGE_PNG,
MimeType.IMAGE_SVG_XML,
MimeType.IMAGE_TIFF,
MimeType.SCRIPT,
MimeType.CSS,
MimeType.SOUND,
MimeType.VIDEO
);
ByteArray content = ByteArray.byteArray("");
MimeType type = requestResponse.response().statedMimeType();
if (!disabled.contains(type)) {
content = requestResponse.response().toByteArray();
if (disabled.contains(type)) {
return false;
}
return presenter.isEnabled(content, requestResponse.response().cookies(), null);
return presenter.isEnabled(requestResponse.response().toByteArray(), requestResponse.response().cookies(), null);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ public List<TokenSigner> prepareAdvanced() {
secrets.forEach(secret -> {
messages.forEach(md -> {
derivations.forEach(d -> {
if (d == Derivation.CONCAT || d == Derivation.DJANGO || d == Derivation.HASH) {
if (d == Derivation.CONCAT || d == Derivation.DJANGO || d == Derivation.HASH || d == Derivation.RUBY_KEY_GENERATOR) {
digests.forEach(mda -> {
attacks.addAll(is.cloneWithSaltDerivation(secret, salts, d, md, mda));
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@ public enum Derivation {
@Expose @SerializedName("6") NONE("none"),
@Expose @SerializedName("7") RUBY("RUBY"),
@Expose @SerializedName("8") RUBY5("RUBY5"),
@Expose @SerializedName("9") RUBY5_TRUNCATED("RUBY5_TRUNCATED");
@Expose @SerializedName("9") RUBY5_TRUNCATED("RUBY5_TRUNCATED"),
@Expose @SerializedName("10") RUBY_KEY_GENERATOR("RUBY_KEY_GENERATOR");
public final String name;

Derivation(String name) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,15 +13,15 @@
public class RubyTokenSigner extends TokenSigner {
public RubyTokenSigner(SecretKey key) {
super(key);
this.knownDerivations = EnumSet.of(Derivation.RUBY);
this.knownDerivations = EnumSet.of(Derivation.RUBY_KEY_GENERATOR, Derivation.RUBY);
}

public RubyTokenSigner(byte[] sep) {
this(new byte[]{}, sep);
}

public RubyTokenSigner(byte[] secret_key, byte[] sep) {
this(Algorithms.SHA1, Derivation.RUBY, MessageDerivation.NONE, MessageDigestAlgorithm.NONE, secret_key, new byte[]{}, sep);
this(Algorithms.SHA1, Derivation.RUBY_KEY_GENERATOR, MessageDerivation.NONE, MessageDigestAlgorithm.SHA256, secret_key, new byte[]{}, sep);
}

public RubyTokenSigner(
Expand All @@ -33,7 +33,7 @@ public RubyTokenSigner(
byte[] salt,
byte[] sep) {
super(digestMethod, keyDerivation, messageDerivation, digest, secret_key, salt, sep);
this.knownDerivations = EnumSet.of(Derivation.RUBY);
this.knownDerivations = EnumSet.of(Derivation.RUBY_KEY_GENERATOR, Derivation.RUBY);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -207,6 +207,28 @@ public byte[] derive_key() throws DerivationException {
SecretKeyFactory f = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
return f.generateSecret(spec).getEncoded();
}
case RUBY_KEY_GENERATOR -> {
KeySpec spec = new PBEKeySpec(
(new String(secret_key)).toCharArray(),
salt,
1000,
64 * 8
);
// PBKDF2With<prf> - Password-based key-derivation algorithm defined in PKCS #5:
// Password-Based Cryptography Specification, Version 2.1 using the specified pseudo-random function (<prf>).
// Example:
// PBKDF2WithHmacSHA256.
String PRF = "HmacSHA256";
switch (messageDigestAlgorithm){
case SHA1 -> PRF = Algorithms.SHA1.name;
case SHA224 -> PRF = Algorithms.SHA224.name;
case SHA256 -> PRF = Algorithms.SHA256.name;
case SHA384 -> PRF = Algorithms.SHA384.name;
case SHA512 -> PRF = Algorithms.SHA512.name;
}
SecretKeyFactory f = SecretKeyFactory.getInstance(String.format("PBKDF2With%s", PRF));
return f.generateSecret(spec).getEncoded();
}
default -> throw new DerivationException("Unknown key derivation method");
}
} catch (NoSuchAlgorithmException | InvalidKeySpecException e) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,14 @@
public class RubySignedToken extends UnknownSignedToken {

public RubySignedToken(String message, String signature) {
this(message, signature, "--".getBytes());
this(message, signature, "--".getBytes(), false);
}
public RubySignedToken(String message, String signature, boolean isURLEncoded) {
this(message, signature, "--".getBytes(), isURLEncoded);
}

public RubySignedToken(String message, String signature, byte[] separator) {
super(message, signature, separator);
public RubySignedToken(String message, String signature, byte[] separator, boolean isURLEncoded) {
super(message, signature, separator, isURLEncoded);
this.signer = new RubyTokenSigner(separator);
}

Expand All @@ -20,6 +23,11 @@ public void resign() throws Exception {
this.signature = HexUtils.encodeHex(signer.get_signature_unsafe(message.getBytes()));
}

@Override
public String getEncodedSignature() {
return signature.toLowerCase();
}

@Override
public String getSignersName() {
return Signers.RUBY.name();
Expand Down
Loading

0 comments on commit 88c6dc7

Please sign in to comment.