├── .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 | [](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 |
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 |
--------------------------------------------------------------------------------