├── .gitignore ├── Bradamsa ├── .gitignore ├── burp │ └── BurpExtender.java └── com │ └── doyensec │ ├── BradamsaPanel.java │ ├── BradamsaTab.java │ ├── BurpUtils.java │ └── RadamsaPayloadGenerator.java ├── BurpExtensionTemplate ├── .gitignore ├── Eclipse │ ├── .classpath │ ├── .project │ ├── BurpExtensionTemplate_Configuration.launch │ └── src │ │ └── burp │ │ └── BurpExtender.java ├── IDEA │ ├── .idea │ │ ├── misc.xml │ │ ├── modules.xml │ │ └── workspace.xml │ ├── BurpExtensionTemplate.iml │ └── src │ │ └── burp │ │ └── BurpExtender.java └── NetBeans │ ├── build.xml │ ├── manifest.mf │ ├── nbproject │ ├── build-impl.xml │ ├── configs │ │ └── Burp_Extension.properties │ ├── genfiles.properties │ ├── project.properties │ └── project.xml │ └── src │ └── burp │ └── BurpExtender.java ├── DetectELJ ├── .gitignore ├── Java │ ├── Final │ │ └── burp │ │ │ └── BurpExtender.java │ ├── WIP1 │ │ └── burp │ │ │ └── BurpExtenderWIP1.java │ └── WIP2 │ │ └── burp │ │ └── BurpExtenderWIP2.java ├── Python │ ├── Final │ │ └── BurpExtender.py │ ├── WIP1 │ │ └── BurpExtenderWIP1.py │ └── WIP2 │ │ └── BurpExtenderWIP2.py └── Ruby │ ├── Final │ └── BurpExtender.rb │ ├── WIP1 │ └── BurpExtenderWIP1.rb │ └── WIP2 │ └── BurpExtenderWIP2.rb ├── DetectSRI ├── .gitignore ├── Java │ ├── Final │ │ └── burp │ │ │ └── BurpExtender.java │ ├── WIP1 │ │ └── burp │ │ │ └── BurpExtenderWIP1.java │ └── WIP2 │ │ └── burp │ │ └── BurpExtenderWIP2.java ├── Python │ ├── Final │ │ └── BurpExtender.py │ ├── WIP1 │ │ └── BurpExtenderWIP1.py │ └── WIP2 │ │ └── BurpExtenderWIP2.py └── Ruby │ ├── Final │ └── BurpExtender.rb │ ├── WIP1 │ └── BurpExtenderWIP1.rb │ └── WIP2 │ └── BurpExtenderWIP2.rb ├── Doyensec_DevelopingBurpSuiteExtensionsTraining.pdf ├── HelloBurp ├── .gitignore ├── Java │ ├── Final │ │ └── burp │ │ │ └── BurpExtender.java │ ├── WIP1 │ │ └── burp │ │ │ └── BurpExtenderWIP1.java │ └── WIP2 │ │ └── burp │ │ └── BurpExtenderWIP2.java ├── Python │ ├── Final │ │ └── BurpExtender.py │ ├── WIP1 │ │ └── BurpExtenderWIP1.py │ └── WIP2 │ │ └── BurpExtenderWIP2.py └── Ruby │ ├── Final │ └── BurpExtender.rb │ ├── WIP1 │ └── BurpExtenderWIP1.rb │ └── WIP2 │ └── BurpExtenderWIP2.rb ├── LICENSE.md ├── README.md ├── ReplayAndDiff ├── .gitignore ├── Java │ ├── Final │ │ └── BurpExtender.java │ ├── WIP1 │ │ └── BurpExtenderWIP1.java │ └── WIP2 │ │ └── BurpExtenderWIP2.java ├── Python │ ├── Final │ │ └── BurpExtender.py │ ├── WIP1 │ │ └── BurpExtenderWIP1.py │ └── WIP2 │ │ └── BurpExtenderWIP2.py └── Ruby │ ├── Final │ └── BurpExtender.rb │ ├── WIP1 │ └── BurpExtenderWIP1.rb │ └── WIP2 │ └── BurpExtenderWIP2.rb └── SiteLogger ├── .gitignore ├── Java ├── Final │ ├── burp │ │ └── BurpExtender.java │ └── com │ │ └── doyensec │ │ └── sitelogger │ │ ├── SiteLoggerPanel.form │ │ ├── SiteLoggerPanel.java │ │ └── SiteLoggerTab.java ├── WIP1 │ ├── burp │ │ └── BurpExtenderWIP1.java │ └── com │ │ └── doyensec │ │ └── sitelogger │ │ ├── SiteLoggerPanelWIP1.java │ │ └── SiteLoggerTabWIP1.java └── WIP2 │ ├── burp │ └── BurpExtenderWIP2.java │ └── com │ └── doyensec │ └── sitelogger │ ├── SiteLoggerPanelWIP2.java │ └── SiteLoggerTabWIP2.java ├── Python ├── Final │ └── BurpExtender.py ├── WIP1 │ └── BurpExtenderWIP1.py └── WIP2 │ └── BurpExtenderWIP2.py └── Ruby ├── Final └── BurpExtender.rb ├── WIP1 └── BurpExtenderWIP1.rb └── WIP2 └── BurpExtenderWIP2.rb /.gitignore: -------------------------------------------------------------------------------- 1 | # Package Files # 2 | *.jar 3 | *.war 4 | *.ear 5 | 6 | # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml 7 | hs_err_pid* 8 | 9 | #ant specific 10 | dist/ 11 | build/ 12 | build.xml 13 | 14 | #netbeans specific 15 | core 16 | nbproject/* 17 | libs/* 18 | lib/* 19 | manifest.mf 20 | .jacocoverage/ 21 | coverage/ 22 | src/ 23 | 24 | #java specific 25 | *.class 26 | 27 | #general swap/backup files 28 | *.so 29 | *.log 30 | *.out 31 | *~ 32 | *.swp 33 | *.DS_Store 34 | *.lock 35 | 36 | #idea specific 37 | .classpath 38 | .project 39 | .settings 40 | .idea 41 | .metadata 42 | *.iml 43 | *.ipr 44 | **/*~ 45 | /target/ 46 | -------------------------------------------------------------------------------- /Bradamsa/.gitignore: -------------------------------------------------------------------------------- 1 | # Package Files # 2 | *.jar 3 | *.war 4 | *.ear 5 | 6 | # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml 7 | hs_err_pid* 8 | 9 | #ant specific 10 | dist/ 11 | build/ 12 | build.xml 13 | 14 | #netbeans specific 15 | core 16 | nbproject/* 17 | libs/* 18 | lib/* 19 | manifest.mf 20 | .jacocoverage/ 21 | coverage/ 22 | src/ 23 | 24 | #java specific 25 | *.class 26 | 27 | #general swap/backup files 28 | *.so 29 | *.log 30 | *.out 31 | *~ 32 | *.swp 33 | *.DS_Store 34 | *.lock 35 | 36 | #idea specific 37 | .classpath 38 | .project 39 | .settings 40 | .idea 41 | .metadata 42 | *.iml 43 | *.ipr 44 | **/*~ 45 | /target/ 46 | -------------------------------------------------------------------------------- /Bradamsa/burp/BurpExtender.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Bradamsa - Burp Intruder payloads generator (simplified code - does not work!) 3 | * 4 | * Copyright (c) 2017 Doyensec LLC. Made with love by Luca Carettoni. 5 | */ 6 | package burp; 7 | 8 | import com.doyensec.BradamsaTab; 9 | import com.doyensec.RadamsaPayloadGenerator; 10 | 11 | /* 12 | * Bradamsa extension for Burp Suite 13 | * 14 | * Burp Suite is an integrated platform for performing web security testing (see http://www.portswigger.net/burp/) 15 | * Radamnsa is a test case generator for robustness testing (see https://code.google.com/p/ouspg/wiki/Radamsa) 16 | * Mix (B)urp Suite + (Radamsa) and you get crashes! 17 | */ 18 | public class BurpExtender implements IBurpExtender { 19 | 20 | private final String version = "v0.2"; 21 | private IBurpExtenderCallbacks callbacks; 22 | private OS currentOS; 23 | private BradamsaTab btab; 24 | 25 | public enum OS { 26 | 27 | LINUX, MAC, WIN, UNDEF; 28 | } 29 | 30 | @Override 31 | public void registerExtenderCallbacks(IBurpExtenderCallbacks callbacks) { 32 | 33 | this.callbacks = callbacks; 34 | callbacks.setExtensionName("Bradamsa " + version); 35 | 36 | //Get current platform 37 | String currentOSName = System.getProperty("os.name"); 38 | if (currentOSName.toLowerCase().contains("linux")) { 39 | currentOS = OS.LINUX; 40 | } else if (currentOSName.toLowerCase().contains("mac")) { 41 | currentOS = OS.MAC; 42 | } else if (currentOSName.toLowerCase().contains("window")) { 43 | currentOS = OS.WIN; 44 | } else { 45 | currentOS = OS.UNDEF; 46 | } 47 | 48 | //Register Bradamsa as IntruderPayloadGenerator 49 | btab = new BradamsaTab(callbacks, currentOS); 50 | callbacks.registerIntruderPayloadGeneratorFactory((IIntruderPayloadGeneratorFactory) new RadamsaPayloadGenerator(this)); 51 | callbacks.issueAlert("Ready to go"); 52 | } 53 | 54 | public OS getPlatform() { 55 | 56 | return currentOS; 57 | } 58 | 59 | public IBurpExtenderCallbacks getCallbacks() { 60 | 61 | return callbacks; 62 | } 63 | 64 | public BradamsaTab getTab() { 65 | 66 | return btab; 67 | } 68 | 69 | } -------------------------------------------------------------------------------- /Bradamsa/com/doyensec/BradamsaPanel.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Bradamsa - Burp Intruder payloads generator (simplified code - does not work!) 3 | * 4 | * Copyright (c) 2017 Doyensec LLC. Made with love by Luca Carettoni. 5 | */ 6 | package com.doyensec; 7 | 8 | import burp.BurpExtender; 9 | import burp.BurpExtender.OS; 10 | import burp.IBurpExtenderCallbacks; 11 | import java.io.File; 12 | import java.io.IOException; 13 | import java.io.PrintWriter; 14 | import java.nio.file.Files; 15 | import java.nio.file.Path; 16 | import java.util.regex.Pattern; 17 | import javax.swing.JOptionPane; 18 | 19 | public final class BradamsaPanel extends javax.swing.JPanel { 20 | 21 | private final IBurpExtenderCallbacks callbacks; 22 | private final OS os; 23 | 24 | public BradamsaPanel(IBurpExtenderCallbacks callbacks, OS os) { 25 | 26 | initComponents(); 27 | this.callbacks = callbacks; 28 | this.os = os; 29 | 30 | //Initialize Radamsa options 31 | resetSettings(); 32 | 33 | JOptionPane.showMessageDialog(null, "Bradamsa allows to generate Intruder payloads using Radamsa. " 34 | + "
The current version supports sniper attack type only!", ":: Welcome to Bradamsa ::", JOptionPane.INFORMATION_MESSAGE); 35 | } 36 | 37 | // Java Swing UI code HERE 38 | 39 | /* 40 | * Validate and return Radamsa command line 41 | * @return the full command string or an empty string (in case of invalid input) 42 | */ 43 | protected String getRadamsaCmdLine() { 44 | 45 | StringBuilder cmdSB = new StringBuilder(); 46 | 47 | //Radamsa binary path - mandatory 48 | if (validateBinary()) { 49 | binary.setBorder(javax.swing.BorderFactory.createLineBorder(new java.awt.Color(0, 153, 102), 2)); 50 | cmdline.setForeground(new java.awt.Color(0, 153, 102)); 51 | cmdSB.append(binary.getText().toLowerCase().trim()); 52 | } else { 53 | binary.setBorder(javax.swing.BorderFactory.createLineBorder(new java.awt.Color(240, 0, 0), 2)); 54 | cmdline.setForeground(new java.awt.Color(240, 0, 0)); 55 | cmdline.setText("Invalid Radamsa binary path. Have you installed it? Where?"); 56 | return ""; 57 | } 58 | //Samples count - mandatory 59 | if (validateCount()) { 60 | count.setBorder(javax.swing.BorderFactory.createLineBorder(new java.awt.Color(0, 153, 102), 2)); 61 | cmdline.setForeground(new java.awt.Color(0, 153, 102)); 62 | cmdSB.append(" -n "); 63 | cmdSB.append(count.getText().toLowerCase().trim()); 64 | } else { 65 | count.setBorder(javax.swing.BorderFactory.createLineBorder(new java.awt.Color(240, 0, 0), 2)); 66 | cmdline.setForeground(new java.awt.Color(240, 0, 0)); 67 | cmdline.setText("Count option is not 'number'"); 68 | return ""; 69 | } 70 | 71 | //Other command line validation and display HERE 72 | 73 | cmdline.setText(cmdSB.toString()); 74 | return cmdSB.toString(); 75 | } 76 | 77 | protected boolean validateBinary() { 78 | 79 | if (binary.getText().toLowerCase().trim().isEmpty()) { 80 | return false; 81 | } 82 | File f = new File(binary.getText().toLowerCase().trim()); 83 | return f.exists() && !f.isDirectory(); 84 | } 85 | 86 | protected boolean validateCount() { 87 | 88 | try { 89 | Long.valueOf(count.getText().toLowerCase().trim()); 90 | } catch (NumberFormatException numExc) { 91 | return false; 92 | } 93 | return true; 94 | } 95 | 96 | protected boolean validatePatterns() { 97 | 98 | if (patterns.getText().toLowerCase().trim().isEmpty()) { 99 | return true; 100 | } 101 | 102 | return Pattern.matches("(od|nd|bu)+(,(od|nd|bu))*", patterns.getText().toLowerCase().trim()); 103 | } 104 | 105 | 106 | //Other validation methods HERE 107 | 108 | protected File getOutputDir() { 109 | 110 | String outputStr = output.getText().toLowerCase().trim(); 111 | File fout = new File(outputStr.substring(0, outputStr.lastIndexOf(File.separatorChar))); 112 | 113 | return fout; 114 | } 115 | 116 | protected Long getCount() { 117 | 118 | try { 119 | return Long.valueOf(count.getText().toLowerCase().trim()); 120 | } catch (NumberFormatException numExc) { 121 | return (long) 0; 122 | } 123 | } 124 | 125 | protected boolean deleteFiles() { 126 | 127 | return deleteAll.isSelected(); 128 | } 129 | 130 | private void resetSettings() { 131 | 132 | //Radamsa binary path 133 | if (os.equals(BurpExtender.OS.LINUX)) { 134 | binary.setText("/usr/bin/radamsa"); 135 | } else if (os.equals(BurpExtender.OS.MAC)) { 136 | binary.setText("/usr/bin/radamsa"); 137 | } else if (os.equals(BurpExtender.OS.WIN)) { 138 | binary.setText("Add here radamsa-0.3.exe filepath"); 139 | } else { 140 | binary.setText("Add here the Radamsa binary path"); 141 | } 142 | 143 | //Samples count 144 | count.setText("10"); 145 | 146 | //Output directory 147 | try { 148 | //Create default temporary directory for samples 149 | Path tmpDirectory = Files.createTempDirectory("radamsa"); 150 | tmpDirectory.toFile().deleteOnExit(); 151 | output.setText(tmpDirectory.toFile().getAbsolutePath() + File.separatorChar + "%n.out"); 152 | } catch (IOException ex) { 153 | new PrintWriter(callbacks.getStdout()).println("[!] Bradamsa Exception: BradamsaPanel IOException"); 154 | } 155 | 156 | seed.setText(""); 157 | mutations.setText(""); 158 | patterns.setText(""); 159 | meta.setText(""); 160 | deleteAll.setSelected(true); 161 | cmdline.setText(getRadamsaCmdLine()); 162 | } 163 | } 164 | -------------------------------------------------------------------------------- /Bradamsa/com/doyensec/BradamsaTab.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Bradamsa - Burp Intruder payloads generator (simplified code - does not work!) 3 | * 4 | * Copyright (c) 2017 Doyensec LLC. Made with love by Luca Carettoni. 5 | */ 6 | package com.doyensec; 7 | 8 | import burp.BurpExtender.OS; 9 | import burp.IBurpExtenderCallbacks; 10 | import burp.ITab; 11 | import java.awt.Component; 12 | 13 | public class BradamsaTab implements ITab { 14 | 15 | private final BradamsaPanel bPanel; 16 | 17 | public BradamsaTab(final IBurpExtenderCallbacks callbacks, OS os) { 18 | 19 | bPanel = new BradamsaPanel(callbacks, os); 20 | callbacks.customizeUiComponent(bPanel); 21 | callbacks.addSuiteTab(BradamsaTab.this); 22 | } 23 | 24 | @Override 25 | public String getTabCaption() { 26 | 27 | return "Bradamsa"; 28 | } 29 | 30 | @Override 31 | public Component getUiComponent() { 32 | 33 | return bPanel; 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /Bradamsa/com/doyensec/BurpUtils.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Bradamsa - Burp Intruder payloads generator (simplified code - does not work!) 3 | * 4 | * Copyright (c) 2017 Doyensec LLC. Made with love by Luca Carettoni. 5 | */ 6 | package com.doyensec; 7 | 8 | import burp.IBurpExtenderCallbacks; 9 | import java.io.BufferedReader; 10 | import java.io.IOException; 11 | import java.io.InputStream; 12 | import java.io.InputStreamReader; 13 | import java.io.OutputStream; 14 | import java.io.PrintStream; 15 | import org.apache.commons.io.IOUtils; 16 | 17 | public class BurpUtils { 18 | 19 | /* 20 | * Retrieve the HTTP message body from a request/response 21 | * 22 | * With the recent Burp's Extender API, you can use analyzeRequest() and analyzeResponse() instead 23 | */ 24 | public static byte[] getBody(byte[] request) { 25 | 26 | int offset = 0; 27 | byte[] body = null; 28 | 29 | for (int i = 0; i < request.length; i++) { 30 | if (i + 3 <= request.length) { 31 | if (request[i] == 13 && request[i + 1] == 10 && request[i + 2] == 13 && request[i + 3] == 10) { 32 | offset = i + 4; //Got a \r\n\r\n 33 | } 34 | } 35 | } 36 | 37 | if (offset != 0 && offset < request.length) { 38 | body = new byte[request.length - offset]; 39 | int cont = 0; 40 | for (int i = offset; i < request.length; i++) { 41 | body[cont] = request[i]; 42 | cont++; 43 | } 44 | } 45 | return body; 46 | } 47 | 48 | /* 49 | * Retrieve the cookies header field from a request/response 50 | * 51 | * With the recent Burp's Extender API, you can use analyzeRequest() and analyzeResponse() instead 52 | */ 53 | public static String getCookies(byte[] request) { 54 | 55 | String requestStr = new String(request); 56 | String cookies = ""; 57 | 58 | if (requestStr.contains("Cookie:")) { 59 | cookies = requestStr.substring(requestStr.indexOf("Cookie:")); 60 | cookies = cookies.substring(7, cookies.indexOf("\r\n")).trim(); 61 | } 62 | return cookies; 63 | } 64 | 65 | /* 66 | * Retrieve the host header field from a request/response 67 | * 68 | * With the recent Burp's Extender API, you can use analyzeRequest() and analyzeResponse() instead 69 | */ 70 | public static String getHost(byte[] request) { 71 | 72 | String requestStr = new String(request); 73 | String cookies = ""; 74 | 75 | if (requestStr.contains("Host:")) { 76 | cookies = requestStr.substring(requestStr.indexOf("Host:")); 77 | cookies = cookies.substring(5, cookies.indexOf("\r\n")).trim(); 78 | } 79 | return cookies; 80 | } 81 | 82 | /* 83 | * Execute a system command and return stdOut as a String 84 | */ 85 | public static String execute(String cmdLine, IBurpExtenderCallbacks callbacks, boolean waitFor) throws IOException, InterruptedException { 86 | 87 | ProcessBuilder pb = new ProcessBuilder(cmdLine.split(" ")); 88 | callbacks.issueAlert("Executing: " + cmdLine); 89 | final Process process; 90 | 91 | process = pb.start(); 92 | 93 | BufferedReader br = new BufferedReader(new InputStreamReader(process.getInputStream())); 94 | 95 | if (waitFor) { 96 | process.waitFor(); 97 | } 98 | 99 | StringBuilder builder = new StringBuilder(); 100 | String line; 101 | while ((line = br.readLine()) != null) { 102 | builder.append(line); 103 | builder.append(System.getProperty("line.separator")); 104 | } 105 | return builder.toString(); 106 | } 107 | 108 | /* 109 | * Execute a system command, pipe stdOut and stdErr to Burp's stream and allow stdIn data 110 | */ 111 | public static void executeAndPipe(String cmdLine, byte[] stdInputData, IBurpExtenderCallbacks callbacks, boolean waitFor) throws IOException, InterruptedException { 112 | 113 | ProcessBuilder pb = new ProcessBuilder(cmdLine.split(" ")); 114 | callbacks.issueAlert("Executing: " + cmdLine); 115 | final Process process; 116 | 117 | process = pb.start(); 118 | 119 | pipe(process.getErrorStream(), new PrintStream(callbacks.getStderr())); 120 | pipe(process.getInputStream(), new PrintStream(callbacks.getStdout())); 121 | 122 | if (stdInputData != null) { 123 | //Stream more data to stdIn 124 | OutputStream stdin = process.getOutputStream(); 125 | IOUtils.write(stdInputData, stdin); 126 | IOUtils.closeQuietly(stdin); 127 | } 128 | 129 | if (waitFor) { 130 | process.waitFor(); 131 | } 132 | } 133 | 134 | private static void pipe(final InputStream src, final PrintStream dest) { 135 | 136 | new Thread(new Runnable() { 137 | @Override 138 | public void run() { 139 | try { 140 | byte[] buffer = new byte[1024]; 141 | for (int n = 0; n != -1; n = src.read(buffer)) { 142 | dest.write(buffer, 0, n); 143 | } 144 | } catch (IOException e) { 145 | } 146 | } 147 | }).start(); 148 | } 149 | 150 | /* 151 | * Basic implementation of String repeat 152 | */ 153 | public static String repeat(String str, int times) { 154 | 155 | if (str == null) { 156 | return null; 157 | } 158 | StringBuilder sb = new StringBuilder(); 159 | for (int i = 0; i < times; i++) { 160 | sb.append(str); 161 | } 162 | return sb.toString(); 163 | } 164 | } 165 | -------------------------------------------------------------------------------- /Bradamsa/com/doyensec/RadamsaPayloadGenerator.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Bradamsa - Burp Intruder payloads generator (simplified code - does not work!) 3 | * 4 | * Copyright (c) 2017 Doyensec LLC. Made with love by Luca Carettoni. 5 | */ 6 | package com.doyensec; 7 | 8 | import burp.BurpExtender; 9 | import burp.IBurpExtenderCallbacks; 10 | import burp.IIntruderAttack; 11 | import burp.IIntruderPayloadGenerator; 12 | import burp.IIntruderPayloadGeneratorFactory; 13 | import java.io.File; 14 | import java.io.IOException; 15 | import java.io.PrintWriter; 16 | import java.util.ArrayList; 17 | import java.util.Arrays; 18 | import java.util.Iterator; 19 | import javax.swing.JOptionPane; 20 | import org.apache.commons.io.FileUtils; 21 | 22 | public class RadamsaPayloadGenerator implements IIntruderPayloadGenerator, IIntruderPayloadGeneratorFactory { 23 | 24 | private final IBurpExtenderCallbacks callbacks; 25 | private boolean firstInvoke; 26 | private ArrayList samples; 27 | private Iterator samplesIte; 28 | private BradamsaPanel panel; 29 | 30 | public RadamsaPayloadGenerator(BurpExtender burpExt) { 31 | 32 | callbacks = burpExt.getCallbacks(); 33 | panel = (BradamsaPanel) burpExt.getTab().getUiComponent(); 34 | firstInvoke = true; 35 | samples = new ArrayList<>(); 36 | samplesIte = samples.iterator(); 37 | } 38 | 39 | @Override 40 | public boolean hasMorePayloads() { 41 | 42 | if (firstInvoke) { 43 | return true; 44 | } 45 | return samplesIte.hasNext(); 46 | } 47 | 48 | @Override 49 | public byte[] getNextPayload(byte[] basePayload) { 50 | 51 | byte[] result = null; 52 | 53 | if(basePayload == null){ 54 | //Display warning. Battering ram attack type was selected 55 | JOptionPane.showMessageDialog(null, "Bradamsa can only be used in a sniper attack", "Abort", JOptionPane.ERROR_MESSAGE); 56 | firstInvoke = false; 57 | } 58 | 59 | try { 60 | if (firstInvoke) { 61 | //Generate samples from Burp's payload 62 | String cmdLine = panel.getRadamsaCmdLine(); 63 | if (!cmdLine.isEmpty()) { 64 | if (panel.getCount() > 9999) { 65 | JOptionPane.showMessageDialog(null, "As you've selected an high count number," 66 | + " generating all Radamsa samples may take some time.
Your intruder " 67 | + "attack will start once all samples are successfully generated.", "Radamsa Samples Generation", JOptionPane.INFORMATION_MESSAGE); 68 | } 69 | 70 | BurpUtils.executeAndPipe(cmdLine, basePayload, callbacks, true); 71 | 72 | //If enabled, mark all files for deletion before JVM shutdown 73 | if (panel.deleteFiles()) { 74 | for (File file : panel.getOutputDir().listFiles()) { 75 | file.deleteOnExit(); 76 | } 77 | } 78 | } else { 79 | //Display warning. Invalid user input 80 | JOptionPane.showMessageDialog(null, "Invalid command line arguments", "Check the 'Bradamsa' tab...", JOptionPane.WARNING_MESSAGE); 81 | } 82 | //create samples index 83 | samples.addAll(Arrays.asList(panel.getOutputDir().listFiles())); 84 | samplesIte = samples.iterator(); 85 | //prevent further initialization 86 | firstInvoke = false; 87 | } 88 | 89 | if (samplesIte.hasNext()) { 90 | File currentSample = samplesIte.next(); 91 | result = FileUtils.readFileToByteArray(currentSample); 92 | //If enabled, remove the sample as it has been already used 93 | if (panel.deleteFiles()) { 94 | currentSample.delete(); 95 | } 96 | } 97 | } catch (IOException | InterruptedException ex) { 98 | new PrintWriter(callbacks.getStdout()).println("[!] Bradamsa Exception: RadamsaPayloadGenerator.getNextPayload()"); 99 | } 100 | return result; 101 | } 102 | 103 | @Override 104 | public void reset() { 105 | 106 | samples.clear(); 107 | samplesIte = samples.iterator(); 108 | firstInvoke = true; 109 | } 110 | 111 | @Override 112 | public String getGeneratorName() { 113 | 114 | return "Bradamsa"; 115 | } 116 | 117 | @Override 118 | public IIntruderPayloadGenerator createNewInstance(IIntruderAttack iia) { 119 | 120 | //Delete previous samples, if applicable 121 | if (panel.deleteFiles()) { 122 | for (File file : panel.getOutputDir().listFiles()) { 123 | file.delete(); 124 | } 125 | } 126 | 127 | samples.clear(); 128 | samplesIte = samples.iterator(); 129 | firstInvoke = true; 130 | return this; 131 | } 132 | } 133 | -------------------------------------------------------------------------------- /BurpExtensionTemplate/.gitignore: -------------------------------------------------------------------------------- 1 | # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml 2 | hs_err_pid* 3 | 4 | #java specific 5 | *.class 6 | 7 | #general swap/backup files 8 | *.so 9 | *.log 10 | *.out 11 | *~ 12 | *.swp 13 | *.DS_Store 14 | *.lock 15 | 16 | -------------------------------------------------------------------------------- /BurpExtensionTemplate/Eclipse/.classpath: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /BurpExtensionTemplate/Eclipse/.project: -------------------------------------------------------------------------------- 1 | 2 | 3 | BurpExtensionTemplate 4 | 5 | 6 | 7 | 8 | 9 | org.eclipse.jdt.core.javabuilder 10 | 11 | 12 | 13 | 14 | 15 | org.eclipse.jdt.core.javanature 16 | 17 | 18 | -------------------------------------------------------------------------------- /BurpExtensionTemplate/Eclipse/BurpExtensionTemplate_Configuration.launch: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /BurpExtensionTemplate/Eclipse/src/burp/BurpExtender.java: -------------------------------------------------------------------------------- 1 | /* 2 | * BurpExtender - This is an empty Burp extension 3 | * 4 | * Copyright (c) 2017 Doyensec LLC. Made with love by Luca Carettoni. 5 | */ 6 | 7 | package burp; 8 | 9 | //Depending on the extension type, you'll add additional 'implements' interfaces here 10 | public class BurpExtender implements IBurpExtender 11 | { 12 | 13 | private IBurpExtenderCallbacks callbacks; 14 | private IExtensionHelpers helpers; 15 | 16 | @Override 17 | public void registerExtenderCallbacks(IBurpExtenderCallbacks callbacks) 18 | { 19 | this.callbacks = callbacks; 20 | helpers = callbacks.getHelpers(); 21 | callbacks.setExtensionName("Empty Burp Extension"); 22 | 23 | //Your code goes here! 24 | } 25 | } -------------------------------------------------------------------------------- /BurpExtensionTemplate/IDEA/.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /BurpExtensionTemplate/IDEA/.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /BurpExtensionTemplate/IDEA/BurpExtensionTemplate.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /BurpExtensionTemplate/IDEA/src/burp/BurpExtender.java: -------------------------------------------------------------------------------- 1 | /* 2 | * BurpExtender - This is an empty Burp extension 3 | * 4 | * Copyright (c) 2017 Doyensec LLC. Made with love by Luca Carettoni. 5 | */ 6 | 7 | package burp; 8 | 9 | //Depending on the extension type, you'll add additional 'implements' interfaces here 10 | public class BurpExtender implements IBurpExtender 11 | { 12 | 13 | private IBurpExtenderCallbacks callbacks; 14 | private IExtensionHelpers helpers; 15 | 16 | @Override 17 | public void registerExtenderCallbacks(IBurpExtenderCallbacks callbacks) 18 | { 19 | this.callbacks = callbacks; 20 | helpers = callbacks.getHelpers(); 21 | callbacks.setExtensionName("Empty Burp Extension"); 22 | 23 | //Your code goes here! 24 | } 25 | } -------------------------------------------------------------------------------- /BurpExtensionTemplate/NetBeans/build.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | Builds, tests, and runs the project BurpExtensionTemplate. 12 | 13 | 73 | 74 | -------------------------------------------------------------------------------- /BurpExtensionTemplate/NetBeans/manifest.mf: -------------------------------------------------------------------------------- 1 | Manifest-Version: 1.0 2 | X-COMMENT: Main-Class will be added automatically by build 3 | 4 | -------------------------------------------------------------------------------- /BurpExtensionTemplate/NetBeans/nbproject/configs/Burp_Extension.properties: -------------------------------------------------------------------------------- 1 | $label=Burp Extension 2 | main.class=burp.StartBurp 3 | -------------------------------------------------------------------------------- /BurpExtensionTemplate/NetBeans/nbproject/genfiles.properties: -------------------------------------------------------------------------------- 1 | build.xml.data.CRC32=4bfdb403 2 | build.xml.script.CRC32=45678695 3 | build.xml.stylesheet.CRC32=8064a381@1.80.1.48 4 | # This file is used by a NetBeans-based IDE to track changes in generated files such as build-impl.xml. 5 | # Do not edit this file. You may delete it but then the IDE will never regenerate such files for you. 6 | nbproject/build-impl.xml.data.CRC32=4bfdb403 7 | nbproject/build-impl.xml.script.CRC32=6de9f133 8 | nbproject/build-impl.xml.stylesheet.CRC32=830a3534@1.80.1.48 9 | -------------------------------------------------------------------------------- /BurpExtensionTemplate/NetBeans/nbproject/project.properties: -------------------------------------------------------------------------------- 1 | annotation.processing.enabled=true 2 | annotation.processing.enabled.in.editor=false 3 | annotation.processing.processors.list= 4 | annotation.processing.run.all.processors=true 5 | annotation.processing.source.output=${build.generated.sources.dir}/ap-source-output 6 | application.title=BurpExtensionTemplate 7 | application.vendor=Doyensec 8 | build.classes.dir=${build.dir}/classes 9 | build.classes.excludes=**/*.java,**/*.form 10 | # This directory is removed when the project is cleaned: 11 | build.dir=build 12 | build.generated.dir=${build.dir}/generated 13 | build.generated.sources.dir=${build.dir}/generated-sources 14 | # Only compile against the classpath explicitly listed here: 15 | build.sysclasspath=ignore 16 | build.test.classes.dir=${build.dir}/test/classes 17 | build.test.results.dir=${build.dir}/test/results 18 | # Uncomment to specify the preferred debugger connection transport: 19 | #debug.transport=dt_socket 20 | debug.classpath=\ 21 | ${run.classpath} 22 | debug.test.classpath=\ 23 | ${run.test.classpath} 24 | # Files in build.classes.dir which should be excluded from distribution jar 25 | dist.archive.excludes= 26 | # This directory is removed when the project is cleaned: 27 | dist.dir=dist 28 | dist.jar=${dist.dir}/BurpExtensionTemplate.jar 29 | dist.javadoc.dir=${dist.dir}/javadoc 30 | endorsed.classpath= 31 | excludes= 32 | file.reference.burpsuite_free_v1.7.17.jar=/Users/CHANGEME/burpsuite_free_v1.7.17.jar 33 | includes=** 34 | jar.compress=false 35 | javac.classpath=\ 36 | ${file.reference.burpsuite_free_v1.7.17.jar} 37 | # Space-separated list of extra javac options 38 | javac.compilerargs= 39 | javac.deprecation=false 40 | javac.external.vm=true 41 | javac.processorpath=\ 42 | ${javac.classpath} 43 | javac.source=1.8 44 | javac.target=1.8 45 | javac.test.classpath=\ 46 | ${javac.classpath}:\ 47 | ${build.classes.dir} 48 | javac.test.processorpath=\ 49 | ${javac.test.classpath} 50 | javadoc.additionalparam= 51 | javadoc.author=false 52 | javadoc.encoding=${source.encoding} 53 | javadoc.noindex=false 54 | javadoc.nonavbar=false 55 | javadoc.notree=false 56 | javadoc.private=false 57 | javadoc.splitindex=true 58 | javadoc.use=true 59 | javadoc.version=false 60 | javadoc.windowtitle= 61 | main.class=burp.StartBurp 62 | manifest.file=manifest.mf 63 | meta.inf.dir=${src.dir}/META-INF 64 | mkdist.disabled=false 65 | platform.active=default_platform 66 | run.classpath=\ 67 | ${javac.classpath}:\ 68 | ${build.classes.dir} 69 | # Space-separated list of JVM arguments used when running the project. 70 | # You may also define separate properties like run-sys-prop.name=value instead of -Dname=value. 71 | # To set system properties for unit tests define test-sys-prop.name=value: 72 | run.jvmargs= 73 | run.test.classpath=\ 74 | ${javac.test.classpath}:\ 75 | ${build.test.classes.dir} 76 | source.encoding=UTF-8 77 | src.dir=src 78 | test.src.dir=test 79 | -------------------------------------------------------------------------------- /BurpExtensionTemplate/NetBeans/nbproject/project.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | org.netbeans.modules.java.j2seproject 4 | 5 | 6 | BurpExtensionTemplate 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /BurpExtensionTemplate/NetBeans/src/burp/BurpExtender.java: -------------------------------------------------------------------------------- 1 | /* 2 | * BurpExtender - This is an empty Burp extension 3 | * 4 | * Copyright (c) 2017 Doyensec LLC. Made with love by Luca Carettoni. 5 | */ 6 | 7 | package burp; 8 | 9 | //Depending on the extension type, you'll add additional 'implements' interfaces here 10 | public class BurpExtender implements IBurpExtender 11 | { 12 | 13 | private IBurpExtenderCallbacks callbacks; 14 | private IExtensionHelpers helpers; 15 | 16 | @Override 17 | public void registerExtenderCallbacks(IBurpExtenderCallbacks callbacks) 18 | { 19 | this.callbacks = callbacks; 20 | helpers = callbacks.getHelpers(); 21 | callbacks.setExtensionName("Empty Burp Extension"); 22 | 23 | //Your code goes here! 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /DetectELJ/.gitignore: -------------------------------------------------------------------------------- 1 | # Package Files # 2 | *.jar 3 | *.war 4 | *.ear 5 | 6 | # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml 7 | hs_err_pid* 8 | 9 | #ant specific 10 | dist/ 11 | build/ 12 | build.xml 13 | 14 | #netbeans specific 15 | core 16 | nbproject/* 17 | libs/* 18 | lib/* 19 | manifest.mf 20 | .jacocoverage/ 21 | coverage/ 22 | src/* 23 | 24 | #java specific 25 | *.class 26 | 27 | #general swap/backup files 28 | *.so 29 | *.log 30 | *.out 31 | *~ 32 | *.swp 33 | *.DS_Store 34 | *.lock 35 | 36 | #idea specific 37 | .classpath 38 | .project 39 | .settings 40 | .idea 41 | .metadata 42 | *.iml 43 | *.ipr 44 | **/*~ 45 | /target/ 46 | -------------------------------------------------------------------------------- /DetectELJ/Java/Final/burp/BurpExtender.java: -------------------------------------------------------------------------------- 1 | /* 2 | * DetectELJ - Active scanner extension to detect Expression Language Injection vulnerabilities 3 | * 4 | * Copyright (c) 2017 Doyensec LLC. Made with love by Luca Carettoni. 5 | */ 6 | package burp; 7 | 8 | import java.io.PrintWriter; 9 | import java.net.URL; 10 | import java.util.ArrayList; 11 | import java.util.Arrays; 12 | import java.util.List; 13 | 14 | public class BurpExtender implements IBurpExtender, IScannerCheck { 15 | 16 | private IBurpExtenderCallbacks callbacks; 17 | private IExtensionHelpers helpers; 18 | 19 | @Override 20 | public void registerExtenderCallbacks(IBurpExtenderCallbacks callbacks) { 21 | this.callbacks = callbacks; 22 | helpers = callbacks.getHelpers(); 23 | callbacks.setExtensionName("DetectELJ"); 24 | 25 | callbacks.issueAlert("DetectELJ Active Scanner check enabled"); 26 | 27 | PrintWriter stdout = new PrintWriter(callbacks.getStdout(), true); 28 | PrintWriter stderr = new PrintWriter(callbacks.getStderr(), true); 29 | 30 | callbacks.registerScannerCheck(this); 31 | } 32 | 33 | @Override 34 | public List doPassiveScan(IHttpRequestResponse ihrr) { 35 | return null; //Active scanner check only 36 | } 37 | 38 | @Override 39 | public List doActiveScan(IHttpRequestResponse ihrr, IScannerInsertionPoint isip) { 40 | 41 | byte[] withPayload = isip.buildRequest("${1336+1}".getBytes()); 42 | IHttpRequestResponse newReqRes = callbacks.makeHttpRequest(ihrr.getHttpService(), withPayload); 43 | 44 | IResponseVariations variation = helpers.analyzeResponseVariations(ihrr.getResponse(), newReqRes.getResponse()); 45 | List pageChanges = variation.getVariantAttributes(); 46 | 47 | boolean length = false; 48 | boolean bodyContent = false; 49 | boolean match = false; 50 | 51 | for (String change : pageChanges) { 52 | if (change.equals("content_length")) length = true; 53 | if (change.equals("whole_body_content")) bodyContent = true; 54 | } 55 | 56 | if (helpers.bytesToString(newReqRes.getResponse()).contains("1337")) match = true; 57 | 58 | if (length && bodyContent && match) { 59 | List issues = new ArrayList<>(1); 60 | issues.add(new ELJ(newReqRes)); 61 | return issues; 62 | } else { 63 | return null; 64 | } 65 | } 66 | 67 | @Override 68 | public int consolidateDuplicateIssues(IScanIssue isb, IScanIssue isa) { 69 | if (Arrays.equals(isb.getHttpMessages()[0].getResponse(), isa.getHttpMessages()[0].getResponse())) { 70 | return -1; 71 | } else { 72 | return 0; 73 | } 74 | } 75 | 76 | class ELJ implements IScanIssue { 77 | 78 | private final IHttpRequestResponse reqres; 79 | 80 | public ELJ(IHttpRequestResponse reqres) { 81 | this.reqres = reqres; 82 | } 83 | 84 | @Override 85 | public String getHost() { 86 | return reqres.getHost(); 87 | } 88 | 89 | @Override 90 | public int getPort() { 91 | return reqres.getPort(); 92 | } 93 | 94 | @Override 95 | public String getProtocol() { 96 | return reqres.getProtocol(); 97 | } 98 | 99 | @Override 100 | public URL getUrl() { 101 | return reqres.getUrl(); 102 | } 103 | 104 | @Override 105 | public String getIssueName() { 106 | return "Expression Language (EL) Injection Detected"; 107 | } 108 | 109 | @Override 110 | public int getIssueType() { 111 | return 0x08000000; //See http://portswigger.net/burp/help/scanner_issuetypes.html 112 | } 113 | 114 | @Override 115 | public String getSeverity() { 116 | return "High"; // "High", "Medium", "Low", "Information" or "False positive" 117 | } 118 | 119 | @Override 120 | public String getConfidence() { 121 | return "Firm"; //"Certain", "Firm" or "Tentative" 122 | } 123 | 124 | @Override 125 | public String getIssueBackground() { 126 | return "Expression Language injections occur when input data is evaluated " 127 | + "by an expression language interpreter. An attacker can read server-side " 128 | + "data, such as the content of server-side variables, and some other inner " 129 | + "configuration details."; 130 | } 131 | 132 | @Override 133 | public String getRemediationBackground() { 134 | return "Apply input validation best practices, and reject ${, #{ and other variations."; 135 | } 136 | 137 | @Override 138 | public String getIssueDetail() { 139 | return "Burp Scanner has identified an Expression Language injection in:" 140 | + reqres.getUrl().toString() + "

"; 141 | } 142 | 143 | @Override 144 | public String getRemediationDetail() { 145 | return null; 146 | } 147 | 148 | @Override 149 | public IHttpRequestResponse[] getHttpMessages() { 150 | //Let's highlight the specific string in the response that triggered the issue 151 | String strRes = helpers.bytesToString(reqres.getResponse()); 152 | int[] marks = new int[2]; 153 | marks[0] = strRes.indexOf("1337"); 154 | marks[1] = marks[0] + 4; 155 | List marksList = new ArrayList<>(1); 156 | marksList.add(marks); 157 | IHttpRequestResponseWithMarkers reqresMark = callbacks.applyMarkers(reqres, null, marksList); 158 | IHttpRequestResponse[] rra = { reqresMark }; 159 | return rra; 160 | } 161 | 162 | @Override 163 | public IHttpService getHttpService() { 164 | return reqres.getHttpService(); 165 | } 166 | } 167 | } 168 | -------------------------------------------------------------------------------- /DetectELJ/Java/WIP1/burp/BurpExtenderWIP1.java: -------------------------------------------------------------------------------- 1 | /* 2 | * DetectELJ - Active scanner extension to detect Expression Language Injection vulnerabilities 3 | * 4 | * Copyright (c) 2017 Doyensec LLC. Made with love by Luca Carettoni. 5 | */ 6 | package burp; 7 | 8 | import java.io.PrintWriter; 9 | import java.net.URL; 10 | import java.util.ArrayList; 11 | import java.util.Arrays; 12 | import java.util.List; 13 | 14 | public class BurpExtender implements IBurpExtender, IScannerCheck { 15 | 16 | private IBurpExtenderCallbacks callbacks; 17 | private IExtensionHelpers helpers; 18 | 19 | @Override 20 | public void registerExtenderCallbacks(IBurpExtenderCallbacks callbacks) { 21 | this.callbacks = callbacks; 22 | helpers = callbacks.getHelpers(); 23 | callbacks.setExtensionName("DetectELJ"); 24 | 25 | callbacks.issueAlert("DetectELJ Active Scanner check enabled"); 26 | 27 | PrintWriter stdout = new PrintWriter(callbacks.getStdout(), true); 28 | PrintWriter stderr = new PrintWriter(callbacks.getStderr(), true); 29 | 30 | callbacks.registerScannerCheck(this); 31 | } 32 | 33 | @Override 34 | public List doPassiveScan(IHttpRequestResponse ihrr) { 35 | return null; //Active scanner check only 36 | } 37 | 38 | @Override 39 | public List doActiveScan(IHttpRequestResponse ihrr, IScannerInsertionPoint isip) { 40 | 41 | //1 - Create a new request with our custom payload (tip: buildRequest) 42 | 43 | //2 - Send the HTTP request 44 | 45 | //3 - Diff original and new responses (tip: analyzeResponseVariations and getVariantAttributes) 46 | 47 | //4 - Based on page changes, determine whether the page is vulnerable or not 48 | 49 | //5 - If vulnerable, create a new IScanIssue and return the List 50 | 51 | } 52 | 53 | @Override 54 | public int consolidateDuplicateIssues(IScanIssue isb, IScanIssue isa) { 55 | //TODO 56 | } 57 | 58 | class ELJ implements IScanIssue { 59 | //TODO 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /DetectELJ/Java/WIP2/burp/BurpExtenderWIP2.java: -------------------------------------------------------------------------------- 1 | /* 2 | * DetectELJ - Active scanner extension to detect Expression Language Injection vulnerabilities 3 | * 4 | * Copyright (c) 2017 Doyensec LLC. Made with love by Luca Carettoni. 5 | */ 6 | package burp; 7 | 8 | import java.io.PrintWriter; 9 | import java.net.URL; 10 | import java.util.ArrayList; 11 | import java.util.Arrays; 12 | import java.util.List; 13 | 14 | public class BurpExtender implements IBurpExtender, IScannerCheck { 15 | 16 | private IBurpExtenderCallbacks callbacks; 17 | private IExtensionHelpers helpers; 18 | 19 | @Override 20 | public void registerExtenderCallbacks(IBurpExtenderCallbacks callbacks) { 21 | this.callbacks = callbacks; 22 | helpers = callbacks.getHelpers(); 23 | callbacks.setExtensionName("DetectELJ"); 24 | 25 | callbacks.issueAlert("DetectELJ Active Scanner check enabled"); 26 | 27 | PrintWriter stdout = new PrintWriter(callbacks.getStdout(), true); 28 | PrintWriter stderr = new PrintWriter(callbacks.getStderr(), true); 29 | 30 | callbacks.registerScannerCheck(this); 31 | } 32 | 33 | @Override 34 | public List doPassiveScan(IHttpRequestResponse ihrr) { 35 | return null; //Active scanner check only 36 | } 37 | 38 | @Override 39 | public List doActiveScan(IHttpRequestResponse ihrr, IScannerInsertionPoint isip) { 40 | 41 | //1 - Create a new request with our custom payload (tip: buildRequest) 42 | byte[] withPayload = isip.buildRequest("${1336+1}".getBytes()); 43 | //2 - Send the HTTP request 44 | IHttpRequestResponse newReqRes = callbacks.makeHttpRequest(ihrr.getHttpService(), withPayload); 45 | //3 - Diff original and new responses (tip: analyzeResponseVariations and getVariantAttributes) 46 | IResponseVariations variation = helpers.analyzeResponseVariations(ihrr.getResponse(), newReqRes.getResponse()); 47 | List pageChanges = variation.getVariantAttributes(); 48 | //4 - Based on page changes, determine whether the page is vulnerable or not 49 | boolean length = false; 50 | boolean bodyContent = false; 51 | boolean match = false; 52 | 53 | for (String change : pageChanges) { 54 | if (change.equals("content_length")) length = true; 55 | if (change.equals("whole_body_content")) bodyContent = true; 56 | } 57 | 58 | if (helpers.bytesToString(newReqRes.getResponse()).contains("1337")) match = true; 59 | //5 - If vulnerable, create a new IScanIssue and return the List 60 | if (length && bodyContent && match) { 61 | //TODO 62 | } else { 63 | return null; 64 | } 65 | } 66 | 67 | @Override 68 | public int consolidateDuplicateIssues(IScanIssue isb, IScanIssue isa) { 69 | //TODO 70 | //If it is the same URL and same type of response, consider as the same security issue, otherwise different 71 | } 72 | 73 | class ELJ implements IScanIssue { 74 | 75 | private final IHttpRequestResponse reqres; 76 | 77 | public ELJ(IHttpRequestResponse reqres) { 78 | this.reqres = reqres; 79 | } 80 | 81 | @Override 82 | public String getHost() { 83 | return reqres.getHost(); 84 | } 85 | 86 | @Override 87 | public int getPort() { 88 | return reqres.getPort(); 89 | } 90 | 91 | @Override 92 | public String getProtocol() { 93 | return reqres.getProtocol(); 94 | } 95 | 96 | @Override 97 | public URL getUrl() { 98 | return reqres.getUrl(); 99 | } 100 | 101 | @Override 102 | public String getIssueName() { 103 | return "Expression Language (EL) Injection Detected"; 104 | } 105 | 106 | @Override 107 | public int getIssueType() { 108 | return 0x08000000; //See http://portswigger.net/burp/help/scanner_issuetypes.html 109 | } 110 | 111 | @Override 112 | public String getSeverity() { 113 | return "High"; // "High", "Medium", "Low", "Information" or "False positive" 114 | } 115 | 116 | @Override 117 | public String getConfidence() { 118 | return "Firm"; //"Certain", "Firm" or "Tentative" 119 | } 120 | 121 | @Override 122 | public String getIssueBackground() { 123 | return "Expression Language injections occur when input data is evaluated " 124 | + "by an expression language interpreter. An attacker can read server-side " 125 | + "data, such as the content of server-side variables, and some other inner " 126 | + "configuration details."; 127 | } 128 | 129 | @Override 130 | public String getRemediationBackground() { 131 | return "Apply input validation best practices, and reject ${, #{ and other variations."; 132 | } 133 | 134 | @Override 135 | public String getIssueDetail() { 136 | return "Burp Scanner has identified an Expression Language injection in:" 137 | + reqres.getUrl().toString() + "

"; 138 | } 139 | 140 | @Override 141 | public String getRemediationDetail() { 142 | return null; 143 | } 144 | 145 | @Override 146 | public IHttpRequestResponse[] getHttpMessages() { 147 | //Let's highlight the specific string in the response that triggered the issue 148 | 149 | //TODO 150 | } 151 | 152 | @Override 153 | public IHttpService getHttpService() { 154 | return reqres.getHttpService(); 155 | } 156 | } 157 | } 158 | -------------------------------------------------------------------------------- /DetectELJ/Python/Final/BurpExtender.py: -------------------------------------------------------------------------------- 1 | # 2 | # DetectELJ - Active scanner extension to detect Expression Language Injection vulnerabilities 3 | # 4 | # Copyright (c) 2017 Doyensec LLC. Made with love by Andrea Brancaleoni. 5 | # 6 | from burp import IBurpExtender, IScannerCheck, IScanIssue 7 | from java.io import PrintWriter 8 | from java.net import URL 9 | from java.util import ArrayList, Arrays, List 10 | 11 | from org.python.core.util import StringUtil 12 | from jarray import array 13 | 14 | 15 | class BurpExtender(IBurpExtender, IScannerCheck): 16 | 17 | def registerExtenderCallbacks(self, callbacks): 18 | self.callbacks = callbacks 19 | self.helpers = callbacks.getHelpers() 20 | callbacks.setExtensionName('DetectELJ') 21 | 22 | callbacks.issueAlert('DetectELJ Active Scanner check enabled') 23 | 24 | stdout = PrintWriter(callbacks.getStdout(), True) 25 | stderr = PrintWriter(callbacks.getStderr(), True) 26 | 27 | callbacks.registerScannerCheck(self) 28 | 29 | def doPassiveScan(self, ihrr): 30 | return None # Active scanner check only 31 | 32 | def doActiveScan(self, ihrr, isip): 33 | withPayload = isip.buildRequest(StringUtil.toBytes('${1336+1}')) 34 | newReqRes = self.callbacks.makeHttpRequest(ihrr.getHttpService(), withPayload) 35 | 36 | variation = self.helpers.analyzeResponseVariations(ihrr.getResponse(), newReqRes.getResponse()) 37 | pageChanges = variation.getVariantAttributes() 38 | 39 | length = False 40 | bodyContent = False 41 | match = False 42 | 43 | for change in pageChanges: 44 | if change == 'content_length': 45 | length = True 46 | if change == 'whole_body_content': 47 | bodyContent = True 48 | 49 | match = '1337' in self.helpers.bytesToString(newReqRes.getResponse()) 50 | 51 | if length and bodyContent and match: 52 | issues = ArrayList() 53 | issues.add(ELJ(newReqRes, self.callbacks, self.helpers)) 54 | return issues 55 | else: 56 | return None 57 | 58 | def consolidateDuplicateIssues(self, isb, isa): 59 | if Arrays.equals(isb.getHttpMessages()[0].getResponse(), isa.getHttpMessages()[0].getResponse()): 60 | return -1 61 | else: 62 | return 0 63 | 64 | 65 | class ELJ(IScanIssue): 66 | 67 | def __init__(self, reqres, callbacks, helpers): 68 | self.reqres = reqres 69 | self.callbacks = callbacks 70 | self.helpers = helpers 71 | 72 | def getHost(self): 73 | return self.reqres.getHost() 74 | 75 | def getPort(self): 76 | return self.reqres.getPort() 77 | 78 | def getProtocol(self): 79 | return self.reqres.getProtocol() 80 | 81 | def getUrl(self): 82 | return self.reqres.getUrl() 83 | 84 | def getIssueName(self): 85 | return 'Expression Language (EL) Injection Detected' 86 | 87 | def getIssueType(self): 88 | return 0x08000000 # See http://portswigger.net/burp/help/scanner_issuetypes.html 89 | 90 | def getSeverity(self): 91 | return 'High' # 'High', 'Medium', 'Low', 'Information' or 'False positive' 92 | 93 | def getConfidence(self): 94 | return 'Firm' # 'Certain', 'Firm' or 'Tentative' 95 | 96 | def getIssueBackground(self): 97 | return str('Expression Language injections occur when input data is evaluated ' 98 | 'by an expression language interpreter. An attacker can read server-side ' 99 | 'data, such as the content of server-side variables, and some other inner ' 100 | 'configuration details.') 101 | 102 | def getRemediationBackground(self): 103 | return 'Apply input validation best practices, and reject $, # and other variations.' 104 | 105 | def getIssueDetail(self): 106 | return str('Burp Scanner has identified an Expression Language injection in:' 107 | '%s

' % (self.reqres.getUrl().toString())) 108 | 109 | def getRemediationDetail(self): 110 | return None 111 | 112 | def getHttpMessages(self): 113 | # Let's highlight the specific string in the response that triggered the issue 114 | strRes = self.helpers.bytesToString(self.reqres.getResponse()) 115 | marks = [None, None] 116 | # XXX: shim for python objects 117 | marks[0] = strRes.index('1337') 118 | marks[1] = marks[0] + 4 119 | marks = array(marks, 'i') 120 | marksList = ArrayList() 121 | marksList.add(marks) 122 | reqresMark = self.callbacks.applyMarkers(self.reqres, None, marksList) 123 | rra = [reqresMark] 124 | return rra 125 | 126 | def getHttpService(self): 127 | return self.reqres.getHttpService() 128 | -------------------------------------------------------------------------------- /DetectELJ/Python/WIP1/BurpExtenderWIP1.py: -------------------------------------------------------------------------------- 1 | # 2 | # DetectELJ - Active scanner extension to detect Expression Language Injection vulnerabilities 3 | # 4 | # Copyright (c) 2017 Doyensec LLC. Made with love by Andrea Brancaleoni. 5 | # 6 | from burp import IBurpExtender, IScannerCheck, IScanIssue 7 | from java.io import PrintWriter 8 | from java.net import URL 9 | from java.util import ArrayList, Arrays, List 10 | 11 | from org.python.core.util import StringUtil 12 | from jarray import array 13 | 14 | 15 | class BurpExtender(IBurpExtender, IScannerCheck): 16 | 17 | def registerExtenderCallbacks(self, callbacks): 18 | self.callbacks = callbacks 19 | self.helpers = callbacks.getHelpers() 20 | callbacks.setExtensionName('DetectELJ') 21 | 22 | callbacks.issueAlert('DetectELJ Active Scanner check enabled') 23 | 24 | stdout = PrintWriter(callbacks.getStdout(), True) 25 | stderr = PrintWriter(callbacks.getStderr(), True) 26 | 27 | callbacks.registerScannerCheck(self) 28 | 29 | def doPassiveScan(self, ihrr): 30 | return None # Active scanner check only 31 | 32 | def doActiveScan(self, ihrr, isip): 33 | # 1 - Create a new request with our custom payload (tip: buildRequest) 34 | 35 | # 2 - Send the HTTP request 36 | 37 | # 3 - Diff original and new responses (tip: analyzeResponseVariations and getVariantAttributes) 38 | 39 | # 4 - Based on page changes, determine whether the page is vulnerable or not 40 | 41 | # 5 - If vulnerable, create a new IScanIssue and return the List 42 | 43 | pass 44 | 45 | def consolidateDuplicateIssues(self, isb, isa): 46 | # TODO 47 | pass 48 | 49 | class ELJ(IScanIssue): 50 | # TODO 51 | pass 52 | -------------------------------------------------------------------------------- /DetectELJ/Python/WIP2/BurpExtenderWIP2.py: -------------------------------------------------------------------------------- 1 | # 2 | # DetectELJ - Active scanner extension to detect Expression Language Injection vulnerabilities 3 | # 4 | # Copyright (c) 2017 Doyensec LLC. Made with love by Andrea Brancaleoni. 5 | # 6 | from burp import IBurpExtender, IScannerCheck, IScanIssue 7 | from java.io import PrintWriter 8 | from java.net import URL 9 | from java.util import ArrayList, Arrays, List 10 | 11 | from org.python.core.util import StringUtil 12 | from jarray import array 13 | 14 | 15 | class BurpExtender(IBurpExtender, IScannerCheck): 16 | 17 | def registerExtenderCallbacks(self, callbacks): 18 | self.callbacks = callbacks 19 | self.helpers = callbacks.getHelpers() 20 | callbacks.setExtensionName('DetectELJ') 21 | 22 | callbacks.issueAlert('DetectELJ Active Scanner check enabled') 23 | 24 | stdout = PrintWriter(callbacks.getStdout(), True) 25 | stderr = PrintWriter(callbacks.getStderr(), True) 26 | 27 | callbacks.registerScannerCheck(self) 28 | 29 | def doPassiveScan(self, ihrr): 30 | return None # Active scanner check only 31 | 32 | def doActiveScan(self, ihrr, isip): 33 | # 1 - Create a new request with our custom payload (tip: buildRequest) 34 | withPayload = isip.buildRequest(StringUtil.toBytes('${1336+1}')) 35 | # 2 - Send the HTTP request 36 | newReqRes = self.callbacks.makeHttpRequest(ihrr.getHttpService(), withPayload) 37 | # 3 - Diff original and new responses (tip: analyzeResponseVariations and getVariantAttributes) 38 | variation = self.helpers.analyzeResponseVariations(ihrr.getResponse(), newReqRes.getResponse()) 39 | pageChanges = variation.getVariantAttributes() 40 | # 4 - Based on page changes, determine whether the page is vulnerable or not 41 | length = False 42 | bodyContent = False 43 | match = False 44 | 45 | for change in pageChanges: 46 | if change == 'content_length': 47 | length = True 48 | if change == 'whole_body_content': 49 | bodyContent = True 50 | 51 | match = '1337' in self.helpers.bytesToString(newReqRes.getResponse()) 52 | # 5 - If vulnerable, create a new IScanIssue and return the List 53 | if length and bodyContent and match: 54 | pass 55 | # TODO 56 | else: 57 | return None 58 | 59 | def consolidateDuplicateIssues(self, isb, isa): 60 | # TODO 61 | # If it is the same URL and same type of response, consider as the same security issue, otherwise different 62 | pass 63 | 64 | 65 | class ELJ(IScanIssue): 66 | # TODO 67 | pass 68 | 69 | def __init__(self, reqres, callbacks, helpers): 70 | self.reqres = reqres 71 | self.callbacks = callbacks 72 | self.helpers = helpers 73 | 74 | def getHost(self): 75 | return self.reqres.getHost() 76 | 77 | def getPort(self): 78 | return self.reqres.getPort() 79 | 80 | def getProtocol(self): 81 | return self.reqres.getProtocol() 82 | 83 | def getUrl(self): 84 | return self.reqres.getUrl() 85 | 86 | def getIssueName(self): 87 | return 'Expression Language (EL) Injection Detected' 88 | 89 | def getIssueType(self): 90 | return 0x08000000 # See http://portswigger.net/burp/help/scanner_issuetypes.html 91 | 92 | def getSeverity(self): 93 | return 'High' # 'High', 'Medium', 'Low', 'Information' or 'False positive' 94 | 95 | def getConfidence(self): 96 | return 'Firm' # 'Certain', 'Firm' or 'Tentative' 97 | 98 | def getIssueBackground(self): 99 | return str('Expression Language injections occur when input data is evaluated ' 100 | 'by an expression language interpreter. An attacker can read server-side ' 101 | 'data, such as the content of server-side variables, and some other inner ' 102 | 'configuration details.') 103 | 104 | def getRemediationBackground(self): 105 | return 'Apply input validation best practices, and reject $, # and other variations.' 106 | 107 | def getIssueDetail(self): 108 | return str('Burp Scanner has identified an Expression Language injection in:' 109 | '%s

' % (self.reqres.getUrl().toString())) 110 | 111 | def getRemediationDetail(self): 112 | return None 113 | 114 | def getHttpMessages(self): 115 | # Let's highlight the specific string in the response that triggered the issue 116 | 117 | # TODO 118 | pass 119 | 120 | def getHttpService(self): 121 | return self.reqres.getHttpService() 122 | -------------------------------------------------------------------------------- /DetectELJ/Ruby/Final/BurpExtender.rb: -------------------------------------------------------------------------------- 1 | # 2 | # DetectELJ - Active scanner extension to detect Expression Language Injection vulnerabilities 3 | # 4 | # Copyright (c) 2017 Doyensec LLC. Made with love by Andrea Brancaleoni. 5 | # 6 | require 'java' 7 | 8 | java_import 'burp.IBurpExtender' 9 | java_import 'burp.IScannerCheck' 10 | java_import 'burp.IScanIssue' 11 | java_import 'burp.IHttpRequestResponse' 12 | java_import 'java.io.PrintWriter' 13 | java_import 'java.net.URL' 14 | java_import 'java.util.ArrayList' 15 | java_import 'java.util.Arrays' 16 | java_import 'java.util.List' 17 | 18 | class BurpExtender 19 | include IBurpExtender 20 | include IScannerCheck 21 | 22 | attr_reader :helpers 23 | attr_reader :callbacks 24 | 25 | def registerExtenderCallbacks(callbacks) 26 | @callbacks = callbacks 27 | @helpers = callbacks.getHelpers() 28 | callbacks.setExtensionName('DetectELJ') 29 | 30 | callbacks.issueAlert('DetectELJ Active Scanner check enabled') 31 | 32 | stdout = PrintWriter.new(callbacks.getStdout(), true) 33 | stderr = PrintWriter.new(callbacks.getStderr(), true) 34 | 35 | callbacks.registerScannerCheck(self) 36 | end 37 | 38 | def print(e) 39 | @callbacks.issueAlert(e.to_s) 40 | end 41 | 42 | def doPassiveScan(ihrr) 43 | return nil # Active scanner check only 44 | end 45 | 46 | 47 | def doActiveScan(ihrr, isip) 48 | withPayload = isip.buildRequest('${1336+1}'.to_java_bytes()) 49 | newReqRes = callbacks.makeHttpRequest(ihrr.getHttpService(), withPayload) 50 | 51 | variation = helpers.analyzeResponseVariations(ihrr.getResponse(), newReqRes.getResponse()) 52 | pageChanges = variation.getVariantAttributes() 53 | 54 | length = false 55 | bodyContent = false 56 | match = false 57 | 58 | pageChanges.each do |change| 59 | length = true if change == 'content_length' 60 | bodyContent = true if change == 'whole_body_content' 61 | end 62 | 63 | # XXX: ruby string contains shim 64 | match = helpers.bytesToString(newReqRes.getResponse())['1337'] 65 | 66 | if (length && bodyContent && match) 67 | issues = ArrayList.new 68 | issues.add(ELJ.new(newReqRes, callbacks, helpers)) 69 | return issues 70 | else 71 | return nil 72 | end 73 | end 74 | 75 | 76 | def consolidateDuplicateIssues(isb, isa) 77 | if Arrays.uquals(isb.getHttpMessages()[0].getResponse(), isa.getHttpMessages()[0].getResponse()) 78 | return -1 79 | else 80 | return 0 81 | end 82 | end 83 | 84 | end 85 | 86 | class ELJ 87 | include IScanIssue 88 | attr_reader :helpers 89 | attr_reader :reqres 90 | attr_reader :callbacks 91 | 92 | def initialize(reqres, callbacks, helpers) 93 | @reqres = reqres 94 | @callbacks = callbacks 95 | @helpers = helpers 96 | end 97 | 98 | 99 | def getHost() 100 | return reqres.getHost() 101 | end 102 | 103 | 104 | def getPort() 105 | return reqres.getPort() 106 | end 107 | 108 | 109 | def getProtocol() 110 | return reqres.getProtocol() 111 | end 112 | 113 | 114 | def getUrl() 115 | return reqres.getUrl() 116 | end 117 | 118 | 119 | def getIssueName() 120 | return 'Expression Language (EL) Injection Detected' 121 | end 122 | 123 | 124 | def getIssueType() 125 | return 0x08000000 # See http://portswigger.net/burp/help/scanner_issuetypes.html 126 | end 127 | 128 | 129 | def getSeverity() 130 | return 'High' # 'High', 'Medium', 'Low', 'Information' or 'False positive' 131 | end 132 | 133 | 134 | def getConfidence() 135 | return 'Firm' # 'Certain', 'Firm' or 'Tentative' 136 | end 137 | 138 | 139 | def getIssueBackground() 140 | return 'Expression Language injections occur when input data is evaluated ' + 141 | 'by an expression language interpreter. An attacker can read server-side ' + 142 | 'data, such as the content of server-side variables, and some other inner ' + 143 | 'configuration details.' 144 | end 145 | 146 | 147 | def getRemediationBackground() 148 | return 'Apply input validation best practices, and reject $, # and other variations.' 149 | end 150 | 151 | 152 | def getIssueDetail() 153 | return 'Burp Scanner has identified an Expression Language injection in:' + 154 | reqres.getUrl().toString() + '

' 155 | end 156 | 157 | 158 | def getRemediationDetail() 159 | return nil 160 | end 161 | 162 | 163 | def getHttpMessages() 164 | #print "getHttpMessages" 165 | # Let's highlight the specific string in the response that triggered the issue 166 | strRes = helpers.bytesToString(reqres.getResponse()) 167 | marks = [] 168 | # XXX: ruby strings doesn't have indexOf, use index instead 169 | marks[0] = strRes.index('1337') 170 | marks[1] = marks[0] + 4 171 | marksList = ArrayList.new 172 | marksList.add(marks.to_java Java::int) 173 | reqresMark = callbacks.applyMarkers(reqres, nil, marksList) 174 | rra = [reqresMark].to_java(IHttpRequestResponse) 175 | #print "rra #{rra}" 176 | return rra 177 | end 178 | 179 | 180 | def getHttpService() 181 | return reqres.getHttpService() 182 | end 183 | end 184 | -------------------------------------------------------------------------------- /DetectELJ/Ruby/WIP1/BurpExtenderWIP1.rb: -------------------------------------------------------------------------------- 1 | # 2 | # DetectELJ - Active scanner extension to detect Expression Language Injection vulnerabilities 3 | # 4 | # Copyright (c) 2017 Doyensec LLC. Made with love by Andrea Brancaleoni. 5 | # 6 | require 'java' 7 | 8 | java_import 'burp.IBurpExtender' 9 | java_import 'burp.IScannerCheck' 10 | java_import 'burp.IScanIssue' 11 | java_import 'burp.IHttpRequestResponse' 12 | java_import 'java.io.PrintWriter' 13 | java_import 'java.net.URL' 14 | java_import 'java.util.ArrayList' 15 | java_import 'java.util.Arrays' 16 | java_import 'java.util.List' 17 | 18 | class BurpExtender 19 | include IBurpExtender 20 | include IScannerCheck 21 | 22 | attr_reader :helpers 23 | attr_reader :callbacks 24 | 25 | def registerExtenderCallbacks(callbacks) 26 | @callbacks = callbacks 27 | @helpers = callbacks.getHelpers() 28 | callbacks.setExtensionName('DetectELJ') 29 | 30 | callbacks.issueAlert('DetectELJ Active Scanner check enabled') 31 | 32 | stdout = PrintWriter.new(callbacks.getStdout(), true) 33 | stderr = PrintWriter.new(callbacks.getStderr(), true) 34 | 35 | callbacks.registerScannerCheck(self) 36 | end 37 | 38 | def print(e) 39 | @callbacks.issueAlert(e.to_s) 40 | end 41 | 42 | def doPassiveScan(ihrr) 43 | return nil # Active scanner check only 44 | end 45 | 46 | 47 | def doActiveScan(ihrr, isip) 48 | # 1 - Create a new request with our custom payload (tip: buildRequest) 49 | 50 | # 2 - Send the HTTP request 51 | 52 | # 3 - Diff original and new responses (tip: analyzeResponseVariations and getVariantAttributes) 53 | 54 | # 4 - Based on page changes, determine whether the page is vulnerable or not 55 | 56 | # 5 - If vulnerable, create a new IScanIssue and return the List 57 | end 58 | 59 | 60 | def consolidateDuplicateIssues(isb, isa) 61 | # TODO 62 | end 63 | 64 | end 65 | 66 | class ELJ 67 | # TODO 68 | end 69 | -------------------------------------------------------------------------------- /DetectELJ/Ruby/WIP2/BurpExtenderWIP2.rb: -------------------------------------------------------------------------------- 1 | # 2 | # DetectELJ - Active scanner extension to detect Expression Language Injection vulnerabilities 3 | # 4 | # Copyright (c) 2017 Doyensec LLC. Made with love by Andrea Brancaleoni. 5 | # 6 | require 'java' 7 | 8 | java_import 'burp.IBurpExtender' 9 | java_import 'burp.IScannerCheck' 10 | java_import 'burp.IScanIssue' 11 | java_import 'burp.IHttpRequestResponse' 12 | java_import 'java.io.PrintWriter' 13 | java_import 'java.net.URL' 14 | java_import 'java.util.ArrayList' 15 | java_import 'java.util.Arrays' 16 | java_import 'java.util.List' 17 | 18 | class BurpExtender 19 | include IBurpExtender 20 | include IScannerCheck 21 | 22 | attr_reader :helpers 23 | attr_reader :callbacks 24 | 25 | def registerExtenderCallbacks(callbacks) 26 | @callbacks = callbacks 27 | @helpers = callbacks.getHelpers() 28 | callbacks.setExtensionName('DetectELJ') 29 | 30 | callbacks.issueAlert('DetectELJ Active Scanner check enabled') 31 | 32 | stdout = PrintWriter.new(callbacks.getStdout(), true) 33 | stderr = PrintWriter.new(callbacks.getStderr(), true) 34 | 35 | callbacks.registerScannerCheck(self) 36 | end 37 | 38 | def print(e) 39 | @callbacks.issueAlert(e.to_s) 40 | end 41 | 42 | def doPassiveScan(ihrr) 43 | return nil # Active scanner check only 44 | end 45 | 46 | 47 | def doActiveScan(ihrr, isip) 48 | # 1 - Create a new request with our custom payload (tip: buildRequest) 49 | withPayload = isip.buildRequest('${1336+1}'.to_java_bytes()) 50 | # 2 - Send the HTTP request 51 | newReqRes = callbacks.makeHttpRequest(ihrr.getHttpService(), withPayload) 52 | # 3 - Diff original and new responses (tip: analyzeResponseVariations and getVariantAttributes) 53 | variation = helpers.analyzeResponseVariations(ihrr.getResponse(), newReqRes.getResponse()) 54 | pageChanges = variation.getVariantAttributes() 55 | # 4 - Based on page changes, determine whether the page is vulnerable or not 56 | length = false 57 | bodyContent = false 58 | match = false 59 | 60 | pageChanges.each do |change| 61 | length = true if change == 'content_length' 62 | bodyContent = true if change == 'whole_body_content' 63 | end 64 | 65 | # XXX: ruby string contains shim 66 | match = helpers.bytesToString(newReqRes.getResponse())['1337'] 67 | # 5 - If vulnerable, create a new IScanIssue and return the List 68 | if (length && bodyContent && match) 69 | # TODO 70 | else 71 | return nil 72 | end 73 | end 74 | 75 | 76 | def consolidateDuplicateIssues(isb, isa) 77 | # TODO 78 | end 79 | 80 | end 81 | 82 | class ELJ 83 | include IScanIssue 84 | attr_reader :helpers 85 | attr_reader :reqres 86 | attr_reader :callbacks 87 | 88 | def initialize(reqres, callbacks, helpers) 89 | @reqres = reqres 90 | @callbacks = callbacks 91 | @helpers = helpers 92 | end 93 | 94 | 95 | def getHost() 96 | return reqres.getHost() 97 | end 98 | 99 | 100 | def getPort() 101 | return reqres.getPort() 102 | end 103 | 104 | 105 | def getProtocol() 106 | return reqres.getProtocol() 107 | end 108 | 109 | 110 | def getUrl() 111 | return reqres.getUrl() 112 | end 113 | 114 | 115 | def getIssueName() 116 | return 'Expression Language (EL) Injection Detected' 117 | end 118 | 119 | 120 | def getIssueType() 121 | return 0x08000000 # See http://portswigger.net/burp/help/scanner_issuetypes.html 122 | end 123 | 124 | 125 | def getSeverity() 126 | return 'High' # 'High', 'Medium', 'Low', 'Information' or 'False positive' 127 | end 128 | 129 | 130 | def getConfidence() 131 | return 'Firm' # 'Certain', 'Firm' or 'Tentative' 132 | end 133 | 134 | 135 | def getIssueBackground() 136 | return 'Expression Language injections occur when input data is evaluated ' + 137 | 'by an expression language interpreter. An attacker can read server-side ' + 138 | 'data, such as the content of server-side variables, and some other inner ' + 139 | 'configuration details.' 140 | end 141 | 142 | 143 | def getRemediationBackground() 144 | return 'Apply input validation best practices, and reject $, # and other variations.' 145 | end 146 | 147 | 148 | def getIssueDetail() 149 | return 'Burp Scanner has identified an Expression Language injection in:' + 150 | reqres.getUrl().toString() + '

' 151 | end 152 | 153 | 154 | def getRemediationDetail() 155 | return nil 156 | end 157 | 158 | 159 | def getHttpMessages() 160 | # Let's highlight the specific string in the response that triggered the issue 161 | # TODO 162 | end 163 | 164 | 165 | def getHttpService() 166 | return reqres.getHttpService() 167 | end 168 | end 169 | -------------------------------------------------------------------------------- /DetectSRI/.gitignore: -------------------------------------------------------------------------------- 1 | # Package Files # 2 | *.jar 3 | *.war 4 | *.ear 5 | 6 | # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml 7 | hs_err_pid* 8 | 9 | #ant specific 10 | dist/ 11 | build/ 12 | build.xml 13 | 14 | #netbeans specific 15 | core 16 | nbproject/* 17 | libs/* 18 | lib/* 19 | manifest.mf 20 | .jacocoverage/ 21 | coverage/ 22 | src/ 23 | 24 | #java specific 25 | *.class 26 | 27 | #general swap/backup files 28 | *.so 29 | *.log 30 | *.out 31 | *~ 32 | *.swp 33 | *.DS_Store 34 | *.lock 35 | 36 | #idea specific 37 | .classpath 38 | .project 39 | .settings 40 | .idea 41 | .metadata 42 | *.iml 43 | *.ipr 44 | **/*~ 45 | /target/ 46 | -------------------------------------------------------------------------------- /DetectSRI/Java/Final/burp/BurpExtender.java: -------------------------------------------------------------------------------- 1 | /* 2 | * DetectSRI - A passive scanner extension to detect missing Subresource Integrity (SRI) within a page 3 | * 4 | * Copyright (c) 2017 Doyensec LLC. Made with love by Luca Carettoni. 5 | */ 6 | package burp; 7 | 8 | import java.io.PrintWriter; 9 | import java.net.URL; 10 | import java.util.ArrayList; 11 | import java.util.List; 12 | import java.util.regex.Matcher; 13 | import java.util.regex.Pattern; 14 | 15 | public class BurpExtender implements IBurpExtender, IScannerCheck { 16 | 17 | private IBurpExtenderCallbacks callbacks; 18 | private IExtensionHelpers helpers; 19 | 20 | @Override 21 | public void registerExtenderCallbacks(IBurpExtenderCallbacks callbacks) { 22 | this.callbacks = callbacks; 23 | helpers = callbacks.getHelpers(); 24 | callbacks.setExtensionName("DetectSRI"); 25 | 26 | callbacks.issueAlert("DetectSRI Passive Scanner check enabled"); 27 | 28 | PrintWriter stdout = new PrintWriter(callbacks.getStdout(), true); 29 | PrintWriter stderr = new PrintWriter(callbacks.getStderr(), true); 30 | 31 | callbacks.registerScannerCheck(this); 32 | } 33 | 34 | @Override 35 | public List doPassiveScan(IHttpRequestResponse ihrr) { 36 | 37 | String response = helpers.bytesToString(ihrr.getResponse()); 38 | Pattern p = Pattern.compile(".*integrity=\"(sha256|sha384|sha512)-[A-Za-z0-9+/=]+.*", Pattern.DOTALL); 39 | Matcher m = p.matcher(response); 40 | //Check match for html pages only 41 | if (response.contains(" issues = new ArrayList<>(1); 44 | issues.add(new SRI(ihrr)); 45 | return issues; 46 | } 47 | return null; 48 | } 49 | 50 | @Override 51 | public List doActiveScan(IHttpRequestResponse ihrr, IScannerInsertionPoint isip) { 52 | return null; //Passive scanner check only 53 | } 54 | 55 | @Override 56 | public int consolidateDuplicateIssues(IScanIssue isb, IScanIssue isa) { 57 | return -1; 58 | } 59 | 60 | class SRI implements IScanIssue { 61 | 62 | private final IHttpRequestResponse reqres; 63 | 64 | public SRI(IHttpRequestResponse reqres) { 65 | this.reqres = reqres; 66 | } 67 | 68 | @Override 69 | public String getHost() { 70 | return reqres.getHost(); 71 | } 72 | 73 | @Override 74 | public int getPort() { 75 | return reqres.getPort(); 76 | } 77 | 78 | @Override 79 | public String getProtocol() { 80 | return reqres.getProtocol(); 81 | } 82 | 83 | @Override 84 | public URL getUrl() { 85 | return reqres.getUrl(); 86 | } 87 | 88 | @Override 89 | public String getIssueName() { 90 | return "Subresource Integrity (SRI) Missing"; 91 | } 92 | 93 | @Override 94 | public int getIssueType() { 95 | return 0x08000000; //See http://portswigger.net/burp/help/scanner_issuetypes.html 96 | } 97 | 98 | @Override 99 | public String getSeverity() { 100 | return "Information"; // "High", "Medium", "Low", "Information" or "False positive" 101 | } 102 | 103 | @Override 104 | public String getConfidence() { 105 | return "Certain"; //"Certain", "Firm" or "Tentative" 106 | } 107 | 108 | @Override 109 | public String getIssueBackground() { 110 | return "Subresource Integrity (SRI) is a security feature that enables " 111 | + "browsers to verify that files they fetch (for example, from a CDN) " 112 | + "are delivered without unexpected manipulation. It works by allowing" 113 | + "you to provide a cryptographic hash that a fetched file must match."; 114 | } 115 | 116 | @Override 117 | public String getRemediationBackground() { 118 | return "This is an informational finding only.
"; 119 | } 120 | 121 | @Override 122 | public String getIssueDetail() { 123 | return "Burp Scanner has not identified Subresource Integrity (SRI) attributes in the following page: " 124 | + reqres.getUrl().toString() + "

"; 125 | } 126 | 127 | @Override 128 | public String getRemediationDetail() { 129 | return null; 130 | } 131 | 132 | @Override 133 | public IHttpRequestResponse[] getHttpMessages() { 134 | IHttpRequestResponse[] rra = { reqres }; 135 | return rra; 136 | } 137 | 138 | @Override 139 | public IHttpService getHttpService() { 140 | return reqres.getHttpService(); 141 | } 142 | } 143 | } 144 | -------------------------------------------------------------------------------- /DetectSRI/Java/WIP1/burp/BurpExtenderWIP1.java: -------------------------------------------------------------------------------- 1 | /* 2 | * DetectSRI - A passive scanner extension to detect missing Subresource Integrity (SRI) within a page 3 | * 4 | * Copyright (c) 2017 Doyensec LLC. Made with love by Luca Carettoni. 5 | */ 6 | package burp; 7 | 8 | import java.io.PrintWriter; 9 | import java.net.URL; 10 | import java.util.ArrayList; 11 | import java.util.List; 12 | import java.util.regex.Matcher; 13 | import java.util.regex.Pattern; 14 | 15 | public class BurpExtender implements IBurpExtender, IScannerCheck { 16 | 17 | private IBurpExtenderCallbacks callbacks; 18 | private IExtensionHelpers helpers; 19 | 20 | @Override 21 | public void registerExtenderCallbacks(IBurpExtenderCallbacks callbacks) { 22 | this.callbacks = callbacks; 23 | helpers = callbacks.getHelpers(); 24 | callbacks.setExtensionName("DetectSRI"); 25 | 26 | callbacks.issueAlert("DetectSRI Passive Scanner check enabled"); 27 | 28 | PrintWriter stdout = new PrintWriter(callbacks.getStdout(), true); 29 | PrintWriter stderr = new PrintWriter(callbacks.getStderr(), true); 30 | 31 | callbacks.registerScannerCheck(this); 32 | } 33 | 34 | @Override 35 | public List doPassiveScan(IHttpRequestResponse ihrr) { 36 | 37 | // 1 - Convert byte[] response to String 38 | 39 | // 2 - Check if the page includes a 'integrity="(sha256|sha384|sha512) ...' attribute (tip: use RegExp Pattern.compile and matcher) 40 | 41 | // 3 - Based on the match and page type, determine whether the page is vulnerable or not 42 | 43 | //4 - If vulnerable, create a new IScanIssue and return the List 44 | 45 | } 46 | 47 | @Override 48 | public List doActiveScan(IHttpRequestResponse ihrr, IScannerInsertionPoint isip) { 49 | return null; //Passive scanner check only 50 | } 51 | 52 | @Override 53 | public int consolidateDuplicateIssues(IScanIssue isb, IScanIssue isa) { 54 | return -1; 55 | } 56 | 57 | class SRI implements IScanIssue { 58 | //TODO 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /DetectSRI/Java/WIP2/burp/BurpExtenderWIP2.java: -------------------------------------------------------------------------------- 1 | /* 2 | * DetectSRI - A passive scanner extension to detect missing Subresource Integrity (SRI) within a page 3 | * 4 | * Copyright (c) 2017 Doyensec LLC. Made with love by Luca Carettoni. 5 | */ 6 | package burp; 7 | 8 | import java.io.PrintWriter; 9 | import java.net.URL; 10 | import java.util.ArrayList; 11 | import java.util.List; 12 | import java.util.regex.Matcher; 13 | import java.util.regex.Pattern; 14 | 15 | public class BurpExtender implements IBurpExtender, IScannerCheck { 16 | 17 | private IBurpExtenderCallbacks callbacks; 18 | private IExtensionHelpers helpers; 19 | 20 | @Override 21 | public void registerExtenderCallbacks(IBurpExtenderCallbacks callbacks) { 22 | this.callbacks = callbacks; 23 | helpers = callbacks.getHelpers(); 24 | callbacks.setExtensionName("DetectSRI"); 25 | 26 | callbacks.issueAlert("DetectSRI Passive Scanner check enabled"); 27 | 28 | PrintWriter stdout = new PrintWriter(callbacks.getStdout(), true); 29 | PrintWriter stderr = new PrintWriter(callbacks.getStderr(), true); 30 | 31 | callbacks.registerScannerCheck(this); 32 | } 33 | 34 | @Override 35 | public List doPassiveScan(IHttpRequestResponse ihrr) { 36 | 37 | // 1 - Convert byte[] response to String 38 | String response = helpers.bytesToString(ihrr.getResponse()); 39 | // 2 - Check if the page includes a 'integrity="(sha256|sha384|sha512) ...' attribute (tip: use RegExp Pattern.compile and matcher) 40 | Pattern p = Pattern.compile(".*integrity=\"(sha256|sha384|sha512)-[A-Za-z0-9+/=]+.*", Pattern.DOTALL); 41 | Matcher m = p.matcher(response); 42 | // 3 - Based on the match and page type, determine whether the page is vulnerable or not 43 | if (response.contains(" 45 | //TODO 46 | } 47 | return null; 48 | } 49 | 50 | @Override 51 | public List doActiveScan(IHttpRequestResponse ihrr, IScannerInsertionPoint isip) { 52 | return null; //Passive scanner check only 53 | } 54 | 55 | @Override 56 | public int consolidateDuplicateIssues(IScanIssue isb, IScanIssue isa) { 57 | return -1; 58 | } 59 | 60 | class SRI implements IScanIssue { 61 | 62 | private final IHttpRequestResponse reqres; 63 | 64 | public SRI(IHttpRequestResponse reqres) { 65 | this.reqres = reqres; 66 | } 67 | 68 | @Override 69 | public String getHost() { 70 | return reqres.getHost(); 71 | } 72 | 73 | @Override 74 | public int getPort() { 75 | return reqres.getPort(); 76 | } 77 | 78 | @Override 79 | public String getProtocol() { 80 | return reqres.getProtocol(); 81 | } 82 | 83 | @Override 84 | public URL getUrl() { 85 | return reqres.getUrl(); 86 | } 87 | 88 | @Override 89 | public String getIssueName() { 90 | return "Subresource Integrity (SRI) Missing"; 91 | } 92 | 93 | @Override 94 | public int getIssueType() { 95 | return 0x08000000; //See http://portswigger.net/burp/help/scanner_issuetypes.html 96 | } 97 | 98 | @Override 99 | public String getSeverity() { 100 | return "Information"; // "High", "Medium", "Low", "Information" or "False positive" 101 | } 102 | 103 | @Override 104 | public String getConfidence() { 105 | return "Certain"; //"Certain", "Firm" or "Tentative" 106 | } 107 | 108 | @Override 109 | public String getIssueBackground() { 110 | return "Subresource Integrity (SRI) is a security feature that enables " 111 | + "browsers to verify that files they fetch (for example, from a CDN) " 112 | + "are delivered without unexpected manipulation. It works by allowing" 113 | + "you to provide a cryptographic hash that a fetched file must match."; 114 | } 115 | 116 | @Override 117 | public String getRemediationBackground() { 118 | return "This is an informational finding only.
"; 119 | } 120 | 121 | @Override 122 | public String getIssueDetail() { 123 | return "Burp Scanner has not identified Subresource Integrity (SRI) attributes in the following page: " 124 | + reqres.getUrl().toString() + "

"; 125 | } 126 | 127 | @Override 128 | public String getRemediationDetail() { 129 | return null; 130 | } 131 | 132 | @Override 133 | public IHttpRequestResponse[] getHttpMessages() { 134 | IHttpRequestResponse[] rra = { reqres }; 135 | return rra; 136 | } 137 | 138 | @Override 139 | public IHttpService getHttpService() { 140 | return reqres.getHttpService(); 141 | } 142 | } 143 | } 144 | -------------------------------------------------------------------------------- /DetectSRI/Python/Final/BurpExtender.py: -------------------------------------------------------------------------------- 1 | # 2 | # DetectSRI - A passive scanner extension to detect missing Subresource Integrity (SRI) within a page 3 | # 4 | # Copyright (c) 2017 Doyensec LLC. Made with love by Andrea Brancaleoni. 5 | # 6 | from burp import IBurpExtender, IScannerCheck, IScanIssue 7 | from java.io import PrintWriter 8 | from java.net import URL 9 | from java.util import ArrayList, List 10 | from java.util.regex import Matcher, Pattern 11 | 12 | 13 | class BurpExtender(IBurpExtender, IScannerCheck): 14 | def registerExtenderCallbacks(self, callbacks): 15 | self.callbacks = callbacks 16 | self.helpers = callbacks.getHelpers() 17 | callbacks.setExtensionName("DetectSRI") 18 | 19 | callbacks.issueAlert("DetectSRI Passive Scanner check enabled") 20 | 21 | stdout = PrintWriter(callbacks.getStdout(), True) 22 | stderr = PrintWriter(callbacks.getStderr(), True) 23 | 24 | callbacks.registerScannerCheck(self) 25 | 26 | def doPassiveScan(self, ihrr): 27 | response = self.helpers.bytesToString(ihrr.getResponse()) 28 | p = Pattern.compile('.*integrity=\"(sha256|sha384|sha512)-[A-Za-z0-9+/=]+.*', Pattern.DOTALL) 29 | m = p.matcher(response) 30 | # Check match for html pages only 31 | # XXX: Java string are automatically boxed into python unicode objects, 32 | # therefore is not possible to use the contains method anymore. 33 | # In order to check if a substring is present in a string, we need 34 | # to use the in operator. 35 | if "informational finding only.
" 86 | 87 | def getIssueDetail(self): 88 | return str("Burp Scanner has not identified Subresource Integrity (SRI) attributes in the following page: " 89 | "%s

" % (self.reqres.getUrl().toString())) 90 | 91 | def getRemediationDetail(self): 92 | return None 93 | 94 | def getHttpMessages(self): 95 | # XXX: Jython arrays are automatically boxed in Java arrays when the 96 | # function returns 97 | rra = [self.reqres] 98 | return rra 99 | 100 | def getHttpService(self): 101 | return self.reqres.getHttpService() 102 | -------------------------------------------------------------------------------- /DetectSRI/Python/WIP1/BurpExtenderWIP1.py: -------------------------------------------------------------------------------- 1 | # 2 | # DetectSRI - A passive scanner extension to detect missing Subresource Integrity (SRI) within a page 3 | # 4 | # Copyright (c) 2017 Doyensec LLC. Made with love by Andrea Brancaleoni. 5 | # 6 | from burp import IBurpExtender, IScannerCheck, IScanIssue 7 | from java.io import PrintWriter 8 | from java.net import URL 9 | from java.util import ArrayList, List 10 | from java.util.regex import Matcher, Pattern 11 | 12 | 13 | class BurpExtender(IBurpExtender, IScannerCheck): 14 | def registerExtenderCallbacks(self, callbacks): 15 | self.callbacks = callbacks 16 | self.helpers = callbacks.getHelpers() 17 | callbacks.setExtensionName("DetectSRI") 18 | 19 | callbacks.issueAlert("DetectSRI Passive Scanner check enabled") 20 | 21 | stdout = PrintWriter(callbacks.getStdout(), True) 22 | stderr = PrintWriter(callbacks.getStderr(), True) 23 | 24 | callbacks.registerScannerCheck(self) 25 | 26 | def doPassiveScan(self, ihrr): 27 | # 1 - Convert byte[] response to String 28 | 29 | # 2 - Check if the page includes a 'integrity="(sha256|sha384|sha512) ...' attribute (tip: use RegExp Pattern.compile and matcher) 30 | 31 | # 3 - Based on the match and page type, determine whether the page is vulnerable or not 32 | 33 | # 4 - If vulnerable, create a new IScanIssue and return the List 34 | 35 | def doActiveScan(self, ihrr, isip): 36 | return None # Passive scanner check only 37 | 38 | def consolidateDuplicateIssues(self, isb, isa): 39 | return -1 40 | 41 | 42 | class SRI(IScanIssue): 43 | # TODO 44 | pass 45 | -------------------------------------------------------------------------------- /DetectSRI/Python/WIP2/BurpExtenderWIP2.py: -------------------------------------------------------------------------------- 1 | # 2 | # DetectSRI - A passive scanner extension to detect missing Subresource Integrity (SRI) within a page 3 | # 4 | # Copyright (c) 2017 Doyensec LLC. Made with love by Andrea Brancaleoni. 5 | # 6 | from burp import IBurpExtender, IScannerCheck, IScanIssue 7 | from java.io import PrintWriter 8 | from java.net import URL 9 | from java.util import ArrayList, List 10 | from java.util.regex import Matcher, Pattern 11 | 12 | 13 | class BurpExtender(IBurpExtender, IScannerCheck): 14 | def registerExtenderCallbacks(self, callbacks): 15 | self.callbacks = callbacks 16 | self.helpers = callbacks.getHelpers() 17 | callbacks.setExtensionName("DetectSRI") 18 | 19 | callbacks.issueAlert("DetectSRI Passive Scanner check enabled") 20 | 21 | stdout = PrintWriter(callbacks.getStdout(), True) 22 | stderr = PrintWriter(callbacks.getStderr(), True) 23 | 24 | callbacks.registerScannerCheck(self) 25 | 26 | def doPassiveScan(self, ihrr): 27 | # 1 - Convert byte[] response to String 28 | response = self.helpers.bytesToString(ihrr.getResponse()) 29 | # 2 - Check if the page includes a 'integrity="(sha256|sha384|sha512) ...' attribute (tip: use RegExp Pattern.compile and matcher) 30 | p = Pattern.compile('.*integrity=\"(sha256|sha384|sha512)-[A-Za-z0-9+/=]+.*', Pattern.DOTALL) 31 | m = p.matcher(response) 32 | # 3 - Based on the match and page type, determine whether the page is vulnerable or not 33 | # Check match for html pages only 34 | # XXX: Java string are automatically boxed into python unicode objects, 35 | # therefore is not possible to use the contains method anymore. 36 | # In order to check if a substring is present in a string, we need 37 | # to use the in operator. 38 | if " 40 | # TODO 41 | 42 | return None 43 | 44 | def doActiveScan(self, ihrr, isip): 45 | return None # Passive scanner check only 46 | 47 | def consolidateDuplicateIssues(self, isb, isa): 48 | return -1 49 | 50 | 51 | class SRI(IScanIssue): 52 | def __init__(self, reqres): 53 | self.reqres = reqres 54 | 55 | def getHost(self): 56 | return self.reqres.getHost() 57 | 58 | def getPort(self): 59 | return self.reqres.getPort() 60 | 61 | def getProtocol(self): 62 | return self.reqres.getProtocol() 63 | 64 | def getUrl(self): 65 | return self.reqres.getUrl() 66 | 67 | def getIssueName(self): 68 | return "Subresource Integrity (SRI) Missing" 69 | 70 | def getIssueType(self): 71 | return 0x08000000 # See http:#portswigger.net/burp/help/scanner_issuetypes.html 72 | 73 | def getSeverity(self): 74 | return "Information" # "High", "Medium", "Low", "Information" or "False positive" 75 | 76 | def getConfidence(self): 77 | return "Certain" # "Certain", "Firm" or "Tentative" 78 | 79 | def getIssueBackground(self): 80 | return str("Subresource Integrity (SRI) is a security feature that enables " 81 | "browsers to verify that files they fetch (for example, from a CDN) " 82 | "are delivered without unexpected manipulation. It works by allowing" 83 | "you to provide a cryptographic hash that a fetched file must match.") 84 | 85 | def getRemediationBackground(self): 86 | return "this is an informational finding only.
" 87 | 88 | def getIssueDetail(self): 89 | return str("Burp Scanner has not identified Subresource Integrity (SRI) attributes in the following page: " 90 | "%s

" % (self.reqres.getUrl().toString())) 91 | 92 | def getRemediationDetail(self): 93 | return None 94 | 95 | def getHttpMessages(self): 96 | # XXX: Jython arrays are automatically boxed in Java arrays when the 97 | # function returns 98 | rra = [self.reqres] 99 | return rra 100 | 101 | def getHttpService(self): 102 | return self.reqres.getHttpService() 103 | -------------------------------------------------------------------------------- /DetectSRI/Ruby/Final/BurpExtender.rb: -------------------------------------------------------------------------------- 1 | # 2 | # DetectSRI - A passive scanner extension to detect missing Subresource Integrity (SRI) within a page 3 | # 4 | # Copyright (c) 2017 Doyensec LLC. Made with love by Andrea Brancaleoni. 5 | # 6 | require 'java' 7 | java_import 'burp.IBurpExtender' 8 | java_import 'burp.IScannerCheck' 9 | java_import 'burp.IScanIssue' 10 | java_import 'burp.IHttpRequestResponse' 11 | java_import 'java.io.PrintWriter' 12 | java_import 'java.net.URL' 13 | java_import 'java.util.ArrayList' 14 | java_import 'java.util.List' 15 | java_import 'java.util.regex.Matcher' 16 | java_import 'java.util.regex.Pattern' 17 | 18 | class BurpExtender 19 | include IBurpExtender 20 | include IScannerCheck 21 | 22 | def registerExtenderCallbacks(callbacks) 23 | @callbacks = callbacks 24 | @helpers = callbacks.getHelpers() 25 | callbacks.setExtensionName("DetectSRI") 26 | 27 | callbacks.issueAlert("DetectSRI Passive Scanner check enabled") 28 | 29 | stdout = PrintWriter.new(callbacks.getStdout(), true) 30 | @stderr = PrintWriter.new(callbacks.getStderr(), true) 31 | 32 | callbacks.registerScannerCheck(self) 33 | end 34 | 35 | def doPassiveScan(ihrr) 36 | response = @helpers.bytesToString(ihrr.getResponse) 37 | p = Pattern.compile(".*integrity=\"(sha256|sha384|sha512)-[A-Za-z0-9+/=]+.*", Pattern::DOTALL) 38 | m = p.matcher(response) 39 | #Check match for html pages only 40 | # XXX: java strings were casted to ruby strings and therefore the contains 41 | # method is missing. We could use ruby methods instead. String[] methods 42 | # in ruby returns the index of the match or nil, then it is sufficient 43 | # to emulate the .contains Java String method. 44 | if (response["informational finding only.
" 110 | end 111 | 112 | def getIssueDetail() 113 | return "Burp Scanner has not identified Subresource Integrity (SRI) attributes in the following page: " + 114 | @reqres.getUrl().toString() + "

