All Downloads are FREE. Search and download functionalities are using the official Maven repository.

burp.BurpExtender Maven / Gradle / Ivy

package burp;

import burp.vuln.VulnerableLibraryIssue;
import burp.vuln.VulnerableLibraryIssueBuilder;
import com.esotericsoftware.minlog.Log;
import com.h3xstream.retirejs.repo.JsLibraryResult;
import com.h3xstream.retirejs.repo.ScannerFacade;
import com.h3xstream.retirejs.repo.VulnerabilitiesRepositoryLoader;

import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.List;

public class BurpExtender implements IBurpExtender, IScannerCheck {


    private IBurpExtenderCallbacks callbacks;
    private IExtensionHelpers helpers;


    @Override
    public void registerExtenderCallbacks(final IBurpExtenderCallbacks callbacks) {

        this.callbacks = callbacks;
        this.helpers = callbacks.getHelpers();
        this.callbacks.setExtensionName("Retire.js");

        PrintWriter stdout = new PrintWriter(callbacks.getStdout(), true);
        stdout.println("== Retire.js plugin ==");
        stdout.println("Passive scan rules to detect vulnerable Javascript libraries");
        stdout.println(" - Github : https://github.com/h3xstream/burp-retire-js");
        stdout.println("");
        stdout.println("== License ==");
        stdout.println("Retire.js repository is release under Apache License v2.");
        stdout.println("Retire.js Burp plugin is release under LGPL.");
        stdout.println("");

        Log.setLogger(new Log.Logger(){
            @Override
            protected void print (String message) {
                try {
                    if(message.contains("ERROR:")) { //Not the most elegant way, but should be effective.
                        callbacks.issueAlert(message);
                    }
                    callbacks.getStdout().write(message.getBytes());
                    callbacks.getStdout().write('\n');
                } catch (IOException e) {
                    System.err.println("Error while printing the log : "+e.getMessage()); //Very unlikely
                }
            }
        });
        Log.INFO();

        try {
            ScannerFacade.loadInstance(new VulnerabilitiesRepositoryLoader().load(VulnerabilitiesRepositoryLoader.REPO_URL,new BurpUpstreamDownloader(this.callbacks)));
        } catch (IOException e) {
            Log.error("ERROR: Problem occurs while preloading the RetireJS vulnerabilities",e);
        }

        callbacks.registerScannerCheck(this);

        //Not fully implemented (the passive scan rule is sufficient)
        //callbacks.registerMessageEditorTabFactory(this);
    }


    @Override
    public List doPassiveScan(IHttpRequestResponse requestResponse) {
        List issues = new ArrayList();

        byte[] respBytes = requestResponse.getResponse();

        IResponseInfo responseInfo = helpers.analyzeResponse(respBytes);
        IRequestInfo requestInfo = helpers.analyzeRequest(requestResponse.getHttpService(), requestResponse.getRequest());

        String path = HttpUtil.getPathRequested(requestInfo);
        String contentType = HttpUtil.getContentType(responseInfo);

        try {
            //Avoid NPE
            boolean jsContentType = contentType != null ? contentType.indexOf("javascript") != -1 : false;

            int bodyOffset = responseInfo.getBodyOffset();
            if (jsContentType || path.endsWith(".js")) {

                //The big analysis is spawn here..
                Log.debug("Analyzing "+path+" (body="+(respBytes.length-bodyOffset)+" bytes)");
                issues = scanJavaScript(respBytes, bodyOffset, path, requestResponse, requestInfo);
            }
            else if (contentType.indexOf("html") != -1
                    || path.endsWith(".htm") //Some additional condition just in case the content-type is bogus
                    || path.endsWith(".html")
                    || path.endsWith(".aspx")
                    || path.endsWith(".asp")
                    || path.endsWith(".php")
                    || path.endsWith(".jsp")) {

                issues = scanHtmlPage(respBytes, bodyOffset, path, requestResponse, requestInfo);
            }
        } catch (Exception e) {
            Log.error("Exception while scanning the script '"+path+"' (" + e.getClass().getName() + ": "+ e.getMessage()+")");
        }
        return issues;
    }

    @Override
    public List doActiveScan(IHttpRequestResponse baseRequestResponse, IScannerInsertionPoint insertionPoint) {
        return new ArrayList();
    }

    @Override
    public int consolidateDuplicateIssues(IScanIssue existingIssue, IScanIssue newIssue) {
        boolean bothRetireJsIssue = existingIssue instanceof VulnerableLibraryIssue && newIssue instanceof VulnerableLibraryIssue;

        if(bothRetireJsIssue) {
            VulnerableLibraryIssue issue1 = (VulnerableLibraryIssue) existingIssue;
            VulnerableLibraryIssue issue2 = (VulnerableLibraryIssue) newIssue;
            return issue1.equals(issue2) ? -1: 0;
        }

        return -1; //Unknown
    }

    private List scanJavaScript(byte[] respBytes, int offset, String scriptName, IHttpRequestResponse resp, IRequestInfo requestInfo) throws IOException {

        List res = ScannerFacade.getInstance().scanScript(scriptName, respBytes, offset);

        Log.debug(String.format("%d vulnerability(ies) for the script '%s'.",res.size(),scriptName));

        if(res.size() > 0) { //Transform the list of vulnerability Issue that can be display in Burp Scanner result.
            return VulnerableLibraryIssueBuilder.convert(res, resp.getHttpService(), resp, requestInfo);
        }

        return new ArrayList(); //Nothing was found
    }

    private List scanHtmlPage(byte[] respBytes, int offset, String scriptName, IHttpRequestResponse resp, IRequestInfo requestInfo) throws IOException {

        List res = ScannerFacade.getInstance().scanHtml(respBytes,offset);

        Log.debug(String.format("%d vulnerability(ies) for the HTML page '%s'.",res.size(),scriptName));

        if(res.size() > 0) { //Transform the list of vulnerability Issue that can be display in Burp Scanner result.
            return VulnerableLibraryIssueBuilder.convert(res, resp.getHttpService(), resp, requestInfo);
        }

        return new ArrayList(); //Nothing was found
    }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy