Merge branch 'main' into atorralba/promote-unsafe-android-webview-fetch

This commit is contained in:
Tony Torralba
2021-07-20 17:30:56 +02:00
2246 changed files with 205894 additions and 30303 deletions

View File

@@ -1,10 +1,14 @@
edges
| Test.java:6:35:6:44 | arg : String | Test.java:7:44:7:69 | ... + ... |
| Test.java:6:35:6:44 | arg : String | Test.java:10:29:10:74 | new String[] |
| Test.java:6:35:6:44 | arg : String | Test.java:10:61:10:73 | ... + ... : String |
| Test.java:6:35:6:44 | arg : String | Test.java:16:13:16:25 | ... + ... : String |
| Test.java:6:35:6:44 | arg : String | Test.java:24:29:24:32 | cmd1 |
| Test.java:16:5:16:7 | cmd [post update] : List | Test.java:18:29:18:31 | cmd |
| Test.java:16:13:16:25 | ... + ... : String | Test.java:16:5:16:7 | cmd [post update] : List |
| Test.java:6:35:6:44 | arg : String | Test.java:22:15:22:27 | ... + ... : String |
| Test.java:10:29:10:74 | {...} [[]] : String | Test.java:10:29:10:74 | new String[] |
| Test.java:10:61:10:73 | ... + ... : String | Test.java:10:29:10:74 | {...} [[]] : String |
| Test.java:16:5:16:7 | cmd [post update] [<element>] : String | Test.java:18:29:18:31 | cmd |
| Test.java:16:13:16:25 | ... + ... : String | Test.java:16:5:16:7 | cmd [post update] [<element>] : String |
| Test.java:22:5:22:8 | cmd1 [post update] [[]] : String | Test.java:24:29:24:32 | cmd1 |
| Test.java:22:15:22:27 | ... + ... : String | Test.java:22:5:22:8 | cmd1 [post update] [[]] : String |
| Test.java:28:38:28:47 | arg : String | Test.java:29:44:29:64 | ... + ... |
| Test.java:57:27:57:39 | args : String[] | Test.java:60:20:60:22 | arg : String |
| Test.java:57:27:57:39 | args : String[] | Test.java:61:23:61:25 | arg : String |
@@ -14,9 +18,13 @@ nodes
| Test.java:6:35:6:44 | arg : String | semmle.label | arg : String |
| Test.java:7:44:7:69 | ... + ... | semmle.label | ... + ... |
| Test.java:10:29:10:74 | new String[] | semmle.label | new String[] |
| Test.java:16:5:16:7 | cmd [post update] : List | semmle.label | cmd [post update] : List |
| Test.java:10:29:10:74 | {...} [[]] : String | semmle.label | {...} [[]] : String |
| Test.java:10:61:10:73 | ... + ... : String | semmle.label | ... + ... : String |
| Test.java:16:5:16:7 | cmd [post update] [<element>] : String | semmle.label | cmd [post update] [<element>] : String |
| Test.java:16:13:16:25 | ... + ... : String | semmle.label | ... + ... : String |
| Test.java:18:29:18:31 | cmd | semmle.label | cmd |
| Test.java:22:5:22:8 | cmd1 [post update] [[]] : String | semmle.label | cmd1 [post update] [[]] : String |
| Test.java:22:15:22:27 | ... + ... : String | semmle.label | ... + ... : String |
| Test.java:24:29:24:32 | cmd1 | semmle.label | cmd1 |
| Test.java:28:38:28:47 | arg : String | semmle.label | arg : String |
| Test.java:29:44:29:64 | ... + ... | semmle.label | ... + ... |

View File

