Burp Pro as a Docker Container

Everyone loves Burp, but sometimes moving around the Professional version among different virtual machines could be laborious.

That’s why I finally decided to port it to docker. Read along if you wanna know how to replicate the setup (or even to know how to run any GUI application from docker).

The complete setup described in this blog post can be found on Github: https://github.com/marco-lancini/docker_burp.

How to run any GUI application from Docker

The idea comes from a couple of handy blog posts (1, 2), which suggested to share the X11 socket of the host with the container and use it directly.

# Install XQuartz
$ brew cask install xquartz

# Start XQuartz
# In the XQuartz preferences, go to the “Security” tab and make sure you’ve got “Allow connections from network clients” ticked:
$ open -a XQuartz

# Export the local IP address
$ export IP=$(ifconfig en0 | grep inet | awk '$1=="inet" {print $2}')

# Add the local IP to xhost
# (I know, not the best thing to do from a security perspective)
$ xhost + $IP

You can now try your setup by, for example, running Firefox from a container:

$ docker run -e DISPLAY=$IP:0 -v /tmp/.X11-unix:/tmp/.X11-unix jess/firefox

Run Burp Pro from Docker

Here is the idea:

  • we want to run Burp Pro from a container;
  • we want the container to be able to maintain the state (so not to have to re-enter the licence after every restart)
  • all automagically managed by docker-compose.
$ tree docker_burp
.
├── _data
│   └── sources
│       ├── burp_free.jar
│       ├── burp_pro.jar
│       └── licence.txt
├── burp
│   └── Dockerfile
└── docker-compose.yml

Let’s start by dissecting the docker-compose file:

$ cat docker-compose.yml

version: '2'

services:
    burp:
        container_name: burp
        build: burp/
        ports:
            - "8080:8080"
        volumes:
            - /tmp/.X11-unix:/tmp/.X11-unix
            - ./_data/:/home/tester/
        environment:
            DISPLAY: ${LOCAL_IP}:0
        command: java -jar -Xmx1024m /home/tester/sources/burp_pro.jar

We define a burp service, based on the Dockerfile defined in the burp/ folder (and shown below). We then expose port 8080 to be able to intercept traffic from Burp. We also specify 2 volumes: /tmp/.X11-unix to share the X11 socket, and _data that will map to our home directory in the container so to provide persistent storage that can survive the container. Finally, we run Burp from its JAR executable.

$ cat burp/Dockerfile

FROM ubuntu:16.04

# Install Java
RUN sed 's/main$/main universe/' -i /etc/apt/sources.list && \
    apt-get update && apt-get install -y wget ca-certificates software-properties-common && \
    add-apt-repository ppa:webupd8team/java -y && \
    apt-get update && \
    echo oracle-java8-installer shared/accepted-oracle-license-v1-1 select true | /usr/bin/debconf-set-selections && \
    apt-get install -y oracle-java8-installer libxext-dev libxrender-dev libxtst-dev && \
    apt-get clean && \
    rm -rf /var/lib/apt/lists/* && \
    rm -rf /tmp/*

# Create tester user
RUN export uid=1000 gid=1000 && \
    mkdir -p /home/tester && \
    echo "tester:x:${uid}:${gid}:tester,,,:/home/tester:/bin/bash" >> /etc/passwd && \
    echo "tester:x:${uid}:" >> /etc/group && \
    chown ${uid}:${gid} -R /home/tester

# Setup working directory
USER tester
ENV HOME /home/tester
WORKDIR /home/tester

Before proceeding, just remember to place the Burp Professional JAR file and the licence key in the _data/sources folder:

...
├── _data
│   └── sources
│       ├── burp_free.jar
│       ├── burp_pro.jar
│       └── licence.txt
...

In Action

Now that we have everything ready, let’s start by bootstrapping our setup with docker-compose up:

$ export LOCAL_IP=$(ifconfig en0 | grep inet | awk '$1=="inet" {print $2}')
$ docker-compose up

Starting burp ... done
Attaching to burp

Burp should now be up and running, accept the terms and conditions and you will be prompted to provide a licence key (which should be available to Burp since we placed it in the _data volume, mapped to the user’s home directory):

To start intercepting, just configure your local browser to point to 127.0.0.1:8080 (the port we exposed in the docker-compose file).

Once done, we can use docker-compose down to stop the service, while all files (like projects, extensions, etc.) will be stored in the _data/ folder:

$ tree docker_burp
.
├── _data
│   ├── .BurpSuite
│   │   ├── UserConfigCommunity.json
│   │   └── bapps
│   │       └── e2a137ad44984ccb908375fa5b2c618d
│   │           ├── BappDescription.html
│   │           ├── BappManifest.bmf
│   │           ├── BappSignature.sig
│   │           └── build
│   │               └── libs
│   │                   └── dotnet-beautifier-all.jar
│   ├── .java
│   │   └── .userPrefs
│   │       ├── .user.lock.developer
│   │       ├── .user.lock.tester
│   │       ├── .userRootModFile.developer
│   │       ├── .userRootModFile.tester
│   │       └── burp
│   │           └── prefs.xml
│   ├── .oracle_jre_usage
│   │   └── 9e360713136aba0a.timestamp
│   ├── sources
│   │   ├── burp_free.jar
│   │   ├── burp_pro.jar
│   │   └── licence.txt
│   └── test-project
│       └── TEST.burp
├── burp
│   └── Dockerfile
└── docker-compose.yml

Next time docker-compose is started, Burp will already be activated, and all the data files are still gonna be present.