fbpx
TCM Security is offering free Active Directory Health Checks to any company with 10 or more employees. To inquire, please contact us.

 

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

  1. First, begin by right-clicking on the “java” folder and navigating to New → Swing UI Designer → GUI Form. Name your form ‘UserInterface’.
  2. Select GridLayoutManager in IntelliJ for an organized layout.
  3. 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

  1. First, click on the JPanel in either the Component Tree or the visual representation. This will load the JPanel’s properties.
  2. To interact with components like JPanel programmatically, assign them a field name, like “ui”.
  3. 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”.
  4. Then drag another JLabel component and position it on the left of the JPanel, setting its text to “Current Hash:”.
  5. Next, drag a JTextField component and place it to the right of the JLabel. Set a fieldName “hashField”.
  6. 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”.
  7. 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.