@@ -0,0 +1,247 @@
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.Variant;
import java.util.Locale;
@Path("")
public class JaxXSS {
@GET
public static Response specificContentType(boolean safeContentType, boolean chainDirectly, boolean contentTypeFirst, String userControlled) {
Response.ResponseBuilder builder = Response.ok();
if(!safeContentType) {
if(chainDirectly) {
if(contentTypeFirst)
return builder.type(MediaType.TEXT_HTML).entity(userControlled).build(); // $xss
else
return builder.entity(userControlled).type(MediaType.TEXT_HTML).build(); // $xss
}
else {
if(contentTypeFirst) {
Response.ResponseBuilder builder2 = builder.type(MediaType.TEXT_HTML);
return builder2.entity(userControlled).build(); // $xss
}
else {
Response.ResponseBuilder builder2 = builder.entity(userControlled);
return builder2.type(MediaType.TEXT_HTML).build(); // $xss
}
}
}
else {
if(chainDirectly) {
if(contentTypeFirst)
return builder.type(MediaType.APPLICATION_JSON).entity(userControlled).build(); // $SPURIOUS: xss
else
return builder.entity(userControlled).type(MediaType.APPLICATION_JSON).build(); // $SPURIOUS: xss
}
else {
if(contentTypeFirst) {
Response.ResponseBuilder builder2 = builder.type(MediaType.APPLICATION_JSON);
return builder2.entity(userControlled).build(); // $SPURIOUS: xss
}
else {
Response.ResponseBuilder builder2 = builder.entity(userControlled);
return builder2.type(MediaType.APPLICATION_JSON).build(); // $SPURIOUS: xss
}
}
}
}
@GET
public static Response specificContentTypeSetterMethods(int route, boolean safeContentType, String userControlled) {
// Test the remarkably many routes to setting a content-type in Jax-RS, besides the ResponseBuilder.entity method used above:
if(safeContentType) {
if(route == 0) {
// via ok, as a string literal:
return Response.ok(userControlled, "application/json").build(); // $SPURIOUS: xss
}
else if(route == 1) {
// via ok, as a string constant:
return Response.ok(userControlled, MediaType.APPLICATION_JSON).build(); // $SPURIOUS: xss
}
else if(route == 2) {
// via ok, as a MediaType constant:
return Response.ok(userControlled, MediaType.APPLICATION_JSON_TYPE).build(); // $SPURIOUS: xss
}
else if(route == 3) {
// via ok, as a Variant, via constructor:
return Response.ok(userControlled, new Variant(MediaType.APPLICATION_JSON_TYPE, "language", "encoding")).build(); // $SPURIOUS: xss
}
else if(route == 4) {
// via ok, as a Variant, via static method:
return Response.ok(userControlled, Variant.mediaTypes(MediaType.APPLICATION_JSON_TYPE).build().get(0)).build(); // $SPURIOUS: xss
}
else if(route == 5) {
// via ok, as a Variant, via instance method:
return Response.ok(userControlled, Variant.languages(Locale.UK).mediaTypes(MediaType.APPLICATION_JSON_TYPE).build().get(0)).build(); // $SPURIOUS: xss
}
else if(route == 6) {
// via builder variant, before entity:
return Response.ok().variant(new Variant(MediaType.APPLICATION_JSON_TYPE, "language", "encoding")).entity(userControlled).build(); // $SPURIOUS: xss
}
else if(route == 7) {
// via builder variant, after entity:
return Response.ok().entity(userControlled).variant(new Variant(MediaType.APPLICATION_JSON_TYPE, "language", "encoding")).build(); // $SPURIOUS: xss
}
else if(route == 8) {
// provide entity via ok, then content-type via builder:
return Response.ok(userControlled).type(MediaType.APPLICATION_JSON_TYPE).build(); // $SPURIOUS: xss
}
}
else {
if(route == 0) {
// via ok, as a string literal:
return Response.ok("text/html").entity(userControlled).build(); // $xss
}
else if(route == 1) {
// via ok, as a string constant:
return Response.ok(MediaType.TEXT_HTML).entity(userControlled).build(); // $xss
}
else if(route == 2) {
// via ok, as a MediaType constant:
return Response.ok(MediaType.TEXT_HTML_TYPE).entity(userControlled).build(); // $xss
}
else if(route == 3) {
// via ok, as a Variant, via constructor:
return Response.ok(new Variant(MediaType.TEXT_HTML_TYPE, "language", "encoding")).entity(userControlled).build(); // $xss
}
else if(route == 4) {
// via ok, as a Variant, via static method:
return Response.ok(Variant.mediaTypes(MediaType.TEXT_HTML_TYPE).build()).entity(userControlled).build(); // $xss
}
else if(route == 5) {
// via ok, as a Variant, via instance method:
return Response.ok(Variant.languages(Locale.UK).mediaTypes(MediaType.TEXT_HTML_TYPE).build()).entity(userControlled).build(); // $xss
}
else if(route == 6) {
// via builder variant, before entity:
return Response.ok().variant(new Variant(MediaType.TEXT_HTML_TYPE, "language", "encoding")).entity(userControlled).build(); // $xss
}
else if(route == 7) {
// via builder variant, after entity:
return Response.ok().entity(userControlled).variant(new Variant(MediaType.TEXT_HTML_TYPE, "language", "encoding")).build(); // $xss
}
else if(route == 8) {
// provide entity via ok, then content-type via builder:
return Response.ok(userControlled).type(MediaType.TEXT_HTML_TYPE).build(); // $xss
}
}
return null;
}
@GET @Produces(MediaType.APPLICATION_JSON)
public static Response methodContentTypeSafe(String userControlled) {
return Response.ok(userControlled).build();
}
@POST @Produces(MediaType.APPLICATION_JSON)
public static Response methodContentTypeSafePost(String userControlled) {
return Response.ok(userControlled).build();
}
@GET @Produces("application/json")
public static Response methodContentTypeSafeStringLiteral(String userControlled) {
return Response.ok(userControlled).build();
}
@GET @Produces(MediaType.TEXT_HTML)
public static Response methodContentTypeUnsafe(String userControlled) {
return Response.ok(userControlled).build(); // $MISSING: xss
}
@POST @Produces(MediaType.TEXT_HTML)
public static Response methodContentTypeUnsafePost(String userControlled) {
return Response.ok(userControlled).build(); // $MISSING: xss
}
@GET @Produces("text/html")
public static Response methodContentTypeUnsafeStringLiteral(String userControlled) {
return Response.ok(userControlled).build(); // $MISSING: xss
}
@GET @Produces({MediaType.TEXT_HTML, MediaType.APPLICATION_JSON})
public static Response methodContentTypeMaybeSafe(String userControlled) {
return Response.ok(userControlled).build(); // $MISSING: xss
}
@GET @Produces(MediaType.APPLICATION_JSON)
public static Response methodContentTypeSafeOverriddenWithUnsafe(String userControlled) {
return Response.ok().type(MediaType.TEXT_HTML).entity(userControlled).build(); // $MISSING: xss
}
@GET @Produces(MediaType.TEXT_HTML)
public static Response methodContentTypeUnsafeOverriddenWithSafe(String userControlled) {
return Response.ok().type(MediaType.APPLICATION_JSON).entity(userControlled).build();
}
@Path("/abc")
@Produces({"application/json"})
public static class ClassContentTypeSafe {
@GET
public Response test(String userControlled) {
return Response.ok(userControlled).build();
}
@GET
public String testDirectReturn(String userControlled) {
return userControlled;
}
@GET @Produces({"text/html"})
public Response overridesWithUnsafe(String userControlled) {
return Response.ok(userControlled).build(); // $MISSING: xss
}
@GET
public Response overridesWithUnsafe2(String userControlled) {
return Response.ok().type(MediaType.TEXT_HTML).entity(userControlled).build(); // $MISSING: xss
}
}
@Path("/abc")
@Produces({"text/html"})
public static class ClassContentTypeUnsafe {
@GET
public Response test(String userControlled) {
return Response.ok(userControlled).build(); // $MISSING: xss
}
@GET
public String testDirectReturn(String userControlled) {
return userControlled; // $MISSING: xss
}
@GET @Produces({"application/json"})
public Response overridesWithSafe(String userControlled) {
return Response.ok(userControlled).build();
}
@GET
public Response overridesWithSafe2(String userControlled) {
return Response.ok().type(MediaType.APPLICATION_JSON).entity(userControlled).build();
}
}
@GET
public static Response entityWithNoMediaType(String userControlled) {
return Response.ok(userControlled).build(); // $xss
}
@GET
public static String stringWithNoMediaType(String userControlled) {
return userControlled; // $xss
}
}

