/* * DetectELJ - Active scanner extension to detect Expression Language Injection vulnerabilities * * Copyright (c) 2017 Luca Carettoni - Doyensec LLC. */ package burp; import java.io.PrintWriter; import java.net.URL; import java.util.ArrayList; import java.util.Arrays; import java.util.List; public class BurpExtender implements IBurpExtender, IScannerCheck { private IBurpExtenderCallbacks callbacks; private IExtensionHelpers helpers; @Override public void registerExtenderCallbacks(IBurpExtenderCallbacks callbacks) { this.callbacks = callbacks; helpers = callbacks.getHelpers(); callbacks.setExtensionName("DetectELJ"); callbacks.issueAlert("DetectELJ Active Scanner check enabled"); PrintWriter stdout = new PrintWriter(callbacks.getStdout(), true); PrintWriter stderr = new PrintWriter(callbacks.getStderr(), true); callbacks.registerScannerCheck(this); } @Override public List<IScanIssue> doPassiveScan(IHttpRequestResponse ihrr) { return null; //Active scanner check only } @Override public List<IScanIssue> doActiveScan(IHttpRequestResponse ihrr, IScannerInsertionPoint isip) { byte[] withPayload = isip.buildRequest("${1336+1}".getBytes()); IHttpRequestResponse newReqRes = callbacks.makeHttpRequest(ihrr.getHttpService(), withPayload); IResponseVariations variation = helpers.analyzeResponseVariations(ihrr.getResponse(), newReqRes.getResponse()); List<String> pageChanges = variation.getVariantAttributes(); boolean length = false; boolean bodyContent = false; boolean match = false; for (String change : pageChanges) { if (change.equals("content_length")) length = true; if (change.equals("whole_body_content")) bodyContent = true; } if (helpers.bytesToString(newReqRes.getResponse()).contains("1337")) match = true; if (length && bodyContent && match) { List<IScanIssue> issues = new ArrayList<>(1); issues.add(new ELJ(newReqRes)); return issues; } else { return null; } } @Override public int consolidateDuplicateIssues(IScanIssue isb, IScanIssue isa) { if (Arrays.equals(isb.getHttpMessages()[0].getResponse(), isa.getHttpMessages()[0].getResponse())) { return -1; } else { return 0; } } class ELJ implements IScanIssue { private final IHttpRequestResponse reqres; public ELJ(IHttpRequestResponse reqres) { this.reqres = reqres; } @Override public String getHost() { return reqres.getHost(); } @Override public int getPort() { return reqres.getPort(); } @Override public String getProtocol() { return reqres.getProtocol(); } @Override public URL getUrl() { return reqres.getUrl(); } @Override public String getIssueName() { return "Expression Language (EL) Injection Detected"; } @Override public int getIssueType() { return 0x08000000; //See http://portswigger.net/burp/help/scanner_issuetypes.html } @Override public String getSeverity() { return "High"; // "High", "Medium", "Low", "Information" or "False positive" } @Override public String getConfidence() { return "Firm"; //"Certain", "Firm" or "Tentative" } @Override public String getIssueBackground() { return "Expression Language injections occur when input data is evaluated " + "by an expression language interpreter. An attacker can read server-side " + "data, such as the content of server-side variables, and some other inner " + "configuration details."; } @Override public String getRemediationBackground() { return "Apply input validation best practices, and reject ${, #{ and other variations."; } @Override public String getIssueDetail() { return "Burp Scanner has identified an Expression Language injection in:<b>" + reqres.getUrl().toString() + "</b><br><br>"; } @Override public String getRemediationDetail() { return null; } @Override public IHttpRequestResponse[] getHttpMessages() { //Let's highlight the specific string in the response that triggered the issue String strRes = helpers.bytesToString(reqres.getResponse()); int[] marks = new int[2]; marks[0] = strRes.indexOf("1337"); marks[1] = marks[0] + 4; List<int[]> marksList = new ArrayList<>(1); marksList.add(marks); IHttpRequestResponseWithMarkers reqresMark = callbacks.applyMarkers(reqres, null, marksList); IHttpRequestResponse[] rra = { reqresMark }; return rra; } @Override public IHttpService getHttpService() { return reqres.getHttpService(); } } }