Part IV: Diving deeper into Extender API Interfaces
Parts of Series
- Introduction to Burp Extender
- Setting Up Extension Development Tools
- Extension Project Structure and Fundamentals
- Diving deeper into Extender API Interfaces
- Exploration - Intruder Payload Processing
We learned how to write a basic Hello World extension showcasing interaction with Burp Suite. In this part of the series, we'll mostly cover the Extender API interfaces and their use cases. In the end, write an extension which will monitor HTTP requests from Burp Suite tools and display the domains passing through the Proxy in the Alert tab.
Helper Interface
In the previous post. We used callbacks
object's methods twice for setting name of the extension and displaying a message on Alert tab. One of the methods exposed by callbacks
is getHelpers()
. This method returns an object of IExtensionHelpers
type, which as the name suggests will be going to help us in making boring tasks easier. The object contains multiple methods such as:
analyzeRequest()
: This method can be used to analyze an HTTP request, and obtain various key details about it.analyzeResponse()
: This method can be used to analyze an HTTP response, and obtain various key details about it.base64Encode()
: This method can be used to Base64-encode the specified data.base64Decode()
: This method can be used to decode Base64-encoded data.urlDecode()
: This method can be used to URL-decode the specified data.urlEncode()
: This method can be used to URL-encode the specified data
The entire list of methods, associated parameters and return values can be read here. This will ensure better clarity on how helpful this helper interface is for us.
Quick Demo of Helper Interface:
package burp;
public class BurpExtender implements IBurpExtender {
@Override
public void registerExtenderCallbacks(IBurpExtenderCallbacks callbacks) {
callbacks.setExtensionName("Prakhar Prasad - Helper Example ");
IExtensionHelpers helpers = callbacks.getHelpers();
String encodedString = helpers.urlEncode("http://www.example.com/dir/path?q=10&a=100");
callbacks.issueAlert(encodedString);
}
}
We call urlEncode()
method from IExtensionHelpers
object acquired by calling callbacks.getHelpers()
. Lastly urlEncode()
will process the URL string and encode it and return. Then the encoded string will be displayed on the Alerts tab
Interface Registration Procedure
To implement certain API interfaces of Extender meaningfully, we'll need to call their registration methods. As an example any class implementing IHTTPListener
interface must have their objects passed to callbacks.registerHttpListener()
method, in order for the class to function properly. Note that callbacks
itself is an object of type IBurpExtenderCallbacks
.
The list of registration methods can be found below:
Now that we know about registration methods, let us move forward and implement IHTTPListener
in a class.
Burp Extension - Reading Hosts From Burp Proxy Requests
We'll go ahead and implement IHTTPListener
interface in a class.
As per the API reference document -IHTTPListener
allows the class to be notified of requests and responses made by Burp tools. Extensions can perform custom analysis or modification of these messages by registering an HTTP listener .
In the code below, we declare a class called readFromProxy
define a constructor which will initialise the extenderCallbacks
and extenderHelpers
when object of this class is created later on in the code. This class implements IHTTPListener
interface therefore it must override the method processHttpMessage()
of the interface.
The method takes three parameters toolFlag
which is a integer flag which tells about the Burp tool which is performing the HTTP call; a boolean type parameter messageIsRequest
which when true means the HTTP message is a request otherwise it is a response and lastly messageInfo
of IHttpRequestResponse
interface which provides information about the HTTP message (ref.).
Inside the overridden function, toolFlag
is used to check whether the tool is Burp Proxy and messageIsRequest
is true, hence a request. We call the helper method analyzeRequest(messageInfo)
to easily process and retrieve information from the messageInfo
object. This method returns the information in the form of a IRequestInfo
object (ref.) which has different methods to extract specific parts of HTTP request. Lastly we call extenderCallbacks.issueAlert()
to push the alert.
The notable part in BurpExtender
class is the registerHttpListener()
method, which takes an object of the readFromProxy
class, passing the callbacks
to its constructor in the process.
package burp;
class readFromProxy implements IHttpListener
{
IBurpExtenderCallbacks extenderCallbacks;
IExtensionHelpers extenderHelpers;
IRequestInfo requestInfo;
String domainName;
@Override
public void processHttpMessage(int toolFlag, boolean messageIsRequest, IHttpRequestResponse messageInfo) {
if(toolFlag == IBurpExtenderCallbacks.TOOL_PROXY && messageIsRequest == true)
requestInfo = extenderHelpers.analyzeRequest(messageInfo);
domainName = requestInfo.getUrl().getHost();
extenderCallbacks.issueAlert("Proxy: " + domainName);
}
public readFromProxy(IBurpExtenderCallbacks callbacks) {
extenderCallbacks = callbacks;
extenderHelpers = callbacks.getHelpers();
}
}
public class BurpExtender implements IBurpExtender {
@Override
public void registerExtenderCallbacks(IBurpExtenderCallbacks callbacks) {
callbacks.setExtensionName("Prakhar Prasad - HTTP Listener");
//create an object of our IHTTPListener class and pass the callbacks
callbacks.registerHttpListener(new readFromProxy(callbacks));
}
}
If things are done right, output of the extension should be somewhat similar to this:
Exercise #2: Use IProxyListener
interface to modify HTTP requests havingGET
parameter q
and replace with base64
value of q
.
Example:
http://www.example.com/?q=Prakhar (original).
http://www.example.com/?q=UHJha2hhcg== (modified by extension).