├── .gitignore
├── LICENSE.txt
├── README.md
├── build.xml
├── clients
└── client.py
└── src
└── burp
├── BurpExtender.java
└── ClientHandler.java
/.gitignore:
--------------------------------------------------------------------------------
1 | src/burp/I*.java
2 |
--------------------------------------------------------------------------------
/LICENSE.txt:
--------------------------------------------------------------------------------
1 | Copyright (c) 2016 Andras Veres-Szentkiralyi
2 |
3 | Permission is hereby granted, free of charge, to any person
4 | obtaining a copy of this software and associated documentation
5 | files (the "Software"), to deal in the Software without
6 | restriction, including without limitation the rights to use,
7 | copy, modify, merge, publish, distribute, sublicense, and/or sell
8 | copies of the Software, and to permit persons to whom the
9 | Software is furnished to do so, subject to the following
10 | conditions:
11 |
12 | The above copyright notice and this permission notice shall be
13 | included in all copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
17 | OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
19 | HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
20 | WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21 | FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22 | OTHER DEALINGS IN THE SOFTWARE.
23 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | Collaborator gateway for Burp Suite
2 | ===================================
3 |
4 | Simple socket-based gateway to the Burp Collaborator.
5 |
6 | Protocol
7 | --------
8 |
9 | - The gateway listens on TCP port 8452 of the loopback interface.
10 | - The protocol uses [MessagePack][1] serialization without additional framing.
11 | - Sending `0` or `1` to the gateway results in a string reply containing
12 | a new payload, which includes the Collaborator location if the number
13 | sent is `1`.
14 | - Sending `2` to the gateway results in a string reply containing the
15 | Collaborator location, this can be used to construct FQDNs if the
16 | payload was requested with the number `0`.
17 | - Sending a string to the gateway results in the string being interpreted
18 | as a payload and the gateway will reply with an array of the interactions
19 | with the specified payload. Elements of the array will be maps with
20 | string keys, the values will be almost always strings, except for
21 | DNS raw queries, HTTP requests and responses and client IP addresses,
22 | which will be represented as binaries.
23 |
24 | A sample client in Python is provided for easier understanding of the above
25 | in the `clients` directory of this repository, in depends only on the
26 | [msgpack-python][2] library, run `pip install msgpack-python` to install it.
27 |
28 | [1]: http://msgpack.org/
29 | [2]: https://github.com/msgpack/msgpack-python
30 |
31 | Building
32 | --------
33 |
34 | - Install the dependencies, in case of libraries, put the JARs into `lib`
35 | - Save the Burp Extender API from Burp and unpack it into `src`
36 | - Execute `ant`, and you'll have the plugin ready in `burp-collab-gw.jar`
37 |
38 | Dependencies
39 | ------------
40 |
41 | - JDK 1.7+ (tested on OpenJDK `1.8.0_91`, Debian/Ubuntu package: `openjdk-7-jdk`)
42 | - Apache ANT (Debian/Ubuntu package: `ant`)
43 | - MessagePack for Java https://github.com/msgpack/msgpack-java/
44 |
45 | License
46 | -------
47 |
48 | The whole project is available under MIT license, see `LICENSE.txt`.
49 |
--------------------------------------------------------------------------------
/build.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/clients/client.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 |
3 | import socket
4 | import msgpack
5 |
6 | class Client(object):
7 | def __init__(self):
8 | sock = socket.socket()
9 | sock.connect(('localhost', 8452))
10 | self.sock = sock
11 |
12 | def get_collaborator_server_location(self):
13 | return self._exchange_packet(2)
14 |
15 | def generate_payload(self, include_location=True):
16 | return self._exchange_packet(int(include_location))
17 |
18 | def fetch_collaborator_interactions_for(self, payload):
19 | return self._exchange_packet(payload)
20 |
21 | def _exchange_packet(self, data):
22 | s = self.sock
23 | s.send(msgpack.packb(data))
24 | unpacker = msgpack.Unpacker()
25 | while True:
26 | unpacker.feed(s.recv(1))
27 | for value in unpacker:
28 | return value
29 |
30 |
31 | if __name__ == '__main__':
32 | from urllib2 import urlopen
33 | c = Client()
34 | print repr(c.get_collaborator_server_location())
35 | print repr(c.generate_payload(False))
36 | payload = c.generate_payload(True)
37 | print repr(payload)
38 | print repr(urlopen('http://{0}/'.format(payload)).read())
39 | print repr(c.fetch_collaborator_interactions_for(payload))
40 |
--------------------------------------------------------------------------------
/src/burp/BurpExtender.java:
--------------------------------------------------------------------------------
1 | package burp;
2 |
3 | import java.util.*;
4 | import java.io.*;
5 | import java.net.*;
6 | import java.util.concurrent.CopyOnWriteArrayList;
7 |
8 | public class BurpExtender extends Thread implements IBurpExtender, IExtensionStateListener
9 | {
10 | private final static String NAME = "Collaborator gateway";
11 | private IBurpCollaboratorClientContext ccc;
12 | private IExtensionHelpers helpers;
13 | private final List sockets = new CopyOnWriteArrayList();
14 |
15 | @Override
16 | public void registerExtenderCallbacks(IBurpExtenderCallbacks callbacks)
17 | {
18 | callbacks.setExtensionName(NAME);
19 | callbacks.registerExtensionStateListener(this);
20 | ccc = callbacks.createBurpCollaboratorClientContext();
21 | helpers = callbacks.getHelpers();
22 | start();
23 | }
24 |
25 | @Override
26 | public void extensionUnloaded() {
27 | for (Closeable s : sockets) try { s.close(); } catch (IOException ioe) {}
28 | }
29 |
30 | @Override
31 | public void run() {
32 | try {
33 | ServerSocket ss = new ServerSocket(8452, 50, InetAddress.getLoopbackAddress());
34 | sockets.add(ss);
35 | ss.setReuseAddress(true);
36 | while (true) {
37 | Socket cs = ss.accept();
38 | sockets.add(cs);
39 | new ClientHandler(cs, ccc, helpers).start();
40 |
41 | }
42 | } catch (SocketException se) {
43 | if (!se.getMessage().equals("Socket closed")) se.printStackTrace();
44 | } catch (IOException ioe) {
45 | ioe.printStackTrace();
46 | }
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/src/burp/ClientHandler.java:
--------------------------------------------------------------------------------
1 | package burp;
2 |
3 | import java.util.*;
4 | import java.io.*;
5 | import java.net.*;
6 |
7 | import org.msgpack.core.*;
8 | import org.msgpack.value.*;
9 |
10 | public class ClientHandler extends Thread {
11 | private final Socket s;
12 | private final IBurpCollaboratorClientContext ccc;
13 | private final IExtensionHelpers helpers;
14 |
15 | public ClientHandler(Socket s, IBurpCollaboratorClientContext ccc,
16 | IExtensionHelpers helpers) {
17 | this.s = s;
18 | this.ccc = ccc;
19 | this.helpers = helpers;
20 | }
21 |
22 | @Override
23 | public void run() {
24 | try {
25 | OutputStream os = s.getOutputStream();
26 | final MessageUnpacker unpacker = MessagePack.newDefaultUnpacker(s.getInputStream());
27 | while (unpacker.hasNext()) {
28 | final Value v = unpacker.unpackValue();
29 | final MessagePacker mbp = MessagePack.newDefaultPacker(os);
30 | switch (v.getValueType()) {
31 | case INTEGER:
32 | switch (v.asIntegerValue().toInt()) {
33 | case 0: mbp.packString(ccc.generatePayload(false)); break;
34 | case 1: mbp.packString(ccc.generatePayload(true)); break;
35 | case 2: mbp.packString(ccc.getCollaboratorServerLocation()); break;
36 | }
37 | mbp.flush();
38 | break;
39 | case STRING:
40 | handleQuery(mbp, v.asStringValue().asString());
41 | break;
42 | }
43 | }
44 | } catch (IOException ioe) {
45 | ioe.printStackTrace();
46 | }
47 | }
48 |
49 | private void handleQuery(MessagePacker mbp, String payload) throws IOException {
50 | final List bci =
51 | ccc.fetchCollaboratorInteractionsFor(payload);
52 | mbp.packArrayHeader(bci.size());
53 | for (IBurpCollaboratorInteraction interaction : bci) {
54 | final Map props = interaction.getProperties();
55 | mbp.packMapHeader(props.size() - (props.containsKey("interaction_id") ? 1 : 0));
56 | for (final Map.Entry entry : props.entrySet()) {
57 | final String k = entry.getKey();
58 | if (k.equals("interaction_id")) continue;
59 | mbp.packString(k);
60 | final String v = entry.getValue();
61 | if (k.equals("request") || k.equals("response") || k.equals("raw_query")) {
62 | final byte[] buf = helpers.base64Decode(v);
63 | mbp.packBinaryHeader(buf.length);
64 | mbp.writePayload(buf);
65 | } else if (k.equals("client_ip")) {
66 | final byte[] buf = InetAddress.getByName(v).getAddress();
67 | mbp.packBinaryHeader(buf.length);
68 | mbp.writePayload(buf);
69 | } else {
70 | mbp.packString(v);
71 | }
72 | }
73 | }
74 | mbp.flush();
75 | }
76 | }
77 |
--------------------------------------------------------------------------------