View File

@@ -1,15 +0,0 @@
edges
| XSS.java:23:21:23:48 | getParameter(...) : String | XSS.java:23:5:23:70 | ... + ... |
| XSS.java:38:67:38:87 | getPathInfo(...) : String | XSS.java:38:30:38:87 | ... + ... |
| XSS.java:41:36:41:56 | getPathInfo(...) : String | XSS.java:41:36:41:67 | getBytes(...) |
nodes
| XSS.java:23:5:23:70 | ... + ... | semmle.label | ... + ... |
| XSS.java:23:21:23:48 | getParameter(...) : String | semmle.label | getParameter(...) : String |
| XSS.java:38:30:38:87 | ... + ... | semmle.label | ... + ... |
| XSS.java:38:67:38:87 | getPathInfo(...) : String | semmle.label | getPathInfo(...) : String |
| XSS.java:41:36:41:56 | getPathInfo(...) : String | semmle.label | getPathInfo(...) : String |
| XSS.java:41:36:41:67 | getBytes(...) | semmle.label | getBytes(...) |
#select
| XSS.java:23:5:23:70 | ... + ... | XSS.java:23:21:23:48 | getParameter(...) : String | XSS.java:23:5:23:70 | ... + ... | Cross-site scripting vulnerability due to $@. | XSS.java:23:21:23:48 | getParameter(...) | user-provided value |
| XSS.java:38:30:38:87 | ... + ... | XSS.java:38:67:38:87 | getPathInfo(...) : String | XSS.java:38:30:38:87 | ... + ... | Cross-site scripting vulnerability due to $@. | XSS.java:38:67:38:87 | getPathInfo(...) | user-provided value |
| XSS.java:41:36:41:67 | getBytes(...) | XSS.java:41:36:41:56 | getPathInfo(...) : String | XSS.java:41:36:41:67 | getBytes(...) | Cross-site scripting vulnerability due to $@. | XSS.java:41:36:41:56 | getPathInfo(...) | user-provided value |

