mirror of
https://github.com/github/codeql.git
synced 2026-05-03 12:45:27 +02:00
Merge branch 'main' into thirdpartyapitelemtry
This commit is contained in:
264
java/ql/test/query-tests/security/CWE-074/JndiInjectionTest.java
Normal file
264
java/ql/test/query-tests/security/CWE-074/JndiInjectionTest.java
Normal file
@@ -0,0 +1,264 @@
|
||||
import java.io.IOException;
|
||||
import java.util.Hashtable;
|
||||
import java.util.Properties;
|
||||
|
||||
import javax.management.remote.JMXConnector;
|
||||
import javax.management.remote.JMXConnectorFactory;
|
||||
import javax.management.remote.JMXServiceURL;
|
||||
import javax.naming.CompositeName;
|
||||
import javax.naming.CompoundName;
|
||||
import javax.naming.Context;
|
||||
import javax.naming.InitialContext;
|
||||
import javax.naming.Name;
|
||||
import javax.naming.NamingException;
|
||||
import javax.naming.directory.DirContext;
|
||||
import javax.naming.directory.InitialDirContext;
|
||||
import javax.naming.directory.SearchControls;
|
||||
import javax.naming.ldap.InitialLdapContext;
|
||||
|
||||
import org.springframework.jndi.JndiTemplate;
|
||||
import org.springframework.ldap.core.AttributesMapper;
|
||||
import org.springframework.ldap.core.ContextMapper;
|
||||
import org.springframework.ldap.core.DirContextProcessor;
|
||||
import org.springframework.ldap.core.LdapTemplate;
|
||||
import org.springframework.ldap.core.NameClassPairCallbackHandler;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
|
||||
@Controller
|
||||
public class JndiInjectionTest {
|
||||
@RequestMapping
|
||||
public void testInitialContextBad1(@RequestParam String nameStr) throws NamingException {
|
||||
Name name = new CompositeName(nameStr);
|
||||
InitialContext ctx = new InitialContext();
|
||||
|
||||
ctx.lookup(nameStr); // $hasJndiInjection
|
||||
ctx.lookupLink(nameStr); // $hasJndiInjection
|
||||
InitialContext.doLookup(nameStr); // $hasJndiInjection
|
||||
ctx.rename(nameStr, ""); // $hasJndiInjection
|
||||
ctx.list(nameStr); // $hasJndiInjection
|
||||
ctx.listBindings(nameStr); // $hasJndiInjection
|
||||
|
||||
ctx.lookup(name); // $hasJndiInjection
|
||||
ctx.lookupLink(name); // $hasJndiInjection
|
||||
InitialContext.doLookup(name); // $hasJndiInjection
|
||||
ctx.rename(name, null); // $hasJndiInjection
|
||||
ctx.list(name); // $hasJndiInjection
|
||||
ctx.listBindings(name); // $hasJndiInjection
|
||||
}
|
||||
|
||||
@RequestMapping
|
||||
public void testDirContextBad1(@RequestParam String nameStr) throws NamingException {
|
||||
Name name = new CompoundName(nameStr, new Properties());
|
||||
DirContext ctx = new InitialDirContext();
|
||||
|
||||
ctx.lookup(nameStr); // $hasJndiInjection
|
||||
ctx.lookupLink(nameStr); // $hasJndiInjection
|
||||
ctx.rename(nameStr, ""); // $hasJndiInjection
|
||||
ctx.list(nameStr); // $hasJndiInjection
|
||||
ctx.listBindings(nameStr); // $hasJndiInjection
|
||||
|
||||
ctx.lookup(name); // $hasJndiInjection
|
||||
ctx.lookupLink(name); // $hasJndiInjection
|
||||
ctx.rename(name, null); // $hasJndiInjection
|
||||
ctx.list(name); // $hasJndiInjection
|
||||
ctx.listBindings(name); // $hasJndiInjection
|
||||
|
||||
SearchControls searchControls = new SearchControls();
|
||||
searchControls.setReturningObjFlag(true);
|
||||
ctx.search(nameStr, "", searchControls); // $hasJndiInjection
|
||||
ctx.search(nameStr, "", new Object[] {}, searchControls); // $hasJndiInjection
|
||||
|
||||
SearchControls searchControls2 = new SearchControls(1, 0, 0, null, true, false);
|
||||
ctx.search(nameStr, "", searchControls2); // $hasJndiInjection
|
||||
ctx.search(nameStr, "", new Object[] {}, searchControls2); // $hasJndiInjection
|
||||
|
||||
SearchControls searchControls3 = new SearchControls(1, 0, 0, null, false, false);
|
||||
ctx.search(nameStr, "", searchControls3); // Safe
|
||||
ctx.search(nameStr, "", new Object[] {}, searchControls3); // Safe
|
||||
}
|
||||
|
||||
@RequestMapping
|
||||
public void testInitialLdapContextBad1(@RequestParam String nameStr) throws NamingException {
|
||||
Name name = new CompositeName(nameStr);
|
||||
InitialLdapContext ctx = new InitialLdapContext();
|
||||
|
||||
ctx.lookup(nameStr); // $hasJndiInjection
|
||||
ctx.lookupLink(nameStr); // $hasJndiInjection
|
||||
ctx.rename(nameStr, ""); // $hasJndiInjection
|
||||
ctx.list(nameStr); // $hasJndiInjection
|
||||
ctx.listBindings(nameStr); // $hasJndiInjection
|
||||
|
||||
ctx.lookup(name); // $hasJndiInjection
|
||||
ctx.lookupLink(name); // $hasJndiInjection
|
||||
ctx.rename(name, null); // $hasJndiInjection
|
||||
ctx.list(name); // $hasJndiInjection
|
||||
ctx.listBindings(name); // $hasJndiInjection
|
||||
}
|
||||
|
||||
@RequestMapping
|
||||
public void testSpringJndiTemplateBad1(@RequestParam String nameStr) throws NamingException {
|
||||
JndiTemplate ctx = new JndiTemplate();
|
||||
|
||||
ctx.lookup(nameStr); // $hasJndiInjection
|
||||
ctx.lookup(nameStr, null); // $hasJndiInjection
|
||||
}
|
||||
|
||||
@RequestMapping
|
||||
public void testSpringLdapTemplateBad1(@RequestParam String nameStr) throws NamingException {
|
||||
LdapTemplate ctx = new LdapTemplate();
|
||||
Name name = new CompositeName().add(nameStr);
|
||||
|
||||
ctx.lookup(nameStr); // $hasJndiInjection
|
||||
ctx.lookupContext(nameStr); // $hasJndiInjection
|
||||
ctx.findByDn(name, null); // $hasJndiInjection
|
||||
ctx.rename(name, null); // $hasJndiInjection
|
||||
ctx.list(name); // $hasJndiInjection
|
||||
ctx.listBindings(name); // $hasJndiInjection
|
||||
ctx.unbind(nameStr, true); // $hasJndiInjection
|
||||
|
||||
ctx.search(nameStr, "", 0, true, null); // $hasJndiInjection
|
||||
ctx.search(nameStr, "", 0, new String[] {}, (ContextMapper<Object>) null); // $hasJndiInjection
|
||||
ctx.search(nameStr, "", 0, (ContextMapper<Object>) null); // $hasJndiInjection
|
||||
ctx.search(nameStr, "", (ContextMapper<Object>) null); // $hasJndiInjection
|
||||
|
||||
SearchControls searchControls = new SearchControls();
|
||||
searchControls.setReturningObjFlag(true);
|
||||
ctx.search(nameStr, "", searchControls, (AttributesMapper<Object>) null); // $hasJndiInjection
|
||||
ctx.search(nameStr, "", searchControls, (AttributesMapper<Object>) null, // $hasJndiInjection
|
||||
(DirContextProcessor) null);
|
||||
ctx.search(nameStr, "", searchControls, (ContextMapper<Object>) null); // $hasJndiInjection
|
||||
ctx.search(nameStr, "", searchControls, (ContextMapper<Object>) null, // $hasJndiInjection
|
||||
(DirContextProcessor) null);
|
||||
ctx.search(nameStr, "", searchControls, (NameClassPairCallbackHandler) null); // $hasJndiInjection
|
||||
ctx.search(nameStr, "", searchControls, (NameClassPairCallbackHandler) null, // $hasJndiInjection
|
||||
(DirContextProcessor) null);
|
||||
|
||||
SearchControls searchControls2 = new SearchControls(1, 0, 0, null, true, false);
|
||||
ctx.search(nameStr, "", searchControls2, (AttributesMapper<Object>) null); // $hasJndiInjection
|
||||
ctx.search(nameStr, "", searchControls2, (AttributesMapper<Object>) null, // $hasJndiInjection
|
||||
(DirContextProcessor) null);
|
||||
ctx.search(nameStr, "", searchControls2, (ContextMapper<Object>) null); // $hasJndiInjection
|
||||
ctx.search(nameStr, "", searchControls2, (ContextMapper<Object>) null, // $hasJndiInjection
|
||||
(DirContextProcessor) null);
|
||||
ctx.search(nameStr, "", searchControls2, (NameClassPairCallbackHandler) null); // $hasJndiInjection
|
||||
ctx.search(nameStr, "", searchControls2, (NameClassPairCallbackHandler) null, // $hasJndiInjection
|
||||
(DirContextProcessor) null);
|
||||
|
||||
SearchControls searchControls3 = new SearchControls(1, 0, 0, null, false, false);
|
||||
ctx.search(nameStr, "", searchControls3, (AttributesMapper<Object>) null); // Safe
|
||||
ctx.search(nameStr, "", searchControls3, (AttributesMapper<Object>) null, // Safe
|
||||
(DirContextProcessor) null);
|
||||
ctx.search(nameStr, "", searchControls3, (ContextMapper<Object>) null); // Safe
|
||||
ctx.search(nameStr, "", searchControls3, (ContextMapper<Object>) null, // Safe
|
||||
(DirContextProcessor) null);
|
||||
ctx.search(nameStr, "", searchControls3, (NameClassPairCallbackHandler) null); // Safe
|
||||
ctx.search(nameStr, "", searchControls3, (NameClassPairCallbackHandler) null, // Safe
|
||||
(DirContextProcessor) null);
|
||||
|
||||
ctx.searchForObject(nameStr, "", (ContextMapper<Object>) null); // $hasJndiInjection
|
||||
}
|
||||
|
||||
@RequestMapping
|
||||
public void testShiroJndiTemplateBad1(@RequestParam String nameStr) throws NamingException {
|
||||
org.apache.shiro.jndi.JndiTemplate ctx = new org.apache.shiro.jndi.JndiTemplate();
|
||||
|
||||
ctx.lookup(nameStr); // $hasJndiInjection
|
||||
ctx.lookup(nameStr, null); // $hasJndiInjection
|
||||
}
|
||||
|
||||
@RequestMapping
|
||||
public void testJMXServiceUrlBad1(@RequestParam String urlStr) throws IOException {
|
||||
JMXConnectorFactory.connect(new JMXServiceURL(urlStr)); // $hasJndiInjection
|
||||
|
||||
JMXServiceURL url = new JMXServiceURL(urlStr);
|
||||
JMXConnector connector = JMXConnectorFactory.newJMXConnector(url, null);
|
||||
connector.connect(); // $hasJndiInjection
|
||||
}
|
||||
|
||||
@RequestMapping
|
||||
public void testEnvBad1(@RequestParam String urlStr) throws NamingException {
|
||||
Hashtable<String, String> env = new Hashtable<String, String>();
|
||||
env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.rmi.registry.RegistryContextFactory");
|
||||
env.put(Context.PROVIDER_URL, urlStr); // $hasJndiInjection
|
||||
new InitialContext(env);
|
||||
}
|
||||
|
||||
@RequestMapping
|
||||
public void testEnvBad2(@RequestParam String urlStr) throws NamingException {
|
||||
Hashtable<String, String> env = new Hashtable<String, String>();
|
||||
env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.rmi.registry.RegistryContextFactory");
|
||||
env.put("java.naming.provider.url", urlStr); // $hasJndiInjection
|
||||
new InitialDirContext(env);
|
||||
}
|
||||
|
||||
@RequestMapping
|
||||
public void testSpringJndiTemplatePropertiesBad1(@RequestParam String urlStr)
|
||||
throws NamingException {
|
||||
Properties props = new Properties();
|
||||
props.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.rmi.registry.RegistryContextFactory");
|
||||
props.put(Context.PROVIDER_URL, urlStr); // $hasJndiInjection
|
||||
new JndiTemplate(props);
|
||||
}
|
||||
|
||||
@RequestMapping
|
||||
public void testSpringJndiTemplatePropertiesBad2(@RequestParam String urlStr)
|
||||
throws NamingException {
|
||||
Properties props = new Properties();
|
||||
props.setProperty(Context.INITIAL_CONTEXT_FACTORY,
|
||||
"com.sun.jndi.rmi.registry.RegistryContextFactory");
|
||||
props.setProperty("java.naming.provider.url", urlStr); // $hasJndiInjection
|
||||
new JndiTemplate(props);
|
||||
}
|
||||
|
||||
@RequestMapping
|
||||
public void testSpringJndiTemplatePropertiesBad3(@RequestParam String urlStr)
|
||||
throws NamingException {
|
||||
Properties props = new Properties();
|
||||
props.setProperty(Context.INITIAL_CONTEXT_FACTORY,
|
||||
"com.sun.jndi.rmi.registry.RegistryContextFactory");
|
||||
props.setProperty("java.naming.provider.url", urlStr); // $hasJndiInjection
|
||||
JndiTemplate template = new JndiTemplate();
|
||||
template.setEnvironment(props);
|
||||
}
|
||||
|
||||
@RequestMapping
|
||||
public void testSpringLdapTemplateOk1(@RequestParam String nameStr) throws NamingException {
|
||||
LdapTemplate ctx = new LdapTemplate();
|
||||
|
||||
ctx.unbind(nameStr); // Safe
|
||||
ctx.unbind(nameStr, false); // Safe
|
||||
|
||||
ctx.search(nameStr, "", 0, false, null); // Safe
|
||||
ctx.search(nameStr, "", new SearchControls(), (NameClassPairCallbackHandler) new Object()); // Safe
|
||||
ctx.search(nameStr, "", new SearchControls(), (NameClassPairCallbackHandler) new Object(), // Safe
|
||||
null);
|
||||
ctx.search(nameStr, "", (NameClassPairCallbackHandler) new Object()); // Safe
|
||||
ctx.search(nameStr, "", 0, new String[] {}, (AttributesMapper<Object>) new Object()); // Safe
|
||||
ctx.search(nameStr, "", 0, (AttributesMapper<Object>) new Object()); // Safe
|
||||
ctx.search(nameStr, "", (AttributesMapper) new Object()); // Safe
|
||||
ctx.search(nameStr, "", new SearchControls(), (ContextMapper) new Object()); // Safe
|
||||
ctx.search(nameStr, "", new SearchControls(), (AttributesMapper) new Object()); // Safe
|
||||
ctx.search(nameStr, "", new SearchControls(), (ContextMapper) new Object(), null); // Safe
|
||||
ctx.search(nameStr, "", new SearchControls(), (AttributesMapper) new Object(), null); // Safe
|
||||
|
||||
ctx.searchForObject(nameStr, "", new SearchControls(), (ContextMapper) new Object()); // Safe
|
||||
}
|
||||
|
||||
@RequestMapping
|
||||
public void testEnvOk1(@RequestParam String urlStr) throws NamingException {
|
||||
Hashtable<String, String> env = new Hashtable<String, String>();
|
||||
env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.rmi.registry.RegistryContextFactory");
|
||||
env.put(Context.SECURITY_PRINCIPAL, urlStr); // Safe
|
||||
new InitialContext(env);
|
||||
}
|
||||
|
||||
@RequestMapping
|
||||
public void testEnvOk2(@RequestParam String urlStr) throws NamingException {
|
||||
Hashtable<String, String> env = new Hashtable<String, String>();
|
||||
env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.rmi.registry.RegistryContextFactory");
|
||||
env.put("java.naming.security.principal", urlStr); // Safe
|
||||
new InitialContext(env);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
import java
|
||||
import semmle.code.java.security.JndiInjectionQuery
|
||||
import TestUtilities.InlineExpectationsTest
|
||||
|
||||
class HasJndiInjectionTest extends InlineExpectationsTest {
|
||||
HasJndiInjectionTest() { this = "HasJndiInjectionTest" }
|
||||
|
||||
override string getARelevantTag() { result = "hasJndiInjection" }
|
||||
|
||||
override predicate hasActualResult(Location location, string element, string tag, string value) {
|
||||
tag = "hasJndiInjection" and
|
||||
exists(DataFlow::Node src, DataFlow::Node sink, JndiInjectionFlowConfig conf |
|
||||
conf.hasFlow(src, sink)
|
||||
|
|
||||
sink.getLocation() = location and
|
||||
element = sink.toString() and
|
||||
value = ""
|
||||
)
|
||||
}
|
||||
}
|
||||
1
java/ql/test/query-tests/security/CWE-074/options
Normal file
1
java/ql/test/query-tests/security/CWE-074/options
Normal file
@@ -0,0 +1 @@
|
||||
//semmle-extractor-options: --javac-args -cp ${testdir}/../../../stubs/springframework-5.3.8:${testdir}/../../../stubs/shiro-core-1.5.2:${testdir}/../../../stubs/spring-ldap-2.3.2
|
||||
@@ -37,18 +37,18 @@ public class JaxXSS {
|
||||
else {
|
||||
if(chainDirectly) {
|
||||
if(contentTypeFirst)
|
||||
return builder.type(MediaType.APPLICATION_JSON).entity(userControlled).build(); // $SPURIOUS: xss
|
||||
return builder.type(MediaType.APPLICATION_JSON).entity(userControlled).build();
|
||||
else
|
||||
return builder.entity(userControlled).type(MediaType.APPLICATION_JSON).build(); // $SPURIOUS: xss
|
||||
return builder.entity(userControlled).type(MediaType.APPLICATION_JSON).build();
|
||||
}
|
||||
else {
|
||||
if(contentTypeFirst) {
|
||||
Response.ResponseBuilder builder2 = builder.type(MediaType.APPLICATION_JSON);
|
||||
return builder2.entity(userControlled).build(); // $SPURIOUS: xss
|
||||
return builder2.entity(userControlled).build();
|
||||
}
|
||||
else {
|
||||
Response.ResponseBuilder builder2 = builder.entity(userControlled);
|
||||
return builder2.type(MediaType.APPLICATION_JSON).build(); // $SPURIOUS: xss
|
||||
return builder2.type(MediaType.APPLICATION_JSON).build();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -63,39 +63,43 @@ public class JaxXSS {
|
||||
if(safeContentType) {
|
||||
if(route == 0) {
|
||||
// via ok, as a string literal:
|
||||
return Response.ok(userControlled, "application/json").build(); // $SPURIOUS: xss
|
||||
return Response.ok(userControlled, "application/json").build();
|
||||
}
|
||||
else if(route == 1) {
|
||||
// via ok, as a string constant:
|
||||
return Response.ok(userControlled, MediaType.APPLICATION_JSON).build(); // $SPURIOUS: xss
|
||||
return Response.ok(userControlled, MediaType.APPLICATION_JSON).build();
|
||||
}
|
||||
else if(route == 2) {
|
||||
// via ok, as a MediaType constant:
|
||||
return Response.ok(userControlled, MediaType.APPLICATION_JSON_TYPE).build(); // $SPURIOUS: xss
|
||||
return Response.ok(userControlled, MediaType.APPLICATION_JSON_TYPE).build();
|
||||
}
|
||||
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
|
||||
return Response.ok(userControlled, new Variant(MediaType.APPLICATION_JSON_TYPE, "language", "encoding")).build();
|
||||
}
|
||||
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
|
||||
return Response.ok(userControlled, Variant.mediaTypes(MediaType.APPLICATION_JSON_TYPE).build().get(0)).build();
|
||||
}
|
||||
else if(route == -4) {
|
||||
// via ok, as a Variant, via static method (testing multiple media types):
|
||||
return Response.ok(userControlled, Variant.mediaTypes(MediaType.APPLICATION_JSON_TYPE, MediaType.APPLICATION_OCTET_STREAM_TYPE).build().get(0)).build();
|
||||
}
|
||||
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
|
||||
return Response.ok(userControlled, Variant.languages(Locale.UK).mediaTypes(MediaType.APPLICATION_JSON_TYPE).build().get(0)).build();
|
||||
}
|
||||
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
|
||||
return Response.ok().variant(new Variant(MediaType.APPLICATION_JSON_TYPE, "language", "encoding")).entity(userControlled).build();
|
||||
}
|
||||
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
|
||||
return Response.ok().entity(userControlled).variant(new Variant(MediaType.APPLICATION_JSON_TYPE, "language", "encoding")).build();
|
||||
}
|
||||
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
|
||||
return Response.ok(userControlled).type(MediaType.APPLICATION_JSON_TYPE).build();
|
||||
}
|
||||
}
|
||||
else {
|
||||
@@ -158,27 +162,27 @@ public class JaxXSS {
|
||||
|
||||
@GET @Produces(MediaType.TEXT_HTML)
|
||||
public static Response methodContentTypeUnsafe(String userControlled) {
|
||||
return Response.ok(userControlled).build(); // $MISSING: xss
|
||||
return Response.ok(userControlled).build(); // $xss
|
||||
}
|
||||
|
||||
@POST @Produces(MediaType.TEXT_HTML)
|
||||
public static Response methodContentTypeUnsafePost(String userControlled) {
|
||||
return Response.ok(userControlled).build(); // $MISSING: xss
|
||||
return Response.ok(userControlled).build(); // $xss
|
||||
}
|
||||
|
||||
@GET @Produces("text/html")
|
||||
public static Response methodContentTypeUnsafeStringLiteral(String userControlled) {
|
||||
return Response.ok(userControlled).build(); // $MISSING: xss
|
||||
return Response.ok(userControlled).build(); // $xss
|
||||
}
|
||||
|
||||
@GET @Produces({MediaType.TEXT_HTML, MediaType.APPLICATION_JSON})
|
||||
public static Response methodContentTypeMaybeSafe(String userControlled) {
|
||||
return Response.ok(userControlled).build(); // $MISSING: xss
|
||||
return Response.ok(userControlled).build(); // $xss
|
||||
}
|
||||
|
||||
@GET @Produces(MediaType.APPLICATION_JSON)
|
||||
public static Response methodContentTypeSafeOverriddenWithUnsafe(String userControlled) {
|
||||
return Response.ok().type(MediaType.TEXT_HTML).entity(userControlled).build(); // $MISSING: xss
|
||||
return Response.ok().type(MediaType.TEXT_HTML).entity(userControlled).build(); // $xss
|
||||
}
|
||||
|
||||
@GET @Produces(MediaType.TEXT_HTML)
|
||||
@@ -201,12 +205,12 @@ public class JaxXSS {
|
||||
|
||||
@GET @Produces({"text/html"})
|
||||
public Response overridesWithUnsafe(String userControlled) {
|
||||
return Response.ok(userControlled).build(); // $MISSING: xss
|
||||
return Response.ok(userControlled).build(); // $xss
|
||||
}
|
||||
|
||||
@GET
|
||||
public Response overridesWithUnsafe2(String userControlled) {
|
||||
return Response.ok().type(MediaType.TEXT_HTML).entity(userControlled).build(); // $MISSING: xss
|
||||
return Response.ok().type(MediaType.TEXT_HTML).entity(userControlled).build(); // $xss
|
||||
}
|
||||
}
|
||||
|
||||
@@ -215,12 +219,12 @@ public class JaxXSS {
|
||||
public static class ClassContentTypeUnsafe {
|
||||
@GET
|
||||
public Response test(String userControlled) {
|
||||
return Response.ok(userControlled).build(); // $MISSING: xss
|
||||
return Response.ok(userControlled).build(); // $xss
|
||||
}
|
||||
|
||||
@GET
|
||||
public String testDirectReturn(String userControlled) {
|
||||
return userControlled; // $MISSING: xss
|
||||
return userControlled; // $xss
|
||||
}
|
||||
|
||||
@GET @Produces({"application/json"})
|
||||
|
||||
@@ -5,6 +5,7 @@ import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import org.springframework.web.util.HtmlUtils;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
@@ -157,4 +158,9 @@ public class SpringXSS {
|
||||
return userControlled; // $xss
|
||||
}
|
||||
|
||||
}
|
||||
@GetMapping(value = "/abc")
|
||||
public static String sanitizedString(String userControlled) {
|
||||
return HtmlUtils.htmlEscape(userControlled);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,55 @@
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.StringReader;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServlet;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import groovy.lang.GroovyClassLoader;
|
||||
import groovy.lang.GroovyCodeSource;
|
||||
|
||||
public class GroovyClassLoaderTest extends HttpServlet {
|
||||
|
||||
protected void doGet(HttpServletRequest request, HttpServletResponse response)
|
||||
throws ServletException, IOException {
|
||||
// "groovy.lang;GroovyClassLoader;false;parseClass;(GroovyCodeSource);;Argument[0];groovy",
|
||||
{
|
||||
String script = request.getParameter("script");
|
||||
final GroovyClassLoader classLoader = new GroovyClassLoader();
|
||||
GroovyCodeSource gcs = new GroovyCodeSource(script, "test", "Test");
|
||||
classLoader.parseClass(gcs); // $hasGroovyInjection
|
||||
}
|
||||
// "groovy.lang;GroovyClassLoader;false;parseClass;(GroovyCodeSource,boolean);;Argument[0];groovy",
|
||||
{
|
||||
String script = request.getParameter("script");
|
||||
final GroovyClassLoader classLoader = new GroovyClassLoader();
|
||||
GroovyCodeSource gcs = new GroovyCodeSource(script, "test", "Test");
|
||||
classLoader.parseClass(gcs, true); // $hasGroovyInjection
|
||||
}
|
||||
// "groovy.lang;GroovyClassLoader;false;parseClass;(InputStream,String);;Argument[0];groovy",
|
||||
{
|
||||
String script = request.getParameter("script");
|
||||
final GroovyClassLoader classLoader = new GroovyClassLoader();
|
||||
classLoader.parseClass(new ByteArrayInputStream(script.getBytes()), "test"); // $hasGroovyInjection
|
||||
}
|
||||
// "groovy.lang;GroovyClassLoader;false;parseClass;(Reader,String);;Argument[0];groovy",
|
||||
{
|
||||
String script = request.getParameter("script");
|
||||
final GroovyClassLoader classLoader = new GroovyClassLoader();
|
||||
classLoader.parseClass(new StringReader(script), "test"); // $hasGroovyInjection
|
||||
}
|
||||
// "groovy.lang;GroovyClassLoader;false;parseClass;(String);;Argument[0];groovy",
|
||||
{
|
||||
String script = request.getParameter("script");
|
||||
final GroovyClassLoader classLoader = new GroovyClassLoader();
|
||||
classLoader.parseClass(script); // $hasGroovyInjection
|
||||
}
|
||||
// "groovy.lang;GroovyClassLoader;false;parseClass;(String,String);;Argument[0];groovy",
|
||||
{
|
||||
String script = request.getParameter("script");
|
||||
final GroovyClassLoader classLoader = new GroovyClassLoader();
|
||||
classLoader.parseClass(script, "test"); // $hasGroovyInjection
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,97 @@
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.IOException;
|
||||
import java.net.URL;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServlet;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import org.codehaus.groovy.control.CompilationUnit;
|
||||
import org.codehaus.groovy.control.SourceUnit;
|
||||
import org.codehaus.groovy.control.io.ReaderSource;
|
||||
import org.codehaus.groovy.control.io.StringReaderSource;
|
||||
import org.codehaus.groovy.tools.javac.JavaAwareCompilationUnit;
|
||||
import org.codehaus.groovy.tools.javac.JavaStubCompilationUnit;
|
||||
|
||||
public class GroovyCompilationUnitTest extends HttpServlet {
|
||||
public void doGet(HttpServletRequest request, HttpServletResponse response)
|
||||
throws ServletException, IOException {
|
||||
// "org.codehaus.groovy.control;CompilationUnit;false;compile;;;Argument[-1];groovy"
|
||||
{
|
||||
CompilationUnit cu = new CompilationUnit();
|
||||
cu.addSource("test", request.getParameter("source"));
|
||||
cu.compile(); // $hasGroovyInjection
|
||||
}
|
||||
{
|
||||
CompilationUnit cu = new CompilationUnit();
|
||||
cu.addSource(request.getParameter("source"), "safe");
|
||||
cu.compile(); // Safe
|
||||
}
|
||||
{
|
||||
CompilationUnit cu = new CompilationUnit();
|
||||
cu.addSource("test",
|
||||
new ByteArrayInputStream(request.getParameter("source").getBytes()));
|
||||
cu.compile(); // $hasGroovyInjection
|
||||
}
|
||||
{
|
||||
CompilationUnit cu = new CompilationUnit();
|
||||
cu.addSource(new URL(request.getParameter("source")));
|
||||
cu.compile(); // $hasGroovyInjection
|
||||
}
|
||||
{
|
||||
CompilationUnit cu = new CompilationUnit();
|
||||
SourceUnit su =
|
||||
new SourceUnit("test", request.getParameter("source"), null, null, null);
|
||||
cu.addSource(su);
|
||||
cu.compile(); // $hasGroovyInjection
|
||||
}
|
||||
{
|
||||
CompilationUnit cu = new CompilationUnit();
|
||||
SourceUnit su =
|
||||
new SourceUnit(request.getParameter("source"), "safe", null, null, null);
|
||||
cu.addSource(su);
|
||||
cu.compile(); // Safe
|
||||
}
|
||||
{
|
||||
CompilationUnit cu = new CompilationUnit();
|
||||
StringReaderSource rs = new StringReaderSource(request.getParameter("source"), null);
|
||||
SourceUnit su = new SourceUnit("test", rs, null, null, null);
|
||||
cu.addSource(su);
|
||||
cu.compile(); // $hasGroovyInjection
|
||||
}
|
||||
{
|
||||
CompilationUnit cu = new CompilationUnit();
|
||||
SourceUnit su =
|
||||
new SourceUnit(new URL(request.getParameter("source")), null, null, null);
|
||||
cu.addSource(su);
|
||||
cu.compile(); // $hasGroovyInjection
|
||||
}
|
||||
{
|
||||
CompilationUnit cu = new CompilationUnit();
|
||||
SourceUnit su = SourceUnit.create("test", request.getParameter("source"));
|
||||
cu.addSource(su);
|
||||
cu.compile(); // $hasGroovyInjection
|
||||
}
|
||||
{
|
||||
CompilationUnit cu = new CompilationUnit();
|
||||
SourceUnit su = SourceUnit.create("test", request.getParameter("source"), 0);
|
||||
cu.addSource(su);
|
||||
cu.compile(); // $hasGroovyInjection
|
||||
}
|
||||
{
|
||||
CompilationUnit cu = new CompilationUnit();
|
||||
SourceUnit su = SourceUnit.create(request.getParameter("source"), "safe", 0);
|
||||
cu.addSource(su);
|
||||
cu.compile(); // Safe
|
||||
}
|
||||
{
|
||||
JavaAwareCompilationUnit cu = new JavaAwareCompilationUnit();
|
||||
cu.addSource("test", request.getParameter("source"));
|
||||
cu.compile(); // $hasGroovyInjection
|
||||
}
|
||||
{
|
||||
JavaStubCompilationUnit cu = new JavaStubCompilationUnit(null, null);
|
||||
cu.addSource("test", request.getParameter("source"));
|
||||
cu.compile(); // Safe - JavaStubCompilationUnit only creates stubs
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServlet;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
import groovy.util.Eval;
|
||||
|
||||
public class GroovyEvalTest extends HttpServlet {
|
||||
|
||||
protected void doGet(HttpServletRequest request, HttpServletResponse response)
|
||||
throws ServletException, IOException {
|
||||
// "groovy.util;Eval;false;me;(String);;Argument[0];groovy",
|
||||
{
|
||||
String script = request.getParameter("script");
|
||||
Eval.me(script); // $hasGroovyInjection
|
||||
}
|
||||
// "groovy.util;Eval;false;me;(String,Object,String);;Argument[2];groovy",
|
||||
{
|
||||
String script = request.getParameter("script");
|
||||
Eval.me("test", "result", script); // $hasGroovyInjection
|
||||
}
|
||||
// "groovy.util;Eval;false;x;(Object,String);;Argument[1];groovy",
|
||||
{
|
||||
String script = request.getParameter("script");
|
||||
Eval.x("result2", script); // $hasGroovyInjection
|
||||
|
||||
}
|
||||
// "groovy.util;Eval;false;xy;(Object,Object,String);;Argument[2];groovy",
|
||||
{
|
||||
String script = request.getParameter("script");
|
||||
Eval.xy("result3", "result4", script); // $hasGroovyInjection
|
||||
}
|
||||
// "groovy.util;Eval;false;xyz;(Object,Object,Object,String);;Argument[3];groovy",
|
||||
{
|
||||
String script = request.getParameter("script");
|
||||
Eval.xyz("result3", "result4", "aaa", script); // $hasGroovyInjection
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
import java
|
||||
import semmle.code.java.dataflow.TaintTracking
|
||||
import semmle.code.java.dataflow.FlowSources
|
||||
import semmle.code.java.security.GroovyInjectionQuery
|
||||
import TestUtilities.InlineExpectationsTest
|
||||
|
||||
class HasGroovyInjectionTest extends InlineExpectationsTest {
|
||||
HasGroovyInjectionTest() { this = "HasGroovyInjectionTest" }
|
||||
|
||||
override string getARelevantTag() { result = "hasGroovyInjection" }
|
||||
|
||||
override predicate hasActualResult(Location location, string element, string tag, string value) {
|
||||
tag = "hasGroovyInjection" and
|
||||
exists(DataFlow::Node src, DataFlow::Node sink, GroovyInjectionConfig conf |
|
||||
conf.hasFlow(src, sink)
|
||||
|
|
||||
sink.getLocation() = location and
|
||||
element = sink.toString() and
|
||||
value = ""
|
||||
)
|
||||
}
|
||||
}
|
||||
154
java/ql/test/query-tests/security/CWE-094/GroovyShellTest.java
Normal file
154
java/ql/test/query-tests/security/CWE-094/GroovyShellTest.java
Normal file
@@ -0,0 +1,154 @@
|
||||
import java.io.IOException;
|
||||
import java.io.Reader;
|
||||
import java.io.StringReader;
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
import java.util.ArrayList;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServlet;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import groovy.lang.GroovyCodeSource;
|
||||
import groovy.lang.GroovyShell;
|
||||
|
||||
public class GroovyShellTest extends HttpServlet {
|
||||
|
||||
protected void doGet(HttpServletRequest request, HttpServletResponse response)
|
||||
throws ServletException, IOException {
|
||||
|
||||
// "groovy.lang;GroovyShell;false;evaluate;(GroovyCodeSource);;Argument[0];groovy",
|
||||
{
|
||||
GroovyShell shell = new GroovyShell();
|
||||
String script = request.getParameter("script");
|
||||
GroovyCodeSource gcs = new GroovyCodeSource(script, "test", "Test");
|
||||
shell.evaluate(gcs); // $hasGroovyInjection
|
||||
}
|
||||
// "groovy.lang;GroovyShell;false;evaluate;(Reader);;Argument[0];groovy",
|
||||
{
|
||||
GroovyShell shell = new GroovyShell();
|
||||
String script = request.getParameter("script");
|
||||
Reader reader = new StringReader(script);
|
||||
shell.evaluate(reader); // $hasGroovyInjection
|
||||
}
|
||||
// "groovy.lang;GroovyShell;false;evaluate;(Reader,String);;Argument[0];groovy",
|
||||
{
|
||||
GroovyShell shell = new GroovyShell();
|
||||
String script = request.getParameter("script");
|
||||
Reader reader = new StringReader(script);
|
||||
shell.evaluate(reader, "_"); // $hasGroovyInjection
|
||||
}
|
||||
// "groovy.lang;GroovyShell;false;evaluate;(String);;Argument[0];groovy",
|
||||
{
|
||||
GroovyShell shell = new GroovyShell();
|
||||
String script = request.getParameter("script");
|
||||
shell.evaluate(script); // $hasGroovyInjection
|
||||
}
|
||||
// "groovy.lang;GroovyShell;false;evaluate;(String,String);;Argument[0];groovy",
|
||||
{
|
||||
GroovyShell shell = new GroovyShell();
|
||||
String script = request.getParameter("script");
|
||||
shell.evaluate(script, "test"); // $hasGroovyInjection
|
||||
}
|
||||
// "groovy.lang;GroovyShell;false;evaluate;(String,String,String);;Argument[0];groovy",
|
||||
{
|
||||
GroovyShell shell = new GroovyShell();
|
||||
String script = request.getParameter("script");
|
||||
shell.evaluate(script, "test", "test2"); // $hasGroovyInjection
|
||||
}
|
||||
// "groovy.lang;GroovyShell;false;evaluate;(URI);;Argument[0];groovy",
|
||||
try {
|
||||
GroovyShell shell = new GroovyShell();
|
||||
String script = request.getParameter("script");
|
||||
shell.parse(new URI(script)); // $hasGroovyInjection
|
||||
} catch (URISyntaxException e) {
|
||||
}
|
||||
// "groovy.lang;GroovyShell;false;parse;(Reader);;Argument[0];groovy",
|
||||
{
|
||||
GroovyShell shell = new GroovyShell();
|
||||
String script = request.getParameter("script");
|
||||
Reader reader = new StringReader(script);
|
||||
shell.parse(reader); // $hasGroovyInjection
|
||||
}
|
||||
// "groovy.lang;GroovyShell;false;parse;(Reader,String);;Argument[0];groovy",
|
||||
{
|
||||
GroovyShell shell = new GroovyShell();
|
||||
String script = request.getParameter("script");
|
||||
Reader reader = new StringReader(script);
|
||||
shell.parse(reader, "_"); // $hasGroovyInjection
|
||||
}
|
||||
// "groovy.lang;GroovyShell;false;parse;(String);;Argument[0];groovy",
|
||||
{
|
||||
GroovyShell shell = new GroovyShell();
|
||||
String script = request.getParameter("script");
|
||||
shell.parse(script); // $hasGroovyInjection
|
||||
}
|
||||
// "groovy.lang;GroovyShell;false;parse;(String,String);;Argument[0];groovy",
|
||||
{
|
||||
GroovyShell shell = new GroovyShell();
|
||||
String script = request.getParameter("script");
|
||||
shell.parse(script, "_"); // $hasGroovyInjection
|
||||
}
|
||||
// "groovy.lang;GroovyShell;false;parse;(URI);;Argument[0];groovy",
|
||||
try {
|
||||
GroovyShell shell = new GroovyShell();
|
||||
String script = request.getParameter("script");
|
||||
shell.parse(new URI(script)); // $hasGroovyInjection
|
||||
} catch (URISyntaxException e) {
|
||||
}
|
||||
// "groovy.lang;GroovyShell;false;run;(GroovyCodeSource,String[]);;Argument[0];groovy",
|
||||
{
|
||||
GroovyShell shell = new GroovyShell();
|
||||
String script = request.getParameter("script");
|
||||
GroovyCodeSource gcs = new GroovyCodeSource(script, "test", "Test");
|
||||
shell.run(gcs, new String[] {}); // $hasGroovyInjection
|
||||
}
|
||||
// "groovy.lang;GroovyShell;false;run;(GroovyCodeSource,List);;Argument[0];groovy",
|
||||
{
|
||||
GroovyShell shell = new GroovyShell();
|
||||
String script = request.getParameter("script");
|
||||
GroovyCodeSource gcs = new GroovyCodeSource(script, "test", "Test");
|
||||
shell.run(gcs, new ArrayList<String>()); // $hasGroovyInjection
|
||||
}
|
||||
// "groovy.lang;GroovyShell;false;run;(Reader,String,String[]);;Argument[0];groovy",
|
||||
{
|
||||
GroovyShell shell = new GroovyShell();
|
||||
String script = request.getParameter("script");
|
||||
Reader reader = new StringReader(script);
|
||||
shell.run(reader, "test", new String[] {}); // $hasGroovyInjection
|
||||
}
|
||||
// "groovy.lang;GroovyShell;false;run;(Reader,String,List);;Argument[0];groovy",
|
||||
{
|
||||
GroovyShell shell = new GroovyShell();
|
||||
String script = request.getParameter("script");
|
||||
Reader reader = new StringReader(script);
|
||||
shell.run(reader, "test", new ArrayList<String>()); // $hasGroovyInjection
|
||||
}
|
||||
// "groovy.lang;GroovyShell;false;run;(String,String,String[]);;Argument[0];groovy",
|
||||
{
|
||||
GroovyShell shell = new GroovyShell();
|
||||
String script = request.getParameter("script");
|
||||
shell.run(script, "_", new String[] {}); // $hasGroovyInjection
|
||||
}
|
||||
// "groovy.lang;GroovyShell;false;run;(String,String,List);;Argument[0];groovy",
|
||||
{
|
||||
GroovyShell shell = new GroovyShell();
|
||||
String script = request.getParameter("script");
|
||||
shell.run(script, "_", new ArrayList<String>()); // $hasGroovyInjection
|
||||
}
|
||||
// "groovy.lang;GroovyShell;false;run;(URI,String[]);;Argument[0];groovy",
|
||||
try {
|
||||
GroovyShell shell = new GroovyShell();
|
||||
String script = request.getParameter("script");
|
||||
shell.run(new URI(script), new String[] {}); // $hasGroovyInjection
|
||||
} catch (URISyntaxException e) {
|
||||
}
|
||||
// "groovy.lang;GroovyShell;false;run;(URI,List);;Argument[0];groovy",
|
||||
try {
|
||||
GroovyShell shell = new GroovyShell();
|
||||
String script = request.getParameter("script");
|
||||
shell.run(new URI(script), new ArrayList<String>()); // $hasGroovyInjection
|
||||
} catch (URISyntaxException e) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1 +1 @@
|
||||
//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:${testdir}/../../../stubs/mvel2-2.4.7:${testdir}/../../../stubs/scriptengine:${testdir}/../../../stubs/jsr223-api
|
||||
//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:${testdir}/../../../stubs/mvel2-2.4.7:${testdir}/../../../stubs/groovy-all-3.0.7:${testdir}/../../../stubs/servlet-api-2.4:${testdir}/../../../stubs/scriptengine:${testdir}/../../../stubs/jsr223-api
|
||||
|
||||
@@ -1,10 +1,15 @@
|
||||
edges
|
||||
| HttpsUrlsTest.java:23:23:23:31 | "http://" : String | HttpsUrlsTest.java:24:21:24:56 | ... + ... : String |
|
||||
| HttpsUrlsTest.java:23:23:23:31 | "http://" : String | HttpsUrlsTest.java:28:50:28:50 | u |
|
||||
| HttpsUrlsTest.java:24:13:24:57 | new URL(...) : URL | HttpsUrlsTest.java:28:50:28:50 | u |
|
||||
| HttpsUrlsTest.java:24:21:24:56 | ... + ... : String | HttpsUrlsTest.java:24:13:24:57 | new URL(...) : URL |
|
||||
| HttpsUrlsTest.java:36:23:36:28 | "http" : String | HttpsUrlsTest.java:41:50:41:50 | u |
|
||||
| HttpsUrlsTest.java:49:23:49:31 | "http://" : String | HttpsUrlsTest.java:55:50:55:50 | u |
|
||||
| HttpsUrlsTest.java:87:23:87:28 | "http" : String | HttpsUrlsTest.java:92:50:92:50 | u |
|
||||
nodes
|
||||
| HttpsUrlsTest.java:23:23:23:31 | "http://" : String | semmle.label | "http://" : String |
|
||||
| HttpsUrlsTest.java:24:13:24:57 | new URL(...) : URL | semmle.label | new URL(...) : URL |
|
||||
| HttpsUrlsTest.java:24:21:24:56 | ... + ... : String | semmle.label | ... + ... : String |
|
||||
| HttpsUrlsTest.java:28:50:28:50 | u | semmle.label | u |
|
||||
| HttpsUrlsTest.java:36:23:36:28 | "http" : String | semmle.label | "http" : String |
|
||||
| HttpsUrlsTest.java:41:50:41:50 | u | semmle.label | u |
|
||||
|
||||
@@ -0,0 +1,141 @@
|
||||
import io.jsonwebtoken.Header;
|
||||
import io.jsonwebtoken.Jws;
|
||||
import io.jsonwebtoken.Jwt;
|
||||
import io.jsonwebtoken.JwtHandlerAdapter;
|
||||
import io.jsonwebtoken.JwtParser;
|
||||
import io.jsonwebtoken.Jwts;
|
||||
import io.jsonwebtoken.impl.DefaultJwtParser;
|
||||
import io.jsonwebtoken.impl.DefaultJwtParserBuilder;
|
||||
|
||||
public class MissingJWTSignatureCheckTest {
|
||||
|
||||
private JwtParser getASignedParser() {
|
||||
return Jwts.parser().setSigningKey("someBase64EncodedKey");
|
||||
}
|
||||
|
||||
private JwtParser getASignedParserFromParserBuilder() {
|
||||
return Jwts.parserBuilder().setSigningKey("someBase64EncodedKey").build();
|
||||
}
|
||||
|
||||
private JwtParser getASignedNewParser() {
|
||||
return new DefaultJwtParser().setSigningKey("someBase64EncodedKey");
|
||||
}
|
||||
|
||||
private void callSignedParsers() {
|
||||
JwtParser parser1 = getASignedParser();
|
||||
badJwtOnParserBuilder(parser1, "");
|
||||
badJwtHandlerOnParserBuilder(parser1, "");
|
||||
goodJwtOnParserBuilder(parser1, "");
|
||||
goodJwtHandler(parser1, "");
|
||||
|
||||
JwtParser parser2 = getASignedParserFromParserBuilder();
|
||||
badJwtOnParserBuilder(parser2, "");
|
||||
badJwtHandlerOnParserBuilder(parser2, "");
|
||||
goodJwtOnParserBuilder(parser2, "");
|
||||
goodJwtHandler(parser2, "");
|
||||
|
||||
JwtParser parser3 = getASignedNewParser();
|
||||
badJwtOnParserBuilder(parser3, "");
|
||||
badJwtHandlerOnParserBuilder(parser3, "");
|
||||
goodJwtOnParserBuilder(parser3, "");
|
||||
goodJwtHandler(parser3, "");
|
||||
}
|
||||
|
||||
private JwtParser getAnUnsignedParser() {
|
||||
return Jwts.parser();
|
||||
}
|
||||
|
||||
private JwtParser getAnUnsignedParserFromParserBuilder() {
|
||||
return Jwts.parserBuilder().build();
|
||||
}
|
||||
|
||||
private JwtParser getAnUnsignedNewParser() {
|
||||
return new DefaultJwtParser();
|
||||
}
|
||||
|
||||
private void callUnsignedParsers() {
|
||||
JwtParser parser1 = getAnUnsignedParser();
|
||||
badJwtOnParserBuilder(parser1, "");
|
||||
badJwtHandlerOnParserBuilder(parser1, "");
|
||||
goodJwtOnParserBuilder(parser1, "");
|
||||
goodJwtHandler(parser1, "");
|
||||
|
||||
JwtParser parser2 = getAnUnsignedParserFromParserBuilder();
|
||||
badJwtOnParserBuilder(parser2, "");
|
||||
badJwtHandlerOnParserBuilder(parser2, "");
|
||||
goodJwtOnParserBuilder(parser2, "");
|
||||
goodJwtHandler(parser2, "");
|
||||
|
||||
JwtParser parser3 = getAnUnsignedNewParser();
|
||||
badJwtOnParserBuilder(parser3, "");
|
||||
badJwtHandlerOnParserBuilder(parser3, "");
|
||||
goodJwtOnParserBuilder(parser3, "");
|
||||
goodJwtHandler(parser3, "");
|
||||
}
|
||||
|
||||
private void signParserAfterParseCall() {
|
||||
JwtParser parser = getAnUnsignedParser();
|
||||
parser.parse(""); // Safe
|
||||
parser.setSigningKey("someBase64EncodedKey");
|
||||
}
|
||||
|
||||
private void badJwtOnParserBuilder(JwtParser parser, String token) {
|
||||
parser.parse(token); // $hasMissingJwtSignatureCheck
|
||||
}
|
||||
|
||||
private void badJwtHandlerOnParserBuilder(JwtParser parser, String token) {
|
||||
parser.parse(token, new JwtHandlerAdapter<Jwt<Header, String>>() { // $hasMissingJwtSignatureCheck
|
||||
@Override
|
||||
public Jwt<Header, String> onPlaintextJwt(Jwt<Header, String> jwt) {
|
||||
return jwt;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void goodJwtOnParserBuilder(JwtParser parser, String token) {
|
||||
parser.parseClaimsJws(token) // Safe
|
||||
.getBody();
|
||||
}
|
||||
|
||||
private void goodJwtHandler(JwtParser parser, String token) {
|
||||
parser.parse(token, new JwtHandlerAdapter<Jws<String>>() { // Safe
|
||||
@Override
|
||||
public Jws<String> onPlaintextJws(Jws<String> jws) {
|
||||
return jws;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void badJwtOnParserBuilder(String token) {
|
||||
Jwts.parserBuilder().setSigningKey("someBase64EncodedKey").build().parse(token); // $hasMissingJwtSignatureCheck
|
||||
}
|
||||
|
||||
private void badJwtOnDefaultParserBuilder(String token) {
|
||||
new DefaultJwtParserBuilder().setSigningKey("someBase64EncodedKey").build().parse(token); // $hasMissingJwtSignatureCheck
|
||||
}
|
||||
|
||||
private void badJwtHandlerOnParser(String token) {
|
||||
Jwts.parser().setSigningKey("someBase64EncodedKey").parse(token, // $hasMissingJwtSignatureCheck
|
||||
new JwtHandlerAdapter<Jwt<Header, String>>() {
|
||||
@Override
|
||||
public Jwt<Header, String> onPlaintextJwt(Jwt<Header, String> jwt) {
|
||||
return jwt;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void goodJwtOnParser(String token) {
|
||||
Jwts.parser().setSigningKey("someBase64EncodedKey").parseClaimsJws(token) // Safe
|
||||
.getBody();
|
||||
}
|
||||
|
||||
private void goodJwtHandlerOnParserBuilder(String token) {
|
||||
Jwts.parserBuilder().setSigningKey("someBase64EncodedKey").build().parse(token, // Safe
|
||||
new JwtHandlerAdapter<Jws<String>>() {
|
||||
@Override
|
||||
public Jws<String> onPlaintextJws(Jws<String> jws) {
|
||||
return jws;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
import java
|
||||
import semmle.code.java.security.MissingJWTSignatureCheckQuery
|
||||
import TestUtilities.InlineExpectationsTest
|
||||
|
||||
class HasMissingJwtSignatureCheckTest extends InlineExpectationsTest {
|
||||
HasMissingJwtSignatureCheckTest() { this = "HasMissingJwtSignatureCheckTest" }
|
||||
|
||||
override string getARelevantTag() { result = "hasMissingJwtSignatureCheck" }
|
||||
|
||||
override predicate hasActualResult(Location location, string element, string tag, string value) {
|
||||
tag = "hasMissingJwtSignatureCheck" and
|
||||
exists(DataFlow::Node source, DataFlow::Node sink, MissingJwtSignatureCheckConf conf |
|
||||
conf.hasFlow(source, sink)
|
||||
|
|
||||
sink.getLocation() = location and
|
||||
element = sink.toString() and
|
||||
value = ""
|
||||
)
|
||||
}
|
||||
}
|
||||
1
java/ql/test/query-tests/security/CWE-347/options
Normal file
1
java/ql/test/query-tests/security/CWE-347/options
Normal file
@@ -0,0 +1 @@
|
||||
semmle-extractor-options: --javac-args -cp ${testdir}/../../../stubs/jwtk-jjwt-0.11.2
|
||||
121
java/ql/test/query-tests/security/CWE-502/JabsorbServlet.java
Normal file
121
java/ql/test/query-tests/security/CWE-502/JabsorbServlet.java
Normal file
@@ -0,0 +1,121 @@
|
||||
import java.io.IOException;
|
||||
|
||||
import javax.servlet.http.HttpServlet;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.json.JSONObject;
|
||||
import org.jabsorb.JSONSerializer;
|
||||
import org.jabsorb.serializer.SerializerState;
|
||||
import org.jabsorb.serializer.ObjectMatch;
|
||||
|
||||
import com.example.User;
|
||||
import com.thirdparty.Person;
|
||||
|
||||
public class JabsorbServlet extends HttpServlet {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@Override
|
||||
// GOOD: final class type specified
|
||||
public void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException {
|
||||
String json = req.getParameter("json");
|
||||
String clazz = req.getParameter("class");
|
||||
|
||||
try {
|
||||
Object jsonObject = new JSONObject(json);
|
||||
|
||||
JSONSerializer serializer = new JSONSerializer();
|
||||
serializer.registerDefaultSerializers();
|
||||
|
||||
serializer.setMarshallClassHints(true);
|
||||
serializer.setMarshallNullAttributes(true);
|
||||
|
||||
SerializerState state = new SerializerState();
|
||||
User user = (User) serializer.unmarshall(state, User.class, jsonObject);
|
||||
} catch (Exception e) {
|
||||
throw new IOException(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
// GOOD: concrete class type specified even if it has vulnerable subclasses
|
||||
public void doHead(HttpServletRequest req, HttpServletResponse resp) throws IOException {
|
||||
String json = req.getParameter("json");
|
||||
String clazz = req.getParameter("class");
|
||||
|
||||
try {
|
||||
Object jsonObject = new JSONObject(json);
|
||||
|
||||
JSONSerializer serializer = new JSONSerializer();
|
||||
serializer.registerDefaultSerializers();
|
||||
|
||||
serializer.setMarshallClassHints(true);
|
||||
serializer.setMarshallNullAttributes(true);
|
||||
|
||||
SerializerState state = new SerializerState();
|
||||
Person person = (Person) serializer.unmarshall(state, Person.class, jsonObject);
|
||||
} catch (Exception e) {
|
||||
throw new IOException(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
// GOOD: try unmarshall but doesn't actually marshall the object
|
||||
public void doPost(HttpServletRequest req, HttpServletResponse resp) throws IOException {
|
||||
String json = req.getParameter("json");
|
||||
String clazz = req.getParameter("class");
|
||||
|
||||
try {
|
||||
Object jsonObject = new JSONObject(json);
|
||||
|
||||
JSONSerializer serializer = new JSONSerializer();
|
||||
serializer.registerDefaultSerializers();
|
||||
|
||||
serializer.setMarshallClassHints(true);
|
||||
serializer.setMarshallNullAttributes(true);
|
||||
|
||||
SerializerState state = new SerializerState();
|
||||
ObjectMatch objMatch = serializer.tryUnmarshall(state, Class.forName(clazz), jsonObject);
|
||||
User obj = new User();
|
||||
boolean result = objMatch.equals(obj);
|
||||
} catch (Exception e) {
|
||||
throw new IOException(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
// BAD: allow class name to be controlled by remote source
|
||||
public void doPut(HttpServletRequest req, HttpServletResponse resp) throws IOException {
|
||||
String json = req.getParameter("json");
|
||||
String clazz = req.getParameter("class");
|
||||
|
||||
try {
|
||||
Object jsonObject = new JSONObject(json);
|
||||
|
||||
JSONSerializer serializer = new JSONSerializer();
|
||||
serializer.registerDefaultSerializers();
|
||||
|
||||
serializer.setMarshallClassHints(true);
|
||||
serializer.setMarshallNullAttributes(true);
|
||||
|
||||
SerializerState state = new SerializerState();
|
||||
User user = (User) serializer.unmarshall(state, Class.forName(clazz), jsonObject); // $unsafeDeserialization
|
||||
} catch (Exception e) {
|
||||
throw new IOException(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
// BAD: allow explicit class type controlled by remote source in the format of "json={\"javaClass\":\"com.thirdparty.Attacker\", ...}"
|
||||
public void doPut2(HttpServletRequest req, HttpServletResponse resp) throws IOException {
|
||||
String json = req.getParameter("json");
|
||||
|
||||
try {
|
||||
JSONSerializer serializer = new JSONSerializer();
|
||||
serializer.registerDefaultSerializers();
|
||||
|
||||
User user = (User) serializer.fromJSON(json); // $unsafeDeserialization
|
||||
} catch (Exception e) {
|
||||
throw new IOException(e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
102
java/ql/test/query-tests/security/CWE-502/JoddJsonServlet.java
Normal file
102
java/ql/test/query-tests/security/CWE-502/JoddJsonServlet.java
Normal file
@@ -0,0 +1,102 @@
|
||||
import java.io.IOException;
|
||||
import java.io.Reader;
|
||||
|
||||
import javax.servlet.http.HttpServlet;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import jodd.json.JsonParser;
|
||||
|
||||
import com.example.User;
|
||||
import com.thirdparty.Person;
|
||||
|
||||
public class JoddJsonServlet extends HttpServlet {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@Override
|
||||
// GOOD: class type specified (despite a dangerous configuration)
|
||||
public void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException {
|
||||
String json = req.getParameter("json");
|
||||
String clazz = req.getParameter("class");
|
||||
|
||||
JsonParser parser = new JsonParser();
|
||||
parser.setClassMetadataName("class");
|
||||
Person person = parser.parse(json, Person.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
// BAD: dangerously configured parser with no class restriction passed to `parse`,
|
||||
// using a few different possible call sequences.
|
||||
public void doHead(HttpServletRequest req, HttpServletResponse resp) throws IOException {
|
||||
String json = req.getParameter("json");
|
||||
String clazz = req.getParameter("class");
|
||||
int callOrder;
|
||||
try {
|
||||
callOrder = Integer.parseInt(req.getParameter("callOrder"));
|
||||
}
|
||||
catch(NumberFormatException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
|
||||
JsonParser parser = new JsonParser();
|
||||
if(callOrder == 0) {
|
||||
parser.setClassMetadataName("class");
|
||||
User obj = parser.parse(json, null); // $unsafeDeserialization
|
||||
} else if(callOrder == 1) {
|
||||
parser.setClassMetadataName("class").parse(json, null); // $unsafeDeserialization
|
||||
} else if(callOrder == 2) {
|
||||
parser.setClassMetadataName("class").lazy(true).parse(json, null); // $unsafeDeserialization
|
||||
} else if(callOrder == 3) {
|
||||
parser.withClassMetadata(true).lazy(true).parse(json, null); // $unsafeDeserialization
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
// BAD: allow class name to be controlled by remote source
|
||||
public void doPost(HttpServletRequest req, HttpServletResponse resp) throws IOException {
|
||||
String json = req.getParameter("json");
|
||||
String clazz = req.getParameter("class");
|
||||
|
||||
try {
|
||||
JsonParser parser = new JsonParser();
|
||||
Object obj = parser.parse(json, Class.forName(clazz)); // $unsafeDeserialization
|
||||
} catch (ClassNotFoundException cne) {
|
||||
throw new IOException(cne.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
// GOOD: dangerously configured parser is ameliorated by setting a list of allowed classes, using various call orders,
|
||||
// or by explicitly disabling the class metadata option.
|
||||
public void doPut(HttpServletRequest req, HttpServletResponse resp) throws IOException {
|
||||
String json = req.getParameter("json");
|
||||
String clazz = req.getParameter("class");
|
||||
int callOrder;
|
||||
try {
|
||||
callOrder = Integer.parseInt(req.getParameter("callOrder"));
|
||||
}
|
||||
catch(NumberFormatException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
|
||||
JsonParser parser = new JsonParser();
|
||||
if(callOrder == 0) {
|
||||
parser.setClassMetadataName("class");
|
||||
parser.allowClass("example.Class");
|
||||
User obj = parser.parse(json, null);
|
||||
} else if(callOrder == 1) {
|
||||
parser.allowClass("example.Class");
|
||||
parser.setClassMetadataName("class");
|
||||
User obj = parser.parse(json, null);
|
||||
} else if(callOrder == 2) {
|
||||
parser.setClassMetadataName("class").allowClass("example.Class").parse(json, null);
|
||||
} else if(callOrder == 3) {
|
||||
parser.allowClass("example.Class").setClassMetadataName("class").parse(json, null);
|
||||
} else if(callOrder == 4) {
|
||||
parser.setClassMetadataName("class").withClassMetadata(false).parse(json, null);
|
||||
} else if(callOrder == 5) {
|
||||
parser.withClassMetadata(true).setClassMetadataName(null).parse(json, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
package com.example;
|
||||
|
||||
public final class User {
|
||||
private String uid;
|
||||
private String name;
|
||||
|
||||
public User() {
|
||||
}
|
||||
|
||||
public String getUid() {
|
||||
return uid;
|
||||
}
|
||||
|
||||
public void setUid(String uid) {
|
||||
this.uid = uid;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return "User[ name = "+name+", uid: "+uid+ "]";
|
||||
}
|
||||
}
|
||||
29
java/ql/test/query-tests/security/CWE-502/com/thirdparty/Person.java
vendored
Normal file
29
java/ql/test/query-tests/security/CWE-502/com/thirdparty/Person.java
vendored
Normal file
@@ -0,0 +1,29 @@
|
||||
package com.thirdparty;
|
||||
|
||||
public class Person {
|
||||
private int snum;
|
||||
private String name;
|
||||
|
||||
public Person() {
|
||||
}
|
||||
|
||||
public int getSnum() {
|
||||
return snum;
|
||||
}
|
||||
|
||||
public void setSnum(int snum) {
|
||||
this.snum = snum;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return "Person[ name = "+name+", snum: "+snum+ "]";
|
||||
}
|
||||
}
|
||||
@@ -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.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:${testdir}/../../../stubs/jackson-databind-2.10
|
||||
//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:${testdir}/../../../stubs/jackson-databind-2.12:${testdir}/../../../stubs/jackson-core-2.12:${testdir}/../../../stubs/jabsorb-1.3.2:${testdir}/../../../stubs/json-java-20210307:${testdir}/../../../stubs/joddjson-6.0.3
|
||||
|
||||
51
java/ql/test/query-tests/security/CWE-749/AndroidManifest.xml
Executable file
51
java/ql/test/query-tests/security/CWE-749/AndroidManifest.xml
Executable file
@@ -0,0 +1,51 @@
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="com.example.app"
|
||||
android:installLocation="auto"
|
||||
android:versionCode="1"
|
||||
android:versionName="0.1" >
|
||||
|
||||
<uses-permission android:name="android.permission.INTERNET" />
|
||||
|
||||
<application
|
||||
android:icon="@drawable/ic_launcher"
|
||||
android:label="@string/app_name"
|
||||
android:theme="@style/AppTheme" >
|
||||
<activity
|
||||
android:name=".UnsafeAndroidAccess"
|
||||
android:icon="@drawable/ic_launcher"
|
||||
android:label="@string/app_name">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
<category android:name="android.intent.category.LAUNCHER" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
|
||||
<activity android:name=".UnsafeActivity1" android:exported="true">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.VIEW"/>
|
||||
</intent-filter>
|
||||
</activity>
|
||||
|
||||
<activity android:name=".UnsafeActivity2">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.VIEW"/>
|
||||
</intent-filter>
|
||||
</activity>
|
||||
|
||||
<activity android:name=".SafeActivity1" android:exported="false">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.VIEW"/>
|
||||
</intent-filter>
|
||||
</activity>
|
||||
|
||||
<activity android:name=".SafeActivity2" android:exported="false" />
|
||||
|
||||
<activity android:name=".SafeActivity3" />
|
||||
|
||||
<activity android:name=".UnsafeActivity3" android:exported="true" />
|
||||
<activity android:name=".UnsafeActivity4" android:exported="true" />
|
||||
|
||||
<receiver android:name=".UnsafeAndroidBroadcastReceiver" android:exported="true" />
|
||||
</application>
|
||||
|
||||
</manifest>
|
||||
24
java/ql/test/query-tests/security/CWE-749/IntentUtils.java
Normal file
24
java/ql/test/query-tests/security/CWE-749/IntentUtils.java
Normal file
@@ -0,0 +1,24 @@
|
||||
package com.example.app;
|
||||
|
||||
import android.app.Activity;
|
||||
|
||||
import android.os.Bundle;
|
||||
|
||||
import android.webkit.WebSettings;
|
||||
import android.webkit.WebView;
|
||||
import android.webkit.WebViewClient;
|
||||
|
||||
/** A utility program for getting intent extra information from Android activity */
|
||||
public class IntentUtils {
|
||||
/** Get intent extra */
|
||||
public static String getIntentUrl(Activity a) {
|
||||
String thisUrl = a.getIntent().getStringExtra("url");
|
||||
return thisUrl;
|
||||
}
|
||||
|
||||
/** Get bundle extra */
|
||||
public static String getBundleUrl(Activity a) {
|
||||
String thisUrl = a.getIntent().getExtras().getString("url");
|
||||
return thisUrl;
|
||||
}
|
||||
}
|
||||
36
java/ql/test/query-tests/security/CWE-749/SafeActivity1.java
Normal file
36
java/ql/test/query-tests/security/CWE-749/SafeActivity1.java
Normal file
@@ -0,0 +1,36 @@
|
||||
package com.example.app;
|
||||
|
||||
import android.app.Activity;
|
||||
|
||||
import android.os.Bundle;
|
||||
|
||||
import android.webkit.WebSettings;
|
||||
import android.webkit.WebView;
|
||||
import android.webkit.WebViewClient;
|
||||
|
||||
public class SafeActivity1 extends Activity {
|
||||
// Test onCreate with both JavaScript and cross-origin resource access enabled while taking
|
||||
// remote user inputs from bundle extras.
|
||||
// The Activity is explicitly not exported, even though it has an intent-filter.
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(-1);
|
||||
|
||||
WebView wv = (WebView) findViewById(-1);
|
||||
WebSettings webSettings = wv.getSettings();
|
||||
|
||||
webSettings.setJavaScriptEnabled(true);
|
||||
webSettings.setAllowFileAccessFromFileURLs(true);
|
||||
|
||||
wv.setWebViewClient(new WebViewClient() {
|
||||
@Override
|
||||
public boolean shouldOverrideUrlLoading(WebView view, String url) {
|
||||
view.loadUrl(url);
|
||||
return true;
|
||||
}
|
||||
});
|
||||
|
||||
String thisUrl = getIntent().getExtras().getString("url");
|
||||
wv.loadUrl(thisUrl); // Safe
|
||||
}
|
||||
}
|
||||
36
java/ql/test/query-tests/security/CWE-749/SafeActivity2.java
Normal file
36
java/ql/test/query-tests/security/CWE-749/SafeActivity2.java
Normal file
@@ -0,0 +1,36 @@
|
||||
package com.example.app;
|
||||
|
||||
import android.app.Activity;
|
||||
|
||||
import android.os.Bundle;
|
||||
|
||||
import android.webkit.WebSettings;
|
||||
import android.webkit.WebView;
|
||||
import android.webkit.WebViewClient;
|
||||
|
||||
public class SafeActivity2 extends Activity {
|
||||
// Test onCreate with both JavaScript and cross-origin resource access enabled while taking
|
||||
// remote user inputs from bundle extras.
|
||||
// The Activity is explicitly not exported.
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(-1);
|
||||
|
||||
WebView wv = (WebView) findViewById(-1);
|
||||
WebSettings webSettings = wv.getSettings();
|
||||
|
||||
webSettings.setJavaScriptEnabled(true);
|
||||
webSettings.setAllowFileAccessFromFileURLs(true);
|
||||
|
||||
wv.setWebViewClient(new WebViewClient() {
|
||||
@Override
|
||||
public boolean shouldOverrideUrlLoading(WebView view, String url) {
|
||||
view.loadUrl(url);
|
||||
return true;
|
||||
}
|
||||
});
|
||||
|
||||
String thisUrl = getIntent().getExtras().getString("url");
|
||||
wv.loadUrl(thisUrl); // Safe
|
||||
}
|
||||
}
|
||||
36
java/ql/test/query-tests/security/CWE-749/SafeActivity3.java
Normal file
36
java/ql/test/query-tests/security/CWE-749/SafeActivity3.java
Normal file
@@ -0,0 +1,36 @@
|
||||
package com.example.app;
|
||||
|
||||
import android.app.Activity;
|
||||
|
||||
import android.os.Bundle;
|
||||
|
||||
import android.webkit.WebSettings;
|
||||
import android.webkit.WebView;
|
||||
import android.webkit.WebViewClient;
|
||||
|
||||
public class SafeActivity3 extends Activity {
|
||||
// Test onCreate with both JavaScript and cross-origin resource access enabled while taking
|
||||
// remote user inputs from bundle extras.
|
||||
// The Activity is implicitly not exported.
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(-1);
|
||||
|
||||
WebView wv = (WebView) findViewById(-1);
|
||||
WebSettings webSettings = wv.getSettings();
|
||||
|
||||
webSettings.setJavaScriptEnabled(true);
|
||||
webSettings.setAllowFileAccessFromFileURLs(true);
|
||||
|
||||
wv.setWebViewClient(new WebViewClient() {
|
||||
@Override
|
||||
public boolean shouldOverrideUrlLoading(WebView view, String url) {
|
||||
view.loadUrl(url);
|
||||
return true;
|
||||
}
|
||||
});
|
||||
|
||||
String thisUrl = getIntent().getExtras().getString("url");
|
||||
wv.loadUrl(thisUrl); // Safe
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
package com.example.app;
|
||||
|
||||
import android.app.Activity;
|
||||
|
||||
import android.os.Bundle;
|
||||
|
||||
import android.webkit.WebSettings;
|
||||
import android.webkit.WebView;
|
||||
import android.webkit.WebViewClient;
|
||||
|
||||
public class UnsafeActivity1 extends Activity {
|
||||
// Test onCreate with both JavaScript and cross-origin resource access enabled while taking
|
||||
// remote user inputs from bundle extras.
|
||||
// The Activity is exported and has an intent-filter.
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(-1);
|
||||
|
||||
WebView wv = (WebView) findViewById(-1);
|
||||
WebSettings webSettings = wv.getSettings();
|
||||
|
||||
webSettings.setJavaScriptEnabled(true);
|
||||
webSettings.setAllowFileAccessFromFileURLs(true);
|
||||
|
||||
wv.setWebViewClient(new WebViewClient() {
|
||||
@Override
|
||||
public boolean shouldOverrideUrlLoading(WebView view, String url) {
|
||||
view.loadUrl(url);
|
||||
return true;
|
||||
}
|
||||
});
|
||||
|
||||
String thisUrl = getIntent().getExtras().getString("url");
|
||||
wv.loadUrl(thisUrl); // $hasUnsafeAndroidAccess
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
package com.example.app;
|
||||
|
||||
import android.app.Activity;
|
||||
|
||||
import android.os.Bundle;
|
||||
|
||||
import android.webkit.WebSettings;
|
||||
import android.webkit.WebView;
|
||||
import android.webkit.WebViewClient;
|
||||
|
||||
public class UnsafeActivity2 extends Activity {
|
||||
// Test onCreate with both JavaScript and cross-origin resource access enabled while taking
|
||||
// remote user inputs from bundle extras.
|
||||
// The Activity is implicitly exported because it has an intent-filter.
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(-1);
|
||||
|
||||
WebView wv = (WebView) findViewById(-1);
|
||||
WebSettings webSettings = wv.getSettings();
|
||||
|
||||
webSettings.setJavaScriptEnabled(true);
|
||||
webSettings.setAllowFileAccessFromFileURLs(true);
|
||||
|
||||
wv.setWebViewClient(new WebViewClient() {
|
||||
@Override
|
||||
public boolean shouldOverrideUrlLoading(WebView view, String url) {
|
||||
view.loadUrl(url);
|
||||
return true;
|
||||
}
|
||||
});
|
||||
|
||||
String thisUrl = getIntent().getExtras().getString("url");
|
||||
wv.loadUrl(thisUrl); // $hasUnsafeAndroidAccess
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
package com.example.app;
|
||||
|
||||
import android.app.Activity;
|
||||
|
||||
import android.os.Bundle;
|
||||
|
||||
import android.webkit.WebSettings;
|
||||
import android.webkit.WebView;
|
||||
import android.webkit.WebViewClient;
|
||||
|
||||
public class UnsafeActivity3 extends Activity {
|
||||
// Test onCreate with both JavaScript and cross-origin resource access enabled while taking
|
||||
// remote user inputs from bundle extras.
|
||||
// The Activity is explicitly exported.
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(-1);
|
||||
|
||||
WebView wv = (WebView) findViewById(-1);
|
||||
WebSettings webSettings = wv.getSettings();
|
||||
|
||||
webSettings.setJavaScriptEnabled(true);
|
||||
webSettings.setAllowFileAccessFromFileURLs(true);
|
||||
|
||||
wv.setWebViewClient(new WebViewClient() {
|
||||
@Override
|
||||
public boolean shouldOverrideUrlLoading(WebView view, String url) {
|
||||
view.loadUrl(url);
|
||||
return true;
|
||||
}
|
||||
});
|
||||
|
||||
String thisUrl = getIntent().getExtras().getString("url");
|
||||
wv.loadUrl(thisUrl); // $hasUnsafeAndroidAccess
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
package com.example.app;
|
||||
|
||||
import android.app.Activity;
|
||||
|
||||
import android.os.Bundle;
|
||||
|
||||
import android.webkit.WebSettings;
|
||||
import android.webkit.WebView;
|
||||
import android.webkit.WebViewClient;
|
||||
|
||||
public class UnsafeActivity4 extends Activity {
|
||||
/*
|
||||
* Test onCreate with both JavaScript and cross-origin resource access enabled while taking
|
||||
* remote user inputs from bundle extras.
|
||||
*
|
||||
* The Activity is explicitly exported.
|
||||
*
|
||||
* Note this case of invoking a utility method that takes an Activity and then calls
|
||||
* `a.getIntent().getStringExtra(...)` is not yet detected thus is beyond what the query is
|
||||
* capable of.
|
||||
*/
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(-1);
|
||||
|
||||
WebView wv = (WebView) findViewById(-1);
|
||||
WebSettings webSettings = wv.getSettings();
|
||||
|
||||
webSettings.setJavaScriptEnabled(true);
|
||||
webSettings.setAllowFileAccessFromFileURLs(true);
|
||||
|
||||
wv.setWebViewClient(new WebViewClient() {
|
||||
@Override
|
||||
public boolean shouldOverrideUrlLoading(WebView view, String url) {
|
||||
view.loadUrl(url);
|
||||
return true;
|
||||
}
|
||||
});
|
||||
|
||||
String thisUrl = IntentUtils.getIntentUrl(this);
|
||||
thisUrl = IntentUtils.getBundleUrl(this);
|
||||
wv.loadUrl(thisUrl); // $ MISSING: hasUnsafeAndroidAccess
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,151 @@
|
||||
package com.example.app;
|
||||
|
||||
import android.app.Activity;
|
||||
|
||||
import android.os.Bundle;
|
||||
|
||||
import android.webkit.WebSettings;
|
||||
import android.webkit.WebView;
|
||||
import android.webkit.WebViewClient;
|
||||
|
||||
// The Activity is implicitly exported because it has an intent-filter.
|
||||
public class UnsafeAndroidAccess extends Activity {
|
||||
// Test onCreate with both JavaScript and cross-origin resource access enabled while taking
|
||||
// remote user inputs from bundle extras
|
||||
public void testOnCreate1(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(-1);
|
||||
|
||||
WebView wv = (WebView) findViewById(-1);
|
||||
WebSettings webSettings = wv.getSettings();
|
||||
|
||||
webSettings.setJavaScriptEnabled(true);
|
||||
webSettings.setAllowFileAccessFromFileURLs(true);
|
||||
|
||||
wv.setWebViewClient(new WebViewClient() {
|
||||
@Override
|
||||
public boolean shouldOverrideUrlLoading(WebView view, String url) {
|
||||
view.loadUrl(url);
|
||||
return true;
|
||||
}
|
||||
});
|
||||
|
||||
String thisUrl = getIntent().getExtras().getString("url");
|
||||
wv.loadUrl(thisUrl); // $hasUnsafeAndroidAccess
|
||||
}
|
||||
|
||||
// Test onCreate with both JavaScript and cross-origin resource access enabled while taking
|
||||
// remote user inputs from string extra
|
||||
public void testOnCreate2(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(-1);
|
||||
|
||||
WebView wv = (WebView) findViewById(-1);
|
||||
WebSettings webSettings = wv.getSettings();
|
||||
|
||||
webSettings.setJavaScriptEnabled(true);
|
||||
webSettings.setAllowFileAccessFromFileURLs(true);
|
||||
|
||||
wv.setWebViewClient(new WebViewClient() {
|
||||
@Override
|
||||
public boolean shouldOverrideUrlLoading(WebView view, String url) {
|
||||
view.loadUrl(url);
|
||||
return true;
|
||||
}
|
||||
});
|
||||
|
||||
String thisUrl = getIntent().getStringExtra("url");
|
||||
wv.loadUrl(thisUrl); // $hasUnsafeAndroidAccess
|
||||
}
|
||||
|
||||
// Test onCreate with both JavaScript and cross-origin resource access disabled by default while
|
||||
// taking remote user inputs
|
||||
public void testOnCreate3(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(-1);
|
||||
|
||||
WebView wv = (WebView) findViewById(-1);
|
||||
WebSettings webSettings = wv.getSettings();
|
||||
|
||||
wv.setWebViewClient(new WebViewClient() {
|
||||
@Override
|
||||
public boolean shouldOverrideUrlLoading(WebView view, String url) {
|
||||
view.loadUrl(url);
|
||||
return true;
|
||||
}
|
||||
});
|
||||
|
||||
String thisUrl = getIntent().getStringExtra("url");
|
||||
wv.loadUrl(thisUrl); // Safe
|
||||
}
|
||||
|
||||
// Test onCreate with JavaScript enabled but cross-origin resource access disabled while taking
|
||||
// remote user inputs
|
||||
public void testOnCreate4(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(-1);
|
||||
|
||||
WebView wv = (WebView) findViewById(-1);
|
||||
WebSettings webSettings = wv.getSettings();
|
||||
|
||||
webSettings.setJavaScriptEnabled(true);
|
||||
|
||||
wv.setWebViewClient(new WebViewClient() {
|
||||
@Override
|
||||
public boolean shouldOverrideUrlLoading(WebView view, String url) {
|
||||
view.loadUrl(url);
|
||||
return true;
|
||||
}
|
||||
});
|
||||
|
||||
String thisUrl = getIntent().getStringExtra("url");
|
||||
wv.loadUrl(thisUrl); // $hasUnsafeAndroidAccess
|
||||
}
|
||||
|
||||
// Test onCreate with both JavaScript and cross-origin resource access enabled while not taking
|
||||
// remote user inputs
|
||||
public void testOnCreate5(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(-1);
|
||||
|
||||
WebView wv = (WebView) findViewById(-1);
|
||||
WebSettings webSettings = wv.getSettings();
|
||||
|
||||
webSettings.setJavaScriptEnabled(true);
|
||||
webSettings.setAllowFileAccessFromFileURLs(true);
|
||||
|
||||
wv.setWebViewClient(new WebViewClient() {
|
||||
@Override
|
||||
public boolean shouldOverrideUrlLoading(WebView view, String url) {
|
||||
view.loadUrl(url);
|
||||
return true;
|
||||
}
|
||||
});
|
||||
|
||||
wv.loadUrl("https://www.mycorp.com"); // Safe
|
||||
}
|
||||
|
||||
// Test onCreate with both JavaScript and cross-origin resource access enabled while taking
|
||||
// remote user inputs and concatenating them to a safe URL.
|
||||
public void testOnCreate6(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(-1);
|
||||
|
||||
WebView wv = (WebView) findViewById(-1);
|
||||
WebSettings webSettings = wv.getSettings();
|
||||
|
||||
webSettings.setJavaScriptEnabled(true);
|
||||
webSettings.setAllowFileAccessFromFileURLs(true);
|
||||
|
||||
wv.setWebViewClient(new WebViewClient() {
|
||||
@Override
|
||||
public boolean shouldOverrideUrlLoading(WebView view, String url) {
|
||||
view.loadUrl(url);
|
||||
return true;
|
||||
}
|
||||
});
|
||||
|
||||
String thisUrl = getIntent().getStringExtra("url");
|
||||
wv.loadUrl("https://www.mycorp.com/" + thisUrl); // Safe
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
import java
|
||||
import semmle.code.java.security.UnsafeAndroidAccessQuery
|
||||
import TestUtilities.InlineExpectationsTest
|
||||
|
||||
class UnsafeAndroidAccessTest extends InlineExpectationsTest {
|
||||
UnsafeAndroidAccessTest() { this = "HasUnsafeAndroidAccess" }
|
||||
|
||||
override string getARelevantTag() { result = "hasUnsafeAndroidAccess" }
|
||||
|
||||
override predicate hasActualResult(Location location, string element, string tag, string value) {
|
||||
tag = "hasUnsafeAndroidAccess" and
|
||||
exists(DataFlow::Node src, DataFlow::Node sink, FetchUntrustedResourceConfiguration conf |
|
||||
conf.hasFlow(src, sink)
|
||||
|
|
||||
sink.getLocation() = location and
|
||||
element = sink.toString() and
|
||||
value = ""
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
package com.example.app;
|
||||
|
||||
import android.app.Activity;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.os.Bundle;
|
||||
import android.webkit.WebSettings;
|
||||
import android.webkit.WebView;
|
||||
import android.webkit.WebViewClient;
|
||||
|
||||
public class UnsafeAndroidBroadcastReceiver extends BroadcastReceiver {
|
||||
// Test onCreate with JavaScript enabled but cross-origin resource access disabled while taking
|
||||
// remote user inputs
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
String thisUrl = intent.getStringExtra("url");
|
||||
WebView wv = null;
|
||||
WebSettings webSettings = wv.getSettings();
|
||||
|
||||
webSettings.setJavaScriptEnabled(true);
|
||||
webSettings.setAllowFileAccessFromFileURLs(true);
|
||||
|
||||
wv.setWebViewClient(new WebViewClient() {
|
||||
@Override
|
||||
public boolean shouldOverrideUrlLoading(WebView view, String url) {
|
||||
view.loadUrl(url);
|
||||
return true;
|
||||
}
|
||||
});
|
||||
|
||||
wv.loadUrl(thisUrl); // $hasUnsafeAndroidAccess
|
||||
}
|
||||
}
|
||||
1
java/ql/test/query-tests/security/CWE-749/options
Normal file
1
java/ql/test/query-tests/security/CWE-749/options
Normal file
@@ -0,0 +1 @@
|
||||
//semmle-extractor-options: --javac-args -cp ${testdir}/../../../stubs/android
|
||||
73
java/ql/test/query-tests/security/CWE-917/OgnlInjection.java
Normal file
73
java/ql/test/query-tests/security/CWE-917/OgnlInjection.java
Normal file
@@ -0,0 +1,73 @@
|
||||
import ognl.Node;
|
||||
import ognl.Ognl;
|
||||
import ognl.enhance.ExpressionAccessor;
|
||||
|
||||
import java.util.HashMap;
|
||||
|
||||
import com.opensymphony.xwork2.ognl.OgnlUtil;
|
||||
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
|
||||
@Controller
|
||||
public class OgnlInjection {
|
||||
@RequestMapping
|
||||
public void testOgnlParseExpression(@RequestParam String expr) throws Exception {
|
||||
Object tree = Ognl.parseExpression(expr);
|
||||
Ognl.getValue(tree, new HashMap<>(), new Object()); // $hasOgnlInjection
|
||||
Ognl.setValue(tree, new HashMap<>(), new Object()); // $hasOgnlInjection
|
||||
|
||||
Node node = (Node) tree;
|
||||
node.getValue(null, new Object()); // $hasOgnlInjection
|
||||
node.setValue(null, new Object(), new Object()); // $hasOgnlInjection
|
||||
}
|
||||
|
||||
@RequestMapping
|
||||
public void testOgnlCompileExpression(@RequestParam String expr) throws Exception {
|
||||
Node tree = Ognl.compileExpression(null, new Object(), expr);
|
||||
Ognl.getValue(tree, new HashMap<>(), new Object()); // $hasOgnlInjection
|
||||
Ognl.setValue(tree, new HashMap<>(), new Object()); // $hasOgnlInjection
|
||||
|
||||
tree.getValue(null, new Object()); // $hasOgnlInjection
|
||||
tree.setValue(null, new Object(), new Object()); // $hasOgnlInjection
|
||||
}
|
||||
|
||||
@RequestMapping
|
||||
public void testOgnlDirectlyToGetSet(@RequestParam String expr) throws Exception {
|
||||
Ognl.getValue(expr, new Object()); // $hasOgnlInjection
|
||||
Ognl.setValue(expr, new Object(), new Object()); // $hasOgnlInjection
|
||||
}
|
||||
|
||||
@RequestMapping
|
||||
public void testStruts(@RequestParam String expr) throws Exception {
|
||||
OgnlUtil ognl = new OgnlUtil();
|
||||
ognl.getValue(expr, new HashMap<>(), new Object()); // $hasOgnlInjection
|
||||
ognl.setValue(expr, new HashMap<>(), new Object(), new Object()); // $hasOgnlInjection
|
||||
new OgnlUtil().callMethod(expr, new HashMap<>(), new Object()); // $hasOgnlInjection
|
||||
}
|
||||
|
||||
@RequestMapping
|
||||
public void testExpressionAccessor(@RequestParam String expr) throws Exception {
|
||||
Node tree = Ognl.compileExpression(null, new Object(), expr);
|
||||
ExpressionAccessor accessor = tree.getAccessor();
|
||||
accessor.get(null, new Object()); // $hasOgnlInjection
|
||||
accessor.set(null, new Object(), new Object()); // $hasOgnlInjection
|
||||
|
||||
Ognl.getValue(accessor, null, new Object()); // $hasOgnlInjection
|
||||
Ognl.setValue(accessor, null, new Object()); // $hasOgnlInjection
|
||||
}
|
||||
|
||||
@RequestMapping
|
||||
public void testExpressionAccessorSetExpression(@RequestParam String expr) throws Exception {
|
||||
Node tree = Ognl.compileExpression(null, new Object(), "\"some safe expression\".toString()");
|
||||
ExpressionAccessor accessor = tree.getAccessor();
|
||||
Node taintedTree = Ognl.compileExpression(null, new Object(), expr);
|
||||
accessor.setExpression(taintedTree);
|
||||
accessor.get(null, new Object()); // $hasOgnlInjection
|
||||
accessor.set(null, new Object(), new Object()); // $hasOgnlInjection
|
||||
|
||||
Ognl.getValue(accessor, null, new Object()); // $hasOgnlInjection
|
||||
Ognl.setValue(accessor, null, new Object()); // $hasOgnlInjection
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
import java
|
||||
import semmle.code.java.security.OgnlInjectionQuery
|
||||
import TestUtilities.InlineExpectationsTest
|
||||
|
||||
class OgnlInjectionTest extends InlineExpectationsTest {
|
||||
OgnlInjectionTest() { this = "HasOgnlInjection" }
|
||||
|
||||
override string getARelevantTag() { result = "hasOgnlInjection" }
|
||||
|
||||
override predicate hasActualResult(Location location, string element, string tag, string value) {
|
||||
tag = "hasOgnlInjection" and
|
||||
exists(DataFlow::Node src, DataFlow::Node sink, OgnlInjectionFlowConfig conf |
|
||||
conf.hasFlow(src, sink)
|
||||
|
|
||||
sink.getLocation() = location and
|
||||
element = sink.toString() and
|
||||
value = ""
|
||||
)
|
||||
}
|
||||
}
|
||||
1
java/ql/test/query-tests/security/CWE-917/options
Normal file
1
java/ql/test/query-tests/security/CWE-917/options
Normal file
@@ -0,0 +1 @@
|
||||
//semmle-extractor-options: --javac-args -cp ${testdir}/../../../stubs/springframework-5.3.8:${testdir}/../../../stubs/ognl-3.2.14:${testdir}/../../../stubs/struts2-core-2.5.22
|
||||
Reference in New Issue
Block a user