From 87b731cff409c8d611eb3e94570e46c59421a477 Mon Sep 17 00:00:00 2001 From: TNeitzel Date: Wed, 20 May 2020 16:50:33 +0200 Subject: [PATCH 01/36] Allow more flexible variable replacement for bytes When variables are used inside of byte operations, CSTC only allowed a 1 to 1 match for replacements. E.g. ``$Outgoing_step1`` was replaced, ``t: $Outgoing_step1`` was not replaced. This was now chaned. Also in byte oeprations variables should now be replaced with surrounding text. It is also possible to have multiple variables inside the same replacement. --- src/de/usd/cstchef/Utils.java | 26 +++++++++++++++++++++++--- 1 file changed, 23 insertions(+), 3 deletions(-) diff --git a/src/de/usd/cstchef/Utils.java b/src/de/usd/cstchef/Utils.java index c6116f0..bf56061 100644 --- a/src/de/usd/cstchef/Utils.java +++ b/src/de/usd/cstchef/Utils.java @@ -14,6 +14,8 @@ import java.util.zip.ZipInputStream; import burp.BurpUtils; +import burp.IBurpExtenderCallbacks; +import burp.IExtensionHelpers; import burp.Logger; import de.usd.cstchef.operations.Operation; import de.usd.cstchef.operations.arithmetic.Addition; @@ -133,18 +135,36 @@ public static String replaceVariables(String text) { public static byte[] replaceVariablesByte(byte[] bytes) { HashMap variables = VariableStore.getInstance().getVariables(); + IBurpExtenderCallbacks callbacks = BurpUtils.getInstance().getCallbacks(); + IExtensionHelpers helpers = callbacks.getHelpers(); + byte[] currentKey; for (Entry entry : variables.entrySet()) { + int offset = 0; currentKey = ("$" + entry.getKey()).getBytes(); - if( Arrays.equals(currentKey, bytes) ) { - bytes = entry.getValue(); - } + while( offset >= 0 ) { + offset = helpers.indexOf(bytes, currentKey, true, offset, bytes.length); + if( offset >= 0 ) + bytes = insertAtOffset(bytes, offset, offset + currentKey.length, entry.getValue()); + } } return bytes; } + public static byte[] insertAtOffset(byte[] input, int start, int end, byte[] newValue) { + byte[] prefix = Arrays.copyOfRange(input, 0, start); + byte[] rest = Arrays.copyOfRange(input, end, input.length); + + byte[] output = new byte[prefix.length + newValue.length + rest.length]; + System.arraycopy(prefix, 0, output, 0, prefix.length); + System.arraycopy(newValue, 0, output, prefix.length, newValue.length); + System.arraycopy(rest, 0, output, prefix.length + newValue.length, rest.length); + + return output; + } + public static Class[] getOperationsBurp() { ZipInputStream zip = null; List> operations = new ArrayList>(); From 63fcdcabe469e4b6296186efce075652849dbe16 Mon Sep 17 00:00:00 2001 From: TNeitzel Date: Wed, 20 May 2020 17:06:11 +0200 Subject: [PATCH 02/36] Move insertAtOffset to Utils.java The insertAtOffset function is used by several operations. It was already used inside the Utils class and was now made public, so that other classes can also use it. --- .../operations/setter/HttpHeaderSetter.java | 18 +++------------ .../operations/setter/HttpSetCookie.java | 22 +++++-------------- .../cstchef/operations/setter/LineSetter.java | 16 +++----------- 3 files changed, 11 insertions(+), 45 deletions(-) diff --git a/src/de/usd/cstchef/operations/setter/HttpHeaderSetter.java b/src/de/usd/cstchef/operations/setter/HttpHeaderSetter.java index f91a080..01450f2 100644 --- a/src/de/usd/cstchef/operations/setter/HttpHeaderSetter.java +++ b/src/de/usd/cstchef/operations/setter/HttpHeaderSetter.java @@ -1,13 +1,12 @@ package de.usd.cstchef.operations.setter; -import java.util.Arrays; - import javax.swing.JCheckBox; import burp.BurpUtils; import burp.IBurpExtenderCallbacks; import burp.IExtensionHelpers; import burp.IRequestInfo; +import de.usd.cstchef.Utils; import de.usd.cstchef.operations.Operation.OperationInfos; import de.usd.cstchef.operations.OperationCategory; @@ -37,7 +36,7 @@ protected byte[] perform(byte[] input) throws Exception { int offset = helpers.indexOf(input, headerSearch, false, 0, length); int start = helpers.indexOf(input, ": ".getBytes(), false, offset, length) + 2; int end = helpers.indexOf(input, "\r\n".getBytes(), false, start, length); - return insertAtOffset(input, start, end, newValue); + return Utils.insertAtOffset(input, start, end, newValue); } catch( IllegalArgumentException e ) { @@ -51,7 +50,7 @@ protected byte[] perform(byte[] input) throws Exception { System.arraycopy(headerSearch, 0, value, 0, headerSearch.length); System.arraycopy(newValue, 0, value, headerName.length + 2, newValue.length); System.arraycopy("\r\n".getBytes(), 0, value, headerName.length + 2 + newValue.length, 2); - return insertAtOffset(input, bodyOffset, bodyOffset, value); + return Utils.insertAtOffset(input, bodyOffset, bodyOffset, value); } } @@ -64,15 +63,4 @@ public void createUI() { this.addUIElement(null, this.addIfNotPresent); } - private byte[] insertAtOffset(byte[] input, int start, int end, byte[] newValue) { - byte[] prefix = Arrays.copyOfRange(input, 0, start); - byte[] rest = Arrays.copyOfRange(input, end, input.length); - - byte[] output = new byte[prefix.length + newValue.length + rest.length]; - System.arraycopy(prefix, 0, output, 0, prefix.length); - System.arraycopy(newValue, 0, output, prefix.length, newValue.length); - System.arraycopy(rest, 0, output, prefix.length + newValue.length, rest.length); - - return output; - } } diff --git a/src/de/usd/cstchef/operations/setter/HttpSetCookie.java b/src/de/usd/cstchef/operations/setter/HttpSetCookie.java index 23641ae..76dce5b 100644 --- a/src/de/usd/cstchef/operations/setter/HttpSetCookie.java +++ b/src/de/usd/cstchef/operations/setter/HttpSetCookie.java @@ -1,13 +1,12 @@ package de.usd.cstchef.operations.setter; -import java.util.Arrays; - import javax.swing.JCheckBox; import burp.BurpUtils; import burp.IBurpExtenderCallbacks; import burp.IExtensionHelpers; import burp.IResponseInfo; +import de.usd.cstchef.Utils; import de.usd.cstchef.operations.Operation.OperationInfos; import de.usd.cstchef.operations.OperationCategory; @@ -52,7 +51,7 @@ protected byte[] perform(byte[] input) throws Exception { if( end < 0 ) end = line_end; - return insertAtOffset(input, start + cookieSearch.length, end, newValue); + return Utils.insertAtOffset(input, start + cookieSearch.length, end, newValue); } catch( IllegalArgumentException e ) { @@ -66,7 +65,7 @@ protected byte[] perform(byte[] input) throws Exception { System.arraycopy("=".getBytes(), 0, value, cookieName.length, 1); System.arraycopy(newValue, 0, value, cookieName.length + 1, newValue.length); System.arraycopy("; ".getBytes(), 0, value, cookieName.length + 1 + newValue.length, 2); - return insertAtOffset(input, offset + cookieHeaderLength, offset + cookieHeaderLength, value); + return Utils.insertAtOffset(input, offset + cookieHeaderLength, offset + cookieHeaderLength, value); } else { @@ -77,7 +76,7 @@ protected byte[] perform(byte[] input) throws Exception { System.arraycopy("=".getBytes(), 0, value, cookieHeaderLength + cookieName.length, 1); System.arraycopy(newValue, 0, value, cookieHeaderLength + cookieName.length + 1, newValue.length); System.arraycopy(";".getBytes(), 0, value, cookieHeaderLength + cookieName.length + 1 + newValue.length, 1); - return insertAtOffset(input, bodyOffset, bodyOffset, value); + return Utils.insertAtOffset(input, bodyOffset, bodyOffset, value); } } } @@ -89,16 +88,5 @@ public void createUI() { this.addIfNotPresent.setSelected(true); this.addUIElement(null, this.addIfNotPresent); } - - private byte[] insertAtOffset(byte[] input, int start, int end, byte[] newValue) { - byte[] prefix = Arrays.copyOfRange(input, 0, start); - byte[] rest = Arrays.copyOfRange(input, end, input.length); - - byte[] output = new byte[prefix.length + newValue.length + rest.length]; - System.arraycopy(prefix, 0, output, 0, prefix.length); - System.arraycopy(newValue, 0, output, prefix.length, newValue.length); - System.arraycopy(rest, 0, output, prefix.length + newValue.length, rest.length); - - return output; - } + } diff --git a/src/de/usd/cstchef/operations/setter/LineSetter.java b/src/de/usd/cstchef/operations/setter/LineSetter.java index c174674..1d4a3a1 100644 --- a/src/de/usd/cstchef/operations/setter/LineSetter.java +++ b/src/de/usd/cstchef/operations/setter/LineSetter.java @@ -8,6 +8,7 @@ import burp.BurpUtils; import burp.IBurpExtenderCallbacks; import burp.IExtensionHelpers; +import de.usd.cstchef.Utils; import de.usd.cstchef.operations.Operation.OperationInfos; import de.usd.cstchef.operations.OperationCategory; @@ -70,9 +71,9 @@ protected byte[] perform(byte[] input) throws Exception { byte[] value = new byte[newValue.length + lineEndings.length]; System.arraycopy(lineEndings, 0, value, 0, lineEndings.length); System.arraycopy(newValue, 0, value, lineEndings.length, newValue.length); - return insertAtOffset(input, end, end, value); + return Utils.insertAtOffset(input, end, end, value); } else { - return insertAtOffset(input, start, end, newValue); + return Utils.insertAtOffset(input, start, end, newValue); } } @@ -87,15 +88,4 @@ public void createUI() { this.addUIElement("Lineseperator", this.formatBox); } - private byte[] insertAtOffset(byte[] input, int start, int end, byte[] newValue) { - byte[] prefix = Arrays.copyOfRange(input, 0, start); - byte[] rest = Arrays.copyOfRange(input, end, input.length); - - byte[] output = new byte[prefix.length + newValue.length + rest.length]; - System.arraycopy(prefix, 0, output, 0, prefix.length); - System.arraycopy(newValue, 0, output, prefix.length, newValue.length); - System.arraycopy(rest, 0, output, prefix.length + newValue.length, rest.length); - - return output; - } } From f65a671b35f3a8cad891f71dda8888d247c9e78b Mon Sep 17 00:00:00 2001 From: TNeitzel Date: Mon, 22 Jun 2020 08:20:31 +0200 Subject: [PATCH 03/36] Add HTML decode and encode operations Added a HTML encode and decode operation as requested in #19. The operations should work fine in 99% of the time, but they use an implicit string conversion and therefore probably return false results for unicode strings. --- src/de/usd/cstchef/Utils.java | 8 +-- .../operations/dataformat/HtmlDecode.java | 22 ++++++++ .../operations/dataformat/HtmlEncode.java | 54 +++++++++++++++++++ 3 files changed, 81 insertions(+), 3 deletions(-) create mode 100644 src/de/usd/cstchef/operations/dataformat/HtmlDecode.java create mode 100644 src/de/usd/cstchef/operations/dataformat/HtmlEncode.java diff --git a/src/de/usd/cstchef/Utils.java b/src/de/usd/cstchef/Utils.java index bf56061..a1da898 100644 --- a/src/de/usd/cstchef/Utils.java +++ b/src/de/usd/cstchef/Utils.java @@ -37,6 +37,8 @@ import de.usd.cstchef.operations.compression.Inflate; import de.usd.cstchef.operations.dataformat.FromBase64; import de.usd.cstchef.operations.dataformat.FromHex; +import de.usd.cstchef.operations.dataformat.HtmlDecode; +import de.usd.cstchef.operations.dataformat.HtmlEncode; import de.usd.cstchef.operations.dataformat.ToBase64; import de.usd.cstchef.operations.dataformat.ToHex; import de.usd.cstchef.operations.dataformat.UrlDecode; @@ -214,9 +216,9 @@ public static Class[] getOperationsDev() { HttpBodyExtractor.class, HttpCookieExtractor.class, HttpGetExtractor.class, HttpGetSetter.class, HttpHeaderExtractor.class, HttpHeaderSetter.class, HttpJsonExtractor.class, HttpJsonSetter.class, HttpMethodExtractor.class, HttpPostExtractor.class, HttpPostSetter.class, HTTPRequest.class, HttpSetBody.class, HttpSetCookie.class, HttpSetUri.class, - HttpUriExtractor.class, HttpXmlExtractor.class, HttpXmlSetter.class, Inflate.class, JsonExtractor.class, - JsonSetter.class, Length.class, LineExtractor.class, LineSetter.class, MD2.class, MD4.class, MD5.class, - Mean.class, Median.class, Multiply.class, MultiplyList.class, Prefix.class, RandomNumber.class, + HttpUriExtractor.class, HttpXmlExtractor.class, HttpXmlSetter.class, HtmlEncode.class, HtmlDecode.class, + Inflate.class, JsonExtractor.class, JsonSetter.class, Length.class, LineExtractor.class, LineSetter.class, + MD2.class, MD4.class, MD5.class, Mean.class, Median.class, Multiply.class, MultiplyList.class, Prefix.class, RandomNumber.class, ReadFile.class, RegexExtractor.class, Replace.class, RIPEMD.class, SetIfEmpty.class, SHA1.class, SHA2.class, SHA3.class, Skein.class, SplitAndSelect.class, StaticString.class, StoreVariable.class, Sub.class, Substring.class, Subtraction.class, Suffix.class, Sum.class, diff --git a/src/de/usd/cstchef/operations/dataformat/HtmlDecode.java b/src/de/usd/cstchef/operations/dataformat/HtmlDecode.java new file mode 100644 index 0000000..918d0d1 --- /dev/null +++ b/src/de/usd/cstchef/operations/dataformat/HtmlDecode.java @@ -0,0 +1,22 @@ +package de.usd.cstchef.operations.dataformat; + +import java.nio.charset.StandardCharsets; + +import org.apache.commons.text.StringEscapeUtils; + +import de.usd.cstchef.operations.Operation; +import de.usd.cstchef.operations.Operation.OperationInfos; +import de.usd.cstchef.operations.OperationCategory; + +@OperationInfos(name = "HTML Decode", category = OperationCategory.DATAFORMAT, description = "HTML Decode") +public class HtmlDecode extends Operation { + + @Override + protected byte[] perform(byte[] input) throws Exception { + + String tmp = new String(input, StandardCharsets.ISO_8859_1); + tmp = StringEscapeUtils.unescapeHtml4(tmp); + return tmp.getBytes(StandardCharsets.ISO_8859_1); + } + +} diff --git a/src/de/usd/cstchef/operations/dataformat/HtmlEncode.java b/src/de/usd/cstchef/operations/dataformat/HtmlEncode.java new file mode 100644 index 0000000..716030e --- /dev/null +++ b/src/de/usd/cstchef/operations/dataformat/HtmlEncode.java @@ -0,0 +1,54 @@ +package de.usd.cstchef.operations.dataformat; + +import java.io.ByteArrayOutputStream; + +import javax.swing.JCheckBox; + +import org.apache.commons.text.StringEscapeUtils; + +import de.usd.cstchef.operations.Operation; +import de.usd.cstchef.operations.Operation.OperationInfos; +import de.usd.cstchef.operations.OperationCategory; + +@OperationInfos(name = "HTML Encode", category = OperationCategory.DATAFORMAT, description = "HTML Encode") +public class HtmlEncode extends Operation { + + private JCheckBox checkbox; + + @Override + protected byte[] perform(byte[] input) throws Exception { + + byte[] result = null; + if( checkbox.isSelected() ) { + + byte[] delimiter = "&#".getBytes(); + byte[] closer = ";".getBytes(); + ByteArrayOutputStream out = new ByteArrayOutputStream(); + + out.write(delimiter); + for (int i = 0; i < input.length - 1; i++) { + out.write(String.valueOf(Byte.toUnsignedInt(input[i])).getBytes()); + out.write(closer); + out.write(delimiter); + } + + out.write(String.valueOf(Byte.toUnsignedInt(input[input.length - 1])).getBytes()); + out.write(closer); + result = out.toByteArray(); + + } else { + String tmp = new String(input); + tmp = StringEscapeUtils.escapeHtml4(tmp); + result = tmp.getBytes(); + } + + return result; + } + + @Override + public void createUI() { + this.checkbox = new JCheckBox("Encode all"); + this.checkbox.setSelected(false); + this.addUIElement(null, this.checkbox); + } +} From a40bea5a6b385def312a15fb53a7d8ca1547bd97 Mon Sep 17 00:00:00 2001 From: TNeitzel Date: Mon, 22 Jun 2020 08:40:03 +0200 Subject: [PATCH 04/36] Add apache commons-text library to pom.xml --- pom.xml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/pom.xml b/pom.xml index b5cd080..90a78c3 100644 --- a/pom.xml +++ b/pom.xml @@ -79,5 +79,10 @@ jackson-databind 2.9.10.4 + + org.apache.commons + commons-text + 1.8 + From 5d9ca24137ec96656bd152b06cb4b478d5b36de6 Mon Sep 17 00:00:00 2001 From: TNeitzel Date: Tue, 23 Jun 2020 06:20:50 +0200 Subject: [PATCH 05/36] Change SignatureOperation to KeystoreOperation Changed the Operation name from the geneirc SignatureOperation to the even more generic KeystoreOperation. This name is more focused on what the operation is actually used for. --- ...eOperation.java => KeystoreOperation.java} | 102 ++++++++++++------ 1 file changed, 72 insertions(+), 30 deletions(-) rename src/de/usd/cstchef/operations/signature/{SignatureOperation.java => KeystoreOperation.java} (55%) diff --git a/src/de/usd/cstchef/operations/signature/SignatureOperation.java b/src/de/usd/cstchef/operations/signature/KeystoreOperation.java similarity index 55% rename from src/de/usd/cstchef/operations/signature/SignatureOperation.java rename to src/de/usd/cstchef/operations/signature/KeystoreOperation.java index f946375..3699e53 100644 --- a/src/de/usd/cstchef/operations/signature/SignatureOperation.java +++ b/src/de/usd/cstchef/operations/signature/KeystoreOperation.java @@ -6,81 +6,104 @@ import java.io.FileInputStream; import java.security.KeyStore; import java.security.KeyStore.PrivateKeyEntry; +import java.security.cert.Certificate; import java.util.Enumeration; import javax.swing.JButton; import javax.swing.JCheckBox; import javax.swing.JComboBox; import javax.swing.JFileChooser; +import javax.swing.JPasswordField; import de.usd.cstchef.operations.Operation; -import de.usd.cstchef.view.ui.FormatTextField; -public abstract class SignatureOperation extends Operation implements ActionListener { +public abstract class KeystoreOperation extends Operation implements ActionListener { protected String[] keyEntries = new String[] {}; protected String[] keyStoreTypes = new String[] {"PKCS12", "JKS"}; + protected Certificate cert = null; protected KeyStore keyStore = null; protected PrivateKeyEntry selectedEntry = null; protected File keyStoreFile = null; - protected FormatTextField keyStorePass; + protected JPasswordField keyStorePass; protected JCheckBox keyStoreOpen; + protected JCheckBox certAvailable; + protected JCheckBox keyAvailable; + protected JButton chooseFileButton; protected JButton openKeyStoreButton; protected JComboBox keyEntry; protected JComboBox keyStoreType; protected JFileChooser fileChooser = new JFileChooser(); - - public SignatureOperation() { + public KeystoreOperation() { super(); } - private void openKeyStore() { - try { - String storeType = (String)keyStoreType.getSelectedItem(); - String password = new String(keyStorePass.getText()); - KeyStore ks = KeyStore.getInstance(storeType); - ks.load(new FileInputStream(keyStoreFile), password.toCharArray()); - this.keyStore = ks; - this.keyStoreOpen.setSelected(true); - this.updateKeyEntries(); - } catch( Exception e ) { - this.resetKeyStore(); - } + try { + + String storeType = (String)keyStoreType.getSelectedItem(); + char[] password = keyStorePass.getPassword(); + KeyStore ks = KeyStore.getInstance(storeType); + ks.load(new FileInputStream(keyStoreFile), password); + this.keyStore = ks; + this.keyStoreOpen.setSelected(true); + this.certAvailable.setSelected(false); + this.keyAvailable.setSelected(false); + this.updateKeyEntries(); + + } catch( Exception e ) { + this.resetKeyStore(); + } } - - private void updateKeyEntries() { - try { - Enumeration entries = keyStore.aliases(); - keyEntry.removeAllItems(); - while (entries.hasMoreElements()) { + private void updateKeyEntries(){ + try { + Enumeration entries = keyStore.aliases(); + keyEntry.removeAllItems(); + while (entries.hasMoreElements()) { keyEntry.addItem(entries.nextElement()); } } catch( Exception e ) { - this.resetKeyStore(); + this.resetKeyStore(); } } - private void selectKeyEntry() { + + String entry = (String)keyEntry.getSelectedItem(); try { - String password = new String(keyStorePass.getText()); - String entryNumber = (String)keyEntry.getSelectedItem(); - selectedEntry = (KeyStore.PrivateKeyEntry) keyStore.getEntry(entryNumber, new KeyStore.PasswordProtection(password.toCharArray())); + this.cert = keyStore.getCertificate(entry); + if ( this.cert != null ) + this.certAvailable.setSelected(true); + else + this.certAvailable.setSelected(false); } catch( Exception e ) { - this.resetKeyStore(); + this.certAvailable.setSelected(false); } + + char[] password = keyStorePass.getPassword(); + try { + this.selectedEntry = (KeyStore.PrivateKeyEntry)keyStore.getEntry(entry, new KeyStore.PasswordProtection(password)); + if ( this.selectedEntry != null ) + this.keyAvailable.setSelected(true); + else + this.keyAvailable.setSelected(false); + } catch( Exception e) { + this.keyAvailable.setSelected(false); + } + } private void resetKeyStore() { this.keyStoreOpen.setSelected(false); + this.certAvailable.setSelected(false); + this.keyAvailable.setSelected(false); keyStore = null; selectedEntry = null; } @@ -95,7 +118,7 @@ public void createMyUI() { chooseFileButton.addActionListener(this); this.addUIElement(null, this.chooseFileButton); - this.keyStorePass = new FormatTextField(); + this.keyStorePass = new JPasswordField(); this.addUIElement("PrivKeyPassword", this.keyStorePass); openKeyStoreButton = new JButton("Open keystore"); @@ -110,24 +133,43 @@ public void createMyUI() { this.keyStoreOpen.setSelected(false); this.keyStoreOpen.addActionListener(this); this.addUIElement(null, this.keyStoreOpen); + + this.certAvailable = new JCheckBox("Certificate available"); + this.certAvailable.setSelected(false); + this.certAvailable.addActionListener(this); + this.addUIElement(null, this.certAvailable); + + this.keyAvailable = new JCheckBox("PrivKey available"); + this.keyAvailable.setSelected(false); + this.keyAvailable.addActionListener(this); + this.addUIElement(null, this.keyAvailable); + } @Override public void actionPerformed(ActionEvent arg0) { + if( arg0.getSource() == keyStoreType ) { + this.resetKeyStore(); + } else if( arg0.getSource() == openKeyStoreButton ) { + this.resetKeyStore(); this.openKeyStore(); + } else if( arg0.getSource() == chooseFileButton ) { + this.resetKeyStore(); int returnVal = fileChooser.showOpenDialog(this); if (returnVal == JFileChooser.APPROVE_OPTION) { keyStoreFile = fileChooser.getSelectedFile(); } + } else if( arg0.getSource() == keyEntry ) { this.selectKeyEntry(); } + if( keyStore != null && keyEntry != null ) { this.notifyChange(); } From 00b560bee5dbcc8090c893bc188ade7726bc5c38 Mon Sep 17 00:00:00 2001 From: TNeitzel Date: Tue, 23 Jun 2020 06:22:41 +0200 Subject: [PATCH 06/36] Adopt signature operations Adopt the signature operations to the new KeystoreOperation. --- .../usd/cstchef/operations/signature/SoapMultiSignature.java | 4 ++-- src/de/usd/cstchef/operations/signature/XmlSignature.java | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/de/usd/cstchef/operations/signature/SoapMultiSignature.java b/src/de/usd/cstchef/operations/signature/SoapMultiSignature.java index 970f63a..cafca0e 100644 --- a/src/de/usd/cstchef/operations/signature/SoapMultiSignature.java +++ b/src/de/usd/cstchef/operations/signature/SoapMultiSignature.java @@ -43,12 +43,12 @@ import org.w3c.dom.Element; import org.w3c.dom.NodeList; -import de.usd.cstchef.operations.OperationCategory; import de.usd.cstchef.operations.Operation.OperationInfos; +import de.usd.cstchef.operations.OperationCategory; import de.usd.cstchef.view.ui.FormatTextField; @OperationInfos(name = "Soap Multi Signature", category = OperationCategory.ENCRYPTION, description = "Create a Soap signature.") -public class SoapMultiSignature extends SignatureOperation { +public class SoapMultiSignature extends KeystoreOperation { public SoapMultiSignature() { super(); diff --git a/src/de/usd/cstchef/operations/signature/XmlSignature.java b/src/de/usd/cstchef/operations/signature/XmlSignature.java index 3da9381..e9ba6cd 100644 --- a/src/de/usd/cstchef/operations/signature/XmlSignature.java +++ b/src/de/usd/cstchef/operations/signature/XmlSignature.java @@ -37,7 +37,7 @@ import de.usd.cstchef.view.ui.FormatTextField; -public abstract class XmlSignature extends SignatureOperation { +public abstract class XmlSignature extends KeystoreOperation { private boolean multiSignature = false; private XMLSignatureFactory signatureFac; From 3c579c921e382ec12403d43afb06b1842f76f9c0 Mon Sep 17 00:00:00 2001 From: TNeitzel Date: Tue, 23 Jun 2020 06:58:19 +0200 Subject: [PATCH 07/36] Disable checkboxes in KeystoreOperation The checkboxes inside the keystore operation are used to visualize the state of the keystore. They are not ment to be clicked by the user and are therefore now disabled. --- .../signature/KeystoreOperation.java | 62 ++++++++++--------- 1 file changed, 33 insertions(+), 29 deletions(-) diff --git a/src/de/usd/cstchef/operations/signature/KeystoreOperation.java b/src/de/usd/cstchef/operations/signature/KeystoreOperation.java index 3699e53..8c6ae01 100644 --- a/src/de/usd/cstchef/operations/signature/KeystoreOperation.java +++ b/src/de/usd/cstchef/operations/signature/KeystoreOperation.java @@ -20,7 +20,7 @@ public abstract class KeystoreOperation extends Operation implements ActionListener { protected String[] keyEntries = new String[] {}; - protected String[] keyStoreTypes = new String[] {"PKCS12", "JKS"}; + protected String[] keyStoreTypes = new String[] {"JKS", "PKCS12"}; protected Certificate cert = null; protected KeyStore keyStore = null; @@ -32,7 +32,7 @@ public abstract class KeystoreOperation extends Operation implements ActionListe protected JCheckBox keyStoreOpen; protected JCheckBox certAvailable; protected JCheckBox keyAvailable; - + protected JButton chooseFileButton; protected JButton openKeyStoreButton; protected JComboBox keyEntry; @@ -74,27 +74,28 @@ private void updateKeyEntries(){ } private void selectKeyEntry() { - + String entry = (String)keyEntry.getSelectedItem(); try { - this.cert = keyStore.getCertificate(entry); - if ( this.cert != null ) - this.certAvailable.setSelected(true); - else - this.certAvailable.setSelected(false); + this.cert = keyStore.getCertificate(entry); + if ( this.cert != null ) + this.certAvailable.setSelected(true); + else + this.certAvailable.setSelected(false); + } catch( Exception e ) { - this.certAvailable.setSelected(false); + this.certAvailable.setSelected(false); } - + char[] password = keyStorePass.getPassword(); try { - this.selectedEntry = (KeyStore.PrivateKeyEntry)keyStore.getEntry(entry, new KeyStore.PasswordProtection(password)); - if ( this.selectedEntry != null ) + this.selectedEntry = (KeyStore.PrivateKeyEntry)keyStore.getEntry(entry, new KeyStore.PasswordProtection(password)); + if ( this.selectedEntry != null ) this.keyAvailable.setSelected(true); - else + else this.keyAvailable.setSelected(false); } catch( Exception e) { - this.keyAvailable.setSelected(false); + this.keyAvailable.setSelected(false); } } @@ -131,16 +132,19 @@ public void createMyUI() { this.keyStoreOpen = new JCheckBox("KeyStore Opened"); this.keyStoreOpen.setSelected(false); - this.keyStoreOpen.addActionListener(this); + this.keyStoreOpen.setEnabled(false); + this.keyStoreOpen.addActionListener(this); this.addUIElement(null, this.keyStoreOpen); this.certAvailable = new JCheckBox("Certificate available"); this.certAvailable.setSelected(false); + this.certAvailable.setEnabled(false); this.certAvailable.addActionListener(this); this.addUIElement(null, this.certAvailable); this.keyAvailable = new JCheckBox("PrivKey available"); this.keyAvailable.setSelected(false); + this.keyAvailable.setEnabled(false); this.keyAvailable.addActionListener(this); this.addUIElement(null, this.keyAvailable); @@ -151,27 +155,27 @@ public void actionPerformed(ActionEvent arg0) { if( arg0.getSource() == keyStoreType ) { - this.resetKeyStore(); - + this.resetKeyStore(); + } else if( arg0.getSource() == openKeyStoreButton ) { - this.resetKeyStore(); - this.openKeyStore(); - + this.resetKeyStore(); + this.openKeyStore(); + } else if( arg0.getSource() == chooseFileButton ) { - this.resetKeyStore(); - int returnVal = fileChooser.showOpenDialog(this); - if (returnVal == JFileChooser.APPROVE_OPTION) { - keyStoreFile = fileChooser.getSelectedFile(); - } - + this.resetKeyStore(); + int returnVal = fileChooser.showOpenDialog(this); + if (returnVal == JFileChooser.APPROVE_OPTION) { + keyStoreFile = fileChooser.getSelectedFile(); + } + } else if( arg0.getSource() == keyEntry ) { - this.selectKeyEntry(); + this.selectKeyEntry(); } - + if( keyStore != null && keyEntry != null ) { - this.notifyChange(); + this.notifyChange(); } } } From 46c99f22f839c1d6132c725a1c494ca53db1356b Mon Sep 17 00:00:00 2001 From: TNeitzel Date: Tue, 23 Jun 2020 07:07:27 +0200 Subject: [PATCH 08/36] Prevent NullPointerException in Operation class The operation class trew a nullpointer exception when an operation contained a JComboBox with no values inside of it. This was now resolved. --- src/de/usd/cstchef/operations/Operation.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/de/usd/cstchef/operations/Operation.java b/src/de/usd/cstchef/operations/Operation.java index 1cec608..6b416df 100644 --- a/src/de/usd/cstchef/operations/Operation.java +++ b/src/de/usd/cstchef/operations/Operation.java @@ -190,7 +190,9 @@ private Object getUiValues(Component comp) { } else if (comp instanceof JSpinner) { result = ((JSpinner) comp).getValue(); } else if (comp instanceof JComboBox) { - result = ((JComboBox) comp).getSelectedItem().toString(); + result = ((JComboBox) comp).getSelectedItem(); + if( result != null ) + result = result.toString(); } else if (comp instanceof JCheckBox) { result = ((JCheckBox) comp).isSelected(); } else if (comp instanceof FormatTextField) { From e6f3d4771eb025d8983489d974dfa06bc6447c64 Mon Sep 17 00:00:00 2001 From: TNeitzel Date: Tue, 23 Jun 2020 07:48:47 +0200 Subject: [PATCH 09/36] Add RsaEncrypt and RsaDecrypt operations Added to operations to perform RSA decryption / encryption as requetsed in #18. The implementation currently requires a keystore (JKS or PKCS12). Maybe we add support for raw keys later. --- src/de/usd/cstchef/Utils.java | 8 +- .../operations/encryption/RsaDecryption.java | 75 +++++++++++++++++++ .../operations/encryption/RsaEncryption.java | 75 +++++++++++++++++++ 3 files changed, 155 insertions(+), 3 deletions(-) create mode 100644 src/de/usd/cstchef/operations/encryption/RsaDecryption.java create mode 100644 src/de/usd/cstchef/operations/encryption/RsaEncryption.java diff --git a/src/de/usd/cstchef/Utils.java b/src/de/usd/cstchef/Utils.java index a1da898..4def6af 100644 --- a/src/de/usd/cstchef/Utils.java +++ b/src/de/usd/cstchef/Utils.java @@ -49,6 +49,8 @@ import de.usd.cstchef.operations.encryption.AesEncryption; import de.usd.cstchef.operations.encryption.DesDecryption; import de.usd.cstchef.operations.encryption.DesEncryption; +import de.usd.cstchef.operations.encryption.RsaDecryption; +import de.usd.cstchef.operations.encryption.RsaEncryption; import de.usd.cstchef.operations.extractors.HttpBodyExtractor; import de.usd.cstchef.operations.extractors.HttpCookieExtractor; import de.usd.cstchef.operations.extractors.HttpGetExtractor; @@ -219,9 +221,9 @@ public static Class[] getOperationsDev() { HttpUriExtractor.class, HttpXmlExtractor.class, HttpXmlSetter.class, HtmlEncode.class, HtmlDecode.class, Inflate.class, JsonExtractor.class, JsonSetter.class, Length.class, LineExtractor.class, LineSetter.class, MD2.class, MD4.class, MD5.class, Mean.class, Median.class, Multiply.class, MultiplyList.class, Prefix.class, RandomNumber.class, - ReadFile.class, RegexExtractor.class, Replace.class, RIPEMD.class, SetIfEmpty.class, SHA1.class, - SHA2.class, SHA3.class, Skein.class, SplitAndSelect.class, StaticString.class, StoreVariable.class, - Sub.class, Substring.class, Subtraction.class, Suffix.class, Sum.class, + ReadFile.class, RegexExtractor.class, Replace.class, RIPEMD.class, RsaDecryption.class, RsaEncryption.class, + SetIfEmpty.class, SHA1.class, SHA2.class, SHA3.class, Skein.class, SplitAndSelect.class, StaticString.class, + StoreVariable.class, Sub.class, Substring.class, Subtraction.class, Suffix.class, Sum.class, Tiger.class, ToBase64.class, ToHex.class, UnixTimestamp.class, UrlDecode.class, UrlEncode.class, Whirlpool.class, WriteFile.class, XmlFullSignature.class, XmlMultiSignature.class, Xor.class }; diff --git a/src/de/usd/cstchef/operations/encryption/RsaDecryption.java b/src/de/usd/cstchef/operations/encryption/RsaDecryption.java new file mode 100644 index 0000000..908a3e0 --- /dev/null +++ b/src/de/usd/cstchef/operations/encryption/RsaDecryption.java @@ -0,0 +1,75 @@ +package de.usd.cstchef.operations.encryption; + +import javax.crypto.Cipher; +import javax.swing.JComboBox; + +import org.bouncycastle.util.encoders.Base64; +import org.bouncycastle.util.encoders.Hex; + +import de.usd.cstchef.operations.OperationCategory; +import de.usd.cstchef.operations.Operation.OperationInfos; +import de.usd.cstchef.operations.encryption.CipherUtils.CipherInfo; +import de.usd.cstchef.operations.signature.KeystoreOperation; + +@OperationInfos(name = "RSA Decryption", category = OperationCategory.ENCRYPTION, description = "Decrypt input using a private key") +public class RsaDecryption extends KeystoreOperation { + + private static String[] inOutModes = new String[] { "Raw", "Hex", "Base64" }; + + protected String algorithm = "RSA"; + protected String cipherMode = "ECB"; + + protected JComboBox inputMode; + protected JComboBox outputMode; + protected JComboBox paddings; + + public RsaDecryption() { + super(); + this.createMyUI(); + } + + protected byte[] perform(byte[] input) throws Exception { + + if( ! this.keyAvailable.isSelected() ) + throw new IllegalArgumentException("No private key available."); + + String padding = (String)paddings.getSelectedItem(); + Cipher cipher = Cipher.getInstance(String.format("%s/%s/%s", algorithm, cipherMode, padding)); + cipher.init(Cipher.DECRYPT_MODE, this.selectedEntry.getPrivateKey()); + + String selectedInputMode = (String)inputMode.getSelectedItem(); + String selectedOutputMode = (String)outputMode.getSelectedItem(); + + if( selectedInputMode.equals("Hex") ) + input = Hex.decode(input); + if( selectedInputMode.equals("Base64") ) + input = Base64.decode(input); + + byte[] encrypted = cipher.doFinal(input); + + if( selectedOutputMode.equals("Hex") ) + encrypted = Hex.encode(encrypted); + if( selectedOutputMode.equals("Base64") ) + encrypted = Base64.encode(encrypted); + + return encrypted; + } + + public void createMyUI() { + + super.createMyUI(); + + CipherUtils utils = CipherUtils.getInstance(); + CipherInfo info = utils.getCipherInfo(this.algorithm); + + this.paddings = new JComboBox<>(info.getPaddings()); + this.addUIElement("Padding", this.paddings); + + this.inputMode = new JComboBox<>(inOutModes); + this.addUIElement("Input", this.inputMode); + + this.outputMode = new JComboBox<>(inOutModes); + this.addUIElement("Output", this.outputMode); + } + +} diff --git a/src/de/usd/cstchef/operations/encryption/RsaEncryption.java b/src/de/usd/cstchef/operations/encryption/RsaEncryption.java new file mode 100644 index 0000000..edcde37 --- /dev/null +++ b/src/de/usd/cstchef/operations/encryption/RsaEncryption.java @@ -0,0 +1,75 @@ +package de.usd.cstchef.operations.encryption; + +import javax.crypto.Cipher; +import javax.swing.JComboBox; + +import org.bouncycastle.util.encoders.Base64; +import org.bouncycastle.util.encoders.Hex; + +import de.usd.cstchef.operations.OperationCategory; +import de.usd.cstchef.operations.Operation.OperationInfos; +import de.usd.cstchef.operations.encryption.CipherUtils.CipherInfo; +import de.usd.cstchef.operations.signature.KeystoreOperation; + +@OperationInfos(name = "RSA Encryption", category = OperationCategory.ENCRYPTION, description = "Encrypt input using a certificate") +public class RsaEncryption extends KeystoreOperation { + + private static String[] inOutModes = new String[] { "Raw", "Hex", "Base64" }; + + protected String algorithm = "RSA"; + protected String cipherMode = "ECB"; + + protected JComboBox inputMode; + protected JComboBox outputMode; + protected JComboBox paddings; + + public RsaEncryption() { + super(); + this.createMyUI(); + } + + protected byte[] perform(byte[] input) throws Exception { + + if( ! this.certAvailable.isSelected() ) + throw new IllegalArgumentException("No certificate available."); + + String padding = (String)paddings.getSelectedItem(); + Cipher cipher = Cipher.getInstance(String.format("%s/%s/%s", algorithm, cipherMode, padding)); + cipher.init(Cipher.ENCRYPT_MODE, this.cert.getPublicKey()); + + String selectedInputMode = (String)inputMode.getSelectedItem(); + String selectedOutputMode = (String)outputMode.getSelectedItem(); + + if( selectedInputMode.equals("Hex") ) + input = Hex.decode(input); + if( selectedInputMode.equals("Base64") ) + input = Base64.decode(input); + + byte[] encrypted = cipher.doFinal(input); + + if( selectedOutputMode.equals("Hex") ) + encrypted = Hex.encode(encrypted); + if( selectedOutputMode.equals("Base64") ) + encrypted = Base64.encode(encrypted); + + return encrypted; + } + + public void createMyUI() { + + super.createMyUI(); + + CipherUtils utils = CipherUtils.getInstance(); + CipherInfo info = utils.getCipherInfo(this.algorithm); + + this.paddings = new JComboBox<>(info.getPaddings()); + this.addUIElement("Padding", this.paddings); + + this.inputMode = new JComboBox<>(inOutModes); + this.addUIElement("Input", this.inputMode); + + this.outputMode = new JComboBox<>(inOutModes); + this.addUIElement("Output", this.outputMode); + } + +} From 8c8a3604435d12d9f22b0dc2f9af9e414d9c1e95 Mon Sep 17 00:00:00 2001 From: TNeitzel Date: Tue, 23 Jun 2020 07:52:20 +0200 Subject: [PATCH 10/36] Add SignatureUtils class Added a SignatureUtils class to support signature operations. --- .../operations/signature/SignatureUtils.java | 42 +++++++++++++++++++ 1 file changed, 42 insertions(+) create mode 100644 src/de/usd/cstchef/operations/signature/SignatureUtils.java diff --git a/src/de/usd/cstchef/operations/signature/SignatureUtils.java b/src/de/usd/cstchef/operations/signature/SignatureUtils.java new file mode 100644 index 0000000..04be967 --- /dev/null +++ b/src/de/usd/cstchef/operations/signature/SignatureUtils.java @@ -0,0 +1,42 @@ +package de.usd.cstchef.operations.signature; + +import java.security.Provider; +import java.security.Provider.Service; +import java.security.Security; +import java.util.ArrayList; +import java.util.List; +import java.util.stream.Collectors; + +public class SignatureUtils { + + private static SignatureUtils instance; + + private List algos; + + private SignatureUtils() { + algos = new ArrayList();; + getSignatureInfos(); + } + + private void getSignatureInfos() { + for (Provider provider : Security.getProviders()) + for (Service service : provider.getServices()) + if (service.getType().equals("Signature")) + algos.add(service.getAlgorithm()); + } + + public static SignatureUtils getInstance() { + if (instance == null) { + instance = new SignatureUtils(); + } + return instance; + } + + public String[] getAlgos() { + return algos.toArray(new String[0]); + } + public String[] getRsaAlgos() { + List rsaAlgos = algos.stream().filter(p -> p.contains("RSA")).collect(Collectors.toList()); + return rsaAlgos.toArray(new String[0]); + } +} From 74a3e238926dfabf2d45e7006d00556f6b4b0495 Mon Sep 17 00:00:00 2001 From: TNeitzel Date: Tue, 23 Jun 2020 07:54:03 +0200 Subject: [PATCH 11/36] Add RsaSignature operation Added a simple operation that creates a RsaSignature over the input. --- src/de/usd/cstchef/Utils.java | 3 +- .../operations/signature/RsaSignature.java | 69 +++++++++++++++++++ 2 files changed, 71 insertions(+), 1 deletion(-) create mode 100644 src/de/usd/cstchef/operations/signature/RsaSignature.java diff --git a/src/de/usd/cstchef/Utils.java b/src/de/usd/cstchef/Utils.java index 4def6af..92aa648 100644 --- a/src/de/usd/cstchef/Utils.java +++ b/src/de/usd/cstchef/Utils.java @@ -90,6 +90,7 @@ import de.usd.cstchef.operations.setter.HttpXmlSetter; import de.usd.cstchef.operations.setter.JsonSetter; import de.usd.cstchef.operations.setter.LineSetter; +import de.usd.cstchef.operations.signature.RsaSignature; import de.usd.cstchef.operations.signature.XmlFullSignature; import de.usd.cstchef.operations.signature.XmlMultiSignature; import de.usd.cstchef.operations.string.Length; @@ -221,7 +222,7 @@ public static Class[] getOperationsDev() { HttpUriExtractor.class, HttpXmlExtractor.class, HttpXmlSetter.class, HtmlEncode.class, HtmlDecode.class, Inflate.class, JsonExtractor.class, JsonSetter.class, Length.class, LineExtractor.class, LineSetter.class, MD2.class, MD4.class, MD5.class, Mean.class, Median.class, Multiply.class, MultiplyList.class, Prefix.class, RandomNumber.class, - ReadFile.class, RegexExtractor.class, Replace.class, RIPEMD.class, RsaDecryption.class, RsaEncryption.class, + ReadFile.class, RegexExtractor.class, Replace.class, RIPEMD.class, RsaDecryption.class, RsaEncryption.class, RsaSignature.class, SetIfEmpty.class, SHA1.class, SHA2.class, SHA3.class, Skein.class, SplitAndSelect.class, StaticString.class, StoreVariable.class, Sub.class, Substring.class, Subtraction.class, Suffix.class, Sum.class, Tiger.class, ToBase64.class, ToHex.class, UnixTimestamp.class, UrlDecode.class, diff --git a/src/de/usd/cstchef/operations/signature/RsaSignature.java b/src/de/usd/cstchef/operations/signature/RsaSignature.java new file mode 100644 index 0000000..b02b463 --- /dev/null +++ b/src/de/usd/cstchef/operations/signature/RsaSignature.java @@ -0,0 +1,69 @@ +package de.usd.cstchef.operations.signature; + +import java.security.Signature; + +import javax.swing.JComboBox; + +import org.bouncycastle.util.encoders.Base64; +import org.bouncycastle.util.encoders.Hex; + +import de.usd.cstchef.operations.Operation.OperationInfos; +import de.usd.cstchef.operations.OperationCategory; + +@OperationInfos(name = "RSA Signature", category = OperationCategory.SIGNATURE, description = "Create an RSA signature") +public class RsaSignature extends KeystoreOperation { + + private static String[] inOutModes = new String[] { "Raw", "Hex", "Base64" }; + + protected JComboBox algos; + protected JComboBox inputMode; + protected JComboBox outputMode; + + public RsaSignature() { + super(); + this.createMyUI(); + } + + protected byte[] perform(byte[] input) throws Exception { + + if( !this.keyAvailable.isSelected() ) + throw new IllegalArgumentException("No private key available."); + + String algo = (String)algos.getSelectedItem(); + Signature signature = Signature.getInstance(algo); + + String selectedInputMode = (String)inputMode.getSelectedItem(); + String selectedOutputMode = (String)outputMode.getSelectedItem(); + + if( selectedInputMode.equals("Hex") ) + input = Hex.decode(input); + if( selectedInputMode.equals("Base64") ) + input = Base64.decode(input); + + signature.initSign(this.selectedEntry.getPrivateKey()); + signature.update(input); + byte[] result = signature.sign(); + + if( selectedOutputMode.equals("Hex") ) + result = Hex.encode(result); + if( selectedOutputMode.equals("Base64") ) + result = Base64.encode(result); + + return result; + } + + public void createMyUI() { + + super.createMyUI(); + SignatureUtils utils = SignatureUtils.getInstance(); + + this.algos = new JComboBox<>(utils.getRsaAlgos()); + this.addUIElement("Padding", this.algos); + + this.inputMode = new JComboBox<>(inOutModes); + this.addUIElement("Input", this.inputMode); + + this.outputMode = new JComboBox<>(inOutModes); + this.addUIElement("Output", this.outputMode); + } +} From 2b4fc56544e7c4300ec87c7f2b9c61473882f26d Mon Sep 17 00:00:00 2001 From: TNeitzel Date: Tue, 23 Jun 2020 19:48:53 +0200 Subject: [PATCH 12/36] Prepare conditional operations Added the basic functionality required for conditional operations as well as a corresponding category section. This commit should not impact the already existing code and should be compatible with all existing operations. --- src/de/usd/cstchef/operations/Operation.java | 23 +++++++++++++++++++ .../cstchef/operations/OperationCategory.java | 1 + src/de/usd/cstchef/view/RecipePanel.java | 15 +++++++++--- 3 files changed, 36 insertions(+), 3 deletions(-) diff --git a/src/de/usd/cstchef/operations/Operation.java b/src/de/usd/cstchef/operations/Operation.java index 6b416df..861bf56 100644 --- a/src/de/usd/cstchef/operations/Operation.java +++ b/src/de/usd/cstchef/operations/Operation.java @@ -70,6 +70,9 @@ public abstract class Operation extends JPanel { private Box contentBox; private Map uiElements; + private int operationSkip = 0; + private int laneSkip = 0; + public Operation() { super(); this.uiElements = new HashMap<>(); @@ -393,6 +396,26 @@ public void setError(boolean error) { this.error = error; } + public void setOperationSkip(int count) { + if( count < 0 ) + count = 0; + this.operationSkip = count; + } + + public int getOperationSkip() { + return this.operationSkip; + } + + public void setLaneSkip(int count) { + if( count < 0 ) + count = 0; + this.laneSkip = count; + } + + public int getLaneSkip() { + return this.laneSkip; + } + @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.TYPE) public @interface OperationInfos { diff --git a/src/de/usd/cstchef/operations/OperationCategory.java b/src/de/usd/cstchef/operations/OperationCategory.java index e9e87b9..b3f3694 100644 --- a/src/de/usd/cstchef/operations/OperationCategory.java +++ b/src/de/usd/cstchef/operations/OperationCategory.java @@ -4,6 +4,7 @@ public enum OperationCategory { ARITHMETIC("Arithmetic"), BYTEOPERATION("Byte Operations"), COMPRESSION("Compression"), + CONDITIONAL("Conditional"), DATAFORMAT("Data format"), DATES("Date / Time"), ENCRYPTION("Encryption / Encoding"), diff --git a/src/de/usd/cstchef/view/RecipePanel.java b/src/de/usd/cstchef/view/RecipePanel.java index 58886a7..3a4c20a 100644 --- a/src/de/usd/cstchef/view/RecipePanel.java +++ b/src/de/usd/cstchef/view/RecipePanel.java @@ -396,17 +396,26 @@ private byte[] doBake(byte[] input) { intermediateResult = input; outputChanged = false; - // getOperations - for (Operation op : ((RecipeStepPanel) operationLine).getOperations()) { + + List operationList = ((RecipeStepPanel)operationLine).getOperations(); + for(int i = 0; i < operationList.size(); i++) { + + Operation op = operationList.get(i); if (op.isDisabled()) { continue; } + intermediateResult = op.performOperation(intermediateResult); outputChanged = true; + if (op.isBreakpoint()) { result = intermediateResult; - break out; // TODO wow.. + store.setVariable(stepVariableName, intermediateResult); + break out; } + + i += op.getOperationSkip(); + j += op.getLaneSkip(); } if (outputChanged) { From 4d91388532164fb8776d71d0cd6e8dd462ffceac Mon Sep 17 00:00:00 2001 From: TNeitzel Date: Tue, 23 Jun 2020 20:37:05 +0200 Subject: [PATCH 13/36] Add ConditionalOperation abstract class The basis for each conditional operation. Just defines the basic user interface as well as some utility methods. --- .../conditional/Conditionaloperation.java | 52 +++++++++++++++++++ 1 file changed, 52 insertions(+) create mode 100644 src/de/usd/cstchef/operations/conditional/Conditionaloperation.java diff --git a/src/de/usd/cstchef/operations/conditional/Conditionaloperation.java b/src/de/usd/cstchef/operations/conditional/Conditionaloperation.java new file mode 100644 index 0000000..576c9fd --- /dev/null +++ b/src/de/usd/cstchef/operations/conditional/Conditionaloperation.java @@ -0,0 +1,52 @@ +package de.usd.cstchef.operations.conditional; + +import javax.swing.JTextField; + +import de.usd.cstchef.operations.Operation; +import de.usd.cstchef.view.ui.VariableTextField; + +public abstract class Conditionaloperation extends Operation { + + protected VariableTextField expr; + private JTextField operationSkipField; + private JTextField laneSkipField; + + public void setOperationSkip() { + + try { + int operationSkip = Integer.valueOf(laneSkipField.getText()); + this.setOperationSkip(operationSkip); + } catch( Exception e ) { + throw new IllegalArgumentException("Input is not a number."); + } + } + + public void setLaneSkip() { + + try { + int laneSkip = Integer.valueOf(laneSkipField.getText()); + this.setLaneSkip(laneSkip); + } catch( Exception e ) { + throw new IllegalArgumentException("Input is not a number."); + } + } + + public void resetSkips() { + this.setOperationSkip(0); + this.setLaneSkip(0); + } + + @Override + public void createUI() { + this.expr = new VariableTextField(); + this.addUIElement("Expr", this.expr); + + this.operationSkipField = new JTextField("0"); + this.addUIElement("Skip Operations", this.operationSkipField); + + this.laneSkipField = new JTextField("0"); + this.addUIElement("Skip Lanes", this.laneSkipField); + + } + +} From 1c439b32bc593b48ec51a85e5089d0dbe52902b4 Mon Sep 17 00:00:00 2001 From: TNeitzel Date: Tue, 23 Jun 2020 20:38:00 +0200 Subject: [PATCH 14/36] Add NumberCompare conditional operation Just a conditional operation for number comparison. --- .../operations/conditional/NumberCompare.java | 69 +++++++++++++++++++ 1 file changed, 69 insertions(+) create mode 100644 src/de/usd/cstchef/operations/conditional/NumberCompare.java diff --git a/src/de/usd/cstchef/operations/conditional/NumberCompare.java b/src/de/usd/cstchef/operations/conditional/NumberCompare.java new file mode 100644 index 0000000..ae034b1 --- /dev/null +++ b/src/de/usd/cstchef/operations/conditional/NumberCompare.java @@ -0,0 +1,69 @@ +package de.usd.cstchef.operations.conditional; + +import javax.swing.JComboBox; + +import de.usd.cstchef.operations.Operation.OperationInfos; +import de.usd.cstchef.operations.OperationCategory; + +@OperationInfos(name = "Number Compare", category = OperationCategory.CONDITIONAL, description = "Skip if evaluates to true") +public class NumberCompare extends Conditionaloperation { + + private JComboBox operationBox; + + @Override + protected byte[] perform(byte[] input) throws Exception { + + Double inputNumber; + Double userNumber; + + try { + String tmp = new String(input); + inputNumber = Double.valueOf(tmp); + userNumber = Double.valueOf(this.expr.getText()); + } catch( Exception e ) { + throw new IllegalArgumentException("Input is not a number."); + } + + boolean condition = false; + switch ((String)this.operationBox.getSelectedItem()) { + case "equal": + if( inputNumber.compareTo(userNumber) == 0 ) + condition = true; + break; + case "greater": + if( inputNumber < userNumber ) + condition = true; + break; + case "lower": + if( inputNumber > userNumber ) + condition = true; + break; + case "greater equal": + if( inputNumber <= userNumber ) + condition = true; + break; + case "lower equal": + if( inputNumber >= userNumber ) + condition = true; + break; + } + + if( condition ) { + this.setOperationSkip(); + this.setLaneSkip(); + } else { + this.resetSkips(); + } + + return input; + } + + @Override + public void createUI() { + super.createUI(); + this.operationBox = new JComboBox<>(new String[] {"equal", "lower", "greater", "lower equal", "greater equal"}); + this.operationBox.setSelectedItem("equal"); + this.addUIElement("Lineseperator", this.operationBox); + } + +} From 3a65dee1e955d53c2069ec24c60eb6a2e5c63f89 Mon Sep 17 00:00:00 2001 From: TNeitzel Date: Tue, 23 Jun 2020 20:38:46 +0200 Subject: [PATCH 15/36] Add RegexMatch conditional operation Added a conditional operation for regex matches. --- .../operations/conditional/RegexMatch.java | 40 +++++++++++++++++++ 1 file changed, 40 insertions(+) create mode 100644 src/de/usd/cstchef/operations/conditional/RegexMatch.java diff --git a/src/de/usd/cstchef/operations/conditional/RegexMatch.java b/src/de/usd/cstchef/operations/conditional/RegexMatch.java new file mode 100644 index 0000000..975bb9d --- /dev/null +++ b/src/de/usd/cstchef/operations/conditional/RegexMatch.java @@ -0,0 +1,40 @@ +package de.usd.cstchef.operations.conditional; + +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import javax.swing.JCheckBox; + +import de.usd.cstchef.operations.Operation.OperationInfos; +import de.usd.cstchef.operations.OperationCategory; + +@OperationInfos(name = "Regex Match", category = OperationCategory.CONDITIONAL, description = "Skip if regex matches") +public class RegexMatch extends Conditionaloperation { + + private JCheckBox invert; + + @Override + protected byte[] perform(byte[] input) throws Exception { + + Pattern p = Pattern.compile(this.expr.getText()); + Matcher m = p.matcher(new String(input)); + + if( m.matches() ^ invert.isSelected() ) { + this.setOperationSkip(); + this.setLaneSkip(); + } else { + this.resetSkips(); + } + + return input; + } + + @Override + public void createUI() { + super.createUI(); + + this.invert = new JCheckBox(); + this.addUIElement("Invert Match", this.invert); + } + +} From 9b3a8e5d6827792468f151566348a0d0d83ffb52 Mon Sep 17 00:00:00 2001 From: TNeitzel Date: Tue, 23 Jun 2020 20:39:53 +0200 Subject: [PATCH 16/36] Add StringMatch and StringContains conditional op Two simple conditional operations for string matching / contains. --- .../conditional/StringContains.java | 45 +++++++++++++++ .../operations/conditional/StringMatch.java | 56 +++++++++++++++++++ 2 files changed, 101 insertions(+) create mode 100644 src/de/usd/cstchef/operations/conditional/StringContains.java create mode 100644 src/de/usd/cstchef/operations/conditional/StringMatch.java diff --git a/src/de/usd/cstchef/operations/conditional/StringContains.java b/src/de/usd/cstchef/operations/conditional/StringContains.java new file mode 100644 index 0000000..34fadff --- /dev/null +++ b/src/de/usd/cstchef/operations/conditional/StringContains.java @@ -0,0 +1,45 @@ +package de.usd.cstchef.operations.conditional; + +import javax.swing.JCheckBox; + +import burp.BurpUtils; +import burp.IBurpExtenderCallbacks; +import burp.IExtensionHelpers; +import de.usd.cstchef.operations.Operation.OperationInfos; +import de.usd.cstchef.operations.OperationCategory; + +@OperationInfos(name = "String Contains", category = OperationCategory.CONDITIONAL, description = "Skip if input contains") +public class StringContains extends Conditionaloperation { + + private JCheckBox invert; + private JCheckBox caseSensitive; + + @Override + protected byte[] perform(byte[] input) throws Exception { + + IBurpExtenderCallbacks cbs = BurpUtils.getInstance().getCallbacks(); + IExtensionHelpers helpers = cbs.getHelpers(); + int start = helpers.indexOf(input, this.expr.getBytes(), caseSensitive.isSelected(), 0, input.length); + + if( (start >= 0) ^ invert.isSelected() ) { + this.setOperationSkip(); + this.setLaneSkip(); + } else { + this.resetSkips(); + } + + return input; + } + + @Override + public void createUI() { + super.createUI(); + + this.invert = new JCheckBox(); + this.addUIElement("Invert Match", this.invert); + + this.caseSensitive = new JCheckBox(); + this.addUIElement("Case Sensitive", this.caseSensitive); + } + +} diff --git a/src/de/usd/cstchef/operations/conditional/StringMatch.java b/src/de/usd/cstchef/operations/conditional/StringMatch.java new file mode 100644 index 0000000..e448342 --- /dev/null +++ b/src/de/usd/cstchef/operations/conditional/StringMatch.java @@ -0,0 +1,56 @@ +package de.usd.cstchef.operations.conditional; + +import javax.swing.JCheckBox; + +import burp.BurpUtils; +import burp.IBurpExtenderCallbacks; +import burp.IExtensionHelpers; +import de.usd.cstchef.operations.Operation.OperationInfos; +import de.usd.cstchef.operations.OperationCategory; + +@OperationInfos(name = "String Match", category = OperationCategory.CONDITIONAL, description = "Skip if input matches") +public class StringMatch extends Conditionaloperation { + + private JCheckBox invert; + private JCheckBox caseSensitive; + + @Override + protected byte[] perform(byte[] input) throws Exception { + + byte[] search = this.expr.getBytes(); + if( search.length != input.length ) { + if( invert.isSelected() ) { + this.setOperationSkip(); + this.setLaneSkip(); + } else { + this.resetSkips(); + } + return input; + } + + IBurpExtenderCallbacks cbs = BurpUtils.getInstance().getCallbacks(); + IExtensionHelpers helpers = cbs.getHelpers(); + int start = helpers.indexOf(input, search, caseSensitive.isSelected(), 0, input.length); + + if( (start >= 0) ^ invert.isSelected() ) { + this.setOperationSkip(); + this.setLaneSkip(); + } else { + this.resetSkips(); + } + + return input; + } + + @Override + public void createUI() { + super.createUI(); + + this.invert = new JCheckBox(); + this.addUIElement("Invert Match", this.invert); + + this.caseSensitive = new JCheckBox(); + this.addUIElement("Case Sensitive", this.caseSensitive); + } + +} From 1748a35d6c5f5a9fa6cf52db9caf3dac090554fe Mon Sep 17 00:00:00 2001 From: TNeitzel Date: Tue, 23 Jun 2020 20:41:08 +0200 Subject: [PATCH 17/36] Add new operations to Utils --- src/de/usd/cstchef/Utils.java | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/de/usd/cstchef/Utils.java b/src/de/usd/cstchef/Utils.java index 92aa648..ebf63b6 100644 --- a/src/de/usd/cstchef/Utils.java +++ b/src/de/usd/cstchef/Utils.java @@ -35,6 +35,10 @@ import de.usd.cstchef.operations.compression.GUnzip; import de.usd.cstchef.operations.compression.Gzip; import de.usd.cstchef.operations.compression.Inflate; +import de.usd.cstchef.operations.conditional.NumberCompare; +import de.usd.cstchef.operations.conditional.RegexMatch; +import de.usd.cstchef.operations.conditional.StringContains; +import de.usd.cstchef.operations.conditional.StringMatch; import de.usd.cstchef.operations.dataformat.FromBase64; import de.usd.cstchef.operations.dataformat.FromHex; import de.usd.cstchef.operations.dataformat.HtmlDecode; @@ -221,10 +225,10 @@ public static Class[] getOperationsDev() { HttpPostSetter.class, HTTPRequest.class, HttpSetBody.class, HttpSetCookie.class, HttpSetUri.class, HttpUriExtractor.class, HttpXmlExtractor.class, HttpXmlSetter.class, HtmlEncode.class, HtmlDecode.class, Inflate.class, JsonExtractor.class, JsonSetter.class, Length.class, LineExtractor.class, LineSetter.class, - MD2.class, MD4.class, MD5.class, Mean.class, Median.class, Multiply.class, MultiplyList.class, Prefix.class, RandomNumber.class, + MD2.class, MD4.class, MD5.class, Mean.class, Median.class, Multiply.class, MultiplyList.class, NumberCompare.class, Prefix.class, RandomNumber.class, ReadFile.class, RegexExtractor.class, Replace.class, RIPEMD.class, RsaDecryption.class, RsaEncryption.class, RsaSignature.class, - SetIfEmpty.class, SHA1.class, SHA2.class, SHA3.class, Skein.class, SplitAndSelect.class, StaticString.class, - StoreVariable.class, Sub.class, Substring.class, Subtraction.class, Suffix.class, Sum.class, + RegexMatch.class, SetIfEmpty.class, SHA1.class, SHA2.class, SHA3.class, Skein.class, SplitAndSelect.class, StaticString.class, + StoreVariable.class, Sub.class, Substring.class, Subtraction.class, Suffix.class, Sum.class, StringContains.class, StringMatch.class, Tiger.class, ToBase64.class, ToHex.class, UnixTimestamp.class, UrlDecode.class, UrlEncode.class, Whirlpool.class, WriteFile.class, XmlFullSignature.class, XmlMultiSignature.class, Xor.class }; From 13dfad1a11ea3615fe5ecbfc4f46c1104b6c6ec2 Mon Sep 17 00:00:00 2001 From: TNeitzel Date: Tue, 23 Jun 2020 20:49:44 +0200 Subject: [PATCH 18/36] Remove variable set on Breakpoints This was introduced just a few commits before. However, I guess it is not really useful, so we removed it again. --- src/de/usd/cstchef/view/RecipePanel.java | 1 - 1 file changed, 1 deletion(-) diff --git a/src/de/usd/cstchef/view/RecipePanel.java b/src/de/usd/cstchef/view/RecipePanel.java index 3a4c20a..9493711 100644 --- a/src/de/usd/cstchef/view/RecipePanel.java +++ b/src/de/usd/cstchef/view/RecipePanel.java @@ -410,7 +410,6 @@ private byte[] doBake(byte[] input) { if (op.isBreakpoint()) { result = intermediateResult; - store.setVariable(stepVariableName, intermediateResult); break out; } From dc4c8338590ab60fa88d53a99982803b7e0ad294 Mon Sep 17 00:00:00 2001 From: TNeitzel Date: Tue, 23 Jun 2020 20:53:42 +0200 Subject: [PATCH 19/36] Fix logic error in the ConditionalOperation class The laneSkipField was also used for the operationSkip. --- .../cstchef/operations/conditional/Conditionaloperation.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/de/usd/cstchef/operations/conditional/Conditionaloperation.java b/src/de/usd/cstchef/operations/conditional/Conditionaloperation.java index 576c9fd..e421fa5 100644 --- a/src/de/usd/cstchef/operations/conditional/Conditionaloperation.java +++ b/src/de/usd/cstchef/operations/conditional/Conditionaloperation.java @@ -14,7 +14,7 @@ public abstract class Conditionaloperation extends Operation { public void setOperationSkip() { try { - int operationSkip = Integer.valueOf(laneSkipField.getText()); + int operationSkip = Integer.valueOf(operationSkipField.getText()); this.setOperationSkip(operationSkip); } catch( Exception e ) { throw new IllegalArgumentException("Input is not a number."); From c9325ea4d6e035d1be107b145824b00a312e564d Mon Sep 17 00:00:00 2001 From: TNeitzel Date: Tue, 23 Jun 2020 20:55:19 +0200 Subject: [PATCH 20/36] Fix typo in ConditionalOperation Accidently it was named Conditionaloperation instead of ConditionalOperation. --- .../{Conditionaloperation.java => ConditionalOperation.java} | 2 +- src/de/usd/cstchef/operations/conditional/NumberCompare.java | 2 +- src/de/usd/cstchef/operations/conditional/RegexMatch.java | 2 +- src/de/usd/cstchef/operations/conditional/StringContains.java | 2 +- src/de/usd/cstchef/operations/conditional/StringMatch.java | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) rename src/de/usd/cstchef/operations/conditional/{Conditionaloperation.java => ConditionalOperation.java} (95%) diff --git a/src/de/usd/cstchef/operations/conditional/Conditionaloperation.java b/src/de/usd/cstchef/operations/conditional/ConditionalOperation.java similarity index 95% rename from src/de/usd/cstchef/operations/conditional/Conditionaloperation.java rename to src/de/usd/cstchef/operations/conditional/ConditionalOperation.java index e421fa5..a928361 100644 --- a/src/de/usd/cstchef/operations/conditional/Conditionaloperation.java +++ b/src/de/usd/cstchef/operations/conditional/ConditionalOperation.java @@ -5,7 +5,7 @@ import de.usd.cstchef.operations.Operation; import de.usd.cstchef.view.ui.VariableTextField; -public abstract class Conditionaloperation extends Operation { +public abstract class ConditionalOperation extends Operation { protected VariableTextField expr; private JTextField operationSkipField; diff --git a/src/de/usd/cstchef/operations/conditional/NumberCompare.java b/src/de/usd/cstchef/operations/conditional/NumberCompare.java index ae034b1..a67840d 100644 --- a/src/de/usd/cstchef/operations/conditional/NumberCompare.java +++ b/src/de/usd/cstchef/operations/conditional/NumberCompare.java @@ -6,7 +6,7 @@ import de.usd.cstchef.operations.OperationCategory; @OperationInfos(name = "Number Compare", category = OperationCategory.CONDITIONAL, description = "Skip if evaluates to true") -public class NumberCompare extends Conditionaloperation { +public class NumberCompare extends ConditionalOperation { private JComboBox operationBox; diff --git a/src/de/usd/cstchef/operations/conditional/RegexMatch.java b/src/de/usd/cstchef/operations/conditional/RegexMatch.java index 975bb9d..74e00e6 100644 --- a/src/de/usd/cstchef/operations/conditional/RegexMatch.java +++ b/src/de/usd/cstchef/operations/conditional/RegexMatch.java @@ -9,7 +9,7 @@ import de.usd.cstchef.operations.OperationCategory; @OperationInfos(name = "Regex Match", category = OperationCategory.CONDITIONAL, description = "Skip if regex matches") -public class RegexMatch extends Conditionaloperation { +public class RegexMatch extends ConditionalOperation { private JCheckBox invert; diff --git a/src/de/usd/cstchef/operations/conditional/StringContains.java b/src/de/usd/cstchef/operations/conditional/StringContains.java index 34fadff..bfdc27e 100644 --- a/src/de/usd/cstchef/operations/conditional/StringContains.java +++ b/src/de/usd/cstchef/operations/conditional/StringContains.java @@ -9,7 +9,7 @@ import de.usd.cstchef.operations.OperationCategory; @OperationInfos(name = "String Contains", category = OperationCategory.CONDITIONAL, description = "Skip if input contains") -public class StringContains extends Conditionaloperation { +public class StringContains extends ConditionalOperation { private JCheckBox invert; private JCheckBox caseSensitive; diff --git a/src/de/usd/cstchef/operations/conditional/StringMatch.java b/src/de/usd/cstchef/operations/conditional/StringMatch.java index e448342..cbea4ff 100644 --- a/src/de/usd/cstchef/operations/conditional/StringMatch.java +++ b/src/de/usd/cstchef/operations/conditional/StringMatch.java @@ -9,7 +9,7 @@ import de.usd.cstchef.operations.OperationCategory; @OperationInfos(name = "String Match", category = OperationCategory.CONDITIONAL, description = "Skip if input matches") -public class StringMatch extends Conditionaloperation { +public class StringMatch extends ConditionalOperation { private JCheckBox invert; private JCheckBox caseSensitive; From 0de3607ab6745c2a91739ff0a4738448f41acc5b Mon Sep 17 00:00:00 2001 From: TNeitzel Date: Tue, 23 Jun 2020 21:53:17 +0200 Subject: [PATCH 21/36] Add find option to RegexMatch RegexMatch did nonly work "match-based" so far. Now added a switch to allow "find-based" matches. --- .../cstchef/operations/conditional/RegexMatch.java | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/src/de/usd/cstchef/operations/conditional/RegexMatch.java b/src/de/usd/cstchef/operations/conditional/RegexMatch.java index 74e00e6..26b185a 100644 --- a/src/de/usd/cstchef/operations/conditional/RegexMatch.java +++ b/src/de/usd/cstchef/operations/conditional/RegexMatch.java @@ -12,6 +12,7 @@ public class RegexMatch extends ConditionalOperation { private JCheckBox invert; + private JCheckBox find; @Override protected byte[] perform(byte[] input) throws Exception { @@ -19,7 +20,14 @@ protected byte[] perform(byte[] input) throws Exception { Pattern p = Pattern.compile(this.expr.getText()); Matcher m = p.matcher(new String(input)); - if( m.matches() ^ invert.isSelected() ) { + boolean condition = false; + if( find.isSelected() ) { + condition = m.find(); + } else { + condition = m.matches(); + } + + if( condition ^ invert.isSelected() ) { this.setOperationSkip(); this.setLaneSkip(); } else { @@ -35,6 +43,9 @@ public void createUI() { this.invert = new JCheckBox(); this.addUIElement("Invert Match", this.invert); + + this.find = new JCheckBox(); + this.addUIElement("Find anywhere", this.find); } } From 15fc57a3fbdca63cf304260b5c7f727a0e78c058 Mon Sep 17 00:00:00 2001 From: TNeitzel Date: Tue, 23 Jun 2020 21:53:59 +0200 Subject: [PATCH 22/36] Add "not equal" filter to NumberCompare --- .../usd/cstchef/operations/conditional/NumberCompare.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/de/usd/cstchef/operations/conditional/NumberCompare.java b/src/de/usd/cstchef/operations/conditional/NumberCompare.java index a67840d..6f19a6d 100644 --- a/src/de/usd/cstchef/operations/conditional/NumberCompare.java +++ b/src/de/usd/cstchef/operations/conditional/NumberCompare.java @@ -30,6 +30,10 @@ protected byte[] perform(byte[] input) throws Exception { if( inputNumber.compareTo(userNumber) == 0 ) condition = true; break; + case "not equal": + if( inputNumber.compareTo(userNumber) != 0 ) + condition = true; + break; case "greater": if( inputNumber < userNumber ) condition = true; @@ -61,7 +65,7 @@ protected byte[] perform(byte[] input) throws Exception { @Override public void createUI() { super.createUI(); - this.operationBox = new JComboBox<>(new String[] {"equal", "lower", "greater", "lower equal", "greater equal"}); + this.operationBox = new JComboBox<>(new String[] {"equal", "not equal", "lower", "greater", "lower equal", "greater equal"}); this.operationBox.setSelectedItem("equal"); this.addUIElement("Lineseperator", this.operationBox); } From 719c219845cef14a4e25777328848425d9c373e6 Mon Sep 17 00:00:00 2001 From: TNeitzel Date: Tue, 23 Jun 2020 21:58:20 +0200 Subject: [PATCH 23/36] Rename Conditional category to Conditionals --- src/de/usd/cstchef/operations/OperationCategory.java | 2 +- src/de/usd/cstchef/operations/conditional/NumberCompare.java | 2 +- src/de/usd/cstchef/operations/conditional/RegexMatch.java | 2 +- src/de/usd/cstchef/operations/conditional/StringContains.java | 2 +- src/de/usd/cstchef/operations/conditional/StringMatch.java | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/de/usd/cstchef/operations/OperationCategory.java b/src/de/usd/cstchef/operations/OperationCategory.java index b3f3694..10abe79 100644 --- a/src/de/usd/cstchef/operations/OperationCategory.java +++ b/src/de/usd/cstchef/operations/OperationCategory.java @@ -4,7 +4,7 @@ public enum OperationCategory { ARITHMETIC("Arithmetic"), BYTEOPERATION("Byte Operations"), COMPRESSION("Compression"), - CONDITIONAL("Conditional"), + CONDITIONALS("Conditionals"), DATAFORMAT("Data format"), DATES("Date / Time"), ENCRYPTION("Encryption / Encoding"), diff --git a/src/de/usd/cstchef/operations/conditional/NumberCompare.java b/src/de/usd/cstchef/operations/conditional/NumberCompare.java index 6f19a6d..f336d85 100644 --- a/src/de/usd/cstchef/operations/conditional/NumberCompare.java +++ b/src/de/usd/cstchef/operations/conditional/NumberCompare.java @@ -5,7 +5,7 @@ import de.usd.cstchef.operations.Operation.OperationInfos; import de.usd.cstchef.operations.OperationCategory; -@OperationInfos(name = "Number Compare", category = OperationCategory.CONDITIONAL, description = "Skip if evaluates to true") +@OperationInfos(name = "Number Compare", category = OperationCategory.CONDITIONALS, description = "Skip if evaluates to true") public class NumberCompare extends ConditionalOperation { private JComboBox operationBox; diff --git a/src/de/usd/cstchef/operations/conditional/RegexMatch.java b/src/de/usd/cstchef/operations/conditional/RegexMatch.java index 26b185a..2f156af 100644 --- a/src/de/usd/cstchef/operations/conditional/RegexMatch.java +++ b/src/de/usd/cstchef/operations/conditional/RegexMatch.java @@ -8,7 +8,7 @@ import de.usd.cstchef.operations.Operation.OperationInfos; import de.usd.cstchef.operations.OperationCategory; -@OperationInfos(name = "Regex Match", category = OperationCategory.CONDITIONAL, description = "Skip if regex matches") +@OperationInfos(name = "Regex Match", category = OperationCategory.CONDITIONALS, description = "Skip if regex matches") public class RegexMatch extends ConditionalOperation { private JCheckBox invert; diff --git a/src/de/usd/cstchef/operations/conditional/StringContains.java b/src/de/usd/cstchef/operations/conditional/StringContains.java index bfdc27e..d29ee8a 100644 --- a/src/de/usd/cstchef/operations/conditional/StringContains.java +++ b/src/de/usd/cstchef/operations/conditional/StringContains.java @@ -8,7 +8,7 @@ import de.usd.cstchef.operations.Operation.OperationInfos; import de.usd.cstchef.operations.OperationCategory; -@OperationInfos(name = "String Contains", category = OperationCategory.CONDITIONAL, description = "Skip if input contains") +@OperationInfos(name = "String Contains", category = OperationCategory.CONDITIONALS, description = "Skip if input contains") public class StringContains extends ConditionalOperation { private JCheckBox invert; diff --git a/src/de/usd/cstchef/operations/conditional/StringMatch.java b/src/de/usd/cstchef/operations/conditional/StringMatch.java index cbea4ff..56cfbf0 100644 --- a/src/de/usd/cstchef/operations/conditional/StringMatch.java +++ b/src/de/usd/cstchef/operations/conditional/StringMatch.java @@ -8,7 +8,7 @@ import de.usd.cstchef.operations.Operation.OperationInfos; import de.usd.cstchef.operations.OperationCategory; -@OperationInfos(name = "String Match", category = OperationCategory.CONDITIONAL, description = "Skip if input matches") +@OperationInfos(name = "String Match", category = OperationCategory.CONDITIONALS, description = "Skip if input matches") public class StringMatch extends ConditionalOperation { private JCheckBox invert; From d64e103bc6fb9d5892169211981c2f35e92d9a3e Mon Sep 17 00:00:00 2001 From: TNeitzel Date: Sat, 27 Jun 2020 08:24:23 +0200 Subject: [PATCH 24/36] Update Jackson Databind on dev --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 90a78c3..2cf2a6e 100644 --- a/pom.xml +++ b/pom.xml @@ -77,7 +77,7 @@ com.fasterxml.jackson.core jackson-databind - 2.9.10.4 + 2.10.0.pr1 org.apache.commons From 9d261215c1ba4f34bebb8927560c6fba75808ff5 Mon Sep 17 00:00:00 2001 From: TNeitzel Date: Sat, 27 Jun 2020 08:33:17 +0200 Subject: [PATCH 25/36] Create dependabot.yml dependabot currenly pushes all changes directly on master. This is not ideal, since we want to test if the dependency update brakes out current development build. Therefore, a config was created and the ``target_branch`` was set to the ``develop`` branch. --- .github/dependabot.yml | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 .github/dependabot.yml diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 0000000..19c84b3 --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,7 @@ +version: 2 +updates: + - package-ecosystem: "java:maven" + directory: "/" + target_branch: "develop" + schedule: + interval: "daily" From 0bfb12853d2a37ad33d95c3c5b45356423a741e6 Mon Sep 17 00:00:00 2001 From: TNeitzel Date: Sat, 27 Jun 2020 08:44:54 +0200 Subject: [PATCH 26/36] Add maven workflow --- .github/workflows/maven.yml | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) create mode 100644 .github/workflows/maven.yml diff --git a/.github/workflows/maven.yml b/.github/workflows/maven.yml new file mode 100644 index 0000000..e516ad4 --- /dev/null +++ b/.github/workflows/maven.yml @@ -0,0 +1,16 @@ +name: Java CI with Maven +on: [push] + +jobs: + build: + + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v2 + - name: Set up JDK 1.8 + uses: actions/setup-java@v1 + with: + java-version: 1.8 + - name: Build with Maven + run: mvn -B package --file pom.xml From 9d4069aa2c15e932e5fba15ded0059bc6786b573 Mon Sep 17 00:00:00 2001 From: TNeitzel Date: Sat, 27 Jun 2020 19:59:21 +0200 Subject: [PATCH 27/36] Add workflow badges --- .github/workflows/maven.yml | 2 +- README.md | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/.github/workflows/maven.yml b/.github/workflows/maven.yml index e516ad4..98eeebd 100644 --- a/.github/workflows/maven.yml +++ b/.github/workflows/maven.yml @@ -1,4 +1,4 @@ -name: Java CI with Maven +name: maven on: [push] jobs: diff --git a/README.md b/README.md index 6236c0e..119a007 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,4 @@ + *Copyright 2017-2020 usd AG* Licensed under the *GNU General Public License, Version 3.0* (the "License"). You may not use this tool except in compliance with the License. @@ -5,6 +6,9 @@ You may obtain a copy of the License at https://www.gnu.org/licenses/gpl-3.0.htm ![CSTC](media/CSTC_White_Smaller.png) +![](https://github.com/usdAG/cstc/workflows/maven/badge.svg?branch=master) +![](https://github.com/usdAG/cstc/workflows/maven/badge.svg?branch=develop) + # Cyber Security Transformation Chef *The Cyber Security Transformation Chef* (*CSTC*) is a *Burp Suite* extension. It is build for security experts to From 694c12fc63b8108ba8c887900db6c9b91fc57851 Mon Sep 17 00:00:00 2001 From: TNeitzel Date: Sat, 27 Jun 2020 20:13:42 +0200 Subject: [PATCH 28/36] Update workflows --- .github/workflows/develop.yml | 30 ++++++++++++++++++++++++++++++ .github/workflows/master.yml | 30 ++++++++++++++++++++++++++++++ .github/workflows/maven.yml | 16 ---------------- README.md | 4 ++-- 4 files changed, 62 insertions(+), 18 deletions(-) create mode 100644 .github/workflows/develop.yml create mode 100644 .github/workflows/master.yml delete mode 100644 .github/workflows/maven.yml diff --git a/.github/workflows/develop.yml b/.github/workflows/develop.yml new file mode 100644 index 0000000..0a9e3cd --- /dev/null +++ b/.github/workflows/develop.yml @@ -0,0 +1,30 @@ +name: develop maven CI + +on: + push: + branches: + - develop + pull_request: + branches: + - develop + +jobs: + build: + + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v2 + - name: Set up JDK 1.8 + uses: actions/setup-java@v1 + with: + java-version: 1.8 + - name: Cache local Maven repository + uses: actions/cache@v2 + with: + path: ~/.m2/repository + key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }} + restore-keys: | + ${{ runner.os }}-maven- + - name: Build with Maven + run: mvn -B package --file pom.xml diff --git a/.github/workflows/master.yml b/.github/workflows/master.yml new file mode 100644 index 0000000..7552e72 --- /dev/null +++ b/.github/workflows/master.yml @@ -0,0 +1,30 @@ +name: master maven CI + +on: + push: + branches: + - master + pull_request: + branches: + - master + +jobs: + build: + + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v2 + - name: Set up JDK 1.8 + uses: actions/setup-java@v1 + with: + java-version: 1.8 + - name: Cache local Maven repository + uses: actions/cache@v2 + with: + path: ~/.m2/repository + key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }} + restore-keys: | + ${{ runner.os }}-maven- + - name: Build with Maven + run: mvn -B package --file pom.xml diff --git a/.github/workflows/maven.yml b/.github/workflows/maven.yml deleted file mode 100644 index 98eeebd..0000000 --- a/.github/workflows/maven.yml +++ /dev/null @@ -1,16 +0,0 @@ -name: maven -on: [push] - -jobs: - build: - - runs-on: ubuntu-latest - - steps: - - uses: actions/checkout@v2 - - name: Set up JDK 1.8 - uses: actions/setup-java@v1 - with: - java-version: 1.8 - - name: Build with Maven - run: mvn -B package --file pom.xml diff --git a/README.md b/README.md index 119a007..979042a 100644 --- a/README.md +++ b/README.md @@ -6,8 +6,8 @@ You may obtain a copy of the License at https://www.gnu.org/licenses/gpl-3.0.htm ![CSTC](media/CSTC_White_Smaller.png) -![](https://github.com/usdAG/cstc/workflows/maven/badge.svg?branch=master) -![](https://github.com/usdAG/cstc/workflows/maven/badge.svg?branch=develop) +![](https://github.com/usdAG/cstc/workflows/master%20maven%20CI/badge.svg?branch=master) +![](https://github.com/usdAG/cstc/workflows/develop%20maven%20CI/badge.svg?branch=develop) # Cyber Security Transformation Chef From 4d0bc67c22cf4d22d73c1b358cdfc231be0c53b3 Mon Sep 17 00:00:00 2001 From: TNeitzel Date: Sat, 27 Jun 2020 20:27:35 +0200 Subject: [PATCH 29/36] Update jackson dependencies to newest version So far we left the jackson dependency on the one that was present on the original release. However, seems that the newsest one works fine as well. During initial testing, no error was encountered. --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 2cf2a6e..5ec6242 100644 --- a/pom.xml +++ b/pom.xml @@ -71,13 +71,13 @@ com.fasterxml.jackson.core jackson-core - 2.9.9 + 2.11.1 com.fasterxml.jackson.core jackson-databind - 2.10.0.pr1 + 2.11.1 org.apache.commons From 5b0d72feef9fa309cf57f48caa612f03cdfb8126 Mon Sep 17 00:00:00 2001 From: TNeitzel Date: Sat, 27 Jun 2020 20:47:51 +0200 Subject: [PATCH 30/36] Add NoOperation operation Just a simple operation that does absolutly nothing. This is useful for the input lanes, where you probably only want to extract some value for a variable on one lane and to restore the actual request on another. --- src/de/usd/cstchef/Utils.java | 31 ++++++++++++------- .../cstchef/operations/utils/NoOperation.java | 15 +++++++++ 2 files changed, 34 insertions(+), 12 deletions(-) create mode 100644 src/de/usd/cstchef/operations/utils/NoOperation.java diff --git a/src/de/usd/cstchef/Utils.java b/src/de/usd/cstchef/Utils.java index ebf63b6..065cbd5 100644 --- a/src/de/usd/cstchef/Utils.java +++ b/src/de/usd/cstchef/Utils.java @@ -105,6 +105,7 @@ import de.usd.cstchef.operations.string.Substring; import de.usd.cstchef.operations.string.Suffix; import de.usd.cstchef.operations.utils.GetVariable; +import de.usd.cstchef.operations.utils.NoOperation; import de.usd.cstchef.operations.utils.RandomNumber; import de.usd.cstchef.operations.utils.SetIfEmpty; import de.usd.cstchef.operations.utils.StoreVariable; @@ -220,18 +221,24 @@ public static Class[] getOperationsDev() { Blake.class, DateTime.class, Deflate.class, DesDecryption.class, DesEncryption.class, Divide.class, DivideList.class, DSTU7564.class, FromBase64.class, FromHex.class, GetVariable.class, Gost.class, GUnzip.class, Gzip.class, Hmac.class, - HttpBodyExtractor.class, HttpCookieExtractor.class, HttpGetExtractor.class, HttpGetSetter.class, HttpHeaderExtractor.class, - HttpHeaderSetter.class, HttpJsonExtractor.class, HttpJsonSetter.class, HttpMethodExtractor.class, HttpPostExtractor.class, - HttpPostSetter.class, HTTPRequest.class, HttpSetBody.class, HttpSetCookie.class, HttpSetUri.class, - HttpUriExtractor.class, HttpXmlExtractor.class, HttpXmlSetter.class, HtmlEncode.class, HtmlDecode.class, - Inflate.class, JsonExtractor.class, JsonSetter.class, Length.class, LineExtractor.class, LineSetter.class, - MD2.class, MD4.class, MD5.class, Mean.class, Median.class, Multiply.class, MultiplyList.class, NumberCompare.class, Prefix.class, RandomNumber.class, - ReadFile.class, RegexExtractor.class, Replace.class, RIPEMD.class, RsaDecryption.class, RsaEncryption.class, RsaSignature.class, - RegexMatch.class, SetIfEmpty.class, SHA1.class, SHA2.class, SHA3.class, Skein.class, SplitAndSelect.class, StaticString.class, - StoreVariable.class, Sub.class, Substring.class, Subtraction.class, Suffix.class, Sum.class, StringContains.class, StringMatch.class, - Tiger.class, ToBase64.class, ToHex.class, UnixTimestamp.class, UrlDecode.class, - UrlEncode.class, Whirlpool.class, WriteFile.class, XmlFullSignature.class, XmlMultiSignature.class, - Xor.class }; + HttpBodyExtractor.class, HttpCookieExtractor.class, HttpGetExtractor.class, + HttpGetSetter.class, HttpHeaderExtractor.class, HttpHeaderSetter.class, + HttpJsonExtractor.class, HttpJsonSetter.class, HttpMethodExtractor.class, + HttpPostExtractor.class, HttpPostSetter.class, HTTPRequest.class, HttpSetBody.class, + HttpSetCookie.class, HttpSetUri.class, HttpUriExtractor.class, HttpXmlExtractor.class, + HttpXmlSetter.class, HtmlEncode.class, HtmlDecode.class, Inflate.class, + JsonExtractor.class, JsonSetter.class, Length.class, LineExtractor.class, + LineSetter.class, MD2.class, MD4.class, MD5.class, Mean.class, Median.class, + Multiply.class, MultiplyList.class, NoOperation.class, NumberCompare.class, Prefix.class, + RandomNumber.class, ReadFile.class, RegexExtractor.class, Replace.class, RIPEMD.class, + RsaDecryption.class, RsaEncryption.class, RsaSignature.class, RegexMatch.class, + SetIfEmpty.class, SHA1.class, SHA2.class, SHA3.class, Skein.class, SplitAndSelect.class, + StaticString.class, StoreVariable.class, Sub.class, Substring.class, Subtraction.class, + Suffix.class, Sum.class, StringContains.class, StringMatch.class, Tiger.class, + ToBase64.class, ToHex.class, UnixTimestamp.class, UrlDecode.class, UrlEncode.class, + Whirlpool.class, WriteFile.class, XmlFullSignature.class, XmlMultiSignature.class, + Xor.class + }; } public static Class[] getOperations() { diff --git a/src/de/usd/cstchef/operations/utils/NoOperation.java b/src/de/usd/cstchef/operations/utils/NoOperation.java new file mode 100644 index 0000000..bfc8e27 --- /dev/null +++ b/src/de/usd/cstchef/operations/utils/NoOperation.java @@ -0,0 +1,15 @@ +package de.usd.cstchef.operations.utils; + +import de.usd.cstchef.operations.Operation; +import de.usd.cstchef.operations.Operation.OperationInfos; +import de.usd.cstchef.operations.OperationCategory; + +@OperationInfos(name = "No Operation", category = OperationCategory.UTILS, description = "Does nothing :)") +public class NoOperation extends Operation { + + @Override + protected byte[] perform(byte[] input) throws Exception { + return input; + } + +} From b689eb6db43b6be89eb418864f9c18b88f4cf5ef Mon Sep 17 00:00:00 2001 From: TNeitzel Date: Sun, 28 Jun 2020 02:16:03 +0200 Subject: [PATCH 31/36] Update CHNAGELOG.md --- CHANGELOG.md | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index a330fed..178e35d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,30 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [1.X.0] - 2020-XX-XX + +### Added + +* Add additional operations: + * *HTMLEncode* (Encode HTML special characters) + * *HTMLDecode* (Decode HTML special characters) + * *RsaEncrypt* (Encrypt data by using a public key) + * *RsaDecrypt* (Decrypt data using a private key) + * *RsaSignature* (Create an RSA signature) +* Add *conditionals* operation class: + * *StringContains* (Skip if input contains a string) + * *StringMatch* (Skip if input matches a string) + * *RegexMatch* (Skip if input matches the specified regex) + * *NumberCompare* (Skip if comparison is true) +* Add *Maven CI* for the master and development branch +* Add *dependabot* config to prevent pushes to master + +### Changed + +* Byte operations now also allow multiple variables in one input field +* *jackson-core* and *jackson-databind* updated to current version + + ## [1.1.1] - 2020-05-20 ### Changed From 1514add5f6fc710466d9a19cecfa8637fedd734a Mon Sep 17 00:00:00 2001 From: TNeitzel Date: Sun, 28 Jun 2020 02:17:10 +0200 Subject: [PATCH 32/36] Update CHANGELOG.md --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 178e35d..e6a8b54 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,6 +16,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 * *RsaEncrypt* (Encrypt data by using a public key) * *RsaDecrypt* (Decrypt data using a private key) * *RsaSignature* (Create an RSA signature) + * *NoOperation* (Does nothing :D) * Add *conditionals* operation class: * *StringContains* (Skip if input contains a string) * *StringMatch* (Skip if input matches a string) From ecc29110fcdcad7bed796bd6907bdce7b68594b0 Mon Sep 17 00:00:00 2001 From: TNeitzel Date: Sun, 28 Jun 2020 14:40:24 +0200 Subject: [PATCH 33/36] Change example server port to 8000 The default port of the example server script was 8080. Did not remember why this was initially chosen like this, because Burp wants to claim the same port. It was now changed to 8000. --- example/example-server.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/example/example-server.py b/example/example-server.py index b9fe54a..8fddf5a 100644 --- a/example/example-server.py +++ b/example/example-server.py @@ -40,7 +40,7 @@ def do_POST(self): self.wfile.write(b"

