Overview
In part 4 of our series on creating extensions for Burp Suite using the Montoya API, we will learn about designing an interactive GUI for our extension.
If you haven’t read the previous installments of this blog post series yet, we highly recommend you do that first. They will guide you through everything we have done so far in this series.
Designing a GUI in IntelliJ IDEA
Creating a GUI in Burp Suite allows for new tabs in the interface, enabling users to interact with your extension more effectively. This is crucial for both changing extension settings and accessing more advanced functionality.
Luckily, with IntelliJ IDEA we can design the GUI visually and the only code we actually need to write is for handling user actions, which is much simpler!
Getting Started with Swing UI Designer
- First, begin by right-clicking on the “java” folder and navigating to New → Swing UI Designer → GUI Form. Name your form ‘UserInterface’.
- Select GridLayoutManager in IntelliJ for an organized layout.
- Upon creating the form, you’ll get a
UserInterface
class and a.form
file, which are essential for your GUI.
Finally, double click the UserInterface.form to open it. This is the Swing UI Designer. Currently, it contains a single component which we can see as a simple outline. On the left, the Component Tree lists this a JPanel. You can think of a JPanel as a canvas upon which you can place other components.
Customizing the JPanel
- First, click on the JPanel in either the Component Tree or the visual representation. This will load the JPanel’s properties.
- To interact with components like JPanel programmatically, assign them a field name, like “ui”.
- Drag a JLabel component from the palette on the right, drop it at the top of the JPanel, and set its text to something like “My First UI”.
- Then drag another JLabel component and position it on the left of the JPanel, setting its text to “Current Hash:”.
- Next, drag a JTextField component and place it to the right of the JLabel. Set a fieldName “hashField”.
- Now, drag a JButton component and place it to the right of the text field, giving it a fieldName “saveHash” and updating the text to “Save Hash”.
- Finally, drag a VSpacer component and position it under the components on the JPanel.
Integrating our GUI
Now, let’s integrate our GUI into Burp Suite. First, switch over to the UserInterface.java class and add the following code:
UserInterface.java
import javax.swing.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
public class UserInterface {
private JPanel ui;
private JTextField hashField;
private JButton saveHash;
private MyFirstHttpHandler handler;
public UserInterface() {
saveHash.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent actionEvent) {
handler.setHash(hashField.getText());
}
});
}
public JPanel getUI() {
return this.ui;
}
public void setHash(String hash) {
this.hashField.setText(hash);
}
public void setHTTPHandler(MyFirstHttpHandler handler) {
this.handler = handler;
}
}
Next, open up the MyFirstExtension.java class and update it so it looks like the following:
MyFirstExtension.java
import burp.api.montoya.BurpExtension;
import burp.api.montoya.MontoyaApi;
public class MyFirstExtension implements BurpExtension {
@Override
public void initialize(MontoyaApi api) {
MAPI.initialize(api);
api.extension().setName("My First Extension");
api.logging().logToOutput("Tib3rius");
String hash = "";
if (api.persistence().preferences().stringKeys().contains("hash")) {
hash = api.persistence().preferences().getString("hash");
}
UserInterface ui = new UserInterface();
api.userInterface().registerSuiteTab("My First Extension", ui.getUI());
ui.setHash(hash);
MyFirstHttpHandler handler = new MyFirstHttpHandler(hash, ui);
ui.setHTTPHandler(handler);
api.http().registerHttpHandler(handler);
api.extension().registerUnloadingHandler(new UnloadingHandler(handler));
}
}
Now, we need to fix the MyFirstHttpHandler class so it will accept an instance of the UI when it is constructed.
In MyFirstHttpHandler.java add an instance variable to store the UserInterface object:
private UserInterface ui;
Next, update the Constructor so it can be passed an instance of the UserInterface and assign it to the instance variable:
public MyFirstHttpHandler(String hash, UserInterface ui) {
this.hash = hash;
this.ui = ui;
}
Finally, in the handleHttpResponseReceived method, once a new hash has been calculated, we need to update the hashField using the setHash method:
MAPI.getAPI().logging().logToOutput("Hash generated: " + this.hash);
this.ui.setHash(this.hash);
The MyFirstHttpHandler.java file should now look like this:
MyFirstHttpHandler.java
import burp.api.montoya.http.handler.*;
import burp.api.montoya.http.message.requests.HttpRequest;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.HexFormat;
public class MyFirstHttpHandler implements HttpHandler {
private String hash = "";
private UserInterface ui;
public MyFirstHttpHandler(String hash, UserInterface ui) {
this.hash = hash;
this.ui = ui;
}
public String getHash() {
return this.hash;
}
public void setHash(String hash) {
this.hash = hash;
}
@Override
public RequestToBeSentAction handleHttpRequestToBeSent(HttpRequestToBeSent httpRequestToBeSent) {
if (!this.hash.isEmpty() && httpRequestToBeSent.isInScope()) {
HttpRequest request = httpRequestToBeSent.withAddedHeader("X-Hash", this.hash);
return RequestToBeSentAction.continueWith(request);
}
return null;
}
@Override
public ResponseReceivedAction handleHttpResponseReceived(HttpResponseReceived httpResponseReceived) {
if (httpResponseReceived.initiatingRequest().isInScope()) {
String input = "";
if (httpResponseReceived.hasHeader("Age")) {
input += httpResponseReceived.headerValue("Age");
}
if (httpResponseReceived.hasHeader("Date")) {
input += httpResponseReceived.headerValue("Date");
}
try {
MessageDigest digest = MessageDigest.getInstance("SHA-256");
digest.update(input.getBytes(StandardCharsets.UTF_8));
this.hash = HexFormat.of().formatHex(digest.digest());
MAPI.getAPI().logging().logToOutput("Hash generated: " + this.hash);
this.ui.setHash(this.hash);
} catch (NoSuchAlgorithmException e) {
throw new RuntimeException(e);
}
}
return null;
}
}
Rebuilding & Testing
Finally, rebuild your extension and reload it in Burp Suite. A new tab called “My First Extension” should appear. Clicking on it will load the user interface we designed, and the current hash value should be displayed.
If we send a new request in the browser to an in-scope site, the value in the current hash field should be updated. If we manually set a new value and save it using the button, sending a new request should result in the value being applied to the outgoing request (you can check this in the Logger tab).
Wrapping Up and Looking Ahead
Hopefully, this guide has walked you through enhancing your Burp Suite extension with a user-friendly GUI, adding dynamic and interactive features. Stay tuned for our next blog post, where we delve deeper into the Montoya API and add more features to our extension.
About TCM Security
TCM Security is a veteran-owned, cybersecurity services and education company founded in Charlotte, NC. Our services division has the mission of protecting people, sensitive data, and systems. With decades of combined experience, thousands of hours of practice, and core values from our time in service, we use our skill set to secure your environment. The TCM Security Academy is an educational platform dedicated to providing affordable, top-notch cybersecurity training to our individual students and corporate clients including both self-paced and instructor-led online courses as well as custom training solutions. We also provide several vendor-agnostic, practical hands-on certification exams to ensure proven job-ready skills to prospective employers.
Pentest Services: https://tcmdev.tcmsecurity.com/our-services/
Follow Us: Blog | LinkedIn | YouTube | Twitter | Facebook | Instagram
Contact Us: sales@tcm-sec.com
See How We Can Secure Your Assets
Let’s talk about how TCM Security can solve your cybersecurity needs. Give us a call, send us an e-mail, or fill out the contact form below to get started.