Merge pull request #10352 from atorralba/atorralba/promote-template-injection

Java: Promote Server-side template injection from experimental
This commit is contained in:
Tony Torralba
2022-09-20 16:11:58 +02:00
committed by GitHub
615 changed files with 16792 additions and 711 deletions

View 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
}
}

View 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
}
}

View 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
}
}

View File

@@ -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 = ""
)
}
}

View 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) {
}
}
}

View 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
}
}

View File

@@ -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