/** * Analyze and categorize each of the parameters in scope. * * @param helpers The standard burp ExtensionHelpers object. * @param messages The set of request messages to be processed. */ private void firstPass(IExtensionHelpers helpers, IHttpRequestResponse[] messages) { publish("Examining parameters..."); for (int i = 0; i < messages.length; i++) { publish(100 * i / messages.length); messages[i].getHttpService(); // Analyze response for cookies if (messages[i].getResponse() != null) { IResponseInfo responseInfo = helpers.analyzeResponse(messages[i].getResponse()); List<String> headers = responseInfo.getHeaders(); for (String header : headers) { if (startsWithIgnoreCase(header, "set-cookie:")) { processCookieHeader(header); } } } IRequestInfo requestInfo = helpers.analyzeRequest(messages[i]); if (callbacks.isInScope(requestInfo.getUrl())) { byte[] responseBytes = messages[i].getResponse(); String responseString = ""; if (responseBytes != null) { responseString = helpers.bytesToString(responseBytes); inScopeMessagesWithResponses.add(messages[i]); } List<IParameter> params = requestInfo.getParameters(); for (IParameter param : params) { if ((!ignoreEmpty || param.getValue().length() > 0) && !ignoreList.contains(param.getName())) { int type = param.getType(); Map<String, CorrelatedParam> paramMap; switch (type) { case IParameter.PARAM_URL: paramMap = urlParameters; break; case IParameter.PARAM_BODY: paramMap = bodyParameters; break; case IParameter.PARAM_COOKIE: paramMap = cookieParameters; break; case IParameter.PARAM_JSON: paramMap = jsonParameters; break; default: paramMap = null; // nothing } if (paramMap != null) { if (messages[i] == null) { callbacks.printOutput("Warning... adding null message!"); } if (paramMap.containsKey(param.getName())) { paramMap .get(param.getName()) .put(param, messages[i], requestInfo, responseString, helpers); } else { paramMap.put( param.getName(), new CorrelatedParam(param, messages[i], requestInfo, responseString, helpers)); } } } } } } }
@Override public List<IScanIssue> scan( IBurpExtenderCallbacks callbacks, IHttpRequestResponse baseRequestResponse, IScannerInsertionPoint insertionPoint) { List<IScanIssue> issues = new ArrayList<>(); IExtensionHelpers helpers = callbacks.getHelpers(); stderr = new PrintWriter(callbacks.getStderr(), true); IRequestInfo reqInfo = helpers.analyzeRequest(baseRequestResponse); URL url = reqInfo.getUrl(); String host = url.getHost(); int port = url.getPort(); String system = host.concat(Integer.toString(port)); // System not yet tested for this vulnerability if (!hs.contains(system)) { hs.add(system); String protocol = url.getProtocol(); Boolean isSSL = (protocol.equals("https")); for (String STATUS_SERVLET_PATH : STATUS_SERVLET_PATHS) { try { // Test the presence of tomcat console URL urlToTest = new URL(protocol, url.getHost(), url.getPort(), STATUS_SERVLET_PATH); byte[] statustest = helpers.buildHttpRequest(urlToTest); byte[] responseBytes = callbacks.makeHttpRequest(url.getHost(), url.getPort(), isSSL, statustest); // look for matches of our active check grep string in the response body IResponseInfo statusInfo = helpers.analyzeResponse(responseBytes); /* * Try basic HTTP Authentication Bruteforcing */ if (statusInfo.getStatusCode() == 401) { issues.add( new CustomScanIssue( baseRequestResponse.getHttpService(), urlToTest, new CustomHttpRequestResponse( statustest, responseBytes, baseRequestResponse.getHttpService()), "HTTP Basic Authentication - Status Servlet", "A status servlet is protected using HTTP Basic authentication", REMEDY, Risk.Low, Confidence.Certain)); // Test Weak Passwords CustomHttpRequestResponse httpWeakPasswordResult; httpWeakPasswordResult = HTTPBasicBruteforce(callbacks, urlToTest); if (httpWeakPasswordResult != null) { // Retrieve the weak credentials String weakCredential = null; String weakCredentialDescription = ""; try { IRequestInfo reqInfoPwd = callbacks .getHelpers() .analyzeRequest( baseRequestResponse.getHttpService(), httpWeakPasswordResult.getRequest()); weakCredential = new String( helpers.base64Decode(HTTPParser.getHTTPBasicCredentials(reqInfoPwd))); } catch (Exception ex) { stderr.println("Error during Authorization Header parsing " + ex); } if (weakCredential != null) { weakCredentialDescription += String.format( "<br /><br /> The weak credentials are " + "<b>%s</b><br /><br />", weakCredential); } issues.add( new CustomScanIssue( baseRequestResponse.getHttpService(), urlToTest, httpWeakPasswordResult, "Status Servlet Weak Password", "Status Servlet is installed on the remote system with a default password" + weakCredentialDescription, "Change default/weak password and/or restrict access to the console only from trusted hosts/networks", Risk.Medium, Confidence.Certain)); return issues; } } if (statusInfo.getStatusCode() == 200) { List<int[]> matches_j2ee = getMatches(responseBytes, GREP_STRING_J2EE, helpers); if (matches_j2ee.size() > 0) { issues.add( new CustomScanIssue( baseRequestResponse.getHttpService(), helpers.analyzeRequest(baseRequestResponse).getUrl(), new CustomHttpRequestResponse( statustest, responseBytes, baseRequestResponse.getHttpService()), StatusServlet.TITLE, StatusServlet.DESCRIPTION, REMEDY, Risk.Low, Confidence.Certain)); return issues; } List<int[]> matches_httpd = getMatches(responseBytes, GREP_STRING_HTTPD, helpers); if (matches_httpd.size() > 0) { issues.add( new CustomScanIssue( baseRequestResponse.getHttpService(), helpers.analyzeRequest(baseRequestResponse).getUrl(), new CustomHttpRequestResponse( statustest, responseBytes, baseRequestResponse.getHttpService()), StatusServlet.TITLE, StatusServlet.DESCRIPTION, REMEDY, Risk.Low, Confidence.Certain)); return issues; } } } catch (MalformedURLException ex) { stderr.println("Malformed URL Exception " + ex); } } } return issues; }