" 115 | end 116 | 117 | def getRemediationDetail() 118 | return nil 119 | end 120 | 121 | def getHttpMessages() 122 | # XXX: it is possible to cast a ruby array to a native Java array with the 123 | # to_java method 124 | return [@reqres].to_java(IHttpRequestResponse) 125 | end 126 | 127 | def getHttpService() 128 | return @reqres.getHttpService() 129 | end 130 | end 131 | -------------------------------------------------------------------------------- /DetectSRI/Ruby/WIP1/BurpExtenderWIP1.rb: -------------------------------------------------------------------------------- 1 | # 2 | # DetectSRI - A passive scanner extension to detect missing Subresource Integrity (SRI) within a page 3 | # 4 | # Copyright (c) 2017 Doyensec LLC. Made with love by Andrea Brancaleoni. 5 | # 6 | require 'java' 7 | java_import 'burp.IBurpExtender' 8 | java_import 'burp.IScannerCheck' 9 | java_import 'burp.IScanIssue' 10 | java_import 'burp.IHttpRequestResponse' 11 | java_import 'java.io.PrintWriter' 12 | java_import 'java.net.URL' 13 | java_import 'java.util.ArrayList' 14 | java_import 'java.util.List' 15 | java_import 'java.util.regex.Matcher' 16 | java_import 'java.util.regex.Pattern' 17 | 18 | class BurpExtender 19 | include IBurpExtender 20 | include IScannerCheck 21 | 22 | def registerExtenderCallbacks(callbacks) 23 | @callbacks = callbacks 24 | @helpers = callbacks.getHelpers() 25 | callbacks.setExtensionName("DetectSRI") 26 | 27 | callbacks.issueAlert("DetectSRI Passive Scanner check enabled") 28 | 29 | stdout = PrintWriter.new(callbacks.getStdout(), true) 30 | @stderr = PrintWriter.new(callbacks.getStderr(), true) 31 | 32 | callbacks.registerScannerCheck(self) 33 | end 34 | 35 | def doPassiveScan(ihrr) 36 | # 1 - Convert byte[] response to String 37 | 38 | # 2 - Check if the page includes a 'integrity="(sha256|sha384|sha512) ...' attribute (tip: use RegExp Pattern.compile and matcher) 39 | 40 | # 3 - Based on the match and page type, determine whether the page is vulnerable or not 41 | 42 | # 4 - If vulnerable, create a new IScanIssue and return the List 43 | 44 | end 45 | 46 | def doActiveScan(ihrr, isip) 47 | return nil #Passive scanner check only 48 | end 49 | 50 | def consolidateDuplicateIssues(isb, isa) 51 | return -1 52 | end 53 | end 54 | 55 | class SRI 56 | # TODO 57 | end 58 | -------------------------------------------------------------------------------- /DetectSRI/Ruby/WIP2/BurpExtenderWIP2.rb: -------------------------------------------------------------------------------- 1 | # 2 | # DetectSRI - A passive scanner extension to detect missing Subresource Integrity (SRI) within a page 3 | # 4 | # Copyright (c) 2017 Doyensec LLC. Made with love by Andrea Brancaleoni. 5 | # 6 | require 'java' 7 | java_import 'burp.IBurpExtender' 8 | java_import 'burp.IScannerCheck' 9 | java_import 'burp.IScanIssue' 10 | java_import 'burp.IHttpRequestResponse' 11 | java_import 'java.io.PrintWriter' 12 | java_import 'java.net.URL' 13 | java_import 'java.util.ArrayList' 14 | java_import 'java.util.List' 15 | java_import 'java.util.regex.Matcher' 16 | java_import 'java.util.regex.Pattern' 17 | 18 | class BurpExtender 19 | include IBurpExtender 20 | include IScannerCheck 21 | 22 | def registerExtenderCallbacks(callbacks) 23 | @callbacks = callbacks 24 | @helpers = callbacks.getHelpers() 25 | callbacks.setExtensionName("DetectSRI") 26 | 27 | callbacks.issueAlert("DetectSRI Passive Scanner check enabled") 28 | 29 | stdout = PrintWriter.new(callbacks.getStdout(), true) 30 | @stderr = PrintWriter.new(callbacks.getStderr(), true) 31 | 32 | callbacks.registerScannerCheck(self) 33 | end 34 | 35 | def doPassiveScan(ihrr) 36 | # 1 - Convert byte[] response to String 37 | response = @helpers.bytesToString(ihrr.getResponse) 38 | # 2 - Check if the page includes a 'integrity="(sha256|sha384|sha512) ...' attribute (tip: use RegExp Pattern.compile and matcher) 39 | p = Pattern.compile(".*integrity=\"(sha256|sha384|sha512)-[A-Za-z0-9+/=]+.*", Pattern::DOTALL) 40 | m = p.matcher(response) 41 | # 3 - Based on the match and page type, determine whether the page is vulnerable or not 42 | # Check match for html pages only 43 | # XXX: java strings were casted to ruby strings and therefore the contains 44 | # method is missing. We could use ruby methods instead. String[] methods 45 | # in ruby returns the index of the match or nil, then it is sufficient 46 | # to emulate the .contains Java String method. 47 | if (response[" 49 | # TODO 50 | end 51 | return nil 52 | end 53 | 54 | def doActiveScan(ihrr, isip) 55 | return nil #Passive scanner check only 56 | end 57 | 58 | def consolidateDuplicateIssues(isb, isa) 59 | return -1 60 | end 61 | end 62 | 63 | class SRI 64 | include IScanIssue 65 | 66 | def initialize(reqres) 67 | @reqres = reqres 68 | end 69 | 70 | def getHost() 71 | return @reqres.getHost() 72 | end 73 | 74 | def getPort() 75 | return @reqres.getPort() 76 | end 77 | 78 | def getProtocol() 79 | return @reqres.getProtocol() 80 | end 81 | 82 | def getUrl() 83 | return @reqres.getUrl() 84 | end 85 | 86 | def getIssueName() 87 | return "Subresource Integrity (SRI) Missing" 88 | end 89 | 90 | def getIssueType() 91 | return 0x08000000 #See http:#portswigger.net/burp/help/scanner_issuetypes.html 92 | end 93 | 94 | def getSeverity() 95 | return "Information" # "High", "Medium", "Low", "Information" or "False positive" 96 | end 97 | 98 | def getConfidence() 99 | return "Certain" #"Certain", "Firm" or "Tentative" 100 | end 101 | 102 | def getIssueBackground() 103 | return "Subresource Integrity (SRI) is a security feature that enables " + 104 | "browsers to verify that files they fetch (for example, from a CDN) " + 105 | "are delivered without unexpected manipulation. It works by allowing" + 106 | "you to provide a cryptographic hash that a fetched file must match." 107 | end 108 | 109 | def getRemediationBackground() 110 | return "this is an informational finding only.
" 111 | end 112 | 113 | def getIssueDetail() 114 | return "Burp Scanner has not identified Subresource Integrity (SRI) attributes in the following page: " + 115 | @reqres.getUrl().toString() + "