Processing Input: '" + result + b"'...

") -def run(server_class=HTTPServer, handler_class=S, port=8080): +def run(server_class=HTTPServer, handler_class=S, port=8000): logging.basicConfig(level=logging.INFO) server_address = ('', port) httpd = server_class(server_address, handler_class) From 2255a33bd3db9db250fe4ed3010173fca12189e5 Mon Sep 17 00:00:00 2001 From: TNeitzel Date: Sun, 28 Jun 2020 14:57:11 +0200 Subject: [PATCH 34/36] Set variables on breakpoints If an operation was set as a breakpoint, cstc did not store a variable for the corresponding lane. This was now changed in order to make conditionals more useful. --- src/de/usd/cstchef/view/RecipePanel.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/de/usd/cstchef/view/RecipePanel.java b/src/de/usd/cstchef/view/RecipePanel.java index 9493711..3350676 100644 --- a/src/de/usd/cstchef/view/RecipePanel.java +++ b/src/de/usd/cstchef/view/RecipePanel.java @@ -410,6 +410,7 @@ private byte[] doBake(byte[] input) { if (op.isBreakpoint()) { result = intermediateResult; + store.setVariable(stepVariableName, intermediateResult); break out; } From 7bf10b907902a0df352e424351fbdf8293b89a5e Mon Sep 17 00:00:00 2001 From: TNeitzel Date: Sun, 28 Jun 2020 14:58:45 +0200 Subject: [PATCH 35/36] Update CHANGELOG.md --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index e6a8b54..f3ca5f2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -29,6 +29,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 * Byte operations now also allow multiple variables in one input field * *jackson-core* and *jackson-databind* updated to current version +* Breakpoint operations now assign variables ## [1.1.1] - 2020-05-20 From e5d2c96605d16048a486eb61b1d0e257442ca49b Mon Sep 17 00:00:00 2001 From: TNeitzel Date: Sun, 28 Jun 2020 15:08:35 +0200 Subject: [PATCH 36/36] Bump version number --- CHANGELOG.md | 2 +- pom.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f3ca5f2..450017f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,7 +6,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). -## [1.X.0] - 2020-XX-XX +## [1.2.0] - 2020-06-28 ### Added diff --git a/pom.xml b/pom.xml index 5ec6242..1eba8d1 100644 --- a/pom.xml +++ b/pom.xml @@ -2,7 +2,7 @@ 4.0.0 de.usd.CSTC CSTC - 1.1.1 + 1.2.0 CSTC CSTC