View File

@@ -20,7 +20,7 @@ public class XSS extends HttpServlet {
throws ServletException, IOException {
// BAD: a request parameter is written directly to the Servlet response stream
response.getWriter().print(
"The page \"" + request.getParameter("page") + "\" was not found.");
"The page \"" + request.getParameter("page") + "\" was not found."); // $xss
// GOOD: servlet API encodes the error message HTML for the HTML context
response.sendError(HttpServletResponse.SC_NOT_FOUND,
@@ -35,10 +35,10 @@ public class XSS extends HttpServlet {
"The page \"" + capitalizeName(request.getParameter("page")) + "\" was not found.");
// BAD: outputting the path of the resource
response.getWriter().print("The path section of the URL was " + request.getPathInfo());
response.getWriter().print("The path section of the URL was " + request.getPathInfo()); // $xss
// BAD: typical XSS, this time written to an OutputStream instead of a Writer
response.getOutputStream().write(request.getPathInfo().getBytes());
response.getOutputStream().write(request.getPathInfo().getBytes()); // $xss
}

View File

@@ -0,0 +1,33 @@
import java
import semmle.code.java.dataflow.FlowSources
import semmle.code.java.security.XSS
import TestUtilities.InlineExpectationsTest
class XSSConfig extends TaintTracking::Configuration {
XSSConfig() { this = "XSSConfig" }
override predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource }
override predicate isSink(DataFlow::Node sink) { sink instanceof XssSink }
override predicate isSanitizer(DataFlow::Node node) { node instanceof XssSanitizer }
override predicate isAdditionalTaintStep(DataFlow::Node node1, DataFlow::Node node2) {
any(XssAdditionalTaintStep s).step(node1, node2)
}
}
class XssTest extends InlineExpectationsTest {
XssTest() { this = "XssTest" }
override string getARelevantTag() { result = ["xss"] }
override predicate hasActualResult(Location location, string element, string tag, string value) {
tag = "xss" and
exists(DataFlow::Node src, DataFlow::Node sink, XSSConfig conf | conf.hasFlow(src, sink) |
sink.getLocation() = location and
element = sink.toString() and
value = ""
)
}
}

View File

@@ -1 +0,0 @@
Security/CWE/CWE-079/XSS.ql

View File

@@ -1 +1 @@
//semmle-extractor-options: --javac-args -cp ${testdir}/../../../../../stubs/servlet-api-2.4
//semmle-extractor-options: --javac-args -cp ${testdir}/../../../../../stubs/servlet-api-2.4:${testdir}/../../../../../stubs/javax-ws-rs-api-2.1.1/

