Serving custom HTML on private collaborator domain

Note: Portswigger has now added support for custom HTML so this blog post is not needed!

https://portswigger.net/burp/documentation/collaborator/deploying#adding-custom-content-to-your-collaborator-server


Hosting a private Burp Collaborator on custom domain can be very handy. It allows you for example to bypass WAFs, to use it on closed networks, to use different port numbers, to appear more professional with branded domain and so on. However it currently has some limitations, one of them being the hard-coded index page. When the collaborator domain is accessed without using any actual collaborator subdomain, a generic web page like above will be shown to the user.
It would be useful to be able to customize this. For example, the default page could instruct viewers how to contact the collaborator owner. Another example would be serving any additional payload files from the same domain.
According to Portswigger support, there is a feature request for customizing it but currently there is no supported way to serve custom content. There are hackish ways to achieve it, but not all are working as intended so let’s take a look how not to do it and how to actually do it.

Wrong ways to implement

An easy way would be using Nginx or HAProxy between the user and collaborator and making it proxy HTTP-requests from collaborator subdomains to collaborator and proxy other subdomains to web server (or serve directly the custom content). This however will lose the user’s IP for HTTP-requests as the Nginx’s/HAProxy’s IP will be shown on all HTTP-request interactions in collaborator.

Another easy way would be using a DNS-proxy which points some specific subdomains to the web server and proxies DNS-queries for all other subdomains to the DNS-server in collaborator. This will lose the user’s IP for DNS-requests as the DNS-proxy’s IP will be shown on all DNS-request interactions in collaborator.

Working way to serve custom html

Well how can we do this without losing the original IP on DNS-request and HTTP-request? Linux kernel supports Netfilter Queue which provides an API for viewing, modifying and dropping packets directly from the Kernel Packet Filter queue. It can be used along with Scapy to transparently inspect DNS-queries and to return fake DNS-replies.
Basically we’ll need to make NFQueue intercept all packets to port 53/UDP (DNS), then parse the DNS-request inside the packet. Then we’ll need to check if the DNS-request is for A-record and what (sub-)domain is it asking for. This (sub-)domain will then be checked against a list of (sub-)domains (e.g. collab.fi and www.collab.fi). If it doesn’t match any (sub-)domain on the list, the packet will be passed back on the queue without any modifications. If it matches something on the white list, Scapy will be used to create a fake DNS-reply pointing towards our web server. This fake DNS-reply will then be sent back to the source and the original packet will be dropped. It’s not actually that hard to do and now there is a script for doing all that automatically!
There are still some limitations with this method, as it fakes the DNS-replies you’ll need to have two IPs. One IP is associated with your collaborator domain and another IP is associated with the web server that you want to serve the custom html with. You don’t need two different virtual machines, having two public IPs on single VM should be enough. Collaborator listening on the first IP and web server listening on the second IP. Please let me know if there is a way to make this work with a single IP!

How to do this automatically

If you installed your private collaborator using the previous guide, you should still have the privatecollaborator-directory. Run git pull inside the directory and you should get the latest code including a new extendburp-directory. The directory contains an installation script, systemd service and dnsmitm.py-script which implements the actual magic.
To install, simply open the extendburp-directory and run the following command:ย  ./extend_burp.sh TARGET_IP COLLABORATOR_DOMAIN
The TARGET_IP-parameter should be IP of the web server that will serve the custom content and COLLABORATOR_DOMAIN-parameter is your private burp collaborator domain.
After the script is done, your server should respond to DNS-queries in the following way thus redirecting the user to correct HTTP-destination:

  • DNS-query for www.yourcustomdomain.com -> Returns IP of the web server.
  • DNS-query for yourcustomdomain.com -> Returns IP of the web server.
  • DNS-query for AnythingElseLikeCollaboratorId.yourcustomdomain.com -> Returns IP of the Burp Collaborator.

In case you want to redirect more subdomains to the web server, simply insert those in the dnsmitm.py script.
Over and out โ€“putsi.