Burp Suite User Forum

Create new post

Get Only Selected Requests in Proxy History

August | Last updated: Mar 26, 2024 09:13PM UTC

I'm writing an extension using Montoya API. It needs to look at items in the proxy history and do some analysis. I see there is a method to get filtered items: List<ProxyHttpRequestResponse> history(ProxyHistoryFilter filter); Where ProxyHistoryFilter takes an instance of ProxyHttpRequestResponse to match against. How do you filter on only the selected/highlighted items in the proxy history? There does not appear to be a method in ProxyHttpRequestResponse (https://portswigger.github.io/burp-extensions-montoya-api/javadoc/burp/api/montoya/proxy/ProxyHttpRequestResponse.html) to indicate whether the particular request is selected in the UI.

Hannah, PortSwigger Agent | Last updated: Mar 27, 2024 10:52AM UTC

Hi If you have selected items in the Proxy History with the mouse, then you would want to provide this as part of the right-click context menu. If you register a ContextMenuItemsProvider, you can add an entry to the context menu. Then, on your provided menu item, you can use "ContextMEnuEvent. selectedRequestResponses()" to retrieve the selected items in the table. Please let me know how you get on.

August | Last updated: Mar 27, 2024 06:26PM UTC

ContextMenuEvent.selectedRequestResponses() might work but it returns HttpRequestResponse whereas api.proxy().history() returns ProxyHttpRequestResponse. The two do not share a common super-interface. So if I wanted to in some cases to process all _selected_ items and in other cases process _all_ items I would need to do some juggling to force one type into another, or write two ActionListeners for the two different types. I'd suggest a feature request to add selected status ProxyHistoryFilter.

Hannah, PortSwigger Agent | Last updated: Mar 28, 2024 12:03PM UTC

This would be a bit of a workaround, but you could use the list of HttpRequestResponses returned by the context menu action to set up your ProxyHistoryFilter. This would mean you can retrieve ProxyHttpRequestResponses from your Proxy History based on the user's selected HtppRequestResponses.

I've put together a quick example that matches based on the request URL here - in practice, you would want a more stringent matching criteria, as you may have multiple requests with the same URL:
import burp.api.montoya.BurpExtension;
import burp.api.montoya.MontoyaApi;
import burp.api.montoya.http.message.HttpRequestResponse;
import burp.api.montoya.proxy.ProxyHttpRequestResponse;
import burp.api.montoya.ui.contextmenu.ContextMenuEvent;
import burp.api.montoya.ui.contextmenu.ContextMenuItemsProvider;
import burp.api.montoya.ui.contextmenu.InvocationType;

import javax.swing.*;
import java.awt.*;
import java.util.Collections;
import java.util.List;

import static java.util.Collections.emptyList;

public class Extension implements BurpExtension
{
    @Override
    public void initialize(MontoyaApi montoyaApi)
    {
        montoyaApi.userInterface().registerContextMenuItemsProvider(new ContextMenuItemsProvider()
        {
            @Override
            public List<Component> provideMenuItems(ContextMenuEvent event)
            {
                if (event.isFrom(InvocationType.PROXY_HISTORY))
                {
                    JMenuItem menuItem = new JMenuItem("Retrieve items");
                    menuItem.addActionListener(l -> {
                        List<HttpRequestResponse> requestResponses = event.selectedRequestResponses();

                        List<ProxyHttpRequestResponse> selectedHistory = montoyaApi.proxy().history(proxyHttpRequestResponse -> requestResponses.stream().anyMatch(r -> proxyHttpRequestResponse.request().url().equals(r.request().url())));

                        selectedHistory.forEach(i -> montoyaApi.logging().logToOutput(i.request().url()));
                    });

                    return List.of(menuItem);
                }

                return emptyList();
            }
        });
    }
}

August | Last updated: Apr 02, 2024 07:36PM UTC

I wound up doing it slightly differently. This way I only have to iterate the List once (the proxy history can get quite large if it is unfiltered): List history; if (event.selectedRequestResponses().isEmpty()) { history = api.proxy().history(); } else { history = event.selectedRequestResponses(); } for (Object oRequestResponse : history) { String url; ZonedDateTime requestTime; HttpResponse response; if (oRequestResponse instanceof ProxyHttpRequestResponse) { ProxyHttpRequestResponse requestResponse = (ProxyHttpRequestResponse)oRequestResponse; url = requestResponse.request().url(); requestTime = requestResponse.time(); response = requestResponse.response(); } else { HttpRequestResponse requestResponse = (HttpRequestResponse) oRequestResponse; url = requestResponse.request().url(); Optional<TimingData> timingDataOptional = requestResponse.timingData(); requestTime = timingDataOptional.map(TimingData::timeRequestSent).orElse(ZonedDateTime.now()); response = requestResponse.response(); } //do processing of response }

You must be an existing, logged-in customer to reply to a thread. Please email us for additional support.