com.codedx.burp.ExportActionListener.java Source code

Java tutorial

Introduction

Here is the source code for com.codedx.burp.ExportActionListener.java

Source

/*
 * Copyright (C) 2016 Code Dx, Inc. - http://www.codedx.com
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.codedx.burp;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
import java.nio.file.InvalidPathException;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;

import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.StatusLine;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.mime.HttpMultipartMode;
import org.apache.http.entity.mime.MultipartEntityBuilder;
import org.apache.http.entity.mime.content.FileBody;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.util.EntityUtils;
import org.json.JSONException;
import org.json.JSONObject;

import burp.BurpExtender;
import burp.IBurpExtenderCallbacks;
import burp.IScanIssue;

public class ExportActionListener implements ActionListener {
    private BurpExtender burpExtender;
    private IBurpExtenderCallbacks callbacks;

    public ExportActionListener(BurpExtender burpExtender, IBurpExtenderCallbacks callbacks) {
        this.burpExtender = burpExtender;
        this.callbacks = callbacks;
    }

    public void actionPerformed(ActionEvent e) {
        IScanIssue[] issues = getIssues();
        callbacks.saveExtensionSetting(BurpExtender.PROJECT_KEY, getProject());
        if (issues != null && issues.length > 0) {
            final File report = generateReport(issues);
            if (report != null && report.exists()) {
                Thread uploadThread = new Thread() {
                    public void run() {
                        try {
                            HttpResponse response = sendData(report, getServer());
                            StatusLine responseLine = null;
                            int responseCode = -1;
                            if (response != null) {
                                responseLine = response.getStatusLine();
                                responseCode = responseLine.getStatusCode();
                            }
                            if (responseCode == 202) {
                                burpExtender.message("The report was successfully uploaded to Code Dx.", "Success");
                            } else if (responseCode == 400) {
                                burpExtender.error(
                                        "An unexpected error occurred and the report could not be sent.\nThe server returned Error 400: Bad Request"
                                                + getResponseError(response));
                            } else if (responseCode == 403) {
                                burpExtender.error(
                                        "The report could not be sent. The server returned Error 403: Forbidden.\nThe API Key may be incorrect or have insufficient permissions for this project.");
                            } else if (responseCode == 404) {
                                burpExtender.error(
                                        "The report could not be sent. The server returned Error 404: Not Found.\nThe Server URL may be wrong or the project may no longer exist.");
                            } else if (responseCode == 415) {
                                burpExtender.error(
                                        "An unexpected error occurred and the report could not be sent.\nThe server returned Error 415: Unsupported Media Type"
                                                + getResponseError(response));
                            } else if (response != null) { // Don't give any errors if it's null, errors are handled higher up.
                                burpExtender.error(
                                        "An unexpected error occurred and the report could not be sent.\nThe response code is: "
                                                + responseLine);
                            }
                        } catch (IOException e1) {
                            burpExtender.error("An unexpected error occurred and the report could not be sent.",
                                    e1);
                        }
                        report.delete();
                    }
                };
                uploadThread.start();
            } else {
                burpExtender.error("The report file could not be created.");
            }
        } else {
            burpExtender.warn("There are no issues with the selected target.");
        }
    }

    private String getResponseError(HttpResponse response) {
        String msg = ".";
        try (BufferedReader rd = new BufferedReader(
                new InputStreamReader(response.getEntity().getContent(), "UTF-8"))) {
            StringBuffer result = new StringBuffer();
            String line = "";
            while ((line = rd.readLine()) != null) {
                result.append(line);
            }

            JSONObject obj = new JSONObject(result.toString());
            msg = " with the response: " + obj.getString("error");
        } catch (JSONException | IOException e) {
        }
        return msg;
    }

    private File generateReport(IScanIssue[] issues) {
        File report = null;
        try {
            String OS = System.getProperty("os.name").toUpperCase(Locale.getDefault());
            Path env;
            if (OS.contains("WIN")) {
                env = Paths.get(System.getenv("APPDATA"), "Code Dx", "Burp Extension");
            } else if (OS.contains("MAC")) {
                env = Paths.get(System.getProperty("user.home"), "Library", "Application Support", "Code Dx",
                        "Burp Extension");
            } else if (OS.contains("NUX")) {
                env = Paths.get(System.getProperty("user.home"), ".codedx", "burp-extension");
            } else {
                env = Paths.get(System.getProperty("user.dir"), "codedx", "burp-extension");
            }
            env.toFile().mkdirs();
            report = new File(env.toFile(), "Burp.xml");
        } catch (SecurityException | InvalidPathException | UnsupportedOperationException e) {
        }
        callbacks.generateScanReport("XML", issues, report);
        return report;
    }

    private HttpResponse sendData(File data, String urlStr) throws IOException {
        CloseableHttpClient client = burpExtender.getHttpClient();
        if (client == null)
            return null;

        HttpPost post = new HttpPost(urlStr);
        post.setHeader("API-Key", burpExtender.getApiKey());

        MultipartEntityBuilder builder = MultipartEntityBuilder.create();
        builder.setMode(HttpMultipartMode.BROWSER_COMPATIBLE);
        builder.addPart("file", new FileBody(data));

        HttpEntity entity = builder.build();
        post.setEntity(entity);

        HttpResponse response = client.execute(post);
        HttpEntity resEntity = response.getEntity();

        if (resEntity != null) {
            EntityUtils.consume(resEntity);
        }
        client.close();

        return response;
    }

    protected IScanIssue[] getIssues() {
        String target = burpExtender.getTargetUrl();
        IScanIssue[] issues = callbacks.getScanIssues(target);
        if (target != null && hasMismatchedTargets(target)) {
            List<IScanIssue> lst = new ArrayList<IScanIssue>();
            for (IScanIssue issue : issues) {
                if (issue.getHttpService().toString().equals(target))
                    lst.add(issue);
            }
            issues = lst.toArray(new IScanIssue[lst.size()]);
        }

        return issues;
    }

    // Finds if any of the targets are prefixed by the selected target.
    // This is required because the getScanIssues function uses the target url
    // as a prefix. Any url that starts with the given prefix will match. If
    // any URLs match, they need to be filtered.
    private boolean hasMismatchedTargets(String selected) {
        for (String target : burpExtender.getTargetUrls()) {
            if (target != null && selected != null && target.startsWith(selected)) {
                return true;
            }
        }
        return false;
    }

    protected String getProject() {
        return burpExtender.getProject().getValue();
    }

    private String getServer() {
        return burpExtender.getServerUrl() + "/api/projects/" + getProject() + "/analysis";
    }
}