├── HandyCollaborator1.png
├── HandyCollaborator2.png
├── HandyCollaborator3.png
├── HandyCollaborator4.png
├── LICENSE
├── src
└── main
│ └── java
│ └── burp
│ ├── CustomScanIssue.java
│ ├── InteractionServer.java
│ └── BurpExtender.java
├── pom.xml
└── README.md
/HandyCollaborator1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/federicodotta/HandyCollaborator/HEAD/HandyCollaborator1.png
--------------------------------------------------------------------------------
/HandyCollaborator2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/federicodotta/HandyCollaborator/HEAD/HandyCollaborator2.png
--------------------------------------------------------------------------------
/HandyCollaborator3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/federicodotta/HandyCollaborator/HEAD/HandyCollaborator3.png
--------------------------------------------------------------------------------
/HandyCollaborator4.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/federicodotta/HandyCollaborator/HEAD/HandyCollaborator4.png
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2017 federicodotta
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/src/main/java/burp/CustomScanIssue.java:
--------------------------------------------------------------------------------
1 | package burp;
2 |
3 | import java.net.URL;
4 |
5 | public class CustomScanIssue implements IScanIssue {
6 |
7 | private IHttpService httpService;
8 | private URL url;
9 | private IHttpRequestResponse[] httpMessages;
10 | private String name;
11 | private String severity;
12 | private String confidence;
13 | private String issueDetail;
14 | private String remediationDetail;
15 |
16 | public CustomScanIssue(
17 | IHttpService httpService,
18 | URL url,
19 | IHttpRequestResponse[] httpMessages,
20 | String name,
21 | String severity,
22 | String confidence,
23 | String issueDetail,
24 | String remediationDetail
25 | )
26 | {
27 | this.httpService = httpService;
28 | this.url = url;
29 | this.httpMessages = httpMessages;
30 | this.name = name;
31 | this.severity = severity;
32 | this.confidence = confidence;
33 | this.issueDetail = issueDetail;
34 | this.remediationDetail = remediationDetail;
35 | }
36 |
37 | @Override
38 | public URL getUrl()
39 | {
40 | return url;
41 | }
42 |
43 | @Override
44 | public String getIssueName()
45 | {
46 | return name;
47 | }
48 |
49 | @Override
50 | public int getIssueType()
51 | {
52 | return 0;
53 | }
54 |
55 | @Override
56 | public String getSeverity()
57 | {
58 | return severity;
59 | }
60 |
61 | @Override
62 | public String getConfidence()
63 | {
64 | return confidence;
65 | }
66 |
67 | @Override
68 | public String getIssueBackground()
69 | {
70 | return null;
71 | }
72 |
73 | @Override
74 | public String getRemediationBackground()
75 | {
76 | return null;
77 | }
78 |
79 | @Override
80 | public String getIssueDetail()
81 | {
82 | return issueDetail;
83 | }
84 |
85 | @Override
86 | public String getRemediationDetail()
87 | {
88 | return remediationDetail;
89 | }
90 |
91 | @Override
92 | public IHttpRequestResponse[] getHttpMessages()
93 | {
94 | return httpMessages;
95 | }
96 |
97 | @Override
98 | public IHttpService getHttpService()
99 | {
100 | return httpService;
101 | }
102 |
103 | }
104 |
--------------------------------------------------------------------------------
/pom.xml:
--------------------------------------------------------------------------------
1 |
2 | 4.0.0
3 | org.fd
4 | HandyCollaborator
5 | 0.2
6 | Handy Collaborator
7 | Burp Suite Plugin to use Collaborator during manual testing
8 | jar
9 |
10 |
11 | UTF-8
12 |
13 |
14 |
15 |
16 |
17 | org.apache.maven.plugins
18 | maven-compiler-plugin
19 | 3.1
20 |
21 | 1.7
22 | 1.7
23 |
24 |
25 |
26 | maven-assembly-plugin
27 |
28 |
29 | true
30 |
31 |
32 | jar-with-dependencies
33 |
34 |
35 |
36 |
37 | true
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 | make-assembly
46 | package
47 |
48 | single
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 | net.portswigger.burp.extender
60 | burp-extender-api
61 | 1.7.22
62 |
63 |
64 |
65 |
66 | org.apache.commons
67 | commons-lang3
68 | 3.6
69 |
70 |
71 |
72 |
73 | org.json
74 | json
75 | 20180130
76 |
77 |
78 |
79 |
80 |
81 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Handy Collaborator
2 | Handy Collaborator is a Burp Suite Extension that lets you use the Collaborator tool during manual testing in a comfortable way. It is possible to generate a Collaborator payload from the contextual menu of editable tabs (Repeater, Intercept, etc.) and a separate thread will check periodically all interactions (DNS, HTTP and SMTP) received by the Collaborator for the generated payloads. If an interaction is found, an issue with all the details is added to the target host.
3 |
4 | # Authors
5 | - Federico Dotta, Security Advisor at @ Mediaservice.net
6 | - Gianluca Baldi, Security Expert at @ Mediaservice.net
7 |
8 | # Installation
9 | 1. Download Burp Suite: http://portswigger.net/burp/download.html
10 | 2. Install Handy Collaborator from the BApp Store or follow these steps:
11 | 3. Download the last release of Handy Collaborator
12 | 4. Open Burp -> Extender -> Extensions -> Add -> Choose HandyCollaboratorXX.jar file
13 |
14 | # Usage and examples
15 | 1. In the Repeater or the Intercept tab, right click on the point where you want to insert the Collaborator payload (or select a portion of text that will be replaced with the Collaborator payload) and click on "Insert Collaborator payload" or on "Insert Collaborator insertion point".
16 | 2. Execute the request with the payload or with the insertion point
17 | 3. If the payload causes an external interaction (DNS, HTTP or SMTP), soon an issue will appear in the Target tab with all the details of the interaction (request/reponse, type, timestamp and specific details that depend on the type of interaction)
18 | 4. That's all!
19 |
20 | If you choose the "Insert Collaborator insertion point" option, the insertion point will be transparently replaced with a new Collaborator payload every time that the request will be executed. In this way, if you execute multiple tests on the same request, a different Collaborator URL will be transparently inserted in each request and, in the case of an interaction, the exact request responsible for the interaction will be reported.
21 |
22 | # Limitations
23 | Currently, due to limitations in Burp Suite API, it is not possible to retrieve details on Collaborator interactions related to the payloads generated with this extension after unloading the extension or closing Burp Suite. The reason is that it is not possible to save the Collaborator context. An issue has been opened in Burp Suite Support Center on February 2017 and maybe this feature will be added in future (fingers crossed).
24 |
25 | # Screenshot
26 | 
27 | 
28 | 
29 | 
30 |
31 | # MIT License
32 |
33 | Copyright (c) 2017 Handy Collaborator
34 |
35 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
36 |
37 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
38 |
39 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
--------------------------------------------------------------------------------
/src/main/java/burp/InteractionServer.java:
--------------------------------------------------------------------------------
1 | package burp;
2 |
3 | import java.io.PrintWriter;
4 | import java.text.DateFormat;
5 | import java.text.SimpleDateFormat;
6 | import java.util.HashMap;
7 | import java.util.List;
8 | import java.util.TimeZone;
9 | import java.util.regex.Matcher;
10 | import java.util.regex.Pattern;
11 | import java.util.ArrayList;
12 | import java.util.Base64;
13 | import java.util.Date;
14 | import static java.util.concurrent.TimeUnit.*;
15 |
16 | public class InteractionServer extends Thread {
17 |
18 | private IBurpExtenderCallbacks callbacks;
19 | private HashMap processedRequestResponse;
20 |
21 | private PrintWriter stdout;
22 | private PrintWriter stderr;
23 |
24 | private List collaboratorContextList;
25 |
26 | private volatile boolean goOn;
27 |
28 | private static final String issueName = " Collaborator interaction - Handy Collaborator";
29 | String remediation = "The remediations depends on the specific issue manually tested.";
30 | private static final String severity = "High";
31 | private static final String confidence = "Certain";
32 |
33 | private static final int pollingMilliseconds = 3000;
34 |
35 | private final Object pauseLock = new Object();
36 | private volatile boolean paused = false;
37 |
38 | public InteractionServer(IBurpExtenderCallbacks callbacks, HashMap processedRequestResponse, IBurpCollaboratorClientContext initialCollaboratorContext) {
39 |
40 | this.callbacks = callbacks;
41 | this.processedRequestResponse = processedRequestResponse;
42 |
43 | // Initialize stdout and stderr
44 | this.stdout = new PrintWriter(callbacks.getStdout(), true);
45 | this.stderr = new PrintWriter(callbacks.getStderr(), true);
46 |
47 | this.collaboratorContextList = new ArrayList();
48 |
49 | if(initialCollaboratorContext != null) {
50 | this.collaboratorContextList.add(initialCollaboratorContext);
51 | } else {
52 | stdout.println("Collaborator disabled");
53 | }
54 |
55 | this.goOn = true;
56 |
57 | }
58 |
59 | public void setGoOn(boolean goOn) {
60 | this.goOn = goOn;
61 | }
62 |
63 | public void pause() {
64 | paused = true;
65 | stdout.println("Stopping Collaborator interactions polling");
66 | }
67 |
68 | public void resumeThread() {
69 | synchronized (pauseLock) {
70 | paused = false;
71 | pauseLock.notifyAll(); // Unblocks thread
72 | }
73 | stdout.println("Restarting Collaborator interactions polling");
74 | }
75 |
76 | public void addNewCollaboratorContext(IBurpCollaboratorClientContext collaboratorContext) {
77 | this.collaboratorContextList.add(collaboratorContext);
78 | }
79 |
80 | public void addIssue(IBurpCollaboratorInteraction interaction, IBurpCollaboratorClientContext collaboratorContext) {
81 |
82 | String interactionId = interaction.getProperty("interaction_id");
83 | IHttpRequestResponse requestResponse = processedRequestResponse.get(interactionId + "." + collaboratorContext.getCollaboratorServerLocation());
84 |
85 | String issueDetails = "";
86 |
87 | // Convert timestamp to local time
88 | String dateStr = interaction.getProperty("time_stamp");
89 | SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MMM-dd HH:mm:ss z");
90 | TimeZone tz = TimeZone.getDefault();
91 | sdf.setTimeZone(tz);
92 | String localTimestamp = "";
93 | try{
94 | Date date = sdf.parse(dateStr);
95 | localTimestamp = sdf.format(date);
96 | } catch(Exception e) {
97 | localTimestamp = dateStr;
98 | }
99 |
100 | switch (interaction.getProperty("type")) {
101 |
102 | case "DNS":
103 |
104 | issueDetails = "The Collaborator server received a DNS lookup of type " + interaction.getProperty("query_type") +
105 | " for the domain name " + interaction.getProperty("interaction_id") + "." +
106 | collaboratorContext.getCollaboratorServerLocation() + "
" +
107 | "The lookup was received from IP address " + interaction.getProperty("client_ip") + " at " +
108 | localTimestamp + "
" + "DNS query (encoded in Base64) " +
109 | interaction.getProperty("raw_query");
110 | break;
111 |
112 | case "HTTP":
113 |
114 | issueDetails = "The Collaborator server received an HTTP request for the domain name " + interaction.getProperty("interaction_id") +
115 | "." + collaboratorContext.getCollaboratorServerLocation() + ".
The request was received from IP address " +
116 | interaction.getProperty("client_ip") + " at " + localTimestamp + "
" +
117 | "Request to collaborator (encoded in Base64) " + interaction.getProperty("request") + "
" +
118 | "Response from collaborator (encoded in Base64) " + interaction.getProperty("response");
119 |
120 | break;
121 |
122 | case "SMTP":
123 |
124 | String decodedConversation = new String(Base64.getDecoder().decode(interaction.getProperty("conversation")));
125 |
126 | Pattern p = Pattern.compile(".*mail from:.*?<(.*?)>.*rcpt to:.*?<(.*?)>.*\\r\\n\\r\\n(.*?)\\r\\n\\.\\r\\n.*",Pattern.CASE_INSENSITIVE + Pattern.DOTALL);
127 | Matcher m = p.matcher(decodedConversation);
128 |
129 | if(m.find()) {
130 | String from = m.group(1);
131 | String to = m.group(2);
132 | String message = m.group(3);
133 |
134 | issueDetails = "The Collaborator server received an SMTP connection from IP address " +
135 | interaction.getProperty("client_ip") + " at " + localTimestamp + "
" +
136 | "The email details were:
From: " + from + "
To: " + to +
137 | "
Message: " + message + "
" +
138 | "SMTP Conversation:
" + decodedConversation.replace("\r\n", " ");
139 | } else {
140 | issueDetails = "The Collaborator server received an SMTP connection from IP address " +
141 | interaction.getProperty("client_ip") + " at " + localTimestamp + "