" 116 | end 117 | 118 | def getRemediationDetail() 119 | return nil 120 | end 121 | 122 | def getHttpMessages() 123 | # XXX: it is possible to cast a ruby array to a native Java array with the 124 | # to_java method 125 | return [@reqres].to_java(IHttpRequestResponse) 126 | end 127 | 128 | def getHttpService() 129 | return @reqres.getHttpService() 130 | end 131 | end 132 | -------------------------------------------------------------------------------- /Doyensec_DevelopingBurpSuiteExtensionsTraining.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/doyensec/burpdeveltraining/355eb0ae02dc8d34c114592bb036b7320e5bd54b/Doyensec_DevelopingBurpSuiteExtensionsTraining.pdf -------------------------------------------------------------------------------- /HelloBurp/.gitignore: -------------------------------------------------------------------------------- 1 | # Package Files # 2 | *.jar 3 | *.war 4 | *.ear 5 | 6 | # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml 7 | hs_err_pid* 8 | 9 | #ant specific 10 | dist/ 11 | build/ 12 | build.xml 13 | 14 | #netbeans specific 15 | core 16 | nbproject/* 17 | libs/* 18 | lib/* 19 | manifest.mf 20 | .jacocoverage/ 21 | coverage/ 22 | src/ 23 | 24 | #java specific 25 | *.class 26 | 27 | #general swap/backup files 28 | *.so 29 | *.log 30 | *.out 31 | *~ 32 | *.swp 33 | *.DS_Store 34 | *.lock 35 | 36 | #idea specific 37 | .classpath 38 | .project 39 | .settings 40 | .idea 41 | .metadata 42 | *.iml 43 | *.ipr 44 | **/*~ 45 | /target/ 46 | -------------------------------------------------------------------------------- /HelloBurp/Java/Final/burp/BurpExtender.java: -------------------------------------------------------------------------------- 1 | /* 2 | * HelloBurp - A simple extension to show alerts, stdout/stderr and custom UI 3 | * 4 | * Copyright (c) 2017 Doyensec LLC. Made with love by Luca Carettoni. 5 | */ 6 | 7 | package burp; 8 | 9 | import java.awt.Button; 10 | import java.awt.Color; 11 | import java.awt.Component; 12 | import java.awt.Panel; 13 | import java.io.PrintWriter; 14 | 15 | public class BurpExtender implements IBurpExtender { 16 | 17 | private IBurpExtenderCallbacks callbacks; 18 | private IExtensionHelpers helpers; 19 | 20 | @Override 21 | public void registerExtenderCallbacks(IBurpExtenderCallbacks callbacks) { 22 | this.callbacks = callbacks; 23 | helpers = callbacks.getHelpers(); 24 | callbacks.setExtensionName("Hello Burp!"); 25 | 26 | callbacks.issueAlert("Once again, Hello Burp!"); //Alerts tab 27 | 28 | PrintWriter stdout = new PrintWriter(callbacks.getStdout(), true); 29 | PrintWriter stderr = new PrintWriter(callbacks.getStderr(), true); 30 | stdout.println("Hello Burp in StdOut!"); //StdOut (either terminal, file or Burp's UI) 31 | stderr.println("Hello Burp in StdErr!"); //StdErr (either terminal, file or Burp's UI) 32 | 33 | callbacks.addSuiteTab(new HelloBurpTab()); //Custom tab with custom UI components 34 | } 35 | 36 | private class HelloBurpTab implements ITab { 37 | 38 | @Override 39 | public String getTabCaption() { 40 | return "Hello Burp Tab!"; 41 | } 42 | 43 | @Override 44 | public Component getUiComponent() { 45 | Panel panel = new Panel(); 46 | panel.setBackground(Color.gray); 47 | Button button = new Button("Hello Burp Button!"); 48 | panel.add(button); 49 | callbacks.customizeUiComponent(panel); //customize UI components in line with Burp's UI style 50 | return panel; 51 | } 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /HelloBurp/Java/WIP1/burp/BurpExtenderWIP1.java: -------------------------------------------------------------------------------- 1 | /* 2 | * HelloBurp - A simple extension to show alerts, stdout/stderr and custom UI 3 | * 4 | * Copyright (c) 2017 Doyensec LLC. Made with love by Luca Carettoni. 5 | */ 6 | 7 | package burp; 8 | 9 | import java.awt.Button; 10 | import java.awt.Color; 11 | import java.awt.Component; 12 | import java.awt.Panel; 13 | import java.io.PrintWriter; 14 | 15 | public class BurpExtender implements IBurpExtender { 16 | 17 | private IBurpExtenderCallbacks callbacks; 18 | private IExtensionHelpers helpers; 19 | 20 | @Override 21 | public void registerExtenderCallbacks(IBurpExtenderCallbacks callbacks) { 22 | this.callbacks = callbacks; 23 | helpers = callbacks.getHelpers(); 24 | callbacks.setExtensionName("Hello Burp!"); 25 | 26 | // 1 - Use issueAlert to trigger an alert 27 | 28 | // 2 - Use getStdout and getStderr to instantiate two PrintWriter instances 29 | 30 | // 3 - Instantiate a custom ITab implementation and add the tab to Burp (tip: use addSuiteTab) 31 | } 32 | 33 | private class HelloBurpTab implements ITab { 34 | 35 | @Override 36 | public String getTabCaption() { 37 | //TODO 38 | } 39 | 40 | @Override 41 | public Component getUiComponent() { 42 | //TODO 43 | } 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /HelloBurp/Java/WIP2/burp/BurpExtenderWIP2.java: -------------------------------------------------------------------------------- 1 | /* 2 | * HelloBurp - A simple extension to show alerts, stdout/stderr and custom UI 3 | * 4 | * Copyright (c) 2017 Doyensec LLC. Made with love by Luca Carettoni. 5 | */ 6 | 7 | package burp; 8 | 9 | import java.awt.Button; 10 | import java.awt.Color; 11 | import java.awt.Component; 12 | import java.awt.Panel; 13 | import java.io.PrintWriter; 14 | 15 | public class BurpExtender implements IBurpExtender { 16 | 17 | private IBurpExtenderCallbacks callbacks; 18 | private IExtensionHelpers helpers; 19 | 20 | @Override 21 | public void registerExtenderCallbacks(IBurpExtenderCallbacks callbacks) { 22 | this.callbacks = callbacks; 23 | helpers = callbacks.getHelpers(); 24 | callbacks.setExtensionName("Hello Burp!"); 25 | 26 | // 1 - Use issueAlert to trigger an alert 27 | callbacks.issueAlert("Once again, Hello Burp!"); //Alerts tab 28 | 29 | // 2 - Use getStdout and getStderr to instantiate two PrintWriter instances 30 | PrintWriter stdout = new PrintWriter(callbacks.getStdout(), true); 31 | PrintWriter stderr = new PrintWriter(callbacks.getStderr(), true); 32 | stdout.println("Hello Burp in StdOut!"); //StdOut (either terminal, file or Burp's UI) 33 | stderr.println("Hello Burp in StdErr!"); //StdErr (either terminal, file or Burp's UI) 34 | 35 | // 3 - Instantiate a custom ITab implementation and add the tab to Burp (tip: use addSuiteTab) 36 | callbacks.addSuiteTab(new HelloBurpTab()); //Custom tab with custom UI components 37 | } 38 | 39 | private class HelloBurpTab implements ITab { 40 | 41 | @Override 42 | public String getTabCaption() { 43 | //TODO 44 | } 45 | 46 | @Override 47 | public Component getUiComponent() { 48 | //TODO 49 | } 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /HelloBurp/Python/Final/BurpExtender.py: -------------------------------------------------------------------------------- 1 | # 2 | # HelloBurp - A simple extension to show alerts, stdout/stderr and custom UI 3 | # 4 | # Copyright (c) 2017 Doyensec LLC. Made with love by Andrea Brancaleoni. 5 | # 6 | 7 | from burp import IBurpExtender, ITab 8 | from java.awt import Button, Color, Panel 9 | from java.io import PrintWriter 10 | 11 | 12 | class BurpExtender(IBurpExtender): 13 | def registerExtenderCallbacks(self, callbacks): 14 | self.callbacks = callbacks 15 | self.helpers = callbacks.getHelpers() 16 | callbacks.setExtensionName('Hello Burp!') 17 | 18 | callbacks.issueAlert('Once again, Hello Burp!') # Alerts tab 19 | 20 | stdout = PrintWriter(callbacks.getStdout(), True) 21 | stderr = PrintWriter(callbacks.getStderr(), True) 22 | 23 | stdout.println('Hello Burp in StdOut!') # StdOut (either terminal, file or Burp's UI) 24 | stderr.println('Hello Burp in StdErr!') # StdErr (either terminal, file or Burp's UI) 25 | 26 | # XXX: It is not possible to use the "friendly" accessors in python 27 | # XXX: it is therefore necessary to pass the callback object during HelloBurpTab construction 28 | callbacks.addSuiteTab(HelloBurpTab(self.callbacks)) # Custom tab with custom UI components 29 | 30 | class HelloBurpTab(ITab): 31 | def __init__(self, callbacks): 32 | self.callbacks = callbacks 33 | 34 | def getTabCaption(self): 35 | return 'Hello Burp Tab!' 36 | 37 | def getUiComponent(self): 38 | panel = Panel() 39 | panel.setBackground(Color.gray) 40 | button = Button('Hello Burp Button!') 41 | panel.add(button) 42 | self.callbacks.customizeUiComponent(panel) # customize UI components in line with Burp's UI style 43 | return panel 44 | -------------------------------------------------------------------------------- /HelloBurp/Python/WIP1/BurpExtenderWIP1.py: -------------------------------------------------------------------------------- 1 | # 2 | # HelloBurp - A simple extension to show alerts, stdout/stderr and custom UI 3 | # 4 | # Copyright (c) 2017 Doyensec LLC. Made with love by Andrea Brancaleoni. 5 | # 6 | 7 | from burp import IBurpExtender, ITab 8 | from java.awt import Button, Color, Panel 9 | from java.io import PrintWriter 10 | 11 | 12 | class BurpExtender(IBurpExtender): 13 | def registerExtenderCallbacks(self, callbacks): 14 | self.callbacks = callbacks 15 | self.helpers = callbacks.getHelpers() 16 | callbacks.setExtensionName('Hello Burp!') 17 | 18 | # 1 - Use issueAlert to trigger an alert 19 | # 2 - Use getStdout and getStderr to instantiate two PrintWriter instances 20 | # 3 - Instantiate a custom ITab implementation and add the tab to Burp (tip: use addSuiteTab) 21 | 22 | 23 | class HelloBurpTab(ITab): 24 | def __init__(self, callbacks): 25 | self.callbacks = callbacks 26 | 27 | def getTabCaption(self): 28 | # TODO 29 | pass 30 | 31 | def getUiComponent(self): 32 | # TODO 33 | pass 34 | -------------------------------------------------------------------------------- /HelloBurp/Python/WIP2/BurpExtenderWIP2.py: -------------------------------------------------------------------------------- 1 | # 2 | # HelloBurp - A simple extension to show alerts, stdout/stderr and custom UI 3 | # 4 | # Copyright (c) 2017 Doyensec LLC. Made with love by Andrea Brancaleoni. 5 | # 6 | 7 | from burp import IBurpExtender, ITab 8 | from java.awt import Button, Color, Panel 9 | from java.io import PrintWriter 10 | 11 | 12 | class BurpExtender(IBurpExtender): 13 | def registerExtenderCallbacks(self, callbacks): 14 | self.callbacks = callbacks 15 | self.helpers = callbacks.getHelpers() 16 | callbacks.setExtensionName('Hello Burp!') 17 | 18 | # 1 - Use issueAlert to trigger an alert 19 | callbacks.issueAlert('Once again, Hello Burp!') # Alerts tab 20 | 21 | # 2 - Use getStdout and getStderr to instantiate two PrintWriter instances 22 | stdout = PrintWriter(callbacks.getStdout(), True) 23 | stderr = PrintWriter(callbacks.getStderr(), True) 24 | 25 | stdout.println('Hello Burp in StdOut!') # StdOut (either terminal, file or Burp's UI) 26 | stderr.println('Hello Burp in StdErr!') # StdErr (either terminal, file or Burp's UI) 27 | 28 | # XXX: It is not possible to use the "friendly" accessors in python 29 | # XXX: it is therefore necessary to pass the callback object during HelloBurpTab construction 30 | # 3 - Instantiate a custom ITab implementation and add the tab to Burp (tip: use addSuiteTab) 31 | callbacks.addSuiteTab(HelloBurpTab(self.callbacks)) # Custom tab with custom UI components 32 | 33 | class HelloBurpTab(ITab): 34 | def __init__(self, callbacks): 35 | self.callbacks = callbacks 36 | 37 | def getTabCaption(self): 38 | # TODO 39 | pass 40 | 41 | def getUiComponent(self): 42 | # TODO 43 | pass 44 | -------------------------------------------------------------------------------- /HelloBurp/Ruby/Final/BurpExtender.rb: -------------------------------------------------------------------------------- 1 | # 2 | # HelloBurp - A simple extension to show alerts, stdout/stderr and custom UI 3 | # 4 | # Copyright (c) 2017 Doyensec LLC. Made with love by Andrea Brancaleoni. 5 | # 6 | 7 | require 'java' 8 | java_import 'burp.IBurpExtender' 9 | java_import 'burp.ITab' 10 | java_import 'java.awt.Button' 11 | java_import 'java.awt.Color' 12 | java_import 'java.awt.Component' 13 | java_import 'java.awt.Panel' 14 | java_import 'java.io.PrintWriter' 15 | 16 | class BurpExtender 17 | include IBurpExtender 18 | 19 | def registerExtenderCallbacks(callbacks) 20 | @callbacks = callbacks 21 | @helpers = callbacks.getHelpers() 22 | callbacks.setExtensionName('Hello Burp!') 23 | 24 | callbacks.issueAlert('Once again, Hello Burp!') # Alerts tab 25 | 26 | stdout = PrintWriter.new(callbacks.getStdout, true) 27 | stderr = PrintWriter.new(callbacks.getStderr, true) 28 | 29 | stdout.println('Hello Burp in StdOut!') # StdOut (either terminal, file or Burp's UI) 30 | stderr.println('Hello Burp in StdErr!') # StdErr (either terminal, file or Burp's UI) 31 | 32 | # XXX: It is not possible to use the "friendly" accessors in ruby 33 | # XXX: it is therefore necessary to pass the callback object during HelloBurpTab construction 34 | callbacks.addSuiteTab(HelloBurpTab.new(@callbacks)) # Custom tab with custom UI components 35 | end 36 | end 37 | 38 | class HelloBurpTab 39 | include ITab 40 | def initialize(callbacks) 41 | @callbacks = callbacks 42 | end 43 | 44 | def getTabCaption 45 | 'Hello Burp Tab!' 46 | end 47 | 48 | def getUiComponent 49 | panel = Panel.new 50 | panel.setBackground(Color.gray) 51 | button = Button.new('Hello Burp Button!') 52 | panel.add(button) 53 | @callbacks.customizeUiComponent(panel) # customize UI components in line with Burp's UI style 54 | panel 55 | end 56 | end 57 | -------------------------------------------------------------------------------- /HelloBurp/Ruby/WIP1/BurpExtenderWIP1.rb: -------------------------------------------------------------------------------- 1 | # 2 | # HelloBurp - A simple extension to show alerts, stdout/stderr and custom UI 3 | # 4 | # Copyright (c) 2017 Doyensec LLC. Made with love by Andrea Brancaleoni. 5 | # 6 | 7 | require 'java' 8 | java_import 'burp.IBurpExtender' 9 | java_import 'burp.ITab' 10 | java_import 'java.awt.Button' 11 | java_import 'java.awt.Color' 12 | java_import 'java.awt.Component' 13 | java_import 'java.awt.Panel' 14 | java_import 'java.io.PrintWriter' 15 | 16 | class BurpExtender 17 | include IBurpExtender 18 | 19 | def registerExtenderCallbacks(callbacks) 20 | @callbacks = callbacks 21 | @helpers = callbacks.getHelpers() 22 | callbacks.setExtensionName('Hello Burp!') 23 | 24 | # 1 - Use issueAlert to trigger an alert 25 | # 2 - Use getStdout and getStderr to instantiate two PrintWriter instances 26 | # 3 - Instantiate a custom ITab implementation and add the tab to Burp (tip: use addSuiteTab) 27 | end 28 | end 29 | 30 | class HelloBurpTab 31 | include ITab 32 | def initialize(callbacks) 33 | @callbacks = callbacks 34 | end 35 | 36 | def getTabCaption 37 | # TODO 38 | end 39 | 40 | def getUiComponent 41 | # TODO 42 | end 43 | end 44 | -------------------------------------------------------------------------------- /HelloBurp/Ruby/WIP2/BurpExtenderWIP2.rb: -------------------------------------------------------------------------------- 1 | # 2 | # HelloBurp - A simple extension to show alerts, stdout/stderr and custom UI 3 | # 4 | # Copyright (c) 2017 Doyensec LLC. Made with love by Andrea Brancaleoni. 5 | # 6 | 7 | require 'java' 8 | java_import 'burp.IBurpExtender' 9 | java_import 'burp.ITab' 10 | java_import 'java.awt.Button' 11 | java_import 'java.awt.Color' 12 | java_import 'java.awt.Component' 13 | java_import 'java.awt.Panel' 14 | java_import 'java.io.PrintWriter' 15 | 16 | class BurpExtender 17 | include IBurpExtender 18 | 19 | def registerExtenderCallbacks(callbacks) 20 | @callbacks = callbacks 21 | @helpers = callbacks.getHelpers() 22 | callbacks.setExtensionName('Hello Burp!') 23 | 24 | # 1 - Use issueAlert to trigger an alert 25 | callbacks.issueAlert('Once again, Hello Burp!') # Alerts tab 26 | 27 | # 2 - Use getStdout and getStderr to instantiate two PrintWriter instances 28 | stdout = PrintWriter.new(callbacks.getStdout, true) 29 | stderr = PrintWriter.new(callbacks.getStderr, true) 30 | 31 | stdout.println('Hello Burp in StdOut!') # StdOut (either terminal, file or Burp's UI) 32 | stderr.println('Hello Burp in StdErr!') # StdErr (either terminal, file or Burp's UI) 33 | 34 | # XXX: It is not possible to use the "friendly" accessors in ruby 35 | # XXX: it is therefore necessary to pass the callback object during HelloBurpTab construction 36 | # 3 - Instantiate a custom ITab implementation and add the tab to Burp (tip: use addSuiteTab) 37 | callbacks.addSuiteTab(HelloBurpTab.new(@callbacks)) # Custom tab with custom UI components 38 | end 39 | end 40 | 41 | class HelloBurpTab 42 | include ITab 43 | def initialize(callbacks) 44 | @callbacks = callbacks 45 | end 46 | 47 | def getTabCaption 48 | # TODO 49 | end 50 | 51 | def getUiComponent 52 | # TODO 53 | end 54 | end 55 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Developing Burp Suite Extensions 2 | 3 | [![Doyensec](https://www.doyensec.com/images/logo.svg)](https://www.doyensec.com/images/logo.svg) 4 | 5 | This repository contains the slides and code for the training *Developing Burp Suite Extensions - From Manual Testing to Security Automation* 6 | 7 | # Content 8 | - **BurpExtensionTemplate** - Empty extension templates for NetBeans, Eclipse and IDEA 9 | - **HelloBurp** - Our first Burp extension 10 | - **SiteLogger** - Log sitemap and findings to database (MongoDB) 11 | - **ReplayAndDiff** - Replay a scan with a fresh session and diff the results 12 | - **DetectSRI** - Passive scanner check to detect the use of Subresource Integrity (SRI) attribute 13 | - **DetectELJ** - Active scanner check to detect Expression Language (EL) injection vulnerabilities 14 | - **Bradamsa** - Simplified code of [Bradansa Intruder payloads generator](https://github.com/ikkisoft/bradamsa) 15 | - **Doyensec_DevelopingBurpSuiteExtensionsTraining.pdf** - Full slides of the training (PDF, 155 pages) 16 | 17 | All exercises are provided in *Java*, *Python* and *Ruby*. 18 | 19 | This work is licensed under the Creative Commons **Attribution-NonCommercial-ShareAlike** 3.0 Unported (CC BY-NC-SA 3.0). You are free to **Share** and **Adapt** under the following terms: **Attribution**, **NonCommercial**, **ShareAlike**. 20 | 21 | ### Overview of the class 22 | In this hands-on class, attendees will learn how to design and develop Burp Suite extensions for a variety of tasks. In a few hours, we work on several plugins to improve manual security testing efforts as well as to create fully-automated security tools. This workshop is based on real-life use cases where the extension capabilities of the tool can be unleashed to improve efficiency and effectiveness of security auditing. As an attendee, you will bring home a full bag of tricks that will take your web security skills to the next level. The class is available in 1-day and 2-days versions. 23 | ### Audience 24 | Suitable for both web application security specialists and developers. Attendees are expected to have rudimental understanding of Burp Suite as well as basic object-oriented programming experience. While Burp extensions are developed live in Java, attendees can work on Python or Ruby since all exercises are also provided in those languages. 25 | ### Interested? 26 | More details on what to expect from this class can be found on our [blog post](https://blog.doyensec.com/2017/03/02/training-burp.html). 27 | We deliver this class during public events (e.g. security conferences) as well as private company workshops. If you're interested in a forthcoming public training or you want to know more about private classes, please contact info@doyensec.com 28 | -------------------------------------------------------------------------------- /ReplayAndDiff/.gitignore: -------------------------------------------------------------------------------- 1 | # Package Files # 2 | *.jar 3 | *.war 4 | *.ear 5 | 6 | # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml 7 | hs_err_pid* 8 | 9 | #ant specific 10 | dist/ 11 | build/ 12 | build.xml 13 | 14 | #netbeans specific 15 | core 16 | nbproject/* 17 | libs/* 18 | lib/* 19 | manifest.mf 20 | .jacocoverage/ 21 | coverage/ 22 | src/ 23 | 24 | #java specific 25 | *.class 26 | 27 | #general swap/backup files 28 | *.so 29 | *.log 30 | *.out 31 | *~ 32 | *.swp 33 | *.DS_Store 34 | *.lock 35 | 36 | #idea specific 37 | .classpath 38 | .project 39 | .settings 40 | .idea 41 | .metadata 42 | *.iml 43 | *.ipr 44 | **/*~ 45 | /target/ 46 | -------------------------------------------------------------------------------- /ReplayAndDiff/Java/Final/BurpExtender.java: -------------------------------------------------------------------------------- 1 | /* 2 | * ReplayAndDiff - Replay a scan with a fresh session and diff the results 3 | * 4 | * Copyright (c) 2017 Doyensec LLC. Made with love by Luca Carettoni. 5 | */ 6 | package burp; 7 | 8 | import com.mongodb.BasicDBObject; 9 | import com.mongodb.DB; 10 | import com.mongodb.DBCollection; 11 | import com.mongodb.DBCursor; 12 | import com.mongodb.DBObject; 13 | import com.mongodb.MongoClient; 14 | import java.io.File; 15 | import java.net.MalformedURLException; 16 | import java.net.URL; 17 | import java.net.UnknownHostException; 18 | import java.util.Iterator; 19 | 20 | /* 21 | * This extension can be executed in headless mode. Start burp using -Djava.awt.headless=true 22 | */ 23 | public class BurpExtender implements IBurpExtender { 24 | 25 | //Default configuration 26 | static String MONGO_HOST = "127.0.0.1"; 27 | static int MONGO_PORT = 27017; 28 | static String OUTPUT_DIR = "/tmp/"; 29 | static String REPORT_NAME = "burpreport_" + System.currentTimeMillis() + ".html"; 30 | static int TIMEOUT = 10; //seconds 31 | 32 | private IBurpExtenderCallbacks callbacks; 33 | private IExtensionHelpers helpers; 34 | 35 | @Override 36 | public void registerExtenderCallbacks(IBurpExtenderCallbacks callbacks) { 37 | 38 | this.callbacks = callbacks; 39 | helpers = callbacks.getHelpers(); 40 | 41 | callbacks.setExtensionName("ReplayAndDiff"); 42 | System.out.println("\n\n:: ReplayAndDiff Headless Extension ::\n\n"); 43 | 44 | //Parse command line arguments and store values in local variables 45 | //-h|--host=, -p|--port=, -o|--ouput=, -r|--report=, -t|--timeout= 46 | String[] args = callbacks.getCommandLineArguments(); 47 | for (String arg : args) { 48 | if (arg.contains("-h=") || arg.contains("--host=")) { 49 | MONGO_HOST = arg.substring(arg.indexOf('=') + 1); 50 | } else if (arg.contains("-p=") || arg.contains("--port=")) { 51 | MONGO_PORT = Integer.valueOf(arg.substring(arg.indexOf('=') + 1)); 52 | } else if (arg.contains("-o=") || arg.contains("--output=")) { 53 | OUTPUT_DIR = arg.substring(arg.indexOf('=') + 1); 54 | } else if (arg.contains("-r=") || arg.contains("--report=")) { 55 | REPORT_NAME = arg.substring(arg.indexOf('=') + 1); 56 | } else if (arg.contains("-t=") || arg.contains("--timeout=")) { 57 | TIMEOUT = Integer.valueOf(arg.substring(arg.indexOf('=') + 1)); 58 | } 59 | } 60 | System.out.println("[*] Configuration {MONGO_HOST=" + MONGO_HOST + ",MONGO_PORT=" + MONGO_PORT + ",OUTPUT_DIR=" + OUTPUT_DIR + ",REPORT_NAME=" + REPORT_NAME + ",TIMEOUT=" + TIMEOUT + "}"); 61 | 62 | //Retrieve site info and login request from MongoDB 63 | MongoClient mongo = null; 64 | try { 65 | mongo = new MongoClient(MONGO_HOST, MONGO_PORT); 66 | } catch (UnknownHostException ex) { 67 | System.err.println("[!] MongoDB Connection Error: " + ex.toString()); 68 | } 69 | 70 | DB db = mongo.getDB("sitelogger"); 71 | DBCollection table = db.getCollection("login"); 72 | DBCursor cursor = table.find(); 73 | 74 | String host = null; 75 | while (cursor.hasNext()) { 76 | DBObject entry = cursor.next(); 77 | //Replay the HTTP request and save the fresh cookie in Burp's Cookies JAR 78 | host = (String) entry.get("host"); 79 | System.out.println("[*] Retrieving record for: " + host); 80 | byte[] response = callbacks.makeHttpRequest(host, ((int) entry.get("port")), "https".equals((String) entry.get("protocol")), b64d((String) entry.get("request"))); 81 | Iterator cookies = helpers.analyzeResponse(response).getCookies().iterator(); 82 | while (cookies.hasNext()) { 83 | try { 84 | ICookie cookie = cookies.next(); 85 | System.out.println("[*] Obtained cookie: " + cookie.getName() + ":" + cookie.getValue()); 86 | callbacks.updateCookieJar(cookie); 87 | } catch (NullPointerException npe) { 88 | System.out.println("[!] Missing cookie attributes - e.g. domain not set"); 89 | } 90 | } 91 | } 92 | 93 | //Replay a scan on all URLs previously saved for the same site 94 | if (host != null) { 95 | table = db.getCollection(host.replaceAll("\\.", "_") + "_site"); 96 | } else { 97 | throw new NullPointerException(); 98 | } 99 | cursor = table.find(); 100 | URL website = null; 101 | while (cursor.hasNext()) { 102 | DBObject entry = cursor.next(); 103 | //Add host in scope. This is meant to prevent popup since the extension is running headless 104 | try { 105 | website = new URL(((String) entry.get("protocol")) + "://" + ((String) entry.get("host"))); 106 | callbacks.includeInScope(website); 107 | 108 | //Execute passive and active scans 109 | IScanQueueItem item = callbacks.doActiveScan(((String) entry.get("host")), ((int) entry.get("port")), "https".equals((String) entry.get("protocol")), b64d((String) entry.get("request"))); 110 | //Make a new HTTP request and pass request/response to Burp's passive scanner 111 | byte[] response = callbacks.makeHttpRequest(((String) entry.get("host")), ((int) entry.get("port")), "https".equals((String) entry.get("protocol")), b64d((String) entry.get("request"))); 112 | callbacks.doPassiveScan(((String) entry.get("host")), ((int) entry.get("port")), "https".equals((String) entry.get("protocol")), b64d((String) entry.get("request")), response); 113 | 114 | } catch (MalformedURLException ex) { 115 | System.err.println("[!] Malformed website URL: " + ex.toString()); 116 | } catch (NullPointerException ex) { 117 | System.err.println("[!] Missing request or response: " + ex.toString()); 118 | } 119 | } 120 | 121 | try { 122 | System.out.println("[*] Pausing extension..."); 123 | // HOMEWORK - Build a queuing system to check scans status and confirm once all scans are done 124 | Thread.sleep(1000 * TIMEOUT); 125 | System.out.println("[*] Resuming extension..."); 126 | } catch (InterruptedException ex) { 127 | System.err.println("[!] InterruptedException: " + ex.toString()); 128 | } 129 | 130 | table = db.getCollection(host.replaceAll("\\.", "_") + "_vuln"); 131 | BasicDBObject searchQuery = null; 132 | IScanIssue[] allVulns = null; 133 | boolean newFinding = false; 134 | 135 | //Obtain the new scan findings 136 | if (website != null) { 137 | allVulns = callbacks.getScanIssues(website.toString()); 138 | 139 | for (IScanIssue allVuln : allVulns) { 140 | //Diff new and old scan results. 141 | searchQuery = new BasicDBObject(); 142 | searchQuery.put("type", allVuln.getIssueType()); 143 | searchQuery.put("name", allVuln.getIssueName()); 144 | searchQuery.put("URL", allVuln.getUrl().toString()); 145 | System.out.println("[*] Looking for: " + searchQuery.toString()); 146 | cursor = table.find(searchQuery); 147 | if (cursor.size() == 0) { 148 | //There's at least one new finding 149 | System.out.println("[*] Got a new finding!"); 150 | newFinding = true; 151 | } 152 | } 153 | 154 | if (newFinding) { 155 | System.out.println("[*] New findings! Generating report..."); 156 | callbacks.generateScanReport("HTML", allVulns, new File(OUTPUT_DIR + REPORT_NAME)); 157 | } else { 158 | System.out.println("[*] Scan and diff completed. No new results."); 159 | } 160 | 161 | } else { 162 | throw new NullPointerException(); 163 | } 164 | System.out.println("[*] Ready to shutdown...Bye!"); 165 | callbacks.exitSuite(false); 166 | } 167 | 168 | /* Utility method to Base64 decode */ 169 | private byte[] b64d(String input) { 170 | 171 | if (input != null) { 172 | return helpers.base64Decode(input); 173 | } 174 | return new byte[0]; 175 | } 176 | } 177 | -------------------------------------------------------------------------------- /ReplayAndDiff/Java/WIP1/BurpExtenderWIP1.java: -------------------------------------------------------------------------------- 1 | /* 2 | * ReplayAndDiff - Replay a scan with a fresh session and diff the results 3 | * 4 | * Copyright (c) 2017 Doyensec LLC. Made with love by Luca Carettoni. 5 | */ 6 | package burp; 7 | 8 | import com.mongodb.BasicDBObject; 9 | import com.mongodb.DB; 10 | import com.mongodb.DBCollection; 11 | import com.mongodb.DBCursor; 12 | import com.mongodb.DBObject; 13 | import com.mongodb.MongoClient; 14 | import java.io.File; 15 | import java.net.MalformedURLException; 16 | import java.net.URL; 17 | import java.net.UnknownHostException; 18 | import java.util.Iterator; 19 | 20 | /* 21 | * This extension can be executed in headless mode. Start burp using -Djava.awt.headless=true 22 | */ 23 | public class BurpExtender implements IBurpExtender { 24 | 25 | //Default configuration 26 | static String MONGO_HOST = "127.0.0.1"; 27 | static int MONGO_PORT = 27017; 28 | static String OUTPUT_DIR = "/tmp/"; 29 | static String REPORT_NAME = "burpreport_" + System.currentTimeMillis() + ".html"; 30 | static int TIMEOUT = 10; //seconds 31 | 32 | private IBurpExtenderCallbacks callbacks; 33 | private IExtensionHelpers helpers; 34 | 35 | @Override 36 | public void registerExtenderCallbacks(IBurpExtenderCallbacks callbacks) { 37 | 38 | this.callbacks = callbacks; 39 | helpers = callbacks.getHelpers(); 40 | 41 | callbacks.setExtensionName("ReplayAndDiff"); 42 | 43 | // 1 - Parse command line arguments and store values in local variables 44 | // -h|--host=, -p|--port=, -o|--ouput=, -r|--report=, -t|--timeout= 45 | 46 | // 2 - Connect to MongoDB 47 | 48 | // 3 - Retrieve login requests from the 'login' collection in db 'sitelogger' 49 | 50 | // 4 - For each entry, issue a new HTTP request (using Burp's makeHttpRequest) and collect the cookies (using Burp's analyzeResponse) 51 | 52 | // 5 - If there are cookies, update Burp's Cookies jar (using Burp's updateCookieJar) 53 | 54 | // 6 - Retrieve from the database all previously saved HTTP requests 55 | 56 | // 7 - Trigger a new active scan on the same URL (using Burp's doActiveScan) 57 | 58 | // 8 - Reissue a new HTTP request and trigger a new passive scan on the same URL (using Burp's doPassiveScan) 59 | 60 | // 9 - Wait until all scans are completed 61 | // For now, let's simply use our TIMEOUT argument to pause the execution for n seconds 62 | 63 | // 10 - Obtain the list of new findings (using Burp's getScanIssues) 64 | 65 | // 11 - Diff old and new findings 66 | // For now, let's use a simple heuristic: if there's at least a new finding (not previously reported), success! 67 | 68 | // 12 - In case of new findings, generate the report (using Burp's generateScanReport) 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /ReplayAndDiff/Java/WIP2/BurpExtenderWIP2.java: -------------------------------------------------------------------------------- 1 | /* 2 | * ReplayAndDiff - Replay a scan with a fresh session and diff the results 3 | * 4 | * Copyright (c) 2017 Doyensec LLC. Made with love by Luca Carettoni. 5 | */ 6 | package burp; 7 | 8 | import com.mongodb.BasicDBObject; 9 | import com.mongodb.DB; 10 | import com.mongodb.DBCollection; 11 | import com.mongodb.DBCursor; 12 | import com.mongodb.DBObject; 13 | import com.mongodb.MongoClient; 14 | import java.io.File; 15 | import java.net.MalformedURLException; 16 | import java.net.URL; 17 | import java.net.UnknownHostException; 18 | import java.util.Iterator; 19 | 20 | /* 21 | * This extension can be executed in headless mode. Start burp using -Djava.awt.headless=true 22 | */ 23 | public class BurpExtender implements IBurpExtender { 24 | 25 | //Default configuration 26 | static String MONGO_HOST = "127.0.0.1"; 27 | static int MONGO_PORT = 27017; 28 | static String OUTPUT_DIR = "/tmp/"; 29 | static String REPORT_NAME = "burpreport_" + System.currentTimeMillis() + ".html"; 30 | static int TIMEOUT = 10; //seconds 31 | 32 | private IBurpExtenderCallbacks callbacks; 33 | private IExtensionHelpers helpers; 34 | 35 | @Override 36 | public void registerExtenderCallbacks(IBurpExtenderCallbacks callbacks) { 37 | 38 | this.callbacks = callbacks; 39 | helpers = callbacks.getHelpers(); 40 | 41 | callbacks.setExtensionName("ReplayAndDiff"); 42 | System.out.println("\n\n:: ReplayAndDiff Headless Extension ::\n\n"); 43 | 44 | // 1 - Parse command line arguments and store values in local variables 45 | // -h|--host=, -p|--port=, -o|--ouput=, -r|--report=, -t|--timeout= 46 | String[] args = callbacks.getCommandLineArguments(); 47 | for (String arg : args) { 48 | if (arg.contains("-h=") || arg.contains("--host=")) { 49 | MONGO_HOST = arg.substring(arg.indexOf('=') + 1); 50 | } else if (arg.contains("-p=") || arg.contains("--port=")) { 51 | MONGO_PORT = Integer.valueOf(arg.substring(arg.indexOf('=') + 1)); 52 | } else if (arg.contains("-o=") || arg.contains("--output=")) { 53 | OUTPUT_DIR = arg.substring(arg.indexOf('=') + 1); 54 | } else if (arg.contains("-r=") || arg.contains("--report=")) { 55 | REPORT_NAME = arg.substring(arg.indexOf('=') + 1); 56 | } else if (arg.contains("-t=") || arg.contains("--timeout=")) { 57 | TIMEOUT = Integer.valueOf(arg.substring(arg.indexOf('=') + 1)); 58 | } 59 | } 60 | System.out.println("[*] Configuration {MONGO_HOST=" + MONGO_HOST + ",MONGO_PORT=" + MONGO_PORT + ",OUTPUT_DIR=" + OUTPUT_DIR + ",REPORT_NAME=" + REPORT_NAME + ",TIMEOUT=" + TIMEOUT + "}"); 61 | 62 | // 2 - Connect to MongoDB 63 | MongoClient mongo = null; 64 | try { 65 | mongo = new MongoClient(MONGO_HOST, MONGO_PORT); 66 | } catch (UnknownHostException ex) { 67 | System.err.println("[!] MongoDB Connection Error: " + ex.toString()); 68 | } 69 | 70 | // 3 - Retrieve login requests from the 'login' collection in db 'sitelogger' 71 | DB db = mongo.getDB("sitelogger"); 72 | DBCollection table = db.getCollection("login"); 73 | DBCursor cursor = table.find(); 74 | 75 | 76 | String host = null; 77 | while (cursor.hasNext()) { 78 | 79 | // 4 - For each entry, issue a new HTTP request (using Burp's makeHttpRequest) and collect the cookies (using Burp's analyzeResponse) 80 | 81 | // 5 - If there are cookies, update Burp's Cookies jar (using Burp's updateCookieJar) 82 | 83 | // TODO 84 | } 85 | 86 | // 6 - Retrieve from the database all previously saved HTTP requests 87 | if (host != null) { 88 | table = db.getCollection(host.replaceAll("\\.", "_") + "_site"); 89 | } else { 90 | throw new NullPointerException(); 91 | } 92 | cursor = table.find(); 93 | URL website = null; 94 | while (cursor.hasNext()) { 95 | 96 | // 7 - Trigger a new active scan on the same URL (using Burp's doActiveScan) 97 | 98 | // 8 - Reissue a new HTTP request and trigger a new passive scan on the same URL (using Burp's doPassiveScan) 99 | 100 | // TODO 101 | } 102 | 103 | // 9 - Wait until all scans are completed 104 | try { 105 | System.out.println("[*] Pausing extension..."); 106 | // HOMEWORK - Build a queuing system to check scans status and confirm once all scans are done 107 | Thread.sleep(1000 * TIMEOUT); 108 | System.out.println("[*] Resuming extension..."); 109 | } catch (InterruptedException ex) { 110 | System.err.println("[!] InterruptedException: " + ex.toString()); 111 | } 112 | 113 | table = db.getCollection(host.replaceAll("\\.", "_") + "_vuln"); 114 | BasicDBObject searchQuery = null; 115 | IScanIssue[] allVulns = null; 116 | boolean newFinding = false; 117 | 118 | // 10 - Obtain the list of new findings (using Burp's getScanIssues) 119 | if (website != null) { 120 | allVulns = callbacks.getScanIssues(website.toString()); 121 | 122 | for (IScanIssue allVuln : allVulns) { 123 | // 11 - Diff old and new findings 124 | // For now, let's use a simple heuristic: if there's at least a new finding (not previously reported), success! 125 | searchQuery = new BasicDBObject(); 126 | searchQuery.put("type", allVuln.getIssueType()); 127 | searchQuery.put("name", allVuln.getIssueName()); 128 | searchQuery.put("URL", allVuln.getUrl().toString()); 129 | System.out.println("[*] Looking for: " + searchQuery.toString()); 130 | cursor = table.find(searchQuery); 131 | if (cursor.size() == 0) { 132 | //There's at least one new finding 133 | System.out.println("[*] Got a new finding!"); 134 | newFinding = true; 135 | } 136 | } 137 | 138 | // 12 - In case of new findings, generate the report (using Burp's generateScanReport) 139 | if (newFinding) { 140 | // TODO 141 | } 142 | 143 | } else { 144 | throw new NullPointerException(); 145 | } 146 | System.out.println("[*] Ready to shutdown...Bye!"); 147 | callbacks.exitSuite(false); 148 | } 149 | } 150 | -------------------------------------------------------------------------------- /ReplayAndDiff/Python/Final/BurpExtender.py: -------------------------------------------------------------------------------- 1 | # 2 | # ReplayAndDiff - Replay a scan with a fresh session and diff the results 3 | # 4 | # Copyright (c) 2017 Doyensec LLC. Made with love by Andrea Brancaleoni. 5 | # 6 | from com.mongodb import BasicDBObject, DB, DBCollection, DBCursor, MongoClient 7 | from java.io import File 8 | from java.net import MalformedURLException, URL, UnknownHostException 9 | from java.util import Iterator 10 | from java.lang import System, NullPointerException, InterruptedException 11 | from burp import IBurpExtender 12 | from org.python.core.util import StringUtil 13 | 14 | import time 15 | 16 | # 17 | # This extension can be executed in headless mode. Start burp using -Djava.awt.headless=true 18 | # 19 | class BurpExtender(IBurpExtender): 20 | def registerExtenderCallbacks(self, callbacks): 21 | 22 | self.callbacks = callbacks 23 | self.helpers = callbacks.getHelpers() 24 | 25 | callbacks.setExtensionName('ReplayAndDiff') 26 | System.out.println('\n\n:: ReplayAndDiff Headless Extension ::\n\n') 27 | 28 | #Default configuration 29 | mongo_host = '127.0.0.1' 30 | mongo_port = 27017 31 | output_dir = '/tmp/' 32 | report_name = 'burpreport_' + str(System.currentTimeMillis()) + '.html' 33 | timeout = 10 #seconds 34 | 35 | #Parse command line arguments and store values in local variables 36 | #-h|--host=, -p|--port=, -o|--ouput=, -r|--report=, -t|--timeout= 37 | args = callbacks.getCommandLineArguments() 38 | for arg in args: 39 | if ('-h=' in arg or '--host=' in arg): 40 | mongo_host = arg[(arg.index('=') + 1):] 41 | elif ('-p=' in arg or '--port=' in arg): 42 | mongo_port = int(arg[(arg.index('=') + 1):]) 43 | elif ('-o=' in arg or '--output=' in arg): 44 | output_dir = arg[(arg.index('=') + 1):] 45 | elif ('-r=' in arg or '--report=' in arg): 46 | report_name = arg[(arg.index('=') + 1):] 47 | elif ('-t=' in arg or '--timeout=' in arg): 48 | timeout = int(arg[(arg.index('=') + 1):]) 49 | 50 | 51 | System.out.println('[*] Configuration {mongo_host=' + mongo_host + ',mongo_port=' + str(mongo_port) + ',output_dir=' + output_dir + ',report_name=' + report_name + ',timeout=' + str(timeout) + '}') 52 | 53 | #Retrieve site info and login request from MongoDB 54 | mongo = None 55 | try: 56 | mongo = MongoClient(mongo_host, mongo_port) 57 | except UnknownHostException as ex: 58 | System.err.println('[!] MongoDB Connection Error: ' + ex.toString()) 59 | 60 | 61 | db = mongo.getDB('sitelogger') 62 | table = db.getCollection('login') 63 | cursor = table.find() 64 | 65 | host = None 66 | while (cursor.hasNext()): 67 | entry = cursor.next() 68 | #Replay the HTTP request and save the fresh cookie in Burp's Cookies JAR 69 | host = entry.get('host') 70 | System.out.println('[*] Retrieving record for: ' + host) 71 | response = callbacks.makeHttpRequest(host, int(entry.get('port')), 'https' == entry.get('protocol'), self.b64d(entry.get('request'))) 72 | cookies = self.helpers.analyzeResponse(response).getCookies().iterator() 73 | while (cookies.hasNext()): 74 | try: 75 | cookie = cookies.next() 76 | System.out.println('[*] Obtained cookie: ' + cookie.getName() + ':' + cookie.getValue()) 77 | callbacks.updateCookieJar(cookie) 78 | except NullPointerException as npe: 79 | System.out.println('[!] Missing cookie attributes - e.g. domain not set') 80 | 81 | 82 | 83 | 84 | #Replay a scan on all URLs previously saved for the same site 85 | if (host != None): 86 | table = db.getCollection(host.replace(".", '_') + '_site') 87 | else: 88 | raise NullPointerException() 89 | 90 | cursor = table.find() 91 | website = None 92 | while (cursor.hasNext()): 93 | entry = cursor.next() 94 | #Add host in scope. This is meant to prevent popup since the extension is running headless 95 | try: 96 | website = URL((entry.get('protocol')) + '://' + (entry.get('host'))) 97 | callbacks.includeInScope(website) 98 | 99 | #Execute passive and active scans 100 | item = callbacks.doActiveScan(entry.get('host'), entry.get('port'), 'https' == entry.get('protocol'), self.b64d(entry.get('request'))) 101 | #Make a new HTTP request and pass request/response to Burp's passive scanner 102 | response = callbacks.makeHttpRequest(entry.get('host'), int(entry.get('port')), 'https' == entry.get('protocol'), self.b64d(entry.get('request'))) 103 | callbacks.doPassiveScan(entry.get('host'), entry.get('port'), 'https' == entry.get('protocol'), self.b64d(entry.get('request')), response) 104 | 105 | except MalformedURLException as ex: 106 | System.err.println('[!] Malformed website URL: ' + ex.toString()) 107 | except NullPointerException as ex: 108 | System.err.println('[!] Missing request or response: ' + ex.toString()) 109 | 110 | 111 | 112 | try: 113 | System.out.println('[*] Pausing extension...') 114 | # HOMEWORK - Build a queuing system to check scans status and confirm once all scans are done 115 | time.sleep(1 * timeout) 116 | System.out.println('[*] Resuming extension...') 117 | except InterruptedException as ex: 118 | System.err.println('[!] InterruptedException: ' + ex.toString()) 119 | 120 | 121 | table = db.getCollection(host.replace('.', '_') + '_vuln') 122 | searchQuery = None 123 | allVulns = None 124 | newFinding = False 125 | 126 | #Obtain the new scan findings 127 | if (website != None): 128 | allVulns = callbacks.getScanIssues(website.toString()) 129 | 130 | for allVuln in allVulns: 131 | #Diff new and old scan results. 132 | searchQuery = BasicDBObject() 133 | searchQuery.put('type', allVuln.getIssueType()) 134 | searchQuery.put('name', allVuln.getIssueName()) 135 | searchQuery.put('URL', allVuln.getUrl().toString()) 136 | System.out.println('[*] Looking for: ' + searchQuery.toString()) 137 | cursor = table.find(searchQuery) 138 | if (cursor.size() == 0): 139 | #There's at least one new finding 140 | System.out.println('[*] Got a new finding!') 141 | newFinding = True 142 | 143 | 144 | 145 | if (newFinding): 146 | System.out.println('[*] New findings! Generating report...') 147 | callbacks.generateScanReport('HTML', allVulns, File(output_dir + report_name)) 148 | else: 149 | System.out.println('[*] Scan and diff completed. No new results.') 150 | 151 | 152 | else: 153 | raise NullPointerException() 154 | 155 | System.out.println('[*] Ready to shutdown...Bye!') 156 | callbacks.exitSuite(False) 157 | 158 | # Utility method to Base64 decode 159 | def b64d(self, input): 160 | if (input != None): 161 | return self.helpers.base64Decode(input) 162 | return StringUtil.toBytes('') 163 | -------------------------------------------------------------------------------- /ReplayAndDiff/Python/WIP1/BurpExtenderWIP1.py: -------------------------------------------------------------------------------- 1 | # 2 | # ReplayAndDiff - Replay a scan with a fresh session and diff the results 3 | # 4 | # Copyright (c) 2017 Doyensec LLC. Made with love by Andrea Brancaleoni. 5 | # 6 | 7 | from com.mongodb import BasicDBObject, DB, DBCollection, DBCursor, MongoClient 8 | from java.io import File 9 | from java.net import MalformedURLException, URL, UnknownHostException 10 | from java.util import Iterator 11 | from java.lang import System, NullPointerException, InterruptedException 12 | from burp import IBurpExtender 13 | from org.python.core.util import StringUtil 14 | 15 | import time 16 | 17 | # 18 | # This extension can be executed in headless mode. Start burp using -Djava.awt.headless=true 19 | # 20 | class BurpExtender(IBurpExtender): 21 | def registerExtenderCallbacks(self, callbacks): 22 | 23 | self.callbacks = callbacks 24 | self.helpers = callbacks.getHelpers() 25 | 26 | callbacks.setExtensionName('ReplayAndDiff') 27 | System.out.println('\n\n:: ReplayAndDiff Headless Extension ::\n\n') 28 | 29 | #Default configuration 30 | mongo_host = '127.0.0.1' 31 | mongo_port = 27017 32 | output_dir = '/tmp/' 33 | report_name = 'burpreport_' + str(System.currentTimeMillis()) + '.html' 34 | timeout = 10 #seconds 35 | 36 | # 1 - Parse command line arguments and store values in local variables 37 | # -h|--host=, -p|--port=, -o|--ouput=, -r|--report=, -t|--timeout= 38 | 39 | # 2 - Connect to MongoDB 40 | 41 | # 3 - Retrieve login requests from the 'login' collection in db 'sitelogger' 42 | 43 | # 4 - For each entry, issue a new HTTP request (using Burp's makeHttpRequest) and collect the cookies (using Burp's analyzeResponse) 44 | 45 | # 5 - If there are cookies, update Burp's Cookies jar (using Burp's updateCookieJar) 46 | 47 | # 6 - Retrieve from the database all previously saved HTTP requests 48 | 49 | # 7 - Trigger a new active scan on the same URL (using Burp's doActiveScan) 50 | 51 | # 8 - Reissue a new HTTP request and trigger a new passive scan on the same URL (using Burp's doPassiveScan) 52 | 53 | # 9 - Wait until all scans are completed 54 | # For now, let's simply use our TIMEOUT argument to pause the execution for n seconds 55 | 56 | # 10 - Obtain the list of new findings (using Burp's getScanIssues) 57 | 58 | # 11 - Diff old and new findings 59 | # For now, let's use a simple heuristic: if there's at least a new finding (not previously reported), success! 60 | 61 | # 12 - In case of new findings, generate the report (using Burp's generateScanReport) 62 | -------------------------------------------------------------------------------- /ReplayAndDiff/Python/WIP2/BurpExtenderWIP2.py: -------------------------------------------------------------------------------- 1 | # 2 | # ReplayAndDiff - Replay a scan with a fresh session and diff the results 3 | # 4 | # Copyright (c) 2017 Doyensec LLC. Made with love by Andrea Brancaleoni. 5 | # 6 | 7 | from com.mongodb import BasicDBObject, DB, DBCollection, DBCursor, MongoClient 8 | from java.io import File 9 | from java.net import MalformedURLException, URL, UnknownHostException 10 | from java.util import Iterator 11 | from java.lang import System, NullPointerException, InterruptedException 12 | from burp import IBurpExtender 13 | from org.python.core.util import StringUtil 14 | 15 | import time 16 | 17 | # 18 | # This extension can be executed in headless mode. Start burp using -Djava.awt.headless=true 19 | # 20 | class BurpExtender(IBurpExtender): 21 | def registerExtenderCallbacks(self, callbacks): 22 | 23 | self.callbacks = callbacks 24 | self.helpers = callbacks.getHelpers() 25 | 26 | callbacks.setExtensionName('ReplayAndDiff') 27 | System.out.println('\n\n:: ReplayAndDiff Headless Extension ::\n\n') 28 | 29 | #Default configuration 30 | mongo_host = '127.0.0.1' 31 | mongo_port = 27017 32 | output_dir = '/tmp/' 33 | report_name = 'burpreport_' + str(System.currentTimeMillis()) + '.html' 34 | timeout = 10 #seconds 35 | 36 | # 1 - Parse command line arguments and store values in local variables 37 | # -h|--host=, -p|--port=, -o|--ouput=, -r|--report=, -t|--timeout= 38 | args = callbacks.getCommandLineArguments() 39 | for arg in args: 40 | if ('-h=' in arg or '--host=' in arg): 41 | mongo_host = arg[(arg.index('=') + 1):] 42 | elif ('-p=' in arg or '--port=' in arg): 43 | mongo_port = int(arg[(arg.index('=') + 1):]) 44 | elif ('-o=' in arg or '--output=' in arg): 45 | output_dir = arg[(arg.index('=') + 1):] 46 | elif ('-r=' in arg or '--report=' in arg): 47 | report_name = arg[(arg.index('=') + 1):] 48 | elif ('-t=' in arg or '--timeout=' in arg): 49 | timeout = int(arg[(arg.index('=') + 1):]) 50 | 51 | 52 | System.out.println('[*] Configuration {mongo_host=' + mongo_host + ',mongo_port=' + str(mongo_port) + ',output_dir=' + output_dir + ',report_name=' + report_name + ',timeout=' + str(timeout) + '}') 53 | 54 | # 2 - Connect to MongoDB 55 | mongo = None 56 | try: 57 | mongo = MongoClient(mongo_host, mongo_port) 58 | except UnknownHostException as ex: 59 | System.err.println('[!] MongoDB Connection Error: ' + ex.toString()) 60 | 61 | # 3 - Retrieve login requests from the 'login' collection in db 'sitelogger' 62 | db = mongo.getDB('sitelogger') 63 | table = db.getCollection('login') 64 | cursor = table.find() 65 | 66 | host = None 67 | while (cursor.hasNext()): 68 | # 4 - For each entry, issue a new HTTP request (using Burp's makeHttpRequest) and collect the cookies (using Burp's analyzeResponse) 69 | 70 | # 5 - If there are cookies, update Burp's Cookies jar (using Burp's updateCookieJar) 71 | 72 | # TODO 73 | 74 | 75 | # 6 - Retrieve from the database all previously saved HTTP requests 76 | if (host != None): 77 | table = db.getCollection(host.replace(".", '_') + '_site') 78 | else: 79 | raise NullPointerException() 80 | 81 | cursor = table.find() 82 | website = None 83 | while (cursor.hasNext()): 84 | # 7 - Trigger a new active scan on the same URL (using Burp's doActiveScan) 85 | 86 | # 8 - Reissue a new HTTP request and trigger a new passive scan on the same URL (using Burp's doPassiveScan) 87 | 88 | # TODO 89 | 90 | # 9 - Wait until all scans are completed 91 | try: 92 | System.out.println('[*] Pausing extension...') 93 | # HOMEWORK - Build a queuing system to check scans status and confirm once all scans are done 94 | time.sleep(1 * timeout) 95 | System.out.println('[*] Resuming extension...') 96 | except InterruptedException as ex: 97 | System.err.println('[!] InterruptedException: ' + ex.toString()) 98 | 99 | 100 | table = db.getCollection(host.replace('.', '_') + '_vuln') 101 | searchQuery = None 102 | allVulns = None 103 | newFinding = False 104 | 105 | # 10 - Obtain the list of new findings (using Burp's getScanIssues) 106 | if (website != None): 107 | allVulns = callbacks.getScanIssues(website.toString()) 108 | 109 | for allVuln in allVulns: 110 | # 11 - Diff old and new findings 111 | # For now, let's use a simple heuristic: if there's at least a new finding (not previously reported), success! 112 | searchQuery = BasicDBObject() 113 | searchQuery.put('type', allVuln.getIssueType()) 114 | searchQuery.put('name', allVuln.getIssueName()) 115 | searchQuery.put('URL', allVuln.getUrl().toString()) 116 | System.out.println('[*] Looking for: ' + searchQuery.toString()) 117 | cursor = table.find(searchQuery) 118 | if (cursor.size() == 0): 119 | #There's at least one new finding 120 | System.out.println('[*] Got a new finding!') 121 | newFinding = True 122 | 123 | 124 | # 12 - In case of new findings, generate the report (using Burp's generateScanReport) 125 | if (newFinding): 126 | # TODO 127 | pass 128 | 129 | else: 130 | raise NullPointerException() 131 | 132 | System.out.println('[*] Ready to shutdown...Bye!') 133 | callbacks.exitSuite(False) 134 | -------------------------------------------------------------------------------- /ReplayAndDiff/Ruby/Final/BurpExtender.rb: -------------------------------------------------------------------------------- 1 | # 2 | # ReplayAndDiff - Replay a scan with a fresh session and diff the results 3 | # 4 | # Copyright (c) 2017 Doyensec LLC. Made with love by Andrea Brancaleoni. 5 | # 6 | require 'java' 7 | 8 | java_import 'com.mongodb.BasicDBObject' 9 | java_import 'com.mongodb.DB' 10 | java_import 'com.mongodb.DBCollection' 11 | java_import 'com.mongodb.DBCursor' 12 | java_import 'com.mongodb.DBObject' 13 | java_import 'com.mongodb.MongoClient' 14 | java_import 'java.io.File' 15 | java_import 'java.net.MalformedURLException' 16 | java_import 'java.net.URL' 17 | java_import 'java.net.UnknownHostException' 18 | java_import 'java.util.Iterator' 19 | java_import 'burp.IBurpExtender' 20 | java_import 'java.lang.System' 21 | java_import 'java.lang.InterruptedException' 22 | 23 | # 24 | # This extension can be executed in headless mode. Start burp using -Djava.awt.headless=true 25 | # 26 | class BurpExtender 27 | include IBurpExtender 28 | attr_accessor :helpers 29 | 30 | def registerExtenderCallbacks(callbacks) 31 | 32 | @callbacks = callbacks 33 | @helpers = callbacks.getHelpers() 34 | 35 | callbacks.setExtensionName('ReplayAndDiff') 36 | System.out.println("\n\n:: ReplayAndDiff Headless Extension ::\n\n") 37 | 38 | #Default configuration 39 | mongo_host = '127.0.0.1' 40 | mongo_port = 27017 41 | output_dir = '/tmp/' 42 | report_name = 'burpreport_' + System.currentTimeMillis().to_s + '.html' 43 | timeout = 10 #seconds 44 | 45 | #Parse command line arguments and store values in local variables 46 | #-h|--host=, -p|--port=, -o|--ouput=, -r|--report=, -t|--timeout= 47 | args = callbacks.getCommandLineArguments() 48 | for arg in args 49 | if (arg.include?('-h=') || arg.include?('--host=')) 50 | mongo_host = arg[(arg.index('=') + 1),arg.length] 51 | elsif (arg.include?('-p=') || arg.include?('--port=')) 52 | mongo_port = arg[(arg.index('=') + 1),arg.length].to_i 53 | elsif (arg.include?('-o=') || arg.include?('--ouput=')) 54 | output_dir = arg[(arg.index('=') + 1),arg.length] 55 | elsif (arg.include?('-r=') || arg.include?('--report=')) 56 | report_name = arg[(arg.index('=') + 1),arg.length] 57 | elsif (arg.include?('-t=') || arg.include?('--timeout=')) 58 | timeout = arg[(arg.index('=') + 1),arg.length].to_i 59 | end 60 | end 61 | System.out.println('[*] Configuration {mongo_host=' + mongo_host + ',mongo_port=' + mongo_port.to_s + ',output_dir=' + output_dir + ',report_name=' + report_name + ',timeout=' + timeout.to_s + '}') 62 | 63 | #Retrieve site info and login request from MongoDB 64 | mongo = nil 65 | begin 66 | mongo = MongoClient.new(mongo_host, mongo_port) 67 | rescue UnknownHostException => ex 68 | System.err.println('[!] MongoDB Connection Error: ' + ex.toString()) 69 | end 70 | 71 | db = mongo.getDB('sitelogger') 72 | table = db.getCollection('login') 73 | cursor = table.find() 74 | 75 | host = nil 76 | while (cursor.hasNext()) 77 | entry = cursor.next() 78 | #Replay the HTTP request and save the fresh cookie in Burp's Cookies JAR 79 | host = entry.get('host') 80 | System.out.println('[*] Retrieving record for: ' + host) 81 | response = callbacks.makeHttpRequest(host, entry.get('port').to_i, 'https' == entry.get('protocol'), b64d(entry.get('request'))) 82 | cookies = helpers.analyzeResponse(response).getCookies().iterator() 83 | while (cookies.hasNext()) 84 | begin 85 | cookie = cookies.next() 86 | System.out.println('[*] Obtained cookie: ' + cookie.getName() + ':' + cookie.getValue()) 87 | callbacks.updateCookieJar(cookie) 88 | rescue java.lang.NullPointerException => npe 89 | System.out.println('[!] Missing cookie attributes - e.g. domain not set') 90 | end 91 | end 92 | end 93 | 94 | #Replay a scan on all URLs previously saved for the same site 95 | if (host != nil) 96 | table = db.getCollection(host.gsub(".", '_') + '_site') 97 | else 98 | raise java.lang.NullPointerException.new() 99 | end 100 | cursor = table.find() 101 | website = nil 102 | while (cursor.hasNext()) 103 | entry = cursor.next() 104 | #Add host in scope. This is meant to prevent popup since the extension is running headless 105 | begin 106 | website = URL.new((entry.get('protocol')) + '://' + (entry.get('host'))) 107 | callbacks.includeInScope(website) 108 | 109 | #Execute passive and active scans 110 | item = callbacks.doActiveScan(entry.get('host'), entry.get('port'), 'https' == entry.get('protocol'), b64d(entry.get('request'))) 111 | 112 | #Make a new HTTP request and pass request/response to Burp's passive scanner 113 | response = callbacks.makeHttpRequest(entry.get('host'), entry.get('port').to_i, 'https' == entry.get('protocol'), b64d(entry.get('request'))) 114 | callbacks.doPassiveScan(entry.get('host'), entry.get('port'), 'https' == entry.get('protocol'), b64d(entry.get('request')), response) 115 | 116 | rescue MalformedURLException => ex 117 | System.err.println('[!] Malformed website URL: ' + ex.toString()) 118 | rescue java.lang.NullPointerException => ex 119 | System.err.println('[!] Missing request or response: ' + ex.toString()) 120 | end 121 | end 122 | 123 | begin 124 | System.out.println('[*] Pausing extension...') 125 | # HOMEWORK - Build a queuing system to check scans status and confirm once all scans are done 126 | sleep 1 * timeout 127 | System.out.println('[*] Resuming extension...') 128 | rescue InterruptedException => ex 129 | System.err.println('[!] InterruptedException: ' + ex.toString()) 130 | end 131 | 132 | table = db.getCollection(host.gsub('.', '_') + '_vuln') 133 | searchQuery = nil 134 | allVulns = nil 135 | newFinding = false 136 | 137 | #Obtain the new scan findings 138 | if (website != nil) 139 | allVulns = callbacks.getScanIssues(website.toString()) 140 | 141 | for allVuln in allVulns 142 | #Diff new and old scan results. 143 | searchQuery = BasicDBObject.new() 144 | searchQuery.put('type', allVuln.getIssueType()) 145 | searchQuery.put('name', allVuln.getIssueName()) 146 | searchQuery.put('URL', allVuln.getUrl().toString()) 147 | System.out.println('[*] Looking for: ' + searchQuery.toString()) 148 | cursor = table.find(searchQuery) 149 | if (cursor.size() == 0) 150 | #There's at least one new finding 151 | System.out.println('[*] Got a new finding!') 152 | newFinding = true 153 | end 154 | end 155 | 156 | if (newFinding) 157 | System.out.println('[*] New findings! Generating report...') 158 | callbacks.generateScanReport('HTML', allVulns, File.new(output_dir + report_name)) 159 | else 160 | System.out.println('[*] Scan and diff completed. No new results.') 161 | end 162 | 163 | else 164 | raise java.lang.NullPointerException.new() 165 | end 166 | System.out.println('[*] Ready to shutdown...Bye!') 167 | callbacks.exitSuite(false) 168 | end 169 | 170 | # Utility method to Base64 decode 171 | def b64d(input) 172 | if input 173 | return helpers.base64Decode(input) 174 | end 175 | return "".to_java_bytes 176 | end 177 | end 178 | -------------------------------------------------------------------------------- /ReplayAndDiff/Ruby/WIP1/BurpExtenderWIP1.rb: -------------------------------------------------------------------------------- 1 | # 2 | # ReplayAndDiff - Replay a scan with a fresh session and diff the results 3 | # 4 | # Copyright (c) 2017 Doyensec LLC. Made with love by Andrea Brancaleoni. 5 | # 6 | require 'java' 7 | 8 | java_import 'com.mongodb.BasicDBObject' 9 | java_import 'com.mongodb.DB' 10 | java_import 'com.mongodb.DBCollection' 11 | java_import 'com.mongodb.DBCursor' 12 | java_import 'com.mongodb.DBObject' 13 | java_import 'com.mongodb.MongoClient' 14 | java_import 'java.io.File' 15 | java_import 'java.net.MalformedURLException' 16 | java_import 'java.net.URL' 17 | java_import 'java.net.UnknownHostException' 18 | java_import 'java.util.Iterator' 19 | java_import 'burp.IBurpExtender' 20 | java_import 'java.lang.System' 21 | java_import 'java.lang.InterruptedException' 22 | 23 | # 24 | # This extension can be executed in headless mode. Start burp using -Djava.awt.headless=true 25 | # 26 | class BurpExtender 27 | include IBurpExtender 28 | attr_accessor :helpers 29 | 30 | def registerExtenderCallbacks(callbacks) 31 | 32 | @callbacks = callbacks 33 | @helpers = callbacks.getHelpers() 34 | 35 | callbacks.setExtensionName('ReplayAndDiff') 36 | System.out.println("\n\n:: ReplayAndDiff Headless Extension ::\n\n") 37 | 38 | #Default configuration 39 | mongo_host = '127.0.0.1' 40 | mongo_port = 27017 41 | output_dir = '/tmp/' 42 | report_name = 'burpreport_' + System.currentTimeMillis().to_s + '.html' 43 | timeout = 10 #seconds 44 | 45 | 46 | # 1 - Parse command line arguments and store values in local variables 47 | # -h|--host=, -p|--port=, -o|--ouput=, -r|--report=, -t|--timeout= 48 | 49 | # 2 - Connect to MongoDB 50 | 51 | # 3 - Retrieve login requests from the 'login' collection in db 'sitelogger' 52 | 53 | # 4 - For each entry, issue a new HTTP request (using Burp's makeHttpRequest) and collect the cookies (using Burp's analyzeResponse) 54 | 55 | # 5 - If there are cookies, update Burp's Cookies jar (using Burp's updateCookieJar) 56 | 57 | # 6 - Retrieve from the database all previously saved HTTP requests 58 | 59 | # 7 - Trigger a new active scan on the same URL (using Burp's doActiveScan) 60 | 61 | # 8 - Reissue a new HTTP request and trigger a new passive scan on the same URL (using Burp's doPassiveScan) 62 | 63 | # 9 - Wait until all scans are completed 64 | # For now, let's simply use our TIMEOUT argument to pause the execution for n seconds 65 | 66 | # 10 - Obtain the list of new findings (using Burp's getScanIssues) 67 | 68 | # 11 - Diff old and new findings 69 | # For now, let's use a simple heuristic: if there's at least a new finding (not previously reported), success! 70 | 71 | # 12 - In case of new findings, generate the report (using Burp's generateScanReport) 72 | end 73 | end 74 | -------------------------------------------------------------------------------- /ReplayAndDiff/Ruby/WIP2/BurpExtenderWIP2.rb: -------------------------------------------------------------------------------- 1 | # 2 | # ReplayAndDiff - Replay a scan with a fresh session and diff the results 3 | # 4 | # Copyright (c) 2017 Doyensec LLC. Made with love by Andrea Brancaleoni. 5 | # 6 | require 'java' 7 | 8 | java_import 'com.mongodb.BasicDBObject' 9 | java_import 'com.mongodb.DB' 10 | java_import 'com.mongodb.DBCollection' 11 | java_import 'com.mongodb.DBCursor' 12 | java_import 'com.mongodb.DBObject' 13 | java_import 'com.mongodb.MongoClient' 14 | java_import 'java.io.File' 15 | java_import 'java.net.MalformedURLException' 16 | java_import 'java.net.URL' 17 | java_import 'java.net.UnknownHostException' 18 | java_import 'java.util.Iterator' 19 | java_import 'burp.IBurpExtender' 20 | java_import 'java.lang.System' 21 | java_import 'java.lang.InterruptedException' 22 | 23 | # 24 | # This extension can be executed in headless mode. Start burp using -Djava.awt.headless=true 25 | # 26 | class BurpExtender 27 | include IBurpExtender 28 | attr_accessor :helpers 29 | 30 | def registerExtenderCallbacks(callbacks) 31 | 32 | @callbacks = callbacks 33 | @helpers = callbacks.getHelpers() 34 | 35 | callbacks.setExtensionName('ReplayAndDiff') 36 | System.out.println("\n\n:: ReplayAndDiff Headless Extension ::\n\n") 37 | 38 | #Default configuration 39 | mongo_host = '127.0.0.1' 40 | mongo_port = 27017 41 | output_dir = '/tmp/' 42 | report_name = 'burpreport_' + System.currentTimeMillis().to_s + '.html' 43 | timeout = 10 #seconds 44 | 45 | # 1 - Parse command line arguments and store values in local variables 46 | # -h|--host=, -p|--port=, -o|--ouput=, -r|--report=, -t|--timeout= 47 | args = callbacks.getCommandLineArguments() 48 | for arg in args 49 | if (arg.include?('-h=') || arg.include?('--host=')) 50 | mongo_host = arg[(arg.index('=') + 1),arg.length] 51 | elsif (arg.include?('-p=') || arg.include?('--port=')) 52 | mongo_port = arg[(arg.index('=') + 1),arg.length].to_i 53 | elsif (arg.include?('-o=') || arg.include?('--ouput=')) 54 | output_dir = arg[(arg.index('=') + 1),arg.length] 55 | elsif (arg.include?('-r=') || arg.include?('--report=')) 56 | report_name = arg[(arg.index('=') + 1),arg.length] 57 | elsif (arg.include?('-t=') || arg.include?('--timeout=')) 58 | timeout = arg[(arg.index('=') + 1),arg.length].to_i 59 | end 60 | end 61 | System.out.println('[*] Configuration {mongo_host=' + mongo_host + ',mongo_port=' + mongo_port.to_s + ',output_dir=' + output_dir + ',report_name=' + report_name + ',timeout=' + timeout.to_s + '}') 62 | 63 | # 2 - Connect to MongoDB 64 | mongo = nil 65 | begin 66 | mongo = MongoClient.new(mongo_host, mongo_port) 67 | rescue UnknownHostException => ex 68 | System.err.println('[!] MongoDB Connection Error: ' + ex.toString()) 69 | end 70 | 71 | # 3 - Retrieve login requests from the 'login' collection in db 'sitelogger' 72 | db = mongo.getDB('sitelogger') 73 | table = db.getCollection('login') 74 | cursor = table.find() 75 | 76 | host = nil 77 | while (cursor.hasNext()) 78 | # 4 - For each entry, issue a new HTTP request (using Burp's makeHttpRequest) and collect the cookies (using Burp's analyzeResponse) 79 | 80 | # 5 - If there are cookies, update Burp's Cookies jar (using Burp's updateCookieJar) 81 | 82 | # TODO 83 | end 84 | 85 | # 6 - Retrieve from the database all previously saved HTTP requests 86 | if (host != nil) 87 | table = db.getCollection(host.gsub(".", '_') + '_site') 88 | else 89 | raise java.lang.NullPointerException.new() 90 | end 91 | 92 | cursor = table.find() 93 | website = nil 94 | while (cursor.hasNext()) 95 | # 7 - Trigger a new active scan on the same URL (using Burp's doActiveScan) 96 | 97 | # 8 - Reissue a new HTTP request and trigger a new passive scan on the same URL (using Burp's doPassiveScan) 98 | 99 | # TODO 100 | end 101 | 102 | # 9 - Wait until all scans are completed 103 | begin 104 | System.out.println('[*] Pausing extension...') 105 | # HOMEWORK - Build a queuing system to check scans status and confirm once all scans are done 106 | sleep 1 * timeout 107 | System.out.println('[*] Resuming extension...') 108 | rescue InterruptedException => ex 109 | System.err.println('[!] InterruptedException: ' + ex.toString()) 110 | end 111 | 112 | table = db.getCollection(host.gsub('.', '_') + '_vuln') 113 | searchQuery = nil 114 | allVulns = nil 115 | newFinding = false 116 | 117 | # 10 - Obtain the list of new findings (using Burp's getScanIssues) 118 | if (website != nil) 119 | allVulns = callbacks.getScanIssues(website.toString()) 120 | 121 | for allVuln in allVulns 122 | # 11 - Diff old and new findings 123 | # For now, let's use a simple heuristic: if there's at least a new finding (not previously reported), success! 124 | searchQuery = BasicDBObject.new() 125 | searchQuery.put('type', allVuln.getIssueType()) 126 | searchQuery.put('name', allVuln.getIssueName()) 127 | searchQuery.put('URL', allVuln.getUrl().toString()) 128 | System.out.println('[*] Looking for: ' + searchQuery.toString()) 129 | cursor = table.find(searchQuery) 130 | if (cursor.size() == 0) 131 | #There's at least one new finding 132 | System.out.println('[*] Got a new finding!') 133 | newFinding = true 134 | end 135 | end 136 | 137 | # 12 - In case of new findings, generate the report (using Burp's generateScanReport) 138 | if (newFinding) 139 | 140 | else 141 | raise java.lang.NullPointerException.new() 142 | end 143 | System.out.println('[*] Ready to shutdown...Bye!') 144 | callbacks.exitSuite(false) 145 | end 146 | end 147 | -------------------------------------------------------------------------------- /SiteLogger/.gitignore: -------------------------------------------------------------------------------- 1 | # Package Files # 2 | *.jar 3 | *.war 4 | *.ear 5 | 6 | # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml 7 | hs_err_pid* 8 | 9 | #ant specific 10 | dist/ 11 | build/ 12 | build.xml 13 | 14 | #netbeans specific 15 | core 16 | nbproject/* 17 | libs/* 18 | lib/* 19 | manifest.mf 20 | .jacocoverage/ 21 | coverage/ 22 | src/ 23 | 24 | #java specific 25 | *.class 26 | 27 | #general swap/backup files 28 | *.so 29 | *.log 30 | *.out 31 | *~ 32 | *.swp 33 | *.DS_Store 34 | *.lock 35 | 36 | #idea specific 37 | .classpath 38 | .project 39 | .settings 40 | .idea 41 | .metadata 42 | *.iml 43 | *.ipr 44 | **/*~ 45 | /target/ 46 | -------------------------------------------------------------------------------- /SiteLogger/Java/Final/burp/BurpExtender.java: -------------------------------------------------------------------------------- 1 | /* 2 | * SiteLogger - Log sitemap and findings to database 3 | * 4 | * Copyright (c) 2017 Doyensec LLC. Made with love by Luca Carettoni. 5 | */ 6 | package burp; 7 | 8 | import com.doyensec.sitelogger.SiteLoggerTab; 9 | 10 | public class BurpExtender implements IBurpExtender { 11 | 12 | private IBurpExtenderCallbacks callbacks; 13 | private IExtensionHelpers helpers; 14 | 15 | @Override 16 | public void registerExtenderCallbacks(IBurpExtenderCallbacks callbacks) { 17 | this.callbacks = callbacks; 18 | helpers = callbacks.getHelpers(); 19 | callbacks.setExtensionName("SiteLogger"); 20 | callbacks.addSuiteTab(new SiteLoggerTab(callbacks, helpers)); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /SiteLogger/Java/Final/com/doyensec/sitelogger/SiteLoggerPanel.form: -------------------------------------------------------------------------------- 1 | 2 | 3 |
4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 |
115 | -------------------------------------------------------------------------------- /SiteLogger/Java/Final/com/doyensec/sitelogger/SiteLoggerTab.java: -------------------------------------------------------------------------------- 1 | /* 2 | * SiteLogger - Log sitemap and findings to database 3 | * 4 | * Copyright (c) 2017 Doyensec LLC. Made with love by Luca Carettoni. 5 | */ 6 | package com.doyensec.sitelogger; 7 | 8 | import burp.IBurpExtenderCallbacks; 9 | import burp.IExtensionHelpers; 10 | import burp.ITab; 11 | import java.awt.Component; 12 | import javax.swing.JPanel; 13 | 14 | public class SiteLoggerTab implements ITab { 15 | 16 | private final IBurpExtenderCallbacks callbacks; 17 | private final IExtensionHelpers helpers; 18 | 19 | public SiteLoggerTab(IBurpExtenderCallbacks callbacks, IExtensionHelpers helpers) { 20 | this.callbacks = callbacks; 21 | this.helpers = helpers; 22 | } 23 | 24 | @Override 25 | public String getTabCaption() { 26 | return "SiteLogger"; 27 | } 28 | 29 | @Override 30 | public Component getUiComponent() { 31 | JPanel panel = new SiteLoggerPanel(callbacks, helpers); 32 | callbacks.customizeUiComponent(panel); 33 | return panel; 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /SiteLogger/Java/WIP1/burp/BurpExtenderWIP1.java: -------------------------------------------------------------------------------- 1 | /* 2 | * SiteLogger - Log sitemap and findings to database 3 | * 4 | * Copyright (c) 2017 Doyensec LLC. Made with love by Luca Carettoni. 5 | */ 6 | package burp; 7 | 8 | import com.doyensec.sitelogger.SiteLoggerTab; 9 | 10 | public class BurpExtender implements IBurpExtender { 11 | 12 | private IBurpExtenderCallbacks callbacks; 13 | private IExtensionHelpers helpers; 14 | 15 | @Override 16 | public void registerExtenderCallbacks(IBurpExtenderCallbacks callbacks) { 17 | this.callbacks = callbacks; 18 | helpers = callbacks.getHelpers(); 19 | callbacks.setExtensionName("SiteLogger"); 20 | 21 | // 1 - Add a custom tab to Burp (using addSuiteTab) 22 | // Please use a separate file named 'SiteLoggerTab' within the package 'com.doyensec.sitelogger' 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /SiteLogger/Java/WIP1/com/doyensec/sitelogger/SiteLoggerPanelWIP1.java: -------------------------------------------------------------------------------- 1 | /* 2 | * SiteLogger - Log sitemap and findings to database 3 | * 4 | * Copyright (c) 2017 Doyensec LLC. Made with love by Luca Carettoni. 5 | */ 6 | package com.doyensec.sitelogger; 7 | 8 | import burp.IBurpExtenderCallbacks; 9 | import burp.IExtensionHelpers; 10 | import burp.IHttpRequestResponse; 11 | import burp.IScanIssue; 12 | import com.mongodb.BasicDBObject; 13 | import com.mongodb.DB; 14 | import com.mongodb.DBCollection; 15 | import com.mongodb.MongoClient; 16 | import java.io.PrintWriter; 17 | import java.net.MalformedURLException; 18 | import java.net.URL; 19 | import java.net.UnknownHostException; 20 | 21 | public class SiteLoggerPanel extends javax.swing.JPanel { 22 | 23 | private final IBurpExtenderCallbacks callbacks; 24 | private final IExtensionHelpers helpers; 25 | 26 | public SiteLoggerPanel(IBurpExtenderCallbacks callbacks, IExtensionHelpers helpers) { 27 | initComponents(); 28 | this.callbacks = callbacks; 29 | this.helpers = helpers; 30 | } 31 | 32 | private void initComponents() { 33 | 34 | // 4 - Define here the AWT/Swing UI which should contain three text fields (mongohost, mongoport, website) and save button 35 | 36 | // *** Highly recommended to use a WYSIWYG editor *** 37 | } 38 | 39 | // Button Event Click - Our code goes here! 40 | private void logButtonActionPerformed(java.awt.event.ActionEvent evt) { 41 | 42 | // 5 - Connect to the database and create two new collections for storing sitemap and vulns 43 | 44 | // 6 - Retrieve the SiteMap content (using Burp's getSiteMap) 45 | 46 | // 7 - Save each HTTP request/response to the database 47 | 48 | // 8 - Retrieve all scanner findings (using Burp's getScanIssues) 49 | 50 | // 9 - Save each vulnerability report to the database, including HTTP request/response 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /SiteLogger/Java/WIP1/com/doyensec/sitelogger/SiteLoggerTabWIP1.java: -------------------------------------------------------------------------------- 1 | /* 2 | * SiteLogger - Log sitemap and findings to database 3 | * 4 | * Copyright (c) 2017 Doyensec LLC. Made with love by Luca Carettoni. 5 | */ 6 | package com.doyensec.sitelogger; 7 | 8 | import burp.IBurpExtenderCallbacks; 9 | import burp.IExtensionHelpers; 10 | import burp.ITab; 11 | import java.awt.Component; 12 | import javax.swing.JPanel; 13 | 14 | public class SiteLoggerTab implements ITab { 15 | 16 | private final IBurpExtenderCallbacks callbacks; 17 | private final IExtensionHelpers helpers; 18 | 19 | public SiteLoggerTab(IBurpExtenderCallbacks callbacks, IExtensionHelpers helpers) { 20 | this.callbacks = callbacks; 21 | this.helpers = helpers; 22 | } 23 | 24 | // 2 - Simply implement all ITab's methods (getTabCaption and getUiComponent) 25 | 26 | // 3 - In getUiComponent, instantiate a new Jpanel created using standard Java AWT/Swing GUI Editors 27 | } 28 | -------------------------------------------------------------------------------- /SiteLogger/Java/WIP2/burp/BurpExtenderWIP2.java: -------------------------------------------------------------------------------- 1 | /* 2 | * SiteLogger - Log sitemap and findings to database 3 | * 4 | * Copyright (c) 2017 Doyensec LLC. Made with love by Luca Carettoni. 5 | */ 6 | package burp; 7 | 8 | import com.doyensec.sitelogger.SiteLoggerTab; 9 | 10 | public class BurpExtender implements IBurpExtender { 11 | 12 | private IBurpExtenderCallbacks callbacks; 13 | private IExtensionHelpers helpers; 14 | 15 | @Override 16 | public void registerExtenderCallbacks(IBurpExtenderCallbacks callbacks) { 17 | this.callbacks = callbacks; 18 | helpers = callbacks.getHelpers(); 19 | callbacks.setExtensionName("SiteLogger"); 20 | 21 | // 1 - Add a custom tab to Burp (using addSuiteTab) 22 | // Please use a separate file named 'SiteLoggerTab' within the package 'com.doyensec.sitelogger' 23 | callbacks.addSuiteTab(new SiteLoggerTab(callbacks, helpers)); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /SiteLogger/Java/WIP2/com/doyensec/sitelogger/SiteLoggerPanelWIP2.java: -------------------------------------------------------------------------------- 1 | /* 2 | * SiteLogger - Log sitemap and findings to database 3 | * 4 | * Copyright (c) 2017 Doyensec LLC. Made with love by Luca Carettoni. 5 | */ 6 | package com.doyensec.sitelogger; 7 | 8 | import burp.IBurpExtenderCallbacks; 9 | import burp.IExtensionHelpers; 10 | import burp.IHttpRequestResponse; 11 | import burp.IScanIssue; 12 | import com.mongodb.BasicDBObject; 13 | import com.mongodb.DB; 14 | import com.mongodb.DBCollection; 15 | import com.mongodb.MongoClient; 16 | import java.io.PrintWriter; 17 | import java.net.MalformedURLException; 18 | import java.net.URL; 19 | import java.net.UnknownHostException; 20 | 21 | public class SiteLoggerPanel extends javax.swing.JPanel { 22 | 23 | private final IBurpExtenderCallbacks callbacks; 24 | private final IExtensionHelpers helpers; 25 | 26 | public SiteLoggerPanel(IBurpExtenderCallbacks callbacks, IExtensionHelpers helpers) { 27 | initComponents(); 28 | this.callbacks = callbacks; 29 | this.helpers = helpers; 30 | } 31 | 32 | private void initComponents() { 33 | 34 | // 4 - Define here the AWT/Swing UI which should contain three text fields (mongohost, mongoport, website) and save button 35 | 36 | // TODO 37 | 38 | // *** Highly recommended to use a WYSIWYG editor *** 39 | } 40 | 41 | // Button Event Click - Our code goes here! 42 | private void logButtonActionPerformed(java.awt.event.ActionEvent evt) { 43 | 44 | PrintWriter stdout = new PrintWriter(callbacks.getStdout(), true); 45 | PrintWriter stderr = new PrintWriter(callbacks.getStderr(), true); 46 | 47 | try { 48 | // 5 - Connect to the database and create two new collections for storing sitemap and vulns 49 | MongoClient mongo = new MongoClient(mongohost.getText(), Integer.parseInt(mongoport.getText())); 50 | DB db = mongo.getDB("sitelogger"); 51 | URL siteUrl = new URL(website.getText()); 52 | DBCollection tableSite = db.getCollection(siteUrl.getHost().replaceAll("\\.", "_") + "_site"); 53 | DBCollection tableVuln = db.getCollection(siteUrl.getHost().replaceAll("\\.", "_") + "_vuln"); 54 | 55 | // 6 - Retrieve the SiteMap content (using Burp's getSiteMap) 56 | IHttpRequestResponse[] allReqRes = callbacks.getSiteMap(website.getText()); 57 | for (int rc = 0; rc < allReqRes.length; rc++) { 58 | // 7 - Save each HTTP request/response to the database 59 | BasicDBObject document = new BasicDBObject(); 60 | document.put("host", allReqRes[rc].getHost()); 61 | document.put("port", allReqRes[rc].getPort()); 62 | document.put("protocol", allReqRes[rc].getProtocol()); 63 | document.put("URL", allReqRes[rc].getUrl().toString()); 64 | document.put("status_code", allReqRes[rc].getStatusCode()); 65 | if (allReqRes[rc].getRequest() != null) { 66 | document.put("request", helpers.base64Encode(allReqRes[rc].getRequest())); 67 | } 68 | if (allReqRes[rc].getResponse() != null) { 69 | document.put("response", helpers.base64Encode(allReqRes[rc].getResponse())); 70 | } 71 | tableSite.insert(document); 72 | } 73 | 74 | // 8 - Retrieve all scanner findings (using Burp's getScanIssues) 75 | IScanIssue[] allVulns = callbacks.getScanIssues(website.getText()); 76 | for (int vc = 0; vc < allVulns.length; vc++) { 77 | // 9 - Save each vulnerability report to the database, including HTTP request/response 78 | BasicDBObject document = new BasicDBObject(); 79 | document.put("type", allVulns[vc].getIssueType()); 80 | document.put("name", allVulns[vc].getIssueName()); 81 | document.put("detail", allVulns[vc].getIssueDetail()); 82 | document.put("severity", allVulns[vc].getSeverity()); 83 | document.put("confidence", allVulns[vc].getConfidence()); 84 | document.put("host", allVulns[vc].getHost()); 85 | document.put("port", allVulns[vc].getPort()); 86 | document.put("protocol", allVulns[vc].getProtocol()); 87 | document.put("URL", allVulns[vc].getUrl().toString()); 88 | if (allVulns[vc].getHttpMessages().length > 1) { 89 | if (allVulns[vc].getHttpMessages()[0].getRequest() != null) { 90 | document.put("request", helpers.base64Encode(allVulns[vc].getHttpMessages()[0].getRequest())); 91 | } 92 | if (allVulns[vc].getHttpMessages()[0].getResponse() != null) { 93 | document.put("response", helpers.base64Encode(allVulns[vc].getHttpMessages()[0].getResponse())); 94 | } 95 | } 96 | tableVuln.insert(document); 97 | } 98 | 99 | callbacks.issueAlert("Data Saved!"); 100 | 101 | } catch (UnknownHostException ex) { 102 | 103 | stderr.println("Mongo DB Connection Error:" + ex.toString()); 104 | 105 | } catch (MalformedURLException ex) { 106 | 107 | stderr.println("Malformed URL:" + ex.toString()); 108 | 109 | } 110 | } 111 | } 112 | -------------------------------------------------------------------------------- /SiteLogger/Java/WIP2/com/doyensec/sitelogger/SiteLoggerTabWIP2.java: -------------------------------------------------------------------------------- 1 | /* 2 | * SiteLogger - Log sitemap and findings to database 3 | * 4 | * Copyright (c) 2017 Doyensec LLC. Made with love by Luca Carettoni. 5 | */ 6 | package com.doyensec.sitelogger; 7 | 8 | import burp.IBurpExtenderCallbacks; 9 | import burp.IExtensionHelpers; 10 | import burp.ITab; 11 | import java.awt.Component; 12 | import javax.swing.JPanel; 13 | 14 | public class SiteLoggerTab implements ITab { 15 | 16 | private final IBurpExtenderCallbacks callbacks; 17 | private final IExtensionHelpers helpers; 18 | 19 | public SiteLoggerTab(IBurpExtenderCallbacks callbacks, IExtensionHelpers helpers) { 20 | this.callbacks = callbacks; 21 | this.helpers = helpers; 22 | } 23 | 24 | // 2 - Simply implement all ITab's methods (getTabCaption and getUiComponent) 25 | @Override 26 | public String getTabCaption() { 27 | return "SiteLogger"; 28 | } 29 | 30 | @Override 31 | public Component getUiComponent() { 32 | // 3 - In getUiComponent, instantiate a new Jpanel created using standard Java AWT/Swing GUI Editors 33 | JPanel panel = new SiteLoggerPanel(callbacks, helpers); 34 | callbacks.customizeUiComponent(panel); 35 | return panel; 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /SiteLogger/Python/WIP1/BurpExtenderWIP1.py: -------------------------------------------------------------------------------- 1 | # 2 | # SiteLogger - Log sitemap and findings to database 3 | # 4 | # Copyright (c) 2017 Doyensec LLC. Made with love by Andrea Brancaleoni. 5 | # 6 | 7 | from java.awt import Component 8 | 9 | from burp import IBurpExtenderCallbacks, IExtensionHelpers, IHttpRequestResponse 10 | from burp import IScanIssue, ITab, IBurpExtender 11 | from com.mongodb import BasicDBObject, DB, DBCollection, MongoClient 12 | 13 | from java.io import PrintWriter 14 | from java.net import MalformedURLException, URL, UnknownHostException 15 | 16 | from javax.swing import (BoxLayout, ImageIcon, JButton, JFrame, JPanel, 17 | JPasswordField, JLabel, JTextArea, JTextField, JScrollPane, 18 | SwingConstants, WindowConstants, GroupLayout) 19 | import javax 20 | from java.lang import Short, Integer 21 | 22 | 23 | # Original code from src/burp/BurpExtender.java class 24 | class BurpExtender(IBurpExtender): 25 | 26 | def registerExtenderCallbacks(self, callbacks): 27 | self.callbacks = callbacks 28 | helpers = callbacks.getHelpers() 29 | callbacks.setExtensionName("SiteLogger") 30 | 31 | # 1 - Add a custom tab to Burp (using addSuiteTab) 32 | # Please use a separate file named 'SiteLoggerTab' within the package 'com.doyensec.sitelogger' 33 | 34 | 35 | # Original code from src/com/doyensec/SiteLoggerTab.java class 36 | class SiteLoggerTab(ITab): 37 | 38 | def __init__(self, callbacks, helpers): 39 | self.callbacks = callbacks 40 | self.helpers = helpers 41 | 42 | # 2 - Simply implement all ITab's methods (getTabCaption and getUiComponent) 43 | 44 | # 3 - In getUiComponent, instantiate a new Jpanel created using standard Java AWT/Swing GUI Editors 45 | 46 | 47 | # Original code from src/com/doyensec/SiteLoggerPanel.java class 48 | # XXX: inheriting from Java classes is very tricky. It is preferable to use 49 | # the decorator pattern instead. 50 | class SiteLoggerPanel: 51 | 52 | def __init__(self, callbacks, helpers): 53 | self.callbacks = callbacks 54 | self.helpers = helpers 55 | self.this = JPanel() 56 | self.initComponents() 57 | 58 | def initComponents(self): 59 | # 4 - Define here the AWT/Swing UI which should contain three text fields (mongohost, mongoport, website) and save button 60 | pass 61 | 62 | def logButtonActionPerformed(self, evt): 63 | # 5 - Connect to the database and create two new collections for storing sitemap and vulns 64 | 65 | # 6 - Retrieve the SiteMap content (using Burp's getSiteMap) 66 | 67 | # 7 - Save each HTTP request/response to the database 68 | 69 | # 8 - Retrieve all scanner findings (using Burp's getScanIssues) 70 | 71 | # 9 - Save each vulnerability report to the database, including HTTP request/response 72 | -------------------------------------------------------------------------------- /SiteLogger/Python/WIP2/BurpExtenderWIP2.py: -------------------------------------------------------------------------------- 1 | # 2 | # SiteLogger - Log sitemap and findings to database 3 | # 4 | # Copyright (c) 2017 Doyensec LLC. Made with love by Andrea Brancaleoni. 5 | # 6 | 7 | from java.awt import Component 8 | 9 | from burp import IBurpExtenderCallbacks, IExtensionHelpers, IHttpRequestResponse 10 | from burp import IScanIssue, ITab, IBurpExtender 11 | from com.mongodb import BasicDBObject, DB, DBCollection, MongoClient 12 | 13 | from java.io import PrintWriter 14 | from java.net import MalformedURLException, URL, UnknownHostException 15 | 16 | from javax.swing import (BoxLayout, ImageIcon, JButton, JFrame, JPanel, 17 | JPasswordField, JLabel, JTextArea, JTextField, JScrollPane, 18 | SwingConstants, WindowConstants, GroupLayout) 19 | import javax 20 | from java.lang import Short, Integer 21 | 22 | 23 | # Original code from src/burp/BurpExtender.java class 24 | class BurpExtender(IBurpExtender): 25 | 26 | def registerExtenderCallbacks(self, callbacks): 27 | self.callbacks = callbacks 28 | helpers = callbacks.getHelpers() 29 | callbacks.setExtensionName("SiteLogger") 30 | 31 | # 1 - Add a custom tab to Burp (using addSuiteTab) 32 | # Please use a separate file named 'SiteLoggerTab' within the package 'com.doyensec.sitelogger' 33 | callbacks.addSuiteTab(SiteLoggerTab(callbacks, helpers)) 34 | 35 | 36 | # Original code from src/com/doyensec/SiteLoggerTab.java class 37 | class SiteLoggerTab(ITab): 38 | 39 | def __init__(self, callbacks, helpers): 40 | self.callbacks = callbacks 41 | self.helpers = helpers 42 | 43 | def getTabCaption(self): 44 | return "SiteLogger" 45 | 46 | def getUiComponent(self): 47 | panel = SiteLoggerPanel(self.callbacks, self.helpers) 48 | self.callbacks.customizeUiComponent(panel.this) 49 | return panel.this 50 | 51 | 52 | # Original code from src/com/doyensec/SiteLoggerPanel.java class 53 | # XXX: inheriting from Java classes is very tricky. It is preferable to use 54 | # the decorator pattern instead. 55 | class SiteLoggerPanel: 56 | 57 | def __init__(self, callbacks, helpers): 58 | self.callbacks = callbacks 59 | self.helpers = helpers 60 | self.this = JPanel() 61 | self.initComponents() 62 | 63 | def initComponents(self): 64 | 65 | # 4 - Define here the AWT/Swing UI which should contain three text fields (mongohost, mongoport, website) and save button 66 | 67 | # TODO 68 | 69 | pass 70 | 71 | # Button Event Click - Our code goes here! 72 | def logButtonActionPerformed(self, evt): 73 | stdout = PrintWriter(self.callbacks.getStdout(), True) 74 | stderr = PrintWriter(self.callbacks.getStderr(), True) 75 | 76 | try: 77 | # 5 - Connect to the database and create the collections 78 | mongo = MongoClient(self.mongohost.getText(), Integer.parseInt(self.mongoport.getText())) 79 | db = mongo.getDB("sitelogger") 80 | siteUrl = URL(self.website.getText()) 81 | tableSite = db.getCollection(siteUrl.getHost().replace(".", "_") + "_site") 82 | tableVuln = db.getCollection(siteUrl.getHost().replace(".", "_") + "_vuln") 83 | 84 | # 6 - Retrieve SiteMap HTTP Requests and Responses and save to the database 85 | allReqRes = self.callbacks.getSiteMap(self.website.getText()) 86 | for rc in xrange(0, len(allReqRes)): 87 | # 7 - Save each HTTP request/response to the database 88 | document = BasicDBObject() 89 | document.put("host", allReqRes[rc].getHost()) 90 | document.put("port", allReqRes[rc].getPort()) 91 | document.put("protocol", allReqRes[rc].getProtocol()) 92 | document.put("URL", allReqRes[rc].getUrl().toString()) 93 | document.put("status_code", allReqRes[rc].getStatusCode()) 94 | if (allReqRes[rc].getRequest() != None): 95 | document.put("request", self.helpers.base64Encode(allReqRes[rc].getRequest())) 96 | 97 | if (allReqRes[rc].getResponse() != None): 98 | document.put("response", self.helpers.base64Encode(allReqRes[rc].getResponse())) 99 | 100 | tableSite.insert(document) 101 | 102 | 103 | # 8 - Retrieve Scan findings and save to the database 104 | allVulns = self.callbacks.getScanIssues(self.website.getText()) 105 | for vc in xrange(0, len(allVulns)): 106 | # 9 - Save each vulnerability report to the database, including HTTP request/response 107 | document = BasicDBObject() 108 | document.put("type", allVulns[vc].getIssueType()) 109 | document.put("name", allVulns[vc].getIssueName()) 110 | document.put("detail", allVulns[vc].getIssueDetail()) 111 | document.put("severity", allVulns[vc].getSeverity()) 112 | document.put("confidence", allVulns[vc].getConfidence()) 113 | document.put("host", allVulns[vc].getHost()) 114 | document.put("port", allVulns[vc].getPort()) 115 | document.put("protocol", allVulns[vc].getProtocol()) 116 | document.put("URL", allVulns[vc].getUrl().toString()) 117 | if (len(allVulns[vc].getHttpMessages()) > 1): 118 | if (allVulns[vc].getHttpMessages()[0].getRequest() != None): 119 | document.put("request", self.helpers.base64Encode(allVulns[vc].getHttpMessages()[0].getRequest())) 120 | 121 | if (allVulns[vc].getHttpMessages()[0].getResponse() != None): 122 | document.put("response", self.helpers.base64Encode(allVulns[vc].getHttpMessages()[0].getResponse())) 123 | 124 | 125 | tableVuln.insert(document) 126 | 127 | 128 | self.callbacks.issueAlert("Data Saved!") 129 | 130 | except UnknownHostException as ex: 131 | stderr.println("Mongo DB Connection Error:" + ex.toString()) 132 | except MalformedURLException as ex: 133 | stderr.println("Malformed URL:" + ex.toString()) 134 | -------------------------------------------------------------------------------- /SiteLogger/Ruby/Final/BurpExtender.rb: -------------------------------------------------------------------------------- 1 | # 2 | # SiteLogger - Log sitemap and findings to database 3 | # 4 | # Copyright (c) 2017 Doyensec LLC. Made with love by Andrea Brancaleoni. 5 | # 6 | 7 | require 'java' 8 | java_import 'burp.IBurpExtender' 9 | java_import 'burp.IBurpExtenderCallbacks' 10 | java_import 'burp.IExtensionHelpers' 11 | java_import 'burp.ITab' 12 | java_import 'java.awt.Component' 13 | 14 | java_import 'java.awt.Button' 15 | java_import 'java.awt.Color' 16 | java_import 'java.awt.Panel' 17 | 18 | java_import 'javax.swing.JPanel' 19 | java_import 'burp.IBurpExtenderCallbacks' 20 | java_import 'burp.IExtensionHelpers' 21 | java_import 'burp.IHttpRequestResponse' 22 | java_import 'burp.IScanIssue' 23 | java_import 'com.mongodb.BasicDBObject' 24 | java_import 'com.mongodb.DB' 25 | java_import 'com.mongodb.DBCollection' 26 | java_import 'com.mongodb.MongoClient' 27 | java_import 'java.io.PrintWriter' 28 | java_import 'java.net.MalformedURLException' 29 | java_import 'java.net.URL' 30 | java_import 'java.net.UnknownHostException' 31 | java_import 'java.lang.Short' 32 | 33 | # Original code from src/burp/BurpExtender.java class 34 | class BurpExtender 35 | include IBurpExtender 36 | 37 | def registerExtenderCallbacks(callbacks) 38 | @callbacks = callbacks 39 | helpers = callbacks.getHelpers() 40 | callbacks.setExtensionName("SiteLogger") 41 | callbacks.addSuiteTab(SiteLoggerTab.new(callbacks, helpers)) 42 | end 43 | end 44 | 45 | # Original code from src/com/doyensec/SiteLoggerTab.java class 46 | class SiteLoggerTab 47 | include ITab 48 | 49 | attr_reader :callbacks 50 | attr_reader :helpers 51 | 52 | def initialize(callbacks, helpers) 53 | @callbacks = callbacks 54 | @helpers = helpers 55 | end 56 | 57 | def getTabCaption() 58 | return "SiteLogger" 59 | end 60 | 61 | def getUiComponent() 62 | panel = SiteLoggerPanel.new(callbacks, helpers) 63 | callbacks.customizeUiComponent(panel.this) 64 | return panel.this 65 | end 66 | end 67 | 68 | # Original code from src/com/doyensec/SiteLoggerPanel.java class 69 | # XXX: inheriting from Java classes is very tricky. It is preferable to use 70 | # the decorator pattern instead. 71 | class SiteLoggerPanel 72 | attr_accessor :callbacks 73 | attr_accessor :helpers 74 | attr_accessor :this 75 | 76 | def initialize(callbacks, helpers) 77 | @this = JPanel.new 78 | @callbacks = callbacks 79 | @helpers = helpers 80 | initComponents() 81 | end 82 | 83 | # 84 | # This method is called from within the constructor to initialize the form. 85 | # WARNING: Do NOT modify this code. The content of this method is always 86 | # regenerated by the Form Editor. 87 | # 88 | # //GEN-BEGIN:initComponents 89 | def initComponents() 90 | @jLabel1 = javax.swing.JLabel.new() 91 | @website = javax.swing.JTextField.new() 92 | @jLabel2 = javax.swing.JLabel.new() 93 | @mongohost = javax.swing.JTextField.new() 94 | @mongoport = javax.swing.JTextField.new() 95 | @logButton = javax.swing.JButton.new() 96 | @jLabel3 = javax.swing.JLabel.new() 97 | @jLabel1.setText("Website:") 98 | 99 | @jLabel2.setText("MongoDB Host: ") 100 | 101 | @mongohost.setText("127.0.0.1") 102 | 103 | @mongoport.setText("27017") 104 | 105 | @logButton.setText("Log to Database") 106 | @logButton.addActionListener do |evt| 107 | logButtonActionPerformed(evt) 108 | end 109 | @jLabel3.setText("MongoDB Port: ") 110 | 111 | layout = javax.swing.GroupLayout.new(this) 112 | this.setLayout(layout) 113 | layout.setHorizontalGroup( 114 | layout.createParallelGroup(javax.swing.GroupLayout::Alignment::LEADING) 115 | .addGroup(layout.createSequentialGroup() 116 | .addGroup(layout.createParallelGroup(javax.swing.GroupLayout::Alignment::LEADING) 117 | .addGroup(layout.createSequentialGroup() 118 | .addGap(48, 48, 48) 119 | .addGroup(layout.createParallelGroup(javax.swing.GroupLayout::Alignment::LEADING) 120 | .addGroup(layout.createSequentialGroup() 121 | .addComponent(@jLabel3) 122 | .addPreferredGap(javax.swing.LayoutStyle::ComponentPlacement::UNRELATED) 123 | .addComponent(@mongoport, javax.swing.GroupLayout::PREFERRED_SIZE, 226, javax.swing.GroupLayout::PREFERRED_SIZE)) 124 | .addGroup(layout.createParallelGroup(javax.swing.GroupLayout::Alignment::TRAILING, false) 125 | .addGroup(javax.swing.GroupLayout::Alignment::LEADING, layout.createSequentialGroup() 126 | .addComponent(@jLabel2) 127 | .addPreferredGap(javax.swing.LayoutStyle::ComponentPlacement::RELATED) 128 | .addComponent(@mongohost, javax.swing.GroupLayout::PREFERRED_SIZE, 227, javax.swing.GroupLayout::PREFERRED_SIZE)) 129 | .addGroup(javax.swing.GroupLayout::Alignment::LEADING, layout.createSequentialGroup() 130 | .addComponent(@jLabel1) 131 | .addPreferredGap(javax.swing.LayoutStyle::ComponentPlacement::RELATED) 132 | .addComponent(@website))))) 133 | .addGroup(layout.createSequentialGroup() 134 | .addGap(99, 99, 99) 135 | .addComponent(@logButton, javax.swing.GroupLayout::PREFERRED_SIZE, 169, javax.swing.GroupLayout::PREFERRED_SIZE))) 136 | .addContainerGap(818, Short::MAX_VALUE)) 137 | ) 138 | layout.setVerticalGroup( 139 | layout.createParallelGroup(javax.swing.GroupLayout::Alignment::LEADING) 140 | .addGroup(layout.createSequentialGroup() 141 | .addGap(34, 34, 34) 142 | .addGroup(layout.createParallelGroup(javax.swing.GroupLayout::Alignment::BASELINE) 143 | .addComponent(@jLabel1) 144 | .addComponent(@website, javax.swing.GroupLayout::PREFERRED_SIZE, javax.swing.GroupLayout::DEFAULT_SIZE, javax.swing.GroupLayout::PREFERRED_SIZE)) 145 | .addGap(18, 18, 18) 146 | .addGroup(layout.createParallelGroup(javax.swing.GroupLayout::Alignment::BASELINE) 147 | .addComponent(@jLabel2) 148 | .addComponent(@mongohost, javax.swing.GroupLayout::PREFERRED_SIZE, javax.swing.GroupLayout::DEFAULT_SIZE, javax.swing.GroupLayout::PREFERRED_SIZE)) 149 | .addGap(18, 18, 18) 150 | .addGroup(layout.createParallelGroup(javax.swing.GroupLayout::Alignment::BASELINE) 151 | .addComponent(@jLabel3) 152 | .addComponent(@mongoport, javax.swing.GroupLayout::PREFERRED_SIZE, javax.swing.GroupLayout::DEFAULT_SIZE, javax.swing.GroupLayout::PREFERRED_SIZE)) 153 | .addGap(32, 32, 32) 154 | .addComponent(@logButton, javax.swing.GroupLayout::PREFERRED_SIZE, 51, javax.swing.GroupLayout::PREFERRED_SIZE) 155 | .addContainerGap(115, Short::MAX_VALUE)) 156 | ) 157 | end# //GEN-END:initComponents 158 | 159 | def logButtonActionPerformed(evt) #GEN-FIRST:event_logButtonActionPerformed 160 | 161 | stdout = PrintWriter.new(callbacks.getStdout(), true) 162 | stderr = PrintWriter.new(callbacks.getStderr(), true) 163 | 164 | begin 165 | #Connect to the database and create the collections 166 | mongo = MongoClient.new(@mongohost.getText().to_s, @mongoport.getText().to_i) 167 | db = mongo.getDB("sitelogger") 168 | siteUrl = URL.new(@website.getText()) 169 | tableSite = db.getCollection(siteUrl.getHost().gsub(".", "_") + "_site") 170 | tableVuln = db.getCollection(siteUrl.getHost().gsub(".", "_") + "_vuln") 171 | 172 | #Retrieve SiteMap HTTP Requests and Responses and save to the database 173 | allReqRes = callbacks.getSiteMap(@website.getText()) 174 | for rc in 0...allReqRes.length 175 | document = BasicDBObject.new() 176 | document.put("host", allReqRes[rc].getHost()) 177 | document.put("port", allReqRes[rc].getPort().to_i32) 178 | document.put("protocol", allReqRes[rc].getProtocol()) 179 | document.put("URL", allReqRes[rc].getUrl().toString()) 180 | document.put("status_code", allReqRes[rc].getStatusCode()) 181 | if (allReqRes[rc].getRequest() != nil) 182 | document.put("request", helpers.base64Encode(allReqRes[rc].getRequest())) 183 | end 184 | if (allReqRes[rc].getResponse() != nil) 185 | document.put("response", helpers.base64Encode(allReqRes[rc].getResponse())) 186 | end 187 | tableSite.insert(document) 188 | end 189 | 190 | #Retrieve Scan findings and save to the database 191 | allVulns = callbacks.getScanIssues(@website.getText()) 192 | for vc in 0...allVulns.length 193 | document = BasicDBObject.new() 194 | document.put("type", allVulns[vc].getIssueType()) 195 | document.put("name", allVulns[vc].getIssueName()) 196 | document.put("detail", allVulns[vc].getIssueDetail()) 197 | document.put("severity", allVulns[vc].getSeverity()) 198 | document.put("confidence", allVulns[vc].getConfidence()) 199 | document.put("host", allVulns[vc].getHost()) 200 | document.put("port", allVulns[vc].getPort().to_i32) 201 | document.put("protocol", allVulns[vc].getProtocol()) 202 | document.put("URL", allVulns[vc].getUrl().toString()) 203 | if (allVulns[vc].getHttpMessages().length > 1) 204 | if (allVulns[vc].getHttpMessages()[0].getRequest() != nil) 205 | document.put("request", helpers.base64Encode(allVulns[vc].getHttpMessages()[0].getRequest())) 206 | end 207 | if (allVulns[vc].getHttpMessages()[0].getResponse() != nil) 208 | document.put("response", helpers.base64Encode(allVulns[vc].getHttpMessages()[0].getResponse())) 209 | end 210 | end 211 | tableVuln.insert(document) 212 | end 213 | 214 | callbacks.issueAlert("Data Saved!") 215 | 216 | rescue UnknownHostException => ex 217 | stderr.println("Mongo DB Connection Error:" + ex.toString()) 218 | rescue MalformedURLException => ex 219 | stderr.println("Malformed URL:" + ex.toString()) 220 | end 221 | end #GEN-LAST:event_@logButtonActionPerformed 222 | end 223 | -------------------------------------------------------------------------------- /SiteLogger/Ruby/WIP1/BurpExtenderWIP1.rb: -------------------------------------------------------------------------------- 1 | # 2 | # SiteLogger - Log sitemap and findings to database 3 | # 4 | # Copyright (c) 2017 Doyensec LLC. Made with love by Andrea Brancaleoni. 5 | # 6 | 7 | require 'java' 8 | java_import 'burp.IBurpExtender' 9 | java_import 'burp.IBurpExtenderCallbacks' 10 | java_import 'burp.IExtensionHelpers' 11 | java_import 'burp.ITab' 12 | java_import 'java.awt.Component' 13 | 14 | java_import 'java.awt.Button' 15 | java_import 'java.awt.Color' 16 | java_import 'java.awt.Panel' 17 | 18 | java_import 'javax.swing.JPanel' 19 | java_import 'burp.IBurpExtenderCallbacks' 20 | java_import 'burp.IExtensionHelpers' 21 | java_import 'burp.IHttpRequestResponse' 22 | java_import 'burp.IScanIssue' 23 | java_import 'com.mongodb.BasicDBObject' 24 | java_import 'com.mongodb.DB' 25 | java_import 'com.mongodb.DBCollection' 26 | java_import 'com.mongodb.MongoClient' 27 | java_import 'java.io.PrintWriter' 28 | java_import 'java.net.MalformedURLException' 29 | java_import 'java.net.URL' 30 | java_import 'java.net.UnknownHostException' 31 | java_import 'java.lang.Short' 32 | 33 | # Original code from src/burp/BurpExtender.java class 34 | class BurpExtender 35 | include IBurpExtender 36 | 37 | def registerExtenderCallbacks(callbacks) 38 | @callbacks = callbacks 39 | helpers = callbacks.getHelpers() 40 | callbacks.setExtensionName("SiteLogger") 41 | 42 | # 1 - Add a custom tab to Burp (using addSuiteTab) 43 | # Please use a separate file named 'SiteLoggerTab' within the package 'com.doyensec.sitelogger' 44 | end 45 | end 46 | 47 | # Original code from src/com/doyensec/SiteLoggerTab.java class 48 | class SiteLoggerTab 49 | include ITab 50 | 51 | attr_reader :callbacks 52 | attr_reader :helpers 53 | 54 | def initialize(callbacks, helpers) 55 | @callbacks = callbacks 56 | @helpers = helpers 57 | end 58 | 59 | # 2 - Simply implement all ITab's methods (getTabCaption and getUiComponent) 60 | 61 | # 3 - In getUiComponent, instantiate a new Jpanel created using standard Java AWT/Swing GUI Editors 62 | end 63 | 64 | # Original code from src/com/doyensec/SiteLoggerPanel.java class 65 | # XXX: inheriting from Java classes is very tricky. It is preferable to use 66 | # the decorator pattern instead. 67 | class SiteLoggerPanel 68 | attr_accessor :callbacks 69 | attr_accessor :helpers 70 | attr_accessor :this 71 | 72 | def initialize(callbacks, helpers) 73 | @this = JPanel.new 74 | @callbacks = callbacks 75 | @helpers = helpers 76 | initComponents() 77 | end 78 | 79 | def initComponents 80 | # 4 - Define here the AWT/Swing UI which should contain three text fields (mongohost, mongoport, website) and save button 81 | 82 | # TODO 83 | end 84 | 85 | def logButtonActionPerformed(evt) 86 | # 5 - Connect to the database and create two new collections for storing sitemap and vulns 87 | 88 | # 6 - Retrieve the SiteMap content (using Burp's getSiteMap) 89 | 90 | # 7 - Save each HTTP request/response to the database 91 | 92 | # 8 - Retrieve all scanner findings (using Burp's getScanIssues) 93 | 94 | # 9 - Save each vulnerability report to the database, including HTTP request/response 95 | end 96 | end 97 | -------------------------------------------------------------------------------- /SiteLogger/Ruby/WIP2/BurpExtenderWIP2.rb: -------------------------------------------------------------------------------- 1 | # 2 | # SiteLogger - Log sitemap and findings to database 3 | # 4 | # Copyright (c) 2017 Doyensec LLC. Made with love by Andrea Brancaleoni. 5 | # 6 | 7 | require 'java' 8 | java_import 'burp.IBurpExtender' 9 | java_import 'burp.IBurpExtenderCallbacks' 10 | java_import 'burp.IExtensionHelpers' 11 | java_import 'burp.ITab' 12 | java_import 'java.awt.Component' 13 | 14 | java_import 'java.awt.Button' 15 | java_import 'java.awt.Color' 16 | java_import 'java.awt.Panel' 17 | 18 | java_import 'javax.swing.JPanel' 19 | java_import 'burp.IBurpExtenderCallbacks' 20 | java_import 'burp.IExtensionHelpers' 21 | java_import 'burp.IHttpRequestResponse' 22 | java_import 'burp.IScanIssue' 23 | java_import 'com.mongodb.BasicDBObject' 24 | java_import 'com.mongodb.DB' 25 | java_import 'com.mongodb.DBCollection' 26 | java_import 'com.mongodb.MongoClient' 27 | java_import 'java.io.PrintWriter' 28 | java_import 'java.net.MalformedURLException' 29 | java_import 'java.net.URL' 30 | java_import 'java.net.UnknownHostException' 31 | java_import 'java.lang.Short' 32 | 33 | # Original code from src/burp/BurpExtender.java class 34 | class BurpExtender 35 | include IBurpExtender 36 | 37 | def registerExtenderCallbacks(callbacks) 38 | @callbacks = callbacks 39 | helpers = callbacks.getHelpers() 40 | callbacks.setExtensionName("SiteLogger") 41 | 42 | # 1 - Add a custom tab to Burp (using addSuiteTab) 43 | # Please use a separate file named 'SiteLoggerTab' within the package 'com.doyensec.sitelogger' 44 | callbacks.addSuiteTab(SiteLoggerTab.new(callbacks, helpers)) 45 | end 46 | end 47 | 48 | # Original code from src/com/doyensec/SiteLoggerTab.java class 49 | class SiteLoggerTab 50 | include ITab 51 | 52 | attr_reader :callbacks 53 | attr_reader :helpers 54 | 55 | def initialize(callbacks, helpers) 56 | @callbacks = callbacks 57 | @helpers = helpers 58 | end 59 | 60 | def getTabCaption() 61 | return "SiteLogger" 62 | end 63 | 64 | def getUiComponent() 65 | panel = SiteLoggerPanel.new(callbacks, helpers) 66 | callbacks.customizeUiComponent(panel.this) 67 | return panel.this 68 | end 69 | end 70 | 71 | # Original code from src/com/doyensec/SiteLoggerPanel.java class 72 | # XXX: inheriting from Java classes is very tricky. It is preferable to use 73 | # the decorator pattern instead. 74 | class SiteLoggerPanel 75 | attr_accessor :callbacks 76 | attr_accessor :helpers 77 | attr_accessor :this 78 | 79 | def initialize(callbacks, helpers) 80 | @this = JPanel.new 81 | @callbacks = callbacks 82 | @helpers = helpers 83 | initComponents() 84 | end 85 | 86 | def initComponents() 87 | # 4 - Define here the AWT/Swing UI which should contain three text fields (mongohost, mongoport, website) and save button 88 | 89 | # TODO 90 | 91 | pass 92 | end 93 | 94 | def logButtonActionPerformed(evt) #GEN-FIRST:event_logButtonActionPerformed 95 | 96 | stdout = PrintWriter.new(callbacks.getStdout(), true) 97 | stderr = PrintWriter.new(callbacks.getStderr(), true) 98 | 99 | begin 100 | # 5 - Connect to the database and create the collections 101 | mongo = MongoClient.new(@mongohost.getText().to_s, @mongoport.getText().to_i) 102 | db = mongo.getDB("sitelogger") 103 | siteUrl = URL.new(@website.getText()) 104 | tableSite = db.getCollection(siteUrl.getHost().gsub(".", "_") + "_site") 105 | tableVuln = db.getCollection(siteUrl.getHost().gsub(".", "_") + "_vuln") 106 | 107 | # 6 - Retrieve SiteMap HTTP Requests and Responses and save to the database 108 | allReqRes = callbacks.getSiteMap(@website.getText()) 109 | for rc in 0...allReqRes.length 110 | # 7 - Save each HTTP request/response to the database 111 | document = BasicDBObject.new() 112 | document.put("host", allReqRes[rc].getHost()) 113 | document.put("port", allReqRes[rc].getPort().to_i32) 114 | document.put("protocol", allReqRes[rc].getProtocol()) 115 | document.put("URL", allReqRes[rc].getUrl().toString()) 116 | document.put("status_code", allReqRes[rc].getStatusCode()) 117 | if (allReqRes[rc].getRequest() != nil) 118 | document.put("request", helpers.base64Encode(allReqRes[rc].getRequest())) 119 | end 120 | if (allReqRes[rc].getResponse() != nil) 121 | document.put("response", helpers.base64Encode(allReqRes[rc].getResponse())) 122 | end 123 | tableSite.insert(document) 124 | end 125 | 126 | # 8 - Retrieve Scan findings and save to the database 127 | allVulns = callbacks.getScanIssues(@website.getText()) 128 | for vc in 0...allVulns.length 129 | # 9 - Save each vulnerability report to the database, including HTTP request/response 130 | document = BasicDBObject.new() 131 | document.put("type", allVulns[vc].getIssueType()) 132 | document.put("name", allVulns[vc].getIssueName()) 133 | document.put("detail", allVulns[vc].getIssueDetail()) 134 | document.put("severity", allVulns[vc].getSeverity()) 135 | document.put("confidence", allVulns[vc].getConfidence()) 136 | document.put("host", allVulns[vc].getHost()) 137 | document.put("port", allVulns[vc].getPort().to_i32) 138 | document.put("protocol", allVulns[vc].getProtocol()) 139 | document.put("URL", allVulns[vc].getUrl().toString()) 140 | if (allVulns[vc].getHttpMessages().length > 1) 141 | if (allVulns[vc].getHttpMessages()[0].getRequest() != nil) 142 | document.put("request", helpers.base64Encode(allVulns[vc].getHttpMessages()[0].getRequest())) 143 | end 144 | if (allVulns[vc].getHttpMessages()[0].getResponse() != nil) 145 | document.put("response", helpers.base64Encode(allVulns[vc].getHttpMessages()[0].getResponse())) 146 | end 147 | end 148 | tableVuln.insert(document) 149 | end 150 | 151 | callbacks.issueAlert("Data Saved!") 152 | 153 | rescue UnknownHostException => ex 154 | stderr.println("Mongo DB Connection Error:" + ex.toString()) 155 | rescue MalformedURLException => ex 156 | stderr.println("Malformed URL:" + ex.toString()) 157 | end 158 | end #GEN-LAST:event_@logButtonActionPerformed 159 | end 160 | --------------------------------------------------------------------------------