mirror of
https://github.com/github/codeql.git
synced 2026-04-28 10:15:14 +02:00
Merge pull request #10352 from atorralba/atorralba/promote-template-injection
Java: Promote Server-side template injection from experimental
This commit is contained in:
117
java/ql/test/query-tests/security/CWE-094/FreemarkerSSTI.java
Normal file
117
java/ql/test/query-tests/security/CWE-094/FreemarkerSSTI.java
Normal file
@@ -0,0 +1,117 @@
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
|
||||
import java.lang.String;
|
||||
import java.io.Reader;
|
||||
import java.io.StringReader;
|
||||
import java.io.OutputStreamWriter;
|
||||
import java.util.HashMap;
|
||||
|
||||
import freemarker.template.Template;
|
||||
import freemarker.template.Configuration;
|
||||
import freemarker.cache.StringTemplateLoader;
|
||||
import freemarker.core.ParserConfiguration;
|
||||
|
||||
@Controller
|
||||
public class FreemarkerSSTI {
|
||||
String sourceName = "sourceName";
|
||||
|
||||
@GetMapping(value = "bad1")
|
||||
public void bad1(HttpServletRequest request) {
|
||||
String name = "ttemplate";
|
||||
String code = request.getParameter("code");
|
||||
Reader reader = new StringReader(code);
|
||||
|
||||
Template t = new Template(name, reader); // $hasTemplateInjection
|
||||
}
|
||||
|
||||
@GetMapping(value = "bad2")
|
||||
public void bad2(HttpServletRequest request) {
|
||||
String name = "ttemplate";
|
||||
String code = request.getParameter("code");
|
||||
Reader reader = new StringReader(code);
|
||||
Configuration cfg = new Configuration();
|
||||
|
||||
Template t = new Template(name, reader, cfg); // $hasTemplateInjection
|
||||
}
|
||||
|
||||
@GetMapping(value = "bad3")
|
||||
public void bad3(HttpServletRequest request) {
|
||||
String name = "ttemplate";
|
||||
String code = request.getParameter("code");
|
||||
Reader reader = new StringReader(code);
|
||||
Configuration cfg = new Configuration();
|
||||
|
||||
Template t = new Template(name, reader, cfg, "UTF-8"); // $hasTemplateInjection
|
||||
}
|
||||
|
||||
@GetMapping(value = "bad4")
|
||||
public void bad4(HttpServletRequest request) {
|
||||
String name = "ttemplate";
|
||||
String sourceCode = request.getParameter("sourceCode");
|
||||
Configuration cfg = new Configuration();
|
||||
|
||||
Template t = new Template(name, sourceCode, cfg); // $hasTemplateInjection
|
||||
}
|
||||
|
||||
@GetMapping(value = "bad5")
|
||||
public void bad5(HttpServletRequest request) {
|
||||
String name = "ttemplate";
|
||||
String code = request.getParameter("code");
|
||||
Configuration cfg = new Configuration();
|
||||
Reader reader = new StringReader(code);
|
||||
|
||||
Template t = new Template(name, sourceName, reader, cfg); // $hasTemplateInjection
|
||||
}
|
||||
|
||||
@GetMapping(value = "bad6")
|
||||
public void bad6(HttpServletRequest request) {
|
||||
String name = "ttemplate";
|
||||
String code = request.getParameter("code");
|
||||
Configuration cfg = new Configuration();
|
||||
ParserConfiguration customParserConfiguration = new Configuration();
|
||||
Reader reader = new StringReader(code);
|
||||
|
||||
Template t =
|
||||
new Template(name, sourceName, reader, cfg, customParserConfiguration, "UTF-8"); // $hasTemplateInjection
|
||||
}
|
||||
|
||||
@GetMapping(value = "bad7")
|
||||
public void bad7(HttpServletRequest request) {
|
||||
String name = "ttemplate";
|
||||
String code = request.getParameter("code");
|
||||
Configuration cfg = new Configuration();
|
||||
ParserConfiguration customParserConfiguration = new Configuration();
|
||||
Reader reader = new StringReader(code);
|
||||
|
||||
Template t = new Template(name, sourceName, reader, cfg, "UTF-8"); // $hasTemplateInjection
|
||||
}
|
||||
|
||||
@GetMapping(value = "bad8")
|
||||
public void bad8(HttpServletRequest request) {
|
||||
String code = request.getParameter("code");
|
||||
StringTemplateLoader stringLoader = new StringTemplateLoader();
|
||||
|
||||
stringLoader.putTemplate("myTemplate", code); // $hasTemplateInjection
|
||||
}
|
||||
|
||||
@GetMapping(value = "bad9")
|
||||
public void bad9(HttpServletRequest request) {
|
||||
String code = request.getParameter("code");
|
||||
StringTemplateLoader stringLoader = new StringTemplateLoader();
|
||||
|
||||
stringLoader.putTemplate("myTemplate", code, 0); // $hasTemplateInjection
|
||||
}
|
||||
|
||||
@GetMapping(value = "good1")
|
||||
public void good1(HttpServletRequest request) {
|
||||
HashMap<Object, Object> root = new HashMap();
|
||||
String code = request.getParameter("code");
|
||||
root.put("code", code);
|
||||
Configuration cfg = new Configuration();
|
||||
Template temp = cfg.getTemplate("test.ftlh");
|
||||
OutputStreamWriter out = new OutputStreamWriter(System.out);
|
||||
temp.process(root, out); // Safe
|
||||
}
|
||||
}
|
||||
44
java/ql/test/query-tests/security/CWE-094/JinJavaSSTI.java
Normal file
44
java/ql/test/query-tests/security/CWE-094/JinJavaSSTI.java
Normal file
@@ -0,0 +1,44 @@
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
|
||||
import java.lang.String;
|
||||
import java.io.Reader;
|
||||
import java.io.StringReader;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import com.hubspot.jinjava.*;
|
||||
import com.hubspot.jinjava.JinjavaConfig;
|
||||
import com.hubspot.jinjava.interpret.*;
|
||||
|
||||
@Controller
|
||||
public class JinJavaSSTI {
|
||||
String sourceName = "sourceName";
|
||||
|
||||
@GetMapping(value = "bad1")
|
||||
public void bad1(HttpServletRequest request) {
|
||||
String template = request.getParameter("template");
|
||||
Jinjava jinjava = new Jinjava();
|
||||
Map<String, Object> context = new HashMap<>();
|
||||
String renderedTemplate = jinjava.render(template, context); // $hasTemplateInjection
|
||||
}
|
||||
|
||||
@GetMapping(value = "bad2")
|
||||
public void bad2(HttpServletRequest request) {
|
||||
String template = request.getParameter("template");
|
||||
Jinjava jinjava = new Jinjava();
|
||||
Map<String, Object> bindings = new HashMap<>();
|
||||
RenderResult renderResult = jinjava.renderForResult(template, bindings); // $hasTemplateInjection
|
||||
}
|
||||
|
||||
@GetMapping(value = "bad3")
|
||||
public void bad3(HttpServletRequest request) {
|
||||
String template = request.getParameter("template");
|
||||
Jinjava jinjava = new Jinjava();
|
||||
Map<String, Object> bindings = new HashMap<>();
|
||||
JinjavaConfig renderConfig = new JinjavaConfig();
|
||||
|
||||
RenderResult renderResult = jinjava.renderForResult(template, bindings, renderConfig); // $hasTemplateInjection
|
||||
}
|
||||
}
|
||||
29
java/ql/test/query-tests/security/CWE-094/PebbleSSTI.java
Normal file
29
java/ql/test/query-tests/security/CWE-094/PebbleSSTI.java
Normal file
@@ -0,0 +1,29 @@
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
|
||||
import java.lang.String;
|
||||
import java.io.Reader;
|
||||
import java.io.StringReader;
|
||||
|
||||
import com.mitchellbosecke.pebble.PebbleEngine;
|
||||
import com.mitchellbosecke.pebble.template.*;
|
||||
|
||||
@Controller
|
||||
public class PebbleSSTI {
|
||||
String sourceName = "sourceName";
|
||||
|
||||
@GetMapping(value = "bad1")
|
||||
public void bad1(HttpServletRequest request) {
|
||||
String templateName = request.getParameter("templateName");
|
||||
PebbleEngine engine = new PebbleEngine.Builder().build();
|
||||
PebbleTemplate compiledTemplate = engine.getTemplate(templateName); // $hasTemplateInjection
|
||||
}
|
||||
|
||||
@GetMapping(value = "bad2")
|
||||
public void bad2(HttpServletRequest request) {
|
||||
String templateName = request.getParameter("templateName");
|
||||
PebbleEngine engine = new PebbleEngine.Builder().build();
|
||||
PebbleTemplate compiledTemplate = engine.getLiteralTemplate(templateName); // $hasTemplateInjection
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
import java
|
||||
import semmle.code.java.security.TemplateInjectionQuery
|
||||
import TestUtilities.InlineExpectationsTest
|
||||
|
||||
class TemplateInjectionTest extends InlineExpectationsTest {
|
||||
TemplateInjectionTest() { this = "TemplateInjectionTest" }
|
||||
|
||||
override string getARelevantTag() { result = "hasTemplateInjection" }
|
||||
|
||||
override predicate hasActualResult(Location location, string element, string tag, string value) {
|
||||
tag = "hasTemplateInjection" and
|
||||
exists(DataFlow::Node src, DataFlow::Node sink, TemplateInjectionFlowConfig conf |
|
||||
conf.hasFlow(src, sink)
|
||||
|
|
||||
sink.getLocation() = location and
|
||||
element = sink.toString() and
|
||||
value = ""
|
||||
)
|
||||
}
|
||||
}
|
||||
38
java/ql/test/query-tests/security/CWE-094/ThymeleafSSTI.java
Normal file
38
java/ql/test/query-tests/security/CWE-094/ThymeleafSSTI.java
Normal file
@@ -0,0 +1,38 @@
|
||||
import javax.imageio.stream.FileImageInputStream;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
|
||||
import java.lang.String;
|
||||
import java.io.File;
|
||||
import java.io.FileWriter;
|
||||
import java.io.Reader;
|
||||
import java.io.StringReader;
|
||||
import java.io.Writer;
|
||||
import java.util.Set;
|
||||
|
||||
import org.thymeleaf.*;
|
||||
import org.thymeleaf.context.Context;
|
||||
|
||||
@Controller
|
||||
public class ThymeleafSSTI {
|
||||
@GetMapping(value = "bad1")
|
||||
public void bad1(HttpServletRequest request) {
|
||||
String code = request.getParameter("code");
|
||||
try {
|
||||
TemplateEngine templateEngine = new TemplateEngine();
|
||||
templateEngine.process(code, (Set<String>) null, (Context) null); // $hasTemplateInjection
|
||||
templateEngine.process(code, (Set<String>) null, (Context) null, (Writer) null); // $hasTemplateInjection
|
||||
templateEngine.process(code, (Context) null); // $hasTemplateInjection
|
||||
templateEngine.process(code, (Context) null, (Writer) null); // $hasTemplateInjection
|
||||
templateEngine.processThrottled(code, (Set<String>) null, (Context) null); // $hasTemplateInjection
|
||||
templateEngine.processThrottled(code, (Context) null); // $hasTemplateInjection
|
||||
|
||||
TemplateSpec spec = new TemplateSpec(code, "");
|
||||
templateEngine.process(spec, (Context) null); // $hasTemplateInjection
|
||||
templateEngine.process(spec, (Context) null, (Writer) null); // $hasTemplateInjection
|
||||
templateEngine.processThrottled(spec, (Context) null); // $hasTemplateInjection
|
||||
} catch (Exception e) {
|
||||
}
|
||||
}
|
||||
}
|
||||
120
java/ql/test/query-tests/security/CWE-094/VelocitySSTI.java
Normal file
120
java/ql/test/query-tests/security/CWE-094/VelocitySSTI.java
Normal file
@@ -0,0 +1,120 @@
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
|
||||
import java.lang.String;
|
||||
import java.io.Reader;
|
||||
import java.io.StringReader;
|
||||
import java.io.OutputStreamWriter;
|
||||
import java.io.InputStream;
|
||||
import java.io.StringWriter;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedList;
|
||||
|
||||
import org.apache.velocity.VelocityContext;
|
||||
import org.apache.velocity.context.AbstractContext;
|
||||
import org.apache.velocity.context.Context;
|
||||
import org.apache.velocity.Template;
|
||||
import org.apache.velocity.app.Velocity;
|
||||
import org.apache.velocity.app.VelocityEngine;
|
||||
import org.apache.velocity.runtime.RuntimeServices;
|
||||
import org.apache.velocity.runtime.resource.util.StringResourceRepository;
|
||||
import org.apache.velocity.runtime.resource.util.StringResourceRepositoryImpl;
|
||||
|
||||
@Controller
|
||||
public class VelocitySSTI {
|
||||
String sourceName = "sourceName";
|
||||
|
||||
@GetMapping(value = "bad1")
|
||||
public void bad1(HttpServletRequest request) {
|
||||
String name = "ttemplate";
|
||||
String code = request.getParameter("code");
|
||||
|
||||
VelocityContext context = null;
|
||||
|
||||
String s = "We are using $project $name to render this.";
|
||||
StringWriter w = new StringWriter();
|
||||
Velocity.evaluate(context, w, "mystring", code); // $hasTemplateInjection
|
||||
}
|
||||
|
||||
@GetMapping(value = "bad2")
|
||||
public void bad2(HttpServletRequest request) {
|
||||
String name = "ttemplate";
|
||||
String code = request.getParameter("code");
|
||||
|
||||
VelocityContext context = null;
|
||||
|
||||
String s = "We are using $project $name to render this.";
|
||||
StringWriter w = new StringWriter();
|
||||
StringReader reader = new StringReader(code);
|
||||
|
||||
Velocity.evaluate(context, w, "mystring", reader); // $hasTemplateInjection
|
||||
}
|
||||
|
||||
@GetMapping(value = "bad3")
|
||||
public void bad3(HttpServletRequest request) {
|
||||
String name = "ttemplate";
|
||||
String code = request.getParameter("code");
|
||||
|
||||
RuntimeServices runtimeServices = null;
|
||||
StringReader reader = new StringReader(code);
|
||||
runtimeServices.parse(reader, new Template()); // $hasTemplateInjection
|
||||
}
|
||||
|
||||
@GetMapping(value = "good1")
|
||||
public void good1(HttpServletRequest request) {
|
||||
String name = "ttemplate";
|
||||
String code = request.getParameter("code");
|
||||
|
||||
VelocityContext context = new VelocityContext();
|
||||
context.put("code", code);
|
||||
|
||||
StringWriter w = new StringWriter();
|
||||
StringReader reader = new StringReader("test");
|
||||
|
||||
Velocity.evaluate(context, w, "mystring", reader); // Safe
|
||||
}
|
||||
|
||||
@GetMapping(value = "bad5")
|
||||
public void bad5(HttpServletRequest request) {
|
||||
String name = "ttemplate";
|
||||
String code = request.getParameter("code");
|
||||
|
||||
VelocityContext context = new VelocityContext();
|
||||
context.put("code", code);
|
||||
|
||||
StringWriter w = new StringWriter();
|
||||
VelocityEngine engine = null;
|
||||
engine.mergeTemplate("testtemplate.vm", "UTF-8", context, w); // Safe
|
||||
AbstractContext ctx = null;
|
||||
ctx.put("key", code);
|
||||
engine.evaluate(ctx, null, null, (String) null); // Safe
|
||||
engine.evaluate(ctx, null, null, (Reader) null); // Safe
|
||||
engine.evaluate(null, null, null, code); // $hasTemplateInjection
|
||||
engine.evaluate(null, null, null, new StringReader(code)); // $hasTemplateInjection
|
||||
}
|
||||
|
||||
@GetMapping(value = "good2")
|
||||
public void good2(HttpServletRequest request) {
|
||||
String name = "ttemplate";
|
||||
String code = request.getParameter("code");
|
||||
|
||||
VelocityContext context = new VelocityContext();
|
||||
context.put("code", code);
|
||||
|
||||
StringWriter w = new StringWriter();
|
||||
Template t = new Template();
|
||||
t.merge(context, w); // Safe
|
||||
t.merge(context, w, new LinkedList<String>()); // Safe
|
||||
|
||||
}
|
||||
|
||||
@GetMapping(value = "bad6")
|
||||
public void bad6(HttpServletRequest request) {
|
||||
String code = request.getParameter("code");
|
||||
|
||||
StringResourceRepository repo = new StringResourceRepositoryImpl();
|
||||
repo.putStringResource("woogie2", code); // $hasTemplateInjection
|
||||
|
||||
}
|
||||
}
|
||||
@@ -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/groovy-all-3.0.7:${testdir}/../../../stubs/servlet-api-2.4:${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:${testdir}/../../../stubs/apache-freemarker-2.3.31:${testdir}/../../../stubs/jinjava-2.6.0:${testdir}/../../../stubs/pebble-3.1.5:${testdir}/../../../stubs/thymeleaf-3.0.14:${testdir}/../../../stubs/apache-velocity-2.3
|
||||
|
||||
Reference in New Issue
Block a user