View File

@@ -0,0 +1,44 @@
import java.sql.ResultSet;
import java.util.Map;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.jdbc.object.BatchSqlUpdate;
import org.springframework.jdbc.object.MappingSqlQueryWithParameters;
import org.springframework.jdbc.object.SqlFunction;
import org.springframework.jdbc.object.SqlUpdate;
import org.springframework.jdbc.object.UpdatableSqlQuery;
public class SpringJdbc {
public static String source() { return null; }
private static class MyUpdatableSqlQuery extends UpdatableSqlQuery<String> {
public MyUpdatableSqlQuery() {
super(null, source()); // $ sqlInjection
}
protected String updateRow(ResultSet rs, int rowNum, Map<?,?> context) {
return null;
}
}
public static void test(JdbcTemplate template) {
new BatchSqlUpdate(null, source()); // $ sqlInjection
new SqlFunction(null, source()); // $ sqlInjection
new SqlUpdate(null, source()); // $ sqlInjection
(new BatchSqlUpdate()).setSql(source()); // $ sqlInjection
template.batchUpdate(source()); // $ sqlInjection
template.batchUpdate(source(), null, 0, null); // $ sqlInjection
template.execute(source()); // $ sqlInjection
template.update(source()); // $ sqlInjection
template.query(source(), (RowMapper)null); // $ sqlInjection
template.queryForList(source()); // $ sqlInjection
template.queryForMap(source()); // $ sqlInjection
template.queryForObject(source(), (Class)null); // $ sqlInjection
template.queryForRowSet(source()); // $ sqlInjection
template.queryForStream(source(), (RowMapper)null); // $ sqlInjection
}
}

View File

@@ -1 +1 @@
//semmle-extractor-options: --javac-args -cp ${testdir}/../../../../../stubs/mongodbClient
//semmle-extractor-options: --javac-args -cp ${testdir}/../../../../../stubs/mongodbClient:${testdir}/../../../../../stubs/springframework-5.3.8

View File

@@ -0,0 +1,41 @@
import java
import semmle.code.java.dataflow.TaintTracking
import semmle.code.java.security.QueryInjection
import TestUtilities.InlineExpectationsTest
private class QueryInjectionFlowConfig extends TaintTracking::Configuration {
QueryInjectionFlowConfig() { this = "SqlInjectionLib::QueryInjectionFlowConfig" }
override predicate isSource(DataFlow::Node src) {
src.asExpr() = any(MethodAccess ma | ma.getMethod().hasName("source"))
}
override predicate isSink(DataFlow::Node sink) { sink instanceof QueryInjectionSink }
override predicate isSanitizer(DataFlow::Node node) {
node.getType() instanceof PrimitiveType or
node.getType() instanceof BoxedType or
node.getType() instanceof NumberType
}
override predicate isAdditionalTaintStep(DataFlow::Node node1, DataFlow::Node node2) {
any(AdditionalQueryInjectionTaintStep s).step(node1, node2)
}
}
class HasFlowTest extends InlineExpectationsTest {
HasFlowTest() { this = "HasFlowTest" }
override string getARelevantTag() { result = "sqlInjection" }
override predicate hasActualResult(Location location, string element, string tag, string value) {
tag = "sqlInjection" and
exists(DataFlow::Node src, DataFlow::Node sink, QueryInjectionFlowConfig conf |
conf.hasFlow(src, sink)
|
sink.getLocation() = location and
element = sink.toString() and
value = ""
)
}
}

View File

@@ -1 +1 @@
//semmle-extractor-options: --javac-args -cp ${testdir}/../../../stubs/springframework-5.2.3:${testdir}/../../../stubs/spring-ldap-2.3.2:${testdir}/../../../stubs/unboundid-ldap-4.0.14:${testdir}/../../../stubs/esapi-2.0.1:${testdir}/../../../stubs/apache-ldap-1.0.2
//semmle-extractor-options: --javac-args -cp ${testdir}/../../../stubs/springframework-5.3.8:${testdir}/../../../stubs/spring-ldap-2.3.2:${testdir}/../../../stubs/unboundid-ldap-4.0.14:${testdir}/../../../stubs/esapi-2.0.1:${testdir}/../../../stubs/apache-ldap-1.0.2

View File

@@ -1,22 +1,7 @@
import java
import semmle.code.java.dataflow.DataFlow
import semmle.code.java.dataflow.FlowSteps
import semmle.code.java.dataflow.FlowSources
import semmle.code.java.security.JexlInjection
import semmle.code.java.security.JexlInjectionQuery
import TestUtilities.InlineExpectationsTest
class Conf extends TaintTracking::Configuration {
Conf() { this = "qltest:cwe:jexl-injection" }
override predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource }
override predicate isSink(DataFlow::Node sink) { sink instanceof JexlEvaluationSink }
override predicate isAdditionalTaintStep(DataFlow::Node node1, DataFlow::Node node2) {
any(JexlInjectionAdditionalTaintStep c).step(node1, node2)
}
}
class JexlInjectionTest extends InlineExpectationsTest {
JexlInjectionTest() { this = "HasJexlInjectionTest" }
@@ -24,7 +9,9 @@ class JexlInjectionTest extends InlineExpectationsTest {
override predicate hasActualResult(Location location, string element, string tag, string value) {
tag = "hasJexlInjection" and
exists(DataFlow::Node src, DataFlow::Node sink, Conf conf | conf.hasFlow(src, sink) |
exists(DataFlow::Node src, DataFlow::Node sink, JexlInjectionConfig conf |
conf.hasFlow(src, sink)
|
sink.getLocation() = location and
element = sink.toString() and
value = ""

View File

@@ -1 +1 @@
//semmle-extractor-options: --javac-args -cp ${testdir}/../../../stubs/validation-api-2.0.1.Final:${testdir}/../../../stubs/springframework-5.2.3:${testdir}/../../../stubs/apache-commons-jexl-2.1.1:${testdir}/../../../stubs/apache-commons-jexl-3.1:${testdir}/../../../stubs/apache-commons-logging-1.2
//semmle-extractor-options: --javac-args -cp ${testdir}/../../../stubs/validation-api-2.0.1.Final:${testdir}/../../../stubs/springframework-5.3.8:${testdir}/../../../stubs/apache-commons-jexl-2.1.1:${testdir}/../../../stubs/apache-commons-jexl-3.1:${testdir}/../../../stubs/apache-commons-logging-1.2

View File

@@ -1 +1 @@
//semmle-extractor-options: --javac-args -cp ${testdir}/../../../stubs/snakeyaml-1.21:${testdir}/../../../stubs/xstream-1.4.10:${testdir}/../../../stubs/kryo-4.0.2:${testdir}/../../../stubs/jsr311-api-1.1.1:${testdir}/../../../stubs/fastjson-1.2.74:${testdir}/../../../stubs/springframework-5.2.3:${testdir}/../../../stubs/servlet-api-2.4:${testdir}/../../../stubs/jyaml-1.3:${testdir}/../../../stubs/json-io-4.10.0:${testdir}/../../../stubs/yamlbeans-1.09:${testdir}/../../../stubs/hessian-4.0.38:${testdir}/../../../stubs/castor-1.4.1
//semmle-extractor-options: --javac-args -cp ${testdir}/../../../stubs/snakeyaml-1.21:${testdir}/../../../stubs/xstream-1.4.10:${testdir}/../../../stubs/kryo-4.0.2:${testdir}/../../../stubs/jsr311-api-1.1.1:${testdir}/../../../stubs/fastjson-1.2.74:${testdir}/../../../stubs/springframework-5.3.8:${testdir}/../../../stubs/servlet-api-2.4:${testdir}/../../../stubs/jyaml-1.3:${testdir}/../../../stubs/json-io-4.10.0:${testdir}/../../../stubs/yamlbeans-1.09:${testdir}/../../../stubs/hessian-4.0.38:${testdir}/../../../stubs/castor-1.4.1

View File

@@ -0,0 +1,49 @@
import org.springframework.http.HttpHeaders;
import org.springframework.web.reactive.function.client.WebClient;
import reactor.core.publisher.Mono;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
public class ReactiveWebClientSSRF extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
try {
String url = request.getParameter("uri");
WebClient webClient = WebClient.create(url); // $ SSRF
Mono<String> result = webClient.get()
.uri("/")
.retrieve()
.bodyToMono(String.class);
result.block();
} catch (Exception e) {
// Ignore
}
}
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
try {
String url = request.getParameter("uri");
WebClient webClient = WebClient.builder()
.defaultHeader("User-Agent", "Java")
.baseUrl(url) // $ SSRF
.build();
Mono<String> result = webClient.get()
.uri("/")
.retrieve()
.bodyToMono(String.class);
result.block();
} catch (Exception e) {
// Ignore
}
}
}

View File

@@ -0,0 +1,99 @@
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.net.URI;
import java.net.URL;
import java.net.URLClassLoader;
import java.net.URLStreamHandlerFactory;
public class URLClassLoaderSSRF extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
try {
String url = request.getParameter("uri");
URI uri = new URI(url);
URLClassLoader urlClassLoader = new URLClassLoader(new URL[]{uri.toURL()}); // $ SSRF
Class<?> test = urlClassLoader.loadClass("test");
} catch (Exception e) {
// Ignore
}
}
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
try {
String url = request.getParameter("uri");
URI uri = new URI(url);
URLClassLoader urlClassLoader = new URLClassLoader(new URL[]{uri.toURL()}, URLClassLoaderSSRF.class.getClassLoader()); // $ SSRF
Class<?> test = urlClassLoader.loadClass("test");
} catch (Exception e) {
// Ignore
}
}
protected void doPut(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
try {
String url = request.getParameter("uri");
URI uri = new URI(url);
URLStreamHandlerFactory urlStreamHandlerFactory = null;
URLClassLoader urlClassLoader = new URLClassLoader(new URL[]{uri.toURL()}, URLClassLoaderSSRF.class.getClassLoader(), urlStreamHandlerFactory); // $ SSRF
urlClassLoader.findResource("test");
} catch (Exception e) {
// Ignore
}
}
protected void doDelete(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
try {
String url = request.getParameter("uri");
URI uri = new URI(url);
URLClassLoader urlClassLoader = URLClassLoader.newInstance(new URL[]{uri.toURL()}); // $ SSRF
urlClassLoader.getResourceAsStream("test");
} catch (Exception e) {
// Ignore
}
}
protected void doOptions(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
try {
String url = request.getParameter("uri");
URI uri = new URI(url);
URLClassLoader urlClassLoader =
new URLClassLoader("testClassLoader",
new URL[]{uri.toURL()}, // $ SSRF
URLClassLoaderSSRF.class.getClassLoader()
);
Class<?> rceTest = urlClassLoader.loadClass("RCETest");
} catch (Exception e) {
// Ignore
}
}
protected void doTrace(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
try {
String url = request.getParameter("uri");
URI uri = new URI(url);
URLStreamHandlerFactory urlStreamHandlerFactory = null;
URLClassLoader urlClassLoader =
new URLClassLoader("testClassLoader",
new URL[]{uri.toURL()}, // $ SSRF
URLClassLoaderSSRF.class.getClassLoader(),
urlStreamHandlerFactory
);
Class<?> rceTest = urlClassLoader.loadClass("RCETest");
} catch (Exception e) {
// Ignore
}
}
}

View File

@@ -1 +1,2 @@
//semmle-extractor-options: --javac-args -source 11 -target 11 -cp ${testdir}/../../../stubs/springframework-5.2.3:${testdir}/../../../stubs/javax-ws-rs-api-2.1.1:${testdir}/../../../stubs/javax-ws-rs-api-3.0.0:${testdir}/../../../stubs/apache-http-4.4.13/:${testdir}/../../../stubs/servlet-api-2.4/
//semmle-extractor-options: --javac-args -source 11 -target 11 -cp ${testdir}/../../../stubs/springframework-5.3.8:${testdir}/../../../stubs/javax-ws-rs-api-2.1.1:${testdir}/../../../stubs/javax-ws-rs-api-3.0.0:${testdir}/../../../stubs/apache-http-4.4.13/:${testdir}/../../../stubs/servlet-api-2.4/:${testdir}/../../../stubs/projectreactor-3.4.3/