mirror of
https://github.com/github/codeql.git
synced 2025-12-24 04:36:35 +01: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,6 +117,7 @@ private module Frameworks {
|
||||
private import semmle.code.java.frameworks.Retrofit
|
||||
private import semmle.code.java.frameworks.Stream
|
||||
private import semmle.code.java.frameworks.Strings
|
||||
private import semmle.code.java.frameworks.Thymeleaf
|
||||
private import semmle.code.java.frameworks.ratpack.Ratpack
|
||||
private import semmle.code.java.frameworks.ratpack.RatpackExec
|
||||
private import semmle.code.java.frameworks.spring.SpringCache
|
||||
@@ -141,6 +142,7 @@ private module Frameworks {
|
||||
private import semmle.code.java.security.LdapInjection
|
||||
private import semmle.code.java.security.MvelInjection
|
||||
private import semmle.code.java.security.OgnlInjection
|
||||
private import semmle.code.java.security.TemplateInjection
|
||||
private import semmle.code.java.security.XPath
|
||||
private import semmle.code.java.security.XsltInjection
|
||||
private import semmle.code.java.frameworks.Jdbc
|
||||
@@ -625,7 +627,7 @@ module CsvValidation {
|
||||
"open-url", "jndi-injection", "ldap", "sql", "jdbc-url", "logging", "mvel", "xpath",
|
||||
"groovy", "xss", "ognl-injection", "intent-start", "pending-intent-sent",
|
||||
"url-open-stream", "url-redirect", "create-file", "write-file", "set-hostname-verifier",
|
||||
"header-splitting", "information-leak", "xslt", "jexl", "bean-validation"
|
||||
"header-splitting", "information-leak", "xslt", "jexl", "bean-validation", "ssti"
|
||||
] and
|
||||
not kind.matches("regex-use%") and
|
||||
not kind.matches("qltest%") and
|
||||
|
||||
16
java/ql/lib/semmle/code/java/frameworks/Thymeleaf.qll
Normal file
16
java/ql/lib/semmle/code/java/frameworks/Thymeleaf.qll
Normal file
@@ -0,0 +1,16 @@
|
||||
/**
|
||||
* Provides classes and predicates for working with the Thymeleaf template engine.
|
||||
*/
|
||||
|
||||
import java
|
||||
private import semmle.code.java.dataflow.ExternalFlow
|
||||
|
||||
private class ThymeleafSummaryModels extends SummaryModelCsv {
|
||||
override predicate row(string row) {
|
||||
row =
|
||||
[
|
||||
"org.thymeleaf;TemplateSpec;false;TemplateSpec;;;Argument[0];Argument[-1];taint;manual",
|
||||
"org.thymeleaf;TemplateSpec;false;getTemplate;;;Argument[-1];ReturnValue;taint;manual",
|
||||
]
|
||||
}
|
||||
}
|
||||
108
java/ql/lib/semmle/code/java/security/TemplateInjection.qll
Normal file
108
java/ql/lib/semmle/code/java/security/TemplateInjection.qll
Normal file
@@ -0,0 +1,108 @@
|
||||
/** Definitions related to the server-side template injection (SST) query. */
|
||||
|
||||
import java
|
||||
private import semmle.code.java.dataflow.FlowSources
|
||||
private import semmle.code.java.dataflow.ExternalFlow
|
||||
private import semmle.code.java.dataflow.TaintTracking
|
||||
|
||||
/**
|
||||
* A source for server-side template injection (SST) vulnerabilities.
|
||||
*/
|
||||
abstract class TemplateInjectionSource extends DataFlow::Node {
|
||||
/** Holds if this source has the specified `state`. */
|
||||
predicate hasState(DataFlow::FlowState state) { state instanceof DataFlow::FlowStateEmpty }
|
||||
}
|
||||
|
||||
/**
|
||||
* A sink for server-side template injection (SST) vulnerabilities.
|
||||
*/
|
||||
abstract class TemplateInjectionSink extends DataFlow::Node {
|
||||
/** Holds if this sink has the specified `state`. */
|
||||
predicate hasState(DataFlow::FlowState state) { state instanceof DataFlow::FlowStateEmpty }
|
||||
}
|
||||
|
||||
/**
|
||||
* A unit class for adding additional taint steps.
|
||||
*
|
||||
* Extend this class to add additional taint steps that should apply to flows related to
|
||||
* server-side template injection (SST) vulnerabilities.
|
||||
*/
|
||||
class TemplateInjectionAdditionalTaintStep extends Unit {
|
||||
/**
|
||||
* Holds if the step from `node1` to `node2` should be considered a taint
|
||||
* step for flows related to server-side template injection (SST) vulnerabilities.
|
||||
*/
|
||||
predicate isAdditionalTaintStep(DataFlow::Node node1, DataFlow::Node node2) { none() }
|
||||
|
||||
/**
|
||||
* Holds if the step from `node1` to `node2` should be considered a taint
|
||||
* step for flows related toserver-side template injection (SST) vulnerabilities.
|
||||
* This step is only applicable in `state1` and updates the flow state to `state2`.
|
||||
*/
|
||||
predicate isAdditionalTaintStep(
|
||||
DataFlow::Node node1, DataFlow::FlowState state1, DataFlow::Node node2,
|
||||
DataFlow::FlowState state2
|
||||
) {
|
||||
none()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A sanitizer for server-side template injection (SST) vulnerabilities.
|
||||
*/
|
||||
abstract class TemplateInjectionSanitizer extends DataFlow::Node { }
|
||||
|
||||
/**
|
||||
* A sanitizer for server-side template injection (SST) vulnerabilities.
|
||||
* This sanitizer is only applicable when `TemplateInjectionSanitizerWithState::hasState`
|
||||
* holds for the flow state.
|
||||
*/
|
||||
abstract class TemplateInjectionSanitizerWithState extends DataFlow::Node {
|
||||
/** Holds if this sanitizer has the specified `state`. */
|
||||
abstract predicate hasState(DataFlow::FlowState state);
|
||||
}
|
||||
|
||||
private class DefaultTemplateInjectionSource extends TemplateInjectionSource instanceof RemoteFlowSource {
|
||||
}
|
||||
|
||||
private class DefaultTemplateInjectionSink extends TemplateInjectionSink {
|
||||
DefaultTemplateInjectionSink() { sinkNode(this, "ssti") }
|
||||
}
|
||||
|
||||
private class DefaultTemplateInjectionSanitizer extends TemplateInjectionSanitizer {
|
||||
DefaultTemplateInjectionSanitizer() {
|
||||
this.getType() instanceof PrimitiveType or
|
||||
this.getType() instanceof BoxedType or
|
||||
this.getType() instanceof NumericType
|
||||
}
|
||||
}
|
||||
|
||||
private class TemplateInjectionSinkModels extends SinkModelCsv {
|
||||
override predicate row(string row) {
|
||||
row =
|
||||
[
|
||||
"freemarker.template;Template;true;Template;(String,Reader);;Argument[1];ssti;manual",
|
||||
"freemarker.template;Template;true;Template;(String,Reader,Configuration);;Argument[1];ssti;manual",
|
||||
"freemarker.template;Template;true;Template;(String,Reader,Configuration,String);;Argument[1];ssti;manual",
|
||||
"freemarker.template;Template;true;Template;(String,String,Reader,Configuration);;Argument[2];ssti;manual",
|
||||
"freemarker.template;Template;true;Template;(String,String,Reader,Configuration,String);;Argument[2];ssti;manual",
|
||||
"freemarker.template;Template;true;Template;(String,String,Reader,Configuration,ParserConfiguration,String);;Argument[2];ssti;manual",
|
||||
"freemarker.template;Template;true;Template;(String,String,Configuration);;Argument[1];ssti;manual",
|
||||
"freemarker.cache;StringTemplateLoader;true;putTemplate;;;Argument[1];ssti;manual",
|
||||
"com.mitchellbosecke.pebble;PebbleEngine;true;getTemplate;;;Argument[0];ssti;manual",
|
||||
"com.mitchellbosecke.pebble;PebbleEngine;true;getLiteralTemplate;;;Argument[0];ssti;manual",
|
||||
"com.hubspot.jinjava;Jinjava;true;renderForResult;;;Argument[0];ssti;manual",
|
||||
"com.hubspot.jinjava;Jinjava;true;render;;;Argument[0];ssti;manual",
|
||||
"org.thymeleaf;ITemplateEngine;true;process;;;Argument[0];ssti;manual",
|
||||
"org.thymeleaf;ITemplateEngine;true;processThrottled;;;Argument[0];ssti;manual",
|
||||
"org.apache.velocity.app;Velocity;true;evaluate;;;Argument[3];ssti;manual",
|
||||
"org.apache.velocity.app;Velocity;true;mergeTemplate;;;Argument[2];ssti;manual",
|
||||
"org.apache.velocity.app;VelocityEngine;true;evaluate;;;Argument[3];ssti;manual",
|
||||
"org.apache.velocity.app;VelocityEngine;true;mergeTemplate;;;Argument[2];ssti;manual",
|
||||
"org.apache.velocity.runtime.resource.util;StringResourceRepository;true;putStringResource;;;Argument[1];ssti;manual",
|
||||
"org.apache.velocity.runtime;RuntimeServices;true;evaluate;;;Argument[3];ssti;manual",
|
||||
"org.apache.velocity.runtime;RuntimeServices;true;parse;;;Argument[0];ssti;manual",
|
||||
"org.apache.velocity.runtime;RuntimeSingleton;true;parse;;;Argument[0];ssti;manual"
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
/** Provides a taint tracking configuration for server-side template injection (SST) vulnerabilities */
|
||||
|
||||
import java
|
||||
import semmle.code.java.dataflow.TaintTracking
|
||||
import semmle.code.java.dataflow.FlowSources
|
||||
import semmle.code.java.security.TemplateInjection
|
||||
|
||||
/** A taint tracking configuration to reason about server-side template injection (SST) vulnerabilities */
|
||||
class TemplateInjectionFlowConfig extends TaintTracking::Configuration {
|
||||
TemplateInjectionFlowConfig() { this = "TemplateInjectionFlowConfig" }
|
||||
|
||||
override predicate isSource(DataFlow::Node source, DataFlow::FlowState state) {
|
||||
source.(TemplateInjectionSource).hasState(state)
|
||||
}
|
||||
|
||||
override predicate isSink(DataFlow::Node sink, DataFlow::FlowState state) {
|
||||
sink.(TemplateInjectionSink).hasState(state)
|
||||
}
|
||||
|
||||
override predicate isSanitizer(DataFlow::Node sanitizer) {
|
||||
sanitizer instanceof TemplateInjectionSanitizer
|
||||
}
|
||||
|
||||
override predicate isSanitizer(DataFlow::Node sanitizer, DataFlow::FlowState state) {
|
||||
sanitizer.(TemplateInjectionSanitizerWithState).hasState(state)
|
||||
}
|
||||
|
||||
override predicate isAdditionalTaintStep(DataFlow::Node node1, DataFlow::Node node2) {
|
||||
any(TemplateInjectionAdditionalTaintStep a).isAdditionalTaintStep(node1, node2)
|
||||
}
|
||||
|
||||
override predicate isAdditionalTaintStep(
|
||||
DataFlow::Node node1, DataFlow::FlowState state1, DataFlow::Node node2,
|
||||
DataFlow::FlowState state2
|
||||
) {
|
||||
any(TemplateInjectionAdditionalTaintStep a).isAdditionalTaintStep(node1, state1, node2, state2)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user