Merge pull request #12808 from egregius313/egregius313/java/dataflow/refactor-experimental

Java: Refactor experimental queries to new DataFlow API
This commit is contained in:
Edward Minnix III
2023-04-13 10:58:34 -04:00
committed by GitHub
53 changed files with 503 additions and 519 deletions

View File

@@ -16,9 +16,10 @@
*/
import java
import semmle.code.java.dataflow.TaintTracking
import semmle.code.java.dataflow.FlowSources
import semmle.code.java.dataflow.ExternalFlow
import DataFlow::PathGraph
import Log4jInjectionFlow::PathGraph
private class ActivateModels extends ActiveExperimentalModels {
ActivateModels() { this = "log4j-injection" }
@@ -41,17 +42,20 @@ class Log4jInjectionSanitizer extends DataFlow::Node {
/**
* A taint-tracking configuration for tracking untrusted user input used in log entries.
*/
class Log4jInjectionConfiguration extends TaintTracking::Configuration {
Log4jInjectionConfiguration() { this = "Log4jInjectionConfiguration" }
module Log4jInjectionConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource }
override predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource }
predicate isSink(DataFlow::Node sink) { sink instanceof Log4jInjectionSink }
override predicate isSink(DataFlow::Node sink) { sink instanceof Log4jInjectionSink }
override predicate isSanitizer(DataFlow::Node node) { node instanceof Log4jInjectionSanitizer }
predicate isBarrier(DataFlow::Node node) { node instanceof Log4jInjectionSanitizer }
}
from Log4jInjectionConfiguration cfg, DataFlow::PathNode source, DataFlow::PathNode sink
where cfg.hasFlowPath(source, sink)
/**
* Taint-tracking flow for tracking untrusted user input used in log entries.
*/
module Log4jInjectionFlow = TaintTracking::Global<Log4jInjectionConfig>;
from Log4jInjectionFlow::PathNode source, Log4jInjectionFlow::PathNode sink
where Log4jInjectionFlow::flowPath(source, sink)
select sink.getNode(), source, sink, "Log4j log entry depends on a $@.", source.getNode(),
"user-provided value"

View File

@@ -15,7 +15,7 @@ import java
import semmle.code.java.dataflow.TaintTracking
import semmle.code.java.dataflow.FlowSources
import semmle.code.java.dataflow.ExternalFlow
import DataFlow::PathGraph
import RemoteUrlToOpenStreamFlow::PathGraph
class UrlConstructor extends ClassInstanceExpr {
UrlConstructor() { this.getConstructor().getDeclaringType() instanceof TypeUrl }
@@ -28,12 +28,10 @@ class UrlConstructor extends ClassInstanceExpr {
}
}
class RemoteUrlToOpenStreamFlowConfig extends TaintTracking::Configuration {
RemoteUrlToOpenStreamFlowConfig() { this = "OpenStream::RemoteURLToOpenStreamFlowConfig" }
module RemoteUrlToOpenStreamFlowConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource }
override predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource }
override predicate isSink(DataFlow::Node sink) {
predicate isSink(DataFlow::Node sink) {
exists(MethodAccess m |
sink.asExpr() = m.getQualifier() and m.getMethod() instanceof UrlOpenStreamMethod
)
@@ -41,7 +39,7 @@ class RemoteUrlToOpenStreamFlowConfig extends TaintTracking::Configuration {
sinkNode(sink, "url-open-stream")
}
override predicate isAdditionalTaintStep(DataFlow::Node node1, DataFlow::Node node2) {
predicate isAdditionalFlowStep(DataFlow::Node node1, DataFlow::Node node2) {
exists(UrlConstructor u |
node1.asExpr() = u.stringArg() and
node2.asExpr() = u
@@ -49,9 +47,13 @@ class RemoteUrlToOpenStreamFlowConfig extends TaintTracking::Configuration {
}
}
from DataFlow::PathNode source, DataFlow::PathNode sink, MethodAccess call
module RemoteUrlToOpenStreamFlow = TaintTracking::Global<RemoteUrlToOpenStreamFlowConfig>;
from
RemoteUrlToOpenStreamFlow::PathNode source, RemoteUrlToOpenStreamFlow::PathNode sink,
MethodAccess call
where
sink.getNode().asExpr() = call.getQualifier() and
any(RemoteUrlToOpenStreamFlowConfig c).hasFlowPath(source, sink)
RemoteUrlToOpenStreamFlow::flowPath(source, sink)
select call, source, sink,
"URL on which openStream is called may have been constructed from remote source."

View File

@@ -13,12 +13,13 @@
*/
import java
import semmle.code.java.dataflow.TaintTracking
import semmle.code.java.dataflow.ExternalFlow
import semmle.code.java.dataflow.FlowSources
import semmle.code.java.security.PathCreation
import JFinalController
import semmle.code.java.security.PathSanitizer
import DataFlow::PathGraph
import InjectFilePathFlow::PathGraph
private class ActivateModels extends ActiveExperimentalModels {
ActivateModels() { this = "file-path-injection" }
@@ -47,24 +48,24 @@ class NormalizedPathNode extends DataFlow::Node {
}
}
class InjectFilePathConfig extends TaintTracking::Configuration {
InjectFilePathConfig() { this = "InjectFilePathConfig" }
module InjectFilePathConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource }
override predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource }
override predicate isSink(DataFlow::Node sink) {
predicate isSink(DataFlow::Node sink) {
sink.asExpr() = any(PathCreation p).getAnInput() and
not sink instanceof NormalizedPathNode
}
override predicate isSanitizer(DataFlow::Node node) {
predicate isBarrier(DataFlow::Node node) {
exists(Type t | t = node.getType() | t instanceof BoxedType or t instanceof PrimitiveType)
or
node instanceof PathInjectionSanitizer
}
}
from DataFlow::PathNode source, DataFlow::PathNode sink, InjectFilePathConfig conf
where conf.hasFlowPath(source, sink)
module InjectFilePathFlow = TaintTracking::Global<InjectFilePathConfig>;
from InjectFilePathFlow::PathNode source, InjectFilePathFlow::PathNode sink
where InjectFilePathFlow::flowPath(source, sink)
select sink.getNode(), source, sink, "External control of file name or path due to $@.",
source.getNode(), "user-provided value"

View File

@@ -13,27 +13,24 @@
*/
import java
import DataFlow::PathGraph
import MyBatisCommonLib
import MyBatisAnnotationSqlInjectionLib
import semmle.code.java.dataflow.FlowSources
import semmle.code.java.dataflow.TaintTracking
import MyBatisAnnotationSqlInjectionFlow::PathGraph
private class MyBatisAnnotationSqlInjectionConfiguration extends TaintTracking::Configuration {
MyBatisAnnotationSqlInjectionConfiguration() { this = "MyBatis annotation sql injection" }
private module MyBatisAnnotationSqlInjectionConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource }
override predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource }
predicate isSink(DataFlow::Node sink) { sink instanceof MyBatisAnnotatedMethodCallArgument }
override predicate isSink(DataFlow::Node sink) {
sink instanceof MyBatisAnnotatedMethodCallArgument
}
override predicate isSanitizer(DataFlow::Node node) {
predicate isBarrier(DataFlow::Node node) {
node.getType() instanceof PrimitiveType or
node.getType() instanceof BoxedType or
node.getType() instanceof NumberType
}
override predicate isAdditionalTaintStep(DataFlow::Node node1, DataFlow::Node node2) {
predicate isAdditionalFlowStep(DataFlow::Node node1, DataFlow::Node node2) {
exists(MethodAccess ma |
ma.getMethod().getDeclaringType() instanceof TypeObject and
ma.getMethod().getName() = "toString" and
@@ -43,12 +40,15 @@ private class MyBatisAnnotationSqlInjectionConfiguration extends TaintTracking::
}
}
private module MyBatisAnnotationSqlInjectionFlow =
TaintTracking::Global<MyBatisAnnotationSqlInjectionConfig>;
from
MyBatisAnnotationSqlInjectionConfiguration cfg, DataFlow::PathNode source,
DataFlow::PathNode sink, IbatisSqlOperationAnnotation isoa, MethodAccess ma,
string unsafeExpression
MyBatisAnnotationSqlInjectionFlow::PathNode source,
MyBatisAnnotationSqlInjectionFlow::PathNode sink, IbatisSqlOperationAnnotation isoa,
MethodAccess ma, string unsafeExpression
where
cfg.hasFlowPath(source, sink) and
MyBatisAnnotationSqlInjectionFlow::flowPath(source, sink) and
ma.getAnArgument() = sink.getNode().asExpr() and
myBatisSqlOperationAnnotationFromMethod(ma.getMethod(), isoa) and
unsafeExpression = getAMybatisAnnotationSqlValue(isoa) and

View File

@@ -17,23 +17,23 @@ private predicate propertiesKey(DataFlow::Node prop, string key) {
}
/** A data flow configuration tracing flow from ibatis `Configuration.getVariables()` to a store into a `Properties` object. */
private class PropertiesFlowConfig extends DataFlow2::Configuration {
PropertiesFlowConfig() { this = "PropertiesFlowConfig" }
override predicate isSource(DataFlow::Node src) {
private module PropertiesFlowConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node src) {
exists(MethodAccess ma | ma.getMethod() instanceof IbatisConfigurationGetVariablesMethod |
src.asExpr() = ma
)
}
override predicate isSink(DataFlow::Node sink) { propertiesKey(sink, _) }
predicate isSink(DataFlow::Node sink) { propertiesKey(sink, _) }
}
private module PropertiesFlow = DataFlow::Global<PropertiesFlowConfig>;
/** Gets a `Properties` key that may map onto a Mybatis `Configuration` variable. */
string getAMybatisConfigurationVariableKey() {
exists(PropertiesFlowConfig conf, DataFlow::Node n |
exists(DataFlow::Node n |
propertiesKey(n, result) and
conf.hasFlowTo(n)
PropertiesFlow::flowTo(n)
)
}

View File

@@ -13,28 +13,24 @@
*/
import java
import DataFlow::PathGraph
import MyBatisCommonLib
import MyBatisMapperXmlSqlInjectionLib
import semmle.code.xml.MyBatisMapperXML
import semmle.code.java.dataflow.FlowSources
import MyBatisMapperXmlSqlInjectionFlow::PathGraph
private class MyBatisMapperXmlSqlInjectionConfiguration extends TaintTracking::Configuration {
MyBatisMapperXmlSqlInjectionConfiguration() { this = "MyBatis mapper xml sql injection" }
private module MyBatisMapperXmlSqlInjectionConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource }
override predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource }
predicate isSink(DataFlow::Node sink) { sink instanceof MyBatisMapperMethodCallAnArgument }
override predicate isSink(DataFlow::Node sink) {
sink instanceof MyBatisMapperMethodCallAnArgument
}
override predicate isSanitizer(DataFlow::Node node) {
predicate isBarrier(DataFlow::Node node) {
node.getType() instanceof PrimitiveType or
node.getType() instanceof BoxedType or
node.getType() instanceof NumberType
}
override predicate isAdditionalTaintStep(DataFlow::Node node1, DataFlow::Node node2) {
predicate isAdditionalFlowStep(DataFlow::Node node1, DataFlow::Node node2) {
exists(MethodAccess ma |
ma.getMethod().getDeclaringType() instanceof TypeObject and
ma.getMethod().getName() = "toString" and
@@ -44,11 +40,15 @@ private class MyBatisMapperXmlSqlInjectionConfiguration extends TaintTracking::C
}
}
private module MyBatisMapperXmlSqlInjectionFlow =
TaintTracking::Global<MyBatisMapperXmlSqlInjectionConfig>;
from
MyBatisMapperXmlSqlInjectionConfiguration cfg, DataFlow::PathNode source, DataFlow::PathNode sink,
MyBatisMapperXmlElement mmxe, MethodAccess ma, string unsafeExpression
MyBatisMapperXmlSqlInjectionFlow::PathNode source,
MyBatisMapperXmlSqlInjectionFlow::PathNode sink, MyBatisMapperXmlElement mmxe, MethodAccess ma,
string unsafeExpression
where
cfg.hasFlowPath(source, sink) and
MyBatisMapperXmlSqlInjectionFlow::flowPath(source, sink) and
ma.getAnArgument() = sink.getNode().asExpr() and
myBatisMapperXmlElementFromMethod(ma.getMethod(), mmxe) and
unsafeExpression = getAMybatisXmlSetValue(mmxe) and

View File

@@ -14,16 +14,15 @@
import java
import BeanShellInjection
import semmle.code.java.dataflow.FlowSources
import DataFlow::PathGraph
import semmle.code.java.dataflow.TaintTracking
import BeanShellInjectionFlow::PathGraph
class BeanShellInjectionConfig extends TaintTracking::Configuration {
BeanShellInjectionConfig() { this = "BeanShellInjectionConfig" }
module BeanShellInjectionConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource }
override predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource }
predicate isSink(DataFlow::Node sink) { sink instanceof BeanShellInjectionSink }
override predicate isSink(DataFlow::Node sink) { sink instanceof BeanShellInjectionSink }
override predicate isAdditionalTaintStep(DataFlow::Node prod, DataFlow::Node succ) {
predicate isAdditionalFlowStep(DataFlow::Node prod, DataFlow::Node succ) {
exists(ClassInstanceExpr cie |
cie.getConstructedType()
.hasQualifiedName("org.springframework.scripting.support", "StaticScriptSource") and
@@ -42,7 +41,9 @@ class BeanShellInjectionConfig extends TaintTracking::Configuration {
}
}
from DataFlow::PathNode source, DataFlow::PathNode sink, BeanShellInjectionConfig conf
where conf.hasFlowPath(source, sink)
module BeanShellInjectionFlow = TaintTracking::Global<BeanShellInjectionConfig>;
from BeanShellInjectionFlow::PathNode source, BeanShellInjectionFlow::PathNode sink
where BeanShellInjectionFlow::flowPath(source, sink)
select sink.getNode(), source, sink, "BeanShell injection from $@.", source.getNode(),
"this user input"

View File

@@ -13,9 +13,9 @@
import java
import InsecureDexLoading
import DataFlow::PathGraph
import InsecureDexFlow::PathGraph
from DataFlow::PathNode source, DataFlow::PathNode sink, InsecureDexConfiguration conf
where conf.hasFlowPath(source, sink)
from InsecureDexFlow::PathNode source, InsecureDexFlow::PathNode sink
where InsecureDexFlow::flowPath(source, sink)
select sink.getNode(), source, sink, "Potential arbitrary code execution due to $@.",
source.getNode(), "a value loaded from a world-writable source."

View File

@@ -1,22 +1,21 @@
import java
import semmle.code.java.dataflow.TaintTracking
import semmle.code.java.dataflow.FlowSources
/**
* A taint-tracking configuration detecting unsafe use of a
* `DexClassLoader` by an Android app.
*/
class InsecureDexConfiguration extends TaintTracking::Configuration {
InsecureDexConfiguration() { this = "Insecure Dex File Load" }
module InsecureDexConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node source) { source instanceof InsecureDexSource }
override predicate isSource(DataFlow::Node source) { source instanceof InsecureDexSource }
predicate isSink(DataFlow::Node sink) { sink instanceof InsecureDexSink }
override predicate isSink(DataFlow::Node sink) { sink instanceof InsecureDexSink }
override predicate isAdditionalTaintStep(DataFlow::Node pred, DataFlow::Node succ) {
flowStep(pred, succ)
}
predicate isAdditionalFlowStep(DataFlow::Node pred, DataFlow::Node succ) { flowStep(pred, succ) }
}
module InsecureDexFlow = TaintTracking::Global<InsecureDexConfig>;
/** A data flow source for insecure Dex class loading vulnerabilities. */
abstract class InsecureDexSource extends DataFlow::Node { }

View File

@@ -14,16 +14,15 @@
import java
import JShellInjection
import semmle.code.java.dataflow.FlowSources
import DataFlow::PathGraph
import semmle.code.java.dataflow.TaintTracking
import JShellInjectionFlow::PathGraph
class JShellInjectionConfiguration extends TaintTracking::Configuration {
JShellInjectionConfiguration() { this = "JShellInjectionConfiguration" }
module JShellInjectionConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource }
override predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource }
predicate isSink(DataFlow::Node sink) { sink instanceof JShellInjectionSink }
override predicate isSink(DataFlow::Node sink) { sink instanceof JShellInjectionSink }
override predicate isAdditionalTaintStep(DataFlow::Node pred, DataFlow::Node succ) {
predicate isAdditionalFlowStep(DataFlow::Node pred, DataFlow::Node succ) {
exists(SourceCodeAnalysisAnalyzeCompletionCall scaacc |
scaacc.getArgument(0) = pred.asExpr() and scaacc = succ.asExpr()
)
@@ -34,7 +33,9 @@ class JShellInjectionConfiguration extends TaintTracking::Configuration {
}
}
from DataFlow::PathNode source, DataFlow::PathNode sink, JShellInjectionConfiguration conf
where conf.hasFlowPath(source, sink)
module JShellInjectionFlow = TaintTracking::Global<JShellInjectionConfig>;
from JShellInjectionFlow::PathNode source, JShellInjectionFlow::PathNode sink
where JShellInjectionFlow::flowPath(source, sink)
select sink.getNode(), source, sink, "JShell injection from $@.", source.getNode(),
"this user input"

View File

@@ -13,9 +13,9 @@
import java
import JakartaExpressionInjectionLib
import DataFlow::PathGraph
import JakartaExpressionInjectionFlow::PathGraph
from DataFlow::PathNode source, DataFlow::PathNode sink, JakartaExpressionInjectionConfig conf
where conf.hasFlowPath(source, sink)
from JakartaExpressionInjectionFlow::PathNode source, JakartaExpressionInjectionFlow::PathNode sink
where JakartaExpressionInjectionFlow::flowPath(source, sink)
select sink.getNode(), source, sink, "Jakarta Expression Language injection from $@.",
source.getNode(), "this user input"

View File

@@ -7,19 +7,22 @@ import semmle.code.java.dataflow.TaintTracking
* A taint-tracking configuration for unsafe user input
* that is used to construct and evaluate an expression.
*/
class JakartaExpressionInjectionConfig extends TaintTracking::Configuration {
JakartaExpressionInjectionConfig() { this = "JakartaExpressionInjectionConfig" }
module JakartaExpressionInjectionConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource }
override predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource }
predicate isSink(DataFlow::Node sink) { sink instanceof ExpressionEvaluationSink }
override predicate isSink(DataFlow::Node sink) { sink instanceof ExpressionEvaluationSink }
override predicate isAdditionalTaintStep(DataFlow::Node fromNode, DataFlow::Node toNode) {
predicate isAdditionalFlowStep(DataFlow::Node fromNode, DataFlow::Node toNode) {
any(TaintPropagatingCall c).taintFlow(fromNode, toNode) or
hasGetterFlow(fromNode, toNode)
}
}
/**
* Taint-tracking flow from remote sources, through an expression, to its eventual evaluation.
*/
module JakartaExpressionInjectionFlow = TaintTracking::Global<JakartaExpressionInjectionConfig>;
/**
* A sink for Expresssion Language injection vulnerabilities,
* i.e. method calls that run evaluation of an expression.

View File

@@ -14,8 +14,9 @@
import java
import semmle.code.java.dataflow.FlowSources
import semmle.code.java.dataflow.TaintTracking
import semmle.code.java.frameworks.spring.SpringController
import DataFlow::PathGraph
import CodeInjectionFlow::PathGraph
/** The class `org.python.util.PythonInterpreter`. */
class PythonInterpreter extends RefType {
@@ -101,15 +102,19 @@ class CodeInjectionSink extends DataFlow::ExprNode {
* A taint configuration for tracking flow from `RemoteFlowSource` to a Jython method call
* `CodeInjectionSink` that executes injected code.
*/
class CodeInjectionConfiguration extends TaintTracking::Configuration {
CodeInjectionConfiguration() { this = "CodeInjectionConfiguration" }
module CodeInjectionConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource }
override predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource }
override predicate isSink(DataFlow::Node sink) { sink instanceof CodeInjectionSink }
predicate isSink(DataFlow::Node sink) { sink instanceof CodeInjectionSink }
}
from DataFlow::PathNode source, DataFlow::PathNode sink, CodeInjectionConfiguration conf
where conf.hasFlowPath(source, sink)
/**
* Taint tracking flow from `RemoteFlowSource` to a Jython method call
* `CodeInjectionSink` that executes injected code.
*/
module CodeInjectionFlow = TaintTracking::Global<CodeInjectionConfig>;
from CodeInjectionFlow::PathNode source, CodeInjectionFlow::PathNode sink
where CodeInjectionFlow::flowPath(source, sink)
select sink.getNode().(CodeInjectionSink).getMethodAccess(), source, sink, "Jython evaluate $@.",
source.getNode(), "user input"

View File

@@ -12,8 +12,9 @@
*/
import java
import semmle.code.java.dataflow.TaintTracking
import semmle.code.java.dataflow.FlowSources
import DataFlow::PathGraph
import ScriptInjectionFlow::PathGraph
/** A method of ScriptEngine that allows code injection. */
class ScriptEngineMethod extends Method {
@@ -133,15 +134,15 @@ class ScriptInjectionSink extends DataFlow::ExprNode {
* A taint tracking configuration that tracks flow from `RemoteFlowSource` to an argument
* of a method call that executes injected script.
*/
class ScriptInjectionConfiguration extends TaintTracking::Configuration {
ScriptInjectionConfiguration() { this = "ScriptInjectionConfiguration" }
module ScriptInjectionConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource }
override predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource }
override predicate isSink(DataFlow::Node sink) { sink instanceof ScriptInjectionSink }
predicate isSink(DataFlow::Node sink) { sink instanceof ScriptInjectionSink }
}
from DataFlow::PathNode source, DataFlow::PathNode sink, ScriptInjectionConfiguration conf
where conf.hasFlowPath(source, sink)
module ScriptInjectionFlow = TaintTracking::Global<ScriptInjectionConfig>;
from ScriptInjectionFlow::PathNode source, ScriptInjectionFlow::PathNode sink
where ScriptInjectionFlow::flowPath(source, sink)
select sink.getNode().(ScriptInjectionSink).getMethodAccess(), source, sink,
"Java Script Engine evaluate $@.", source.getNode(), "user input"

View File

@@ -12,11 +12,11 @@
import java
import SpringViewManipulationLib
import DataFlow::PathGraph
import SpringViewManipulationFlow::PathGraph
from DataFlow::PathNode source, DataFlow::PathNode sink, SpringViewManipulationConfig conf
from SpringViewManipulationFlow::PathNode source, SpringViewManipulationFlow::PathNode sink
where
thymeleafIsUsed() and
conf.hasFlowPath(source, sink)
SpringViewManipulationFlow::flowPath(source, sink)
select sink.getNode(), source, sink, "Potential Spring Expression Language injection from $@.",
source.getNode(), "this user input"

View File

@@ -40,18 +40,16 @@ class PortletRenderRequestMethod extends Method {
* A taint-tracking configuration for unsafe user input
* that can lead to Spring View Manipulation vulnerabilities.
*/
class SpringViewManipulationConfig extends TaintTracking::Configuration {
SpringViewManipulationConfig() { this = "Spring View Manipulation Config" }
override predicate isSource(DataFlow::Node source) {
module SpringViewManipulationConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node source) {
source instanceof RemoteFlowSource or
source instanceof WebRequestSource or
source.asExpr().(MethodAccess).getMethod() instanceof PortletRenderRequestMethod
}
override predicate isSink(DataFlow::Node sink) { sink instanceof SpringViewManipulationSink }
predicate isSink(DataFlow::Node sink) { sink instanceof SpringViewManipulationSink }
override predicate isSanitizer(DataFlow::Node node) {
predicate isBarrier(DataFlow::Node node) {
// Block flows like
// ```
// a = "redirect:" + taint`
@@ -88,6 +86,8 @@ class SpringViewManipulationConfig extends TaintTracking::Configuration {
}
}
module SpringViewManipulationFlow = TaintTracking::Global<SpringViewManipulationConfig>;
private Call getAStringCombiningCall() {
exists(StringCombiningMethod m | result = m.getAReference())
}

View File

@@ -25,7 +25,7 @@ import semmle.code.java.dataflow.FlowSteps
import semmle.code.java.frameworks.Servlets
import semmle.code.java.dataflow.TaintTracking
import semmle.code.java.dataflow.TaintTracking2
import DataFlow::PathGraph
import MissingHttpOnlyFlow::PathGraph
/** Gets a regular expression for matching common names of sensitive cookies. */
string getSensitiveCookieNameRegex() { result = "(?i).*(auth|session|token|key|credential).*" }
@@ -65,18 +65,18 @@ class SetCookieMethodAccess extends MethodAccess {
* A taint configuration tracking flow from the text `httponly` to argument 1 of
* `SetCookieMethodAccess`.
*/
class MatchesHttpOnlyConfiguration extends TaintTracking2::Configuration {
MatchesHttpOnlyConfiguration() { this = "MatchesHttpOnlyConfiguration" }
override predicate isSource(DataFlow::Node source) {
module MatchesHttpOnlyConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node source) {
source.asExpr().(CompileTimeConstantExpr).getStringValue().toLowerCase().matches("%httponly%")
}
override predicate isSink(DataFlow::Node sink) {
predicate isSink(DataFlow::Node sink) {
sink.asExpr() = any(SetCookieMethodAccess ma).getArgument(1)
}
}
module MatchesHttpOnlyFlow = TaintTracking::Global<MatchesHttpOnlyConfig>;
/** A class descended from `javax.servlet.http.Cookie`. */
class CookieClass extends RefType {
CookieClass() { this.getAnAncestor().hasQualifiedName("javax.servlet.http", "Cookie") }
@@ -126,20 +126,20 @@ predicate isTestMethod(MethodAccess ma) {
* A taint configuration tracking flow of a method that sets the `HttpOnly` flag,
* or one that removes a cookie, to a `ServletResponse.addCookie` call.
*/
class SetHttpOnlyOrRemovesCookieConfiguration extends TaintTracking2::Configuration {
SetHttpOnlyOrRemovesCookieConfiguration() { this = "SetHttpOnlyOrRemovesCookieConfiguration" }
override predicate isSource(DataFlow::Node source) {
module SetHttpOnlyOrRemovesCookieConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node source) {
source.asExpr() =
any(MethodAccess ma | setsCookieHttpOnly(ma) or removesCookie(ma)).getQualifier()
}
override predicate isSink(DataFlow::Node sink) {
predicate isSink(DataFlow::Node sink) {
sink.asExpr() =
any(MethodAccess ma | ma.getMethod() instanceof ResponseAddCookieMethod).getArgument(0)
}
}
module SetHttpOnlyOrRemovesCookieFlow = TaintTracking::Global<SetHttpOnlyOrRemovesCookieConfig>;
/**
* A cookie that is added to an HTTP response and which doesn't have `httpOnly` set, used as a sink
* in `MissingHttpOnlyConfiguration`.
@@ -150,11 +150,11 @@ class CookieResponseSink extends DataFlow::ExprNode {
(
ma.getMethod() instanceof ResponseAddCookieMethod and
this.getExpr() = ma.getArgument(0) and
not exists(SetHttpOnlyOrRemovesCookieConfiguration cc | cc.hasFlowTo(this))
not SetHttpOnlyOrRemovesCookieFlow::flowTo(this)
or
ma instanceof SetCookieMethodAccess and
this.getExpr() = ma.getArgument(1) and
not exists(MatchesHttpOnlyConfiguration cc | cc.hasFlowTo(this)) // response.addHeader("Set-Cookie", "token=" +authId + ";HttpOnly;Secure")
not MatchesHttpOnlyFlow::flowTo(this) // response.addHeader("Set-Cookie", "token=" +authId + ";HttpOnly;Secure")
) and
not isTestMethod(ma) // Test class or method
)
@@ -181,21 +181,17 @@ predicate setsHttpOnlyInNewCookie(ClassInstanceExpr cie) {
* A taint configuration tracking flow from a sensitive cookie without the `HttpOnly` flag
* set to its HTTP response.
*/
class MissingHttpOnlyConfiguration extends TaintTracking::Configuration {
MissingHttpOnlyConfiguration() { this = "MissingHttpOnlyConfiguration" }
module MissingHttpOnlyConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node source) { source.asExpr() instanceof SensitiveCookieNameExpr }
override predicate isSource(DataFlow::Node source) {
source.asExpr() instanceof SensitiveCookieNameExpr
}
predicate isSink(DataFlow::Node sink) { sink instanceof CookieResponseSink }
override predicate isSink(DataFlow::Node sink) { sink instanceof CookieResponseSink }
override predicate isSanitizer(DataFlow::Node node) {
predicate isBarrier(DataFlow::Node node) {
// JAX-RS's `new NewCookie("session-access-key", accessKey, "/", null, null, 0, true, true)` and similar
setsHttpOnlyInNewCookie(node.asExpr())
}
override predicate isAdditionalTaintStep(DataFlow::Node pred, DataFlow::Node succ) {
predicate isAdditionalFlowStep(DataFlow::Node pred, DataFlow::Node succ) {
exists(
ConstructorCall cc // new Cookie(...)
|
@@ -215,7 +211,9 @@ class MissingHttpOnlyConfiguration extends TaintTracking::Configuration {
}
}
from DataFlow::PathNode source, DataFlow::PathNode sink, MissingHttpOnlyConfiguration c
where c.hasFlowPath(source, sink)
module MissingHttpOnlyFlow = TaintTracking::Global<MissingHttpOnlyConfig>;
from MissingHttpOnlyFlow::PathNode source, MissingHttpOnlyFlow::PathNode sink
where MissingHttpOnlyFlow::flowPath(source, sink)
select sink.getNode(), source, sink, "$@ doesn't have the HttpOnly flag set.", source.getNode(),
"This sensitive cookie"

View File

@@ -2,7 +2,7 @@
import java
import semmle.code.java.dataflow.FlowSources
import semmle.code.java.dataflow.TaintTracking2
import semmle.code.java.dataflow.TaintTracking
import semmle.code.java.frameworks.android.Android
/** The `startActivityForResult` method of Android's `Activity` class. */
@@ -29,27 +29,25 @@ class GetContentIntent extends ClassInstanceExpr {
}
/** Taint configuration that identifies `GET_CONTENT` `Intent` instances passed to `startActivityForResult`. */
class GetContentIntentConfig extends TaintTracking2::Configuration {
GetContentIntentConfig() { this = "GetContentIntentConfig" }
module GetContentIntentConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node src) { src.asExpr() instanceof GetContentIntent }
override predicate isSource(DataFlow2::Node src) { src.asExpr() instanceof GetContentIntent }
override predicate isSink(DataFlow2::Node sink) {
predicate isSink(DataFlow::Node sink) {
exists(MethodAccess ma |
ma.getMethod() instanceof StartActivityForResultMethod and sink.asExpr() = ma.getArgument(0)
)
}
override predicate allowImplicitRead(DataFlow::Node node, DataFlow::ContentSet content) {
super.allowImplicitRead(node, content)
or
predicate allowImplicitRead(DataFlow::Node node, DataFlow::ContentSet content) {
// Allow the wrapped intent created by Intent.getChooser to be consumed
// by at the sink:
this.isSink(node) and
isSink(node) and
allowIntentExtrasImplicitRead(node, content)
}
}
module GetContentsIntentFlow = TaintTracking::Global<GetContentIntentConfig>;
/** A `GET_CONTENT` `Intent` instances that is passed to `startActivityForResult`. */
class AndroidFileIntentInput extends DataFlow::Node {
MethodAccess ma;
@@ -57,8 +55,8 @@ class AndroidFileIntentInput extends DataFlow::Node {
AndroidFileIntentInput() {
this.asExpr() = ma.getArgument(0) and
ma.getMethod() instanceof StartActivityForResultMethod and
exists(GetContentIntentConfig cc, GetContentIntent gi |
cc.hasFlow(DataFlow::exprNode(gi), DataFlow::exprNode(ma.getArgument(0)))
exists(GetContentIntent gi |
GetContentsIntentFlow::flow(DataFlow::exprNode(gi), DataFlow::exprNode(ma.getArgument(0)))
)
}

View File

@@ -16,19 +16,20 @@ import semmle.code.java.dataflow.FlowSources
import semmle.code.java.dataflow.TaintTracking
import semmle.code.java.security.PathSanitizer
import AndroidWebResourceResponse
import DataFlow::PathGraph
import InsecureWebResourceResponseFlow::PathGraph
class InsecureWebResourceResponseConfig extends TaintTracking::Configuration {
InsecureWebResourceResponseConfig() { this = "InsecureWebResourceResponseConfig" }
module InsecureWebResourceResponseConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node src) { src instanceof RemoteFlowSource }
override predicate isSource(DataFlow::Node src) { src instanceof RemoteFlowSource }
predicate isSink(DataFlow::Node sink) { sink instanceof WebResourceResponseSink }
override predicate isSink(DataFlow::Node sink) { sink instanceof WebResourceResponseSink }
override predicate isSanitizer(DataFlow::Node node) { node instanceof PathInjectionSanitizer }
predicate isBarrier(DataFlow::Node node) { node instanceof PathInjectionSanitizer }
}
from DataFlow::PathNode source, DataFlow::PathNode sink, InsecureWebResourceResponseConfig conf
where conf.hasFlowPath(source, sink)
module InsecureWebResourceResponseFlow = TaintTracking::Global<InsecureWebResourceResponseConfig>;
from
InsecureWebResourceResponseFlow::PathNode source, InsecureWebResourceResponseFlow::PathNode sink
where InsecureWebResourceResponseFlow::flowPath(source, sink)
select sink.getNode(), source, sink, "Leaking arbitrary content in Android from $@.",
source.getNode(), "this user input"

View File

@@ -14,7 +14,7 @@ import java
import semmle.code.java.controlflow.Guards
import AndroidFileIntentSink
import AndroidFileIntentSource
import DataFlow::PathGraph
import AndroidFileLeakFlow::PathGraph
private predicate startsWithSanitizer(Guard g, Expr e, boolean branch) {
exists(MethodAccess ma |
@@ -25,16 +25,14 @@ private predicate startsWithSanitizer(Guard g, Expr e, boolean branch) {
)
}
class AndroidFileLeakConfig extends TaintTracking::Configuration {
AndroidFileLeakConfig() { this = "AndroidFileLeakConfig" }
module AndroidFileLeakConfig implements DataFlow::ConfigSig {
/**
* Holds if `src` is a read of some Intent-typed variable guarded by a check like
* `requestCode == someCode`, where `requestCode` is the first
* argument to `Activity.onActivityResult` and `someCode` is
* any request code used in a call to `startActivityForResult(intent, someCode)`.
*/
override predicate isSource(DataFlow::Node src) {
predicate isSource(DataFlow::Node src) {
exists(
OnActivityForResultMethod oafr, ConditionBlock cb, CompileTimeConstantExpr cc,
VarAccess intentVar
@@ -50,9 +48,9 @@ class AndroidFileLeakConfig extends TaintTracking::Configuration {
}
/** Holds if it is a sink of file access in Android. */
override predicate isSink(DataFlow::Node sink) { sink instanceof AndroidFileSink }
predicate isSink(DataFlow::Node sink) { sink instanceof AndroidFileSink }
override predicate isAdditionalTaintStep(DataFlow::Node prev, DataFlow::Node succ) {
predicate isAdditionalFlowStep(DataFlow::Node prev, DataFlow::Node succ) {
exists(MethodAccess aema, AsyncTaskRunInBackgroundMethod arm |
// fileAsyncTask.execute(params) will invoke doInBackground(params) of FileAsyncTask
aema.getQualifier().getType() = arm.getDeclaringType() and
@@ -72,12 +70,14 @@ class AndroidFileLeakConfig extends TaintTracking::Configuration {
)
}
override predicate isSanitizer(DataFlow::Node node) {
predicate isBarrier(DataFlow::Node node) {
node = DataFlow::BarrierGuard<startsWithSanitizer/3>::getABarrierNode()
}
}
from DataFlow::PathNode source, DataFlow::PathNode sink, AndroidFileLeakConfig conf
where conf.hasFlowPath(source, sink)
module AndroidFileLeakFlow = TaintTracking::Global<AndroidFileLeakConfig>;
from AndroidFileLeakFlow::PathNode source, AndroidFileLeakFlow::PathNode sink
where AndroidFileLeakFlow::flowPath(source, sink)
select sink.getNode(), source, sink, "Leaking arbitrary Android file from $@.", source.getNode(),
"this user input"

View File

@@ -4,8 +4,6 @@
import semmle.code.java.controlflow.Guards
import semmle.code.java.dataflow.TaintTracking
import semmle.code.java.dataflow.TaintTracking2
import semmle.code.java.dataflow.DataFlow3
import semmle.code.java.dataflow.FlowSources
/** A method call that produces cryptographic result. */
@@ -51,10 +49,8 @@ private class ProduceSignatureCall extends ProduceCryptoCall {
* A config that tracks data flow from initializing a cipher for encryption
* to producing a ciphertext using this cipher.
*/
private class InitializeEncryptorConfig extends DataFlow3::Configuration {
InitializeEncryptorConfig() { this = "InitializeEncryptorConfig" }
override predicate isSource(DataFlow::Node source) {
private module InitializeEncryptorConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node source) {
exists(MethodAccess ma |
ma.getMethod().hasQualifiedName("javax.crypto", "Cipher", "init") and
ma.getArgument(0).(VarAccess).getVariable().hasName("ENCRYPT_MODE") and
@@ -62,7 +58,7 @@ private class InitializeEncryptorConfig extends DataFlow3::Configuration {
)
}
override predicate isSink(DataFlow::Node sink) {
predicate isSink(DataFlow::Node sink) {
exists(MethodAccess ma |
ma.getMethod().hasQualifiedName("javax.crypto", "Cipher", "doFinal") and
ma.getQualifier() = sink.asExpr()
@@ -70,6 +66,8 @@ private class InitializeEncryptorConfig extends DataFlow3::Configuration {
}
}
private module InitializeEncryptorFlow = DataFlow::Global<InitializeEncryptorConfig>;
/** A method call that produces a ciphertext. */
private class ProduceCiphertextCall extends ProduceCryptoCall {
ProduceCiphertextCall() {
@@ -90,9 +88,7 @@ private class ProduceCiphertextCall extends ProduceCryptoCall {
this.getArgument(1) = output
)
) and
exists(InitializeEncryptorConfig config |
config.hasFlowTo(DataFlow3::exprNode(this.getQualifier()))
)
InitializeEncryptorFlow::flowToExpr(this.getQualifier())
}
override string getResultType() { result = "ciphertext" }
@@ -151,16 +147,14 @@ private predicate updateMessageDigestStep(DataFlow2::Node fromNode, DataFlow2::N
* A config that tracks data flow from remote user input to a cryptographic operation
* such as cipher, MAC or signature.
*/
private class UserInputInCryptoOperationConfig extends TaintTracking2::Configuration {
UserInputInCryptoOperationConfig() { this = "UserInputInCryptoOperationConfig" }
private module UserInputInCryptoOperationConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource }
override predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource }
override predicate isSink(DataFlow::Node sink) {
predicate isSink(DataFlow::Node sink) {
exists(ProduceCryptoCall call | call.getQualifier() = sink.asExpr())
}
override predicate isAdditionalTaintStep(DataFlow2::Node fromNode, DataFlow2::Node toNode) {
predicate isAdditionalFlowStep(DataFlow2::Node fromNode, DataFlow2::Node toNode) {
updateCryptoOperationStep(fromNode, toNode)
or
createMessageDigestStep(fromNode, toNode)
@@ -169,6 +163,13 @@ private class UserInputInCryptoOperationConfig extends TaintTracking2::Configura
}
}
/**
* Taint-tracking flow from remote user input to a cryptographic operation
* such as cipher, MAC or signature.
*/
private module UserInputInCryptoOperationFlow =
TaintTracking::Global<UserInputInCryptoOperationConfig>;
/** A source that produces result of cryptographic operation. */
class CryptoOperationSource extends DataFlow::Node {
ProduceCryptoCall call;
@@ -177,8 +178,8 @@ class CryptoOperationSource extends DataFlow::Node {
/** Holds if remote user input was used in the cryptographic operation. */
predicate includesUserInput() {
exists(DataFlow2::PathNode sink, UserInputInCryptoOperationConfig config |
config.hasFlowPath(_, sink)
exists(UserInputInCryptoOperationFlow::PathNode sink |
UserInputInCryptoOperationFlow::flowPath(_, sink)
|
sink.getNode().asExpr() = call.getQualifier()
)
@@ -212,12 +213,10 @@ private class NonConstantTimeComparisonCall extends StaticMethodAccess {
* A config that tracks data flow from remote user input to methods
* that compare inputs using a non-constant-time algorithm.
*/
private class UserInputInComparisonConfig extends TaintTracking2::Configuration {
UserInputInComparisonConfig() { this = "UserInputInComparisonConfig" }
private module UserInputInComparisonConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource }
override predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource }
override predicate isSink(DataFlow::Node sink) {
predicate isSink(DataFlow::Node sink) {
exists(NonConstantTimeEqualsCall call |
sink.asExpr() = [call.getAnArgument(), call.getQualifier()]
)
@@ -226,6 +225,8 @@ private class UserInputInComparisonConfig extends TaintTracking2::Configuration
}
}
private module UserInputInComparisonFlow = TaintTracking::Global<UserInputInComparisonConfig>;
/** Holds if `expr` looks like a constant. */
private predicate looksLikeConstant(Expr expr) {
expr.isCompileTimeConstant()
@@ -301,21 +302,18 @@ class NonConstantTimeComparisonSink extends DataFlow::Node {
}
/** Holds if remote user input was used in the comparison. */
predicate includesUserInput() {
exists(UserInputInComparisonConfig config |
config.hasFlowTo(DataFlow2::exprNode(anotherParameter))
)
}
predicate includesUserInput() { UserInputInComparisonFlow::flowToExpr(anotherParameter) }
}
/**
* A configuration that tracks data flow from cryptographic operations
* to methods that compare data using a non-constant-time algorithm.
*/
class NonConstantTimeCryptoComparisonConfig extends TaintTracking::Configuration {
NonConstantTimeCryptoComparisonConfig() { this = "NonConstantTimeCryptoComparisonConfig" }
module NonConstantTimeCryptoComparisonConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node source) { source instanceof CryptoOperationSource }
override predicate isSource(DataFlow::Node source) { source instanceof CryptoOperationSource }
override predicate isSink(DataFlow::Node sink) { sink instanceof NonConstantTimeComparisonSink }
predicate isSink(DataFlow::Node sink) { sink instanceof NonConstantTimeComparisonSink }
}
module NonConstantTimeCryptoComparisonFlow =
TaintTracking::Global<NonConstantTimeCryptoComparisonConfig>;

View File

@@ -15,9 +15,11 @@
import java
import NonConstantTimeCheckOnSignatureQuery
import DataFlow::PathGraph
import NonConstantTimeCryptoComparisonFlow::PathGraph
from DataFlow::PathNode source, DataFlow::PathNode sink, NonConstantTimeCryptoComparisonConfig conf
where conf.hasFlowPath(source, sink)
from
NonConstantTimeCryptoComparisonFlow::PathNode source,
NonConstantTimeCryptoComparisonFlow::PathNode sink
where NonConstantTimeCryptoComparisonFlow::flowPath(source, sink)
select sink.getNode(), source, sink, "Possible timing attack against $@ validation.", source,
source.getNode().(CryptoOperationSource).getCall().getResultType()

View File

@@ -14,7 +14,7 @@
import java
import semmle.code.java.dataflow.FlowSources
import semmle.code.java.dataflow.TaintTracking
import DataFlow::PathGraph
import NonConstantTimeComparisonFlow::PathGraph
/** A static method that uses a non-constant-time algorithm for comparing inputs. */
private class NonConstantTimeComparisonCall extends StaticMethodAccess {
@@ -54,20 +54,18 @@ class ClientSuppliedIpTokenCheck extends DataFlow::Node {
}
}
class NonConstantTimeComparisonConfig extends TaintTracking::Configuration {
NonConstantTimeComparisonConfig() { this = "NonConstantTimeComparisonConfig" }
module NonConstantTimeComparisonConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node source) { source instanceof ClientSuppliedIpTokenCheck }
override predicate isSource(DataFlow::Node source) {
source instanceof ClientSuppliedIpTokenCheck
}
override predicate isSink(DataFlow::Node sink) {
predicate isSink(DataFlow::Node sink) {
isNonConstantEqualsCallArgument(sink.asExpr()) or
isNonConstantComparisonCallArgument(sink.asExpr())
}
}
from DataFlow::PathNode source, DataFlow::PathNode sink, NonConstantTimeComparisonConfig conf
where conf.hasFlowPath(source, sink)
module NonConstantTimeComparisonFlow = TaintTracking::Global<NonConstantTimeComparisonConfig>;
from NonConstantTimeComparisonFlow::PathNode source, NonConstantTimeComparisonFlow::PathNode sink
where NonConstantTimeComparisonFlow::flowPath(source, sink)
select sink.getNode(), source, sink, "Possible timing attack against $@ validation.",
source.getNode(), "client-supplied token"

View File

@@ -16,11 +16,13 @@
import java
import NonConstantTimeCheckOnSignatureQuery
import DataFlow::PathGraph
import NonConstantTimeCryptoComparisonFlow::PathGraph
from DataFlow::PathNode source, DataFlow::PathNode sink, NonConstantTimeCryptoComparisonConfig conf
from
NonConstantTimeCryptoComparisonFlow::PathNode source,
NonConstantTimeCryptoComparisonFlow::PathNode sink
where
conf.hasFlowPath(source, sink) and
NonConstantTimeCryptoComparisonFlow::flowPath(source, sink) and
(
source.getNode().(CryptoOperationSource).includesUserInput() and
sink.getNode().(NonConstantTimeComparisonSink).includesUserInput()

View File

@@ -66,16 +66,14 @@ private class JxBrowserSafeLoadHandler extends RefType {
* Models flow from the source `new Browser()` to a sink `browser.setLoadHandler(loadHandler)` where `loadHandler`
* has been determined to be safe.
*/
private class JxBrowserFlowConfiguration extends DataFlow::Configuration {
JxBrowserFlowConfiguration() { this = "JxBrowserFlowConfiguration" }
override predicate isSource(DataFlow::Node src) {
private module JxBrowserFlowConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node src) {
exists(ClassInstanceExpr newJxBrowser | newJxBrowser.getConstructedType() instanceof JxBrowser |
newJxBrowser = src.asExpr()
)
}
override predicate isSink(DataFlow::Node sink) {
predicate isSink(DataFlow::Node sink) {
exists(MethodAccess ma | ma.getMethod() instanceof JxBrowserSetLoadHandler |
ma.getArgument(0).getType() instanceof JxBrowserSafeLoadHandler and
ma.getQualifier() = sink.asExpr()
@@ -83,9 +81,11 @@ private class JxBrowserFlowConfiguration extends DataFlow::Configuration {
}
}
from JxBrowserFlowConfiguration cfg, DataFlow::Node src
private module JxBrowserFlow = DataFlow::Global<JxBrowserFlowConfig>;
from DataFlow::Node src
where
cfg.isSource(src) and
not cfg.hasFlow(src, _) and
JxBrowserFlowConfig::isSource(src) and
not JxBrowserFlow::flow(src, _) and
not isSafeJxBrowserVersion()
select src, "This JxBrowser instance may not check HTTPS certificates."

View File

@@ -13,8 +13,8 @@
import java
import RevocationCheckingLib
import DataFlow::PathGraph
import DisabledRevocationCheckingFlow::PathGraph
from DataFlow::PathNode source, DataFlow::PathNode sink, DisabledRevocationCheckingConfig config
where config.hasFlowPath(source, sink)
from DisabledRevocationCheckingFlow::PathNode source, DisabledRevocationCheckingFlow::PathNode sink
where DisabledRevocationCheckingFlow::flowPath(source, sink)
select source.getNode(), source, sink, "This disables revocation checking."

View File

@@ -5,16 +5,16 @@ import DataFlow
/**
* A taint-tracking configuration for disabling revocation checking.
*/
class DisabledRevocationCheckingConfig extends TaintTracking::Configuration {
DisabledRevocationCheckingConfig() { this = "DisabledRevocationCheckingConfig" }
override predicate isSource(DataFlow::Node source) {
exists(BooleanLiteral b | b.getBooleanValue() = false | source.asExpr() = b)
module DisabledRevocationCheckingConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node source) {
source.asExpr().(BooleanLiteral).getBooleanValue() = false
}
override predicate isSink(DataFlow::Node sink) { sink instanceof SetRevocationEnabledSink }
predicate isSink(DataFlow::Node sink) { sink instanceof SetRevocationEnabledSink }
}
module DisabledRevocationCheckingFlow = TaintTracking::Global<DisabledRevocationCheckingConfig>;
/**
* A sink that disables revocation checking,
* i.e. calling `PKIXParameters.setRevocationEnabled(false)`

View File

@@ -50,12 +50,8 @@ predicate isCreatingAzureClientSideEncryptionObjectNewVersion(Call call, Class c
/**
* A dataflow config that tracks `EncryptedBlobClientBuilder.version` argument initialization.
*/
private class EncryptedBlobClientBuilderSafeEncryptionVersionConfig extends DataFlow::Configuration {
EncryptedBlobClientBuilderSafeEncryptionVersionConfig() {
this = "EncryptedBlobClientBuilderSafeEncryptionVersionConfig"
}
override predicate isSource(DataFlow::Node source) {
private module EncryptedBlobClientBuilderSafeEncryptionVersionConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node source) {
exists(FieldRead fr, Field f | fr = source.asExpr() |
f.getAnAccess() = fr and
f.hasQualifiedName("com.azure.storage.blob.specialized.cryptography", "EncryptionVersion",
@@ -63,21 +59,22 @@ private class EncryptedBlobClientBuilderSafeEncryptionVersionConfig extends Data
)
}
override predicate isSink(DataFlow::Node sink) {
predicate isSink(DataFlow::Node sink) {
isCreatingAzureClientSideEncryptionObjectNewVersion(_, _, sink.asExpr())
}
}
private module EncryptedBlobClientBuilderSafeEncryptionVersionFlow =
DataFlow::Global<EncryptedBlobClientBuilderSafeEncryptionVersionConfig>;
/**
* Holds if `call` is an object creation for a class `EncryptedBlobClientBuilder`
* that takes `versionArg` as the argument specifying the encryption version, and that version is safe.
*/
predicate isCreatingSafeAzureClientSideEncryptionObject(Call call, Class c, Expr versionArg) {
isCreatingAzureClientSideEncryptionObjectNewVersion(call, c, versionArg) and
exists(EncryptedBlobClientBuilderSafeEncryptionVersionConfig config, DataFlow::Node sink |
sink.asExpr() = versionArg
|
config.hasFlow(_, sink)
exists(DataFlow::Node sink | sink.asExpr() = versionArg |
EncryptedBlobClientBuilderSafeEncryptionVersionFlow::flowTo(sink)
)
}

View File

@@ -1,18 +1,14 @@
import java
import semmle.code.java.security.Encryption
import semmle.code.java.dataflow.TaintTracking
import DataFlow
import PathGraph
/**
* A taint-tracking configuration for unsafe SSL and TLS versions.
*/
class UnsafeTlsVersionConfig extends TaintTracking::Configuration {
UnsafeTlsVersionConfig() { this = "UnsafeTlsVersion::UnsafeTlsVersionConfig" }
module UnsafeTlsVersionConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node source) { source.asExpr() instanceof UnsafeTlsVersion }
override predicate isSource(DataFlow::Node source) { source.asExpr() instanceof UnsafeTlsVersion }
override predicate isSink(DataFlow::Node sink) {
predicate isSink(DataFlow::Node sink) {
sink instanceof SslContextGetInstanceSink or
sink instanceof CreateSslParametersSink or
sink instanceof SslParametersSetProtocolsSink or
@@ -20,6 +16,8 @@ class UnsafeTlsVersionConfig extends TaintTracking::Configuration {
}
}
module UnsafeTlsVersionFlow = TaintTracking::Global<UnsafeTlsVersionConfig>;
/**
* A sink that sets protocol versions in `SSLContext`,
* i.e `SSLContext.getInstance(protocol)`.

View File

@@ -13,9 +13,9 @@
import java
import SslLib
import DataFlow::PathGraph
import UnsafeTlsVersionFlow::PathGraph
from DataFlow::PathNode source, DataFlow::PathNode sink, UnsafeTlsVersionConfig conf
where conf.hasFlowPath(source, sink)
from UnsafeTlsVersionFlow::PathNode source, UnsafeTlsVersionFlow::PathNode sink
where UnsafeTlsVersionFlow::flowPath(source, sink)
select sink.getNode(), source, sink, "$@ is unsafe.", source.getNode(),
source.getNode().asExpr().(StringLiteral).getValue()

View File

@@ -14,8 +14,7 @@ import java
import semmle.code.java.dataflow.FlowSources
import semmle.code.java.frameworks.Servlets
import semmle.code.java.dataflow.TaintTracking
import semmle.code.java.dataflow.TaintTracking2
import DataFlow::PathGraph
import CorsOriginFlow::PathGraph
/**
* Holds if `header` sets `Access-Control-Allow-Credentials` to `true`. This ensures fair chances of exploitability.
@@ -48,24 +47,25 @@ private Expr getAccessControlAllowOriginHeaderName() {
}
/**
* This taintflow2 configuration checks if there is a flow from source node towards CorsProbableCheckAccess methods.
* A taint-tracking configuration for flow from a source node to CorsProbableCheckAccess methods.
*/
class CorsSourceReachesCheckConfig extends TaintTracking2::Configuration {
CorsSourceReachesCheckConfig() { this = "CorsOriginConfig" }
module CorsSourceReachesCheckConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node source) { CorsOriginFlow::flow(source, _) }
override predicate isSource(DataFlow::Node source) { any(CorsOriginConfig c).hasFlow(source, _) }
override predicate isSink(DataFlow::Node sink) {
predicate isSink(DataFlow::Node sink) {
sink.asExpr() = any(CorsProbableCheckAccess check).getAnArgument()
}
}
private class CorsOriginConfig extends TaintTracking::Configuration {
CorsOriginConfig() { this = "CorsOriginConfig" }
/**
* Taint-tracking flow from a source node to CorsProbableCheckAccess methods.
*/
module CorsSourceReachesCheckFlow = TaintTracking::Global<CorsSourceReachesCheckConfig>;
override predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource }
private module CorsOriginConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource }
override predicate isSink(DataFlow::Node sink) {
predicate isSink(DataFlow::Node sink) {
exists(MethodAccess corsHeader, MethodAccess allowCredentialsHeader |
(
corsHeader.getMethod() instanceof ResponseSetHeaderMethod or
@@ -79,9 +79,11 @@ private class CorsOriginConfig extends TaintTracking::Configuration {
}
}
from
DataFlow::PathNode source, DataFlow::PathNode sink, CorsOriginConfig conf,
CorsSourceReachesCheckConfig sanconf
where conf.hasFlowPath(source, sink) and not sanconf.hasFlow(source.getNode(), _)
private module CorsOriginFlow = TaintTracking::Global<CorsOriginConfig>;
from CorsOriginFlow::PathNode source, CorsOriginFlow::PathNode sink
where
CorsOriginFlow::flowPath(source, sink) and
not CorsSourceReachesCheckFlow::flow(source.getNode(), _)
select sink.getNode(), source, sink, "CORS header is being set using user controlled value $@.",
source.getNode(), "user-provided value"

View File

@@ -12,29 +12,26 @@
*/
import java
import ClientSuppliedIpUsedInSecurityCheckLib
import semmle.code.java.dataflow.TaintTracking
import semmle.code.java.dataflow.FlowSources
import DataFlow::PathGraph
import ClientSuppliedIpUsedInSecurityCheckLib
import ClientSuppliedIpUsedInSecurityCheckFlow::PathGraph
/**
* Taint-tracking configuration tracing flow from obtaining a client ip from an HTTP header to a sensitive use.
*/
class ClientSuppliedIpUsedInSecurityCheckConfig extends TaintTracking::Configuration {
ClientSuppliedIpUsedInSecurityCheckConfig() { this = "ClientSuppliedIpUsedInSecurityCheckConfig" }
override predicate isSource(DataFlow::Node source) {
module ClientSuppliedIpUsedInSecurityCheckConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node source) {
source instanceof ClientSuppliedIpUsedInSecurityCheck
}
override predicate isSink(DataFlow::Node sink) {
sink instanceof ClientSuppliedIpUsedInSecurityCheckSink
}
predicate isSink(DataFlow::Node sink) { sink instanceof ClientSuppliedIpUsedInSecurityCheckSink }
/**
* Splitting a header value by `,` and taking an entry other than the first is sanitizing, because
* later entries may originate from more-trustworthy intermediate proxies, not the original client.
*/
override predicate isSanitizer(DataFlow::Node node) {
predicate isBarrier(DataFlow::Node node) {
exists(ArrayAccess aa, MethodAccess ma | aa.getArray() = ma |
ma.getQualifier() = node.asExpr() and
ma.getMethod() instanceof SplitMethod and
@@ -47,8 +44,12 @@ class ClientSuppliedIpUsedInSecurityCheckConfig extends TaintTracking::Configura
}
}
module ClientSuppliedIpUsedInSecurityCheckFlow =
TaintTracking::Global<ClientSuppliedIpUsedInSecurityCheckConfig>;
from
DataFlow::PathNode source, DataFlow::PathNode sink, ClientSuppliedIpUsedInSecurityCheckConfig conf
where conf.hasFlowPath(source, sink)
ClientSuppliedIpUsedInSecurityCheckFlow::PathNode source,
ClientSuppliedIpUsedInSecurityCheckFlow::PathNode sink
where ClientSuppliedIpUsedInSecurityCheckFlow::flowPath(source, sink)
select sink.getNode(), source, sink, "IP address spoofing might include code from $@.",
source.getNode(), "this user input"

View File

@@ -1,7 +1,6 @@
import java
import semmle.code.java.dataflow.DataFlow
import semmle.code.java.dataflow.FlowSources
import DataFlow::PathGraph
/** Json string type data. */
abstract class JsonStringSource extends DataFlow::Node { }

View File

@@ -12,35 +12,37 @@
*/
import java
import JsonpInjectionLib
import semmle.code.java.dataflow.TaintTracking
import semmle.code.java.dataflow.FlowSources
import semmle.code.java.deadcode.WebEntryPoints
import DataFlow::PathGraph
import semmle.code.java.security.XSS
import JsonpInjectionLib
import RequestResponseFlow::PathGraph
/** Taint-tracking configuration tracing flow from get method request sources to output jsonp data. */
class RequestResponseFlowConfig extends TaintTracking::Configuration {
RequestResponseFlowConfig() { this = "RequestResponseFlowConfig" }
override predicate isSource(DataFlow::Node source) {
module RequestResponseFlowConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node source) {
source instanceof RemoteFlowSource and
any(RequestGetMethod m).polyCalls*(source.getEnclosingCallable())
}
override predicate isSink(DataFlow::Node sink) {
predicate isSink(DataFlow::Node sink) {
sink instanceof XssSink and
any(RequestGetMethod m).polyCalls*(sink.getEnclosingCallable())
}
override predicate isAdditionalTaintStep(DataFlow::Node pred, DataFlow::Node succ) {
predicate isAdditionalFlowStep(DataFlow::Node pred, DataFlow::Node succ) {
exists(MethodAccess ma |
isRequestGetParamMethod(ma) and pred.asExpr() = ma.getQualifier() and succ.asExpr() = ma
)
}
}
from DataFlow::PathNode source, DataFlow::PathNode sink, RequestResponseFlowConfig conf
module RequestResponseFlow = TaintTracking::Global<RequestResponseFlowConfig>;
from RequestResponseFlow::PathNode source, RequestResponseFlow::PathNode sink
where
conf.hasFlowPath(source, sink) and
exists(JsonpInjectionFlowConfig jhfc | jhfc.hasFlowTo(sink.getNode()))
RequestResponseFlow::flowPath(source, sink) and
JsonpInjectionFlow::flowTo(sink.getNode())
select sink.getNode(), source, sink, "Jsonp response might include code from $@.", source.getNode(),
"this user input"

View File

@@ -1,11 +1,8 @@
import java
import DataFlow
import JsonStringLib
import semmle.code.java.security.XSS
import semmle.code.java.dataflow.DataFlow
import semmle.code.java.dataflow.DataFlow3
import semmle.code.java.dataflow.FlowSources
import semmle.code.java.frameworks.spring.SpringController
private import JsonStringLib
private import semmle.code.java.security.XSS
private import semmle.code.java.dataflow.TaintTracking
private import semmle.code.java.dataflow.FlowSources
/**
* A method that is called to handle an HTTP GET request.
@@ -81,38 +78,38 @@ class JsonpBuilderExpr extends AddExpr {
}
/** A data flow configuration tracing flow from remote sources to jsonp function name. */
class RemoteFlowConfig extends DataFlow2::Configuration {
RemoteFlowConfig() { this = "RemoteFlowConfig" }
module RemoteFlowConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node src) { src instanceof RemoteFlowSource }
override predicate isSource(DataFlow::Node src) { src instanceof RemoteFlowSource }
override predicate isSink(DataFlow::Node sink) {
predicate isSink(DataFlow::Node sink) {
exists(JsonpBuilderExpr jhe | jhe.getFunctionName() = sink.asExpr())
}
}
module RemoteFlow = DataFlow::Global<RemoteFlowConfig>;
/** A data flow configuration tracing flow from json data into the argument `json` of JSONP-like string `someFunctionName + "(" + json + ")"`. */
class JsonDataFlowConfig extends DataFlow2::Configuration {
JsonDataFlowConfig() { this = "JsonDataFlowConfig" }
module JsonDataFlowConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node src) { src instanceof JsonStringSource }
override predicate isSource(DataFlow::Node src) { src instanceof JsonStringSource }
override predicate isSink(DataFlow::Node sink) {
predicate isSink(DataFlow::Node sink) {
exists(JsonpBuilderExpr jhe | jhe.getJsonExpr() = sink.asExpr())
}
}
/** Taint-tracking configuration tracing flow from probable jsonp data with a user-controlled function name to an outgoing HTTP entity. */
class JsonpInjectionFlowConfig extends TaintTracking::Configuration {
JsonpInjectionFlowConfig() { this = "JsonpInjectionFlowConfig" }
module JsonDataFlow = DataFlow::Global<JsonDataFlowConfig>;
override predicate isSource(DataFlow::Node src) {
exists(JsonpBuilderExpr jhe, JsonDataFlowConfig jdfc, RemoteFlowConfig rfc |
/** Taint-tracking configuration tracing flow from probable jsonp data with a user-controlled function name to an outgoing HTTP entity. */
module JsonpInjectionFlowConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node src) {
exists(JsonpBuilderExpr jhe |
jhe = src.asExpr() and
jdfc.hasFlowTo(DataFlow::exprNode(jhe.getJsonExpr())) and
rfc.hasFlowTo(DataFlow::exprNode(jhe.getFunctionName()))
JsonDataFlow::flowTo(DataFlow::exprNode(jhe.getJsonExpr())) and
RemoteFlow::flowTo(DataFlow::exprNode(jhe.getFunctionName()))
)
}
override predicate isSink(DataFlow::Node sink) { sink instanceof XssSink }
predicate isSink(DataFlow::Node sink) { sink instanceof XssSink }
}
module JsonpInjectionFlow = TaintTracking::Global<JsonpInjectionFlowConfig>;

View File

@@ -11,8 +11,9 @@
import java
import ThreadResourceAbuse
import semmle.code.java.dataflow.TaintTracking
import semmle.code.java.dataflow.FlowSources
import DataFlow::PathGraph
import ThreadResourceAbuseFlow::PathGraph
/** The `getInitParameter` method of servlet or JSF. */
class GetInitParameter extends Method {
@@ -41,18 +42,16 @@ class InitParameterInput extends LocalUserInput {
}
/** Taint configuration of uncontrolled thread resource consumption from local user input. */
class ThreadResourceAbuse extends TaintTracking::Configuration {
ThreadResourceAbuse() { this = "ThreadResourceAbuse" }
module ThreadResourceAbuseConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node source) { source instanceof LocalUserInput }
override predicate isSource(DataFlow::Node source) { source instanceof LocalUserInput }
predicate isSink(DataFlow::Node sink) { sink instanceof PauseThreadSink }
override predicate isSink(DataFlow::Node sink) { sink instanceof PauseThreadSink }
override predicate isAdditionalTaintStep(DataFlow::Node pred, DataFlow::Node succ) {
predicate isAdditionalFlowStep(DataFlow::Node pred, DataFlow::Node succ) {
any(AdditionalValueStep r).step(pred, succ)
}
override predicate isSanitizer(DataFlow::Node node) {
predicate isBarrier(DataFlow::Node node) {
exists(
MethodAccess ma // Math.min(sleepTime, MAX_INTERVAL)
|
@@ -64,7 +63,9 @@ class ThreadResourceAbuse extends TaintTracking::Configuration {
}
}
from DataFlow::PathNode source, DataFlow::PathNode sink, ThreadResourceAbuse conf
where conf.hasFlowPath(source, sink)
module ThreadResourceAbuseFlow = TaintTracking::Global<ThreadResourceAbuseConfig>;
from ThreadResourceAbuseFlow::PathNode source, ThreadResourceAbuseFlow::PathNode sink
where ThreadResourceAbuseFlow::flowPath(source, sink)
select sink.getNode(), source, sink, "Possible uncontrolled resource consumption due to $@.",
source.getNode(), "local user-provided value"

View File

@@ -13,21 +13,19 @@
import java
import ThreadResourceAbuse
import semmle.code.java.dataflow.FlowSources
import DataFlow::PathGraph
import ThreadResourceAbuseFlow::PathGraph
/** Taint configuration of uncontrolled thread resource consumption. */
class ThreadResourceAbuse extends TaintTracking::Configuration {
ThreadResourceAbuse() { this = "ThreadResourceAbuse" }
module ThreadResourceAbuseConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource }
override predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource }
predicate isSink(DataFlow::Node sink) { sink instanceof PauseThreadSink }
override predicate isSink(DataFlow::Node sink) { sink instanceof PauseThreadSink }
override predicate isAdditionalTaintStep(DataFlow::Node pred, DataFlow::Node succ) {
predicate isAdditionalFlowStep(DataFlow::Node pred, DataFlow::Node succ) {
any(AdditionalValueStep r).step(pred, succ)
}
override predicate isSanitizer(DataFlow::Node node) {
predicate isBarrier(DataFlow::Node node) {
exists(
MethodAccess ma // Math.min(sleepTime, MAX_INTERVAL)
|
@@ -39,8 +37,10 @@ class ThreadResourceAbuse extends TaintTracking::Configuration {
}
}
from DataFlow::PathNode source, DataFlow::PathNode sink, ThreadResourceAbuse conf
where conf.hasFlowPath(source, sink)
module ThreadResourceAbuseFlow = TaintTracking::Global<ThreadResourceAbuseConfig>;
from ThreadResourceAbuseFlow::PathNode source, ThreadResourceAbuseFlow::PathNode sink
where ThreadResourceAbuseFlow::flowPath(source, sink)
select sink.getNode(), source, sink,
"Vulnerability of uncontrolled resource consumption due to $@.", source.getNode(),
"user-provided value"

View File

@@ -17,7 +17,7 @@ import UnsafeReflectionLib
import semmle.code.java.dataflow.DataFlow
import semmle.code.java.dataflow.FlowSources
import semmle.code.java.controlflow.Guards
import DataFlow::PathGraph
import UnsafeReflectionFlow::PathGraph
private predicate containsSanitizer(Guard g, Expr e, boolean branch) {
g.(MethodAccess).getMethod().hasName("contains") and
@@ -31,14 +31,12 @@ private predicate equalsSanitizer(Guard g, Expr e, boolean branch) {
branch = true
}
class UnsafeReflectionConfig extends TaintTracking::Configuration {
UnsafeReflectionConfig() { this = "UnsafeReflectionConfig" }
module UnsafeReflectionConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource }
override predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource }
predicate isSink(DataFlow::Node sink) { sink instanceof UnsafeReflectionSink }
override predicate isSink(DataFlow::Node sink) { sink instanceof UnsafeReflectionSink }
override predicate isAdditionalTaintStep(DataFlow::Node pred, DataFlow::Node succ) {
predicate isAdditionalFlowStep(DataFlow::Node pred, DataFlow::Node succ) {
// Argument -> return of Class.forName, ClassLoader.loadClass
exists(ReflectiveClassIdentifierMethodAccess rcimac |
rcimac.getArgument(0) = pred.asExpr() and rcimac = succ.asExpr()
@@ -75,12 +73,14 @@ class UnsafeReflectionConfig extends TaintTracking::Configuration {
)
}
override predicate isSanitizer(DataFlow::Node node) {
predicate isBarrier(DataFlow::Node node) {
node = DataFlow::BarrierGuard<containsSanitizer/3>::getABarrierNode() or
node = DataFlow::BarrierGuard<equalsSanitizer/3>::getABarrierNode()
}
}
module UnsafeReflectionFlow = TaintTracking::Global<UnsafeReflectionConfig>;
private Expr getAMethodArgument(MethodAccess reflectiveCall) {
result = reflectiveCall.(NewInstance).getAnArgument()
or
@@ -88,10 +88,10 @@ private Expr getAMethodArgument(MethodAccess reflectiveCall) {
}
from
DataFlow::PathNode source, DataFlow::PathNode sink, UnsafeReflectionConfig conf,
UnsafeReflectionFlow::PathNode source, UnsafeReflectionFlow::PathNode sink,
MethodAccess reflectiveCall
where
conf.hasFlowPath(source, sink) and
UnsafeReflectionFlow::flowPath(source, sink) and
sink.getNode().asExpr() = reflectiveCall.getQualifier() and
conf.hasFlowToExpr(getAMethodArgument(reflectiveCall))
UnsafeReflectionFlow::flowToExpr(getAMethodArgument(reflectiveCall))
select sink.getNode(), source, sink, "Unsafe reflection of $@.", source.getNode(), "user input"

View File

@@ -16,7 +16,7 @@
import java
import semmle.code.java.dataflow.TaintTracking
import semmle.code.java.frameworks.Rmi
import DataFlow::PathGraph
import BindingUnsafeRemoteObjectFlow::PathGraph
/**
* A method that binds a name to a remote object.
@@ -48,22 +48,20 @@ private predicate hasVulnerableMethod(RefType type) {
* A taint-tracking configuration for unsafe remote objects
* that are vulnerable to deserialization attacks.
*/
private class BindingUnsafeRemoteObjectConfig extends TaintTracking::Configuration {
BindingUnsafeRemoteObjectConfig() { this = "BindingUnsafeRemoteObjectConfig" }
override predicate isSource(DataFlow::Node source) {
private module BindingUnsafeRemoteObjectConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node source) {
exists(ConstructorCall cc | cc = source.asExpr() |
hasVulnerableMethod(cc.getConstructedType().getAnAncestor())
)
}
override predicate isSink(DataFlow::Node sink) {
predicate isSink(DataFlow::Node sink) {
exists(MethodAccess ma | ma.getArgument(1) = sink.asExpr() |
ma.getMethod() instanceof BindMethod
)
}
override predicate isAdditionalTaintStep(DataFlow::Node fromNode, DataFlow::Node toNode) {
predicate isAdditionalFlowStep(DataFlow::Node fromNode, DataFlow::Node toNode) {
exists(MethodAccess ma, Method m | m = ma.getMethod() |
m.getDeclaringType().hasQualifiedName("java.rmi.server", "UnicastRemoteObject") and
m.hasName("exportObject") and
@@ -74,6 +72,9 @@ private class BindingUnsafeRemoteObjectConfig extends TaintTracking::Configurati
}
}
from DataFlow::PathNode source, DataFlow::PathNode sink, BindingUnsafeRemoteObjectConfig conf
where conf.hasFlowPath(source, sink)
private module BindingUnsafeRemoteObjectFlow =
TaintTracking::Global<BindingUnsafeRemoteObjectConfig>;
from BindingUnsafeRemoteObjectFlow::PathNode source, BindingUnsafeRemoteObjectFlow::PathNode sink
where BindingUnsafeRemoteObjectFlow::flowPath(source, sink)
select sink.getNode(), source, sink, "Unsafe deserialization in a remote object."

View File

@@ -17,12 +17,10 @@ import semmle.code.java.dataflow.FlowSources
import semmle.code.java.dataflow.TaintTracking
import experimental.semmle.code.java.frameworks.Jsf
import semmle.code.java.security.PathSanitizer
import DataFlow::PathGraph
import UnsafeUrlForwardFlow::PathGraph
class UnsafeUrlForwardFlowConfig extends TaintTracking::Configuration {
UnsafeUrlForwardFlowConfig() { this = "UnsafeUrlForwardFlowConfig" }
override predicate isSource(DataFlow::Node source) {
module UnsafeUrlForwardFlowConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node source) {
source instanceof RemoteFlowSource and
not exists(MethodAccess ma, Method m | ma.getMethod() = m |
(
@@ -34,18 +32,16 @@ class UnsafeUrlForwardFlowConfig extends TaintTracking::Configuration {
)
}
override predicate isSink(DataFlow::Node sink) { sink instanceof UnsafeUrlForwardSink }
predicate isSink(DataFlow::Node sink) { sink instanceof UnsafeUrlForwardSink }
override predicate isSanitizer(DataFlow::Node node) {
predicate isBarrier(DataFlow::Node node) {
node instanceof UnsafeUrlForwardSanitizer or
node instanceof PathInjectionSanitizer
}
override DataFlow::FlowFeature getAFeature() {
result instanceof DataFlow::FeatureHasSourceCallContext
}
DataFlow::FlowFeature getAFeature() { result instanceof DataFlow::FeatureHasSourceCallContext }
override predicate isAdditionalTaintStep(DataFlow::Node prev, DataFlow::Node succ) {
predicate isAdditionalFlowStep(DataFlow::Node prev, DataFlow::Node succ) {
exists(MethodAccess ma |
(
ma.getMethod() instanceof GetServletResourceMethod or
@@ -60,7 +56,9 @@ class UnsafeUrlForwardFlowConfig extends TaintTracking::Configuration {
}
}
from DataFlow::PathNode source, DataFlow::PathNode sink, UnsafeUrlForwardFlowConfig conf
where conf.hasFlowPath(source, sink)
module UnsafeUrlForwardFlow = TaintTracking::Global<UnsafeUrlForwardFlowConfig>;
from UnsafeUrlForwardFlow::PathNode source, UnsafeUrlForwardFlow::PathNode sink
where UnsafeUrlForwardFlow::flowPath(source, sink)
select sink.getNode(), source, sink, "Potentially untrusted URL forward due to $@.",
source.getNode(), "user-provided value"

View File

@@ -14,7 +14,7 @@ import java
import semmle.code.java.dataflow.FlowSources
import semmle.code.java.dataflow.TaintTracking
import semmle.code.java.security.SensitiveActions
import DataFlow::PathGraph
import SensitiveGetQueryFlow::PathGraph
/** A variable that holds sensitive information judging by its name. */
class SensitiveInfoExpr extends Expr {
@@ -59,22 +59,22 @@ class RequestGetParamSource extends DataFlow::ExprNode {
}
/** A taint configuration tracking flow from the `ServletRequest` of a GET request handler to an expression whose name suggests it holds security-sensitive data. */
class SensitiveGetQueryConfiguration extends TaintTracking::Configuration {
SensitiveGetQueryConfiguration() { this = "SensitiveGetQueryConfiguration" }
module SensitiveGetQueryConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node source) { source instanceof RequestGetParamSource }
override predicate isSource(DataFlow::Node source) { source instanceof RequestGetParamSource }
override predicate isSink(DataFlow::Node sink) { sink.asExpr() instanceof SensitiveInfoExpr }
predicate isSink(DataFlow::Node sink) { sink.asExpr() instanceof SensitiveInfoExpr }
/** Holds if the node is in a servlet method other than `doGet`. */
override predicate isSanitizer(DataFlow::Node node) {
predicate isBarrier(DataFlow::Node node) {
isServletRequestMethod(node.getEnclosingCallable()) and
not isGetServletMethod(node.getEnclosingCallable())
}
}
from DataFlow::PathNode source, DataFlow::PathNode sink, SensitiveGetQueryConfiguration c
where c.hasFlowPath(source, sink)
module SensitiveGetQueryFlow = TaintTracking::Global<SensitiveGetQueryConfig>;
from SensitiveGetQueryFlow::PathNode source, SensitiveGetQueryFlow::PathNode sink
where SensitiveGetQueryFlow::flowPath(source, sink)
select sink.getNode(), source, sink,
"$@ uses the GET request method to transmit sensitive information.", source.getNode(),
"This request"

View File

@@ -18,7 +18,7 @@ import semmle.code.java.dataflow.FlowSources
import semmle.code.java.dataflow.TaintTracking
import semmle.code.java.frameworks.Servlets
import semmle.code.xml.WebXML
import DataFlow::PathGraph
import UncaughtServletExceptionFlow::PathGraph
/** Holds if a given exception type is caught. */
private predicate exceptionIsCaught(TryStmt t, RefType exType) {
@@ -66,15 +66,15 @@ class UncaughtServletExceptionSink extends DataFlow::ExprNode {
}
/** Taint configuration of uncaught exceptions caused by user provided data from `RemoteFlowSource` */
class UncaughtServletExceptionConfiguration extends TaintTracking::Configuration {
UncaughtServletExceptionConfiguration() { this = "UncaughtServletException" }
module UncaughtServletExceptionConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource }
override predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource }
override predicate isSink(DataFlow::Node sink) { sink instanceof UncaughtServletExceptionSink }
predicate isSink(DataFlow::Node sink) { sink instanceof UncaughtServletExceptionSink }
}
from DataFlow::PathNode source, DataFlow::PathNode sink, UncaughtServletExceptionConfiguration c
where c.hasFlowPath(source, sink) and not hasErrorPage()
module UncaughtServletExceptionFlow = TaintTracking::Global<UncaughtServletExceptionConfig>;
from UncaughtServletExceptionFlow::PathNode source, UncaughtServletExceptionFlow::PathNode sink
where UncaughtServletExceptionFlow::flowPath(source, sink) and not hasErrorPage()
select sink.getNode(), source, sink, "This value depends on a $@ and can throw uncaught exception.",
source.getNode(), "user-provided value"

View File

@@ -15,7 +15,7 @@ import java
import experimental.semmle.code.java.security.SpringUrlRedirect
import semmle.code.java.dataflow.FlowSources
import semmle.code.java.controlflow.Guards
import DataFlow::PathGraph
import SpringUrlRedirectFlow::PathGraph
private predicate startsWithSanitizer(Guard g, Expr e, boolean branch) {
g.(MethodAccess).getMethod().hasName("startsWith") and
@@ -25,18 +25,16 @@ private predicate startsWithSanitizer(Guard g, Expr e, boolean branch) {
branch = true
}
class SpringUrlRedirectFlowConfig extends TaintTracking::Configuration {
SpringUrlRedirectFlowConfig() { this = "SpringUrlRedirectFlowConfig" }
module SpringUrlRedirectFlowConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource }
override predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource }
predicate isSink(DataFlow::Node sink) { sink instanceof SpringUrlRedirectSink }
override predicate isSink(DataFlow::Node sink) { sink instanceof SpringUrlRedirectSink }
override predicate isAdditionalTaintStep(DataFlow::Node fromNode, DataFlow::Node toNode) {
predicate isAdditionalFlowStep(DataFlow::Node fromNode, DataFlow::Node toNode) {
springUrlRedirectTaintStep(fromNode, toNode)
}
override predicate isSanitizer(DataFlow::Node node) {
predicate isBarrier(DataFlow::Node node) {
// Exclude the case where the left side of the concatenated string is not `redirect:`.
// E.g: `String url = "/path?token=" + request.getParameter("token");`
// Note this is quite a broad sanitizer (it will also sanitize the right-hand side of `url = "http://" + request.getParameter("token")`);
@@ -62,7 +60,9 @@ class SpringUrlRedirectFlowConfig extends TaintTracking::Configuration {
}
}
from DataFlow::PathNode source, DataFlow::PathNode sink, SpringUrlRedirectFlowConfig conf
where conf.hasFlowPath(source, sink)
module SpringUrlRedirectFlow = TaintTracking::Global<SpringUrlRedirectFlowConfig>;
from SpringUrlRedirectFlow::PathNode source, SpringUrlRedirectFlow::PathNode sink
where SpringUrlRedirectFlow::flowPath(source, sink)
select sink.getNode(), source, sink, "Potentially untrusted URL redirection due to $@.",
source.getNode(), "user-provided value"

View File

@@ -14,18 +14,19 @@
import java
import XXELib
import semmle.code.java.dataflow.TaintTracking
import semmle.code.java.dataflow.FlowSources
import DataFlow::PathGraph
import XxeFlow::PathGraph
class XxeConfig extends TaintTracking::Configuration {
XxeConfig() { this = "XxeConfig" }
module XxeConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node src) { src instanceof RemoteFlowSource }
override predicate isSource(DataFlow::Node src) { src instanceof RemoteFlowSource }
override predicate isSink(DataFlow::Node sink) { sink instanceof UnsafeXxeSink }
predicate isSink(DataFlow::Node sink) { sink instanceof UnsafeXxeSink }
}
from DataFlow::PathNode source, DataFlow::PathNode sink, XxeConfig conf
where conf.hasFlowPath(source, sink)
module XxeFlow = TaintTracking::Global<XxeConfig>;
from XxeFlow::PathNode source, XxeFlow::PathNode sink
where XxeFlow::flowPath(source, sink)
select sink.getNode(), source, sink, "Unsafe parsing of XML file from $@.", source.getNode(),
"user input"

View File

@@ -52,9 +52,7 @@ class ValidatorValidate extends XmlParserCall {
override Expr getSink() { result = this.getArgument(0) }
override predicate isSafe() {
exists(SafeValidatorFlowConfig svfc | svfc.hasFlowToExpr(this.getQualifier()))
}
override predicate isSafe() { SafeValidatorFlow::flowToExpr(this.getQualifier()) }
}
/** A `ParserConfig` specific to `Validator`. */
@@ -82,21 +80,21 @@ class SafeValidator extends VarAccess {
}
}
private class SafeValidatorFlowConfig extends DataFlow3::Configuration {
SafeValidatorFlowConfig() { this = "SafeValidatorFlowConfig" }
private module SafeValidatorFlowConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node src) { src.asExpr() instanceof SafeValidator }
override predicate isSource(DataFlow::Node src) { src.asExpr() instanceof SafeValidator }
override predicate isSink(DataFlow::Node sink) {
predicate isSink(DataFlow::Node sink) {
exists(MethodAccess ma |
sink.asExpr() = ma.getQualifier() and
ma.getMethod().getDeclaringType() instanceof Validator
)
}
override int fieldFlowBranchLimit() { result = 0 }
int fieldFlowBranchLimit() { result = 0 }
}
private module SafeValidatorFlow = DataFlow::Global<SafeValidatorFlowConfig>;
/**
* The classes `org.apache.commons.digester3.Digester`, `org.apache.commons.digester.Digester` or `org.apache.tomcat.util.digester.Digester`.
*/
@@ -121,9 +119,7 @@ class DigesterParse extends XmlParserCall {
override Expr getSink() { result = this.getArgument(0) }
override predicate isSafe() {
exists(SafeDigesterFlowConfig sdfc | sdfc.hasFlowToExpr(this.getQualifier()))
}
override predicate isSafe() { SafeDigesterFlow::flowToExpr(this.getQualifier()) }
}
/** A `ParserConfig` that is specific to `Digester`. */
@@ -170,20 +166,20 @@ class SafeDigester extends VarAccess {
}
}
private class SafeDigesterFlowConfig extends DataFlow4::Configuration {
SafeDigesterFlowConfig() { this = "SafeDigesterFlowConfig" }
private module SafeDigesterFlowConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node src) { src.asExpr() instanceof SafeDigester }
override predicate isSource(DataFlow::Node src) { src.asExpr() instanceof SafeDigester }
override predicate isSink(DataFlow::Node sink) {
predicate isSink(DataFlow::Node sink) {
exists(MethodAccess ma |
sink.asExpr() = ma.getQualifier() and ma.getMethod().getDeclaringType() instanceof Digester
)
}
override int fieldFlowBranchLimit() { result = 0 }
int fieldFlowBranchLimit() { result = 0 }
}
private module SafeDigesterFlow = DataFlow::Global<SafeDigesterFlowConfig>;
/** The class `java.beans.XMLDecoder`. */
class XmlDecoder extends RefType {
XmlDecoder() { this.hasQualifiedName("java.beans", "XMLDecoder") }

View File

@@ -16,18 +16,19 @@
import java
import XXELib
import semmle.code.java.dataflow.TaintTracking
import semmle.code.java.dataflow.FlowSources
import DataFlow::PathGraph
import XxeLocalFlow::PathGraph
class XxeLocalConfig extends TaintTracking::Configuration {
XxeLocalConfig() { this = "XxeLocalConfig" }
module XxeLocalConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node src) { src instanceof LocalUserInput }
override predicate isSource(DataFlow::Node src) { src instanceof LocalUserInput }
override predicate isSink(DataFlow::Node sink) { sink instanceof UnsafeXxeSink }
predicate isSink(DataFlow::Node sink) { sink instanceof UnsafeXxeSink }
}
from DataFlow::PathNode source, DataFlow::PathNode sink, XxeLocalConfig conf
where conf.hasFlowPath(source, sink)
module XxeLocalFlow = TaintTracking::Global<XxeLocalConfig>;
from XxeLocalFlow::PathNode source, XxeLocalFlow::PathNode sink
where XxeLocalFlow::flowPath(source, sink)
select sink.getNode(), source, sink, "Unsafe parsing of XML file from $@.", source.getNode(),
"user input"

View File

@@ -14,10 +14,10 @@
import java
import semmle.code.java.dataflow.FlowSources
import DataFlow::PathGraph
import MatchRegexFlow::PathGraph
import PermissiveDotRegexQuery
from DataFlow::PathNode source, DataFlow::PathNode sink, MatchRegexConfiguration conf
where conf.hasFlowPath(source, sink)
from MatchRegexFlow::PathNode source, MatchRegexFlow::PathNode sink
where MatchRegexFlow::flowPath(source, sink)
select sink.getNode(), source, sink, "Potentially authentication bypass due to $@.",
source.getNode(), "user-provided value"

View File

@@ -93,14 +93,12 @@ private class CompileRegexSink extends DataFlow::ExprNode {
/**
* A data flow configuration for regular expressions that include permissive dots.
*/
private class PermissiveDotRegexConfig extends DataFlow2::Configuration {
PermissiveDotRegexConfig() { this = "PermissiveDotRegex::PermissiveDotRegexConfig" }
private module PermissiveDotRegexConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow2::Node src) { src.asExpr() instanceof PermissiveDotStr }
override predicate isSource(DataFlow2::Node src) { src.asExpr() instanceof PermissiveDotStr }
predicate isSink(DataFlow2::Node sink) { sink instanceof CompileRegexSink }
override predicate isSink(DataFlow2::Node sink) { sink instanceof CompileRegexSink }
override predicate isBarrier(DataFlow2::Node node) {
predicate isBarrier(DataFlow2::Node node) {
exists(
MethodAccess ma, Field f // Pattern.compile(PATTERN, Pattern.DOTALL)
|
@@ -113,19 +111,19 @@ private class PermissiveDotRegexConfig extends DataFlow2::Configuration {
}
}
private module PermissiveDotRegexFlow = DataFlow::Global<PermissiveDotRegexConfig>;
/**
* A taint-tracking configuration for untrusted user input used to match regular expressions
* that include permissive dots.
*/
class MatchRegexConfiguration extends TaintTracking::Configuration {
MatchRegexConfiguration() { this = "PermissiveDotRegex::MatchRegexConfiguration" }
override predicate isSource(DataFlow::Node source) {
module MatchRegexConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node source) {
sourceNode(source, "uri-path") or // Servlet uri source
source instanceof SpringUriInputParameterSource // Spring uri source
}
override predicate isSink(DataFlow::Node sink) {
predicate isSink(DataFlow::Node sink) {
sink instanceof MatchRegexSink and
exists(
Guard guard, Expr se, Expr ce // used in a condition to control url redirect, which is a typical security enforcement
@@ -145,7 +143,7 @@ class MatchRegexConfiguration extends TaintTracking::Configuration {
) and
guard.controls(se.getBasicBlock(), true)
) and
exists(MethodAccess ma | any(PermissiveDotRegexConfig conf2).hasFlowToExpr(ma.getArgument(0)) |
exists(MethodAccess ma | PermissiveDotRegexFlow::flowToExpr(ma.getArgument(0)) |
// input.matches(regexPattern)
ma.getMethod() instanceof StringMatchMethod and
ma.getQualifier() = sink.asExpr()
@@ -165,6 +163,8 @@ class MatchRegexConfiguration extends TaintTracking::Configuration {
}
}
module MatchRegexFlow = TaintTracking::Global<MatchRegexConfig>;
/**
* A data flow sink representing a string being matched against a regular expression.
*/

View File

@@ -14,17 +14,15 @@
import java
import semmle.code.java.dataflow.FlowSources
import XQueryInjectionLib
import DataFlow::PathGraph
import XQueryInjectionFlow::PathGraph
/**
* A taint-tracking configuration tracing flow from remote sources, through an XQuery parser, to its eventual execution.
*/
class XQueryInjectionConfig extends TaintTracking::Configuration {
XQueryInjectionConfig() { this = "XQueryInjectionConfig" }
module XQueryInjectionConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource }
override predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource }
override predicate isSink(DataFlow::Node sink) {
predicate isSink(DataFlow::Node sink) {
sink.asExpr() = any(XQueryPreparedExecuteCall xpec).getPreparedExpression() or
sink.asExpr() = any(XQueryExecuteCall xec).getExecuteQueryArgument() or
sink.asExpr() = any(XQueryExecuteCommandCall xecc).getExecuteCommandArgument()
@@ -33,12 +31,17 @@ class XQueryInjectionConfig extends TaintTracking::Configuration {
/**
* Holds if taint from the input `pred` to a `prepareExpression` call flows to the returned prepared expression `succ`.
*/
override predicate isAdditionalTaintStep(DataFlow::Node pred, DataFlow::Node succ) {
predicate isAdditionalFlowStep(DataFlow::Node pred, DataFlow::Node succ) {
exists(XQueryParserCall parser | pred.asExpr() = parser.getInput() and succ.asExpr() = parser)
}
}
from DataFlow::PathNode source, DataFlow::PathNode sink, XQueryInjectionConfig conf
where conf.hasFlowPath(source, sink)
/**
* Taint-tracking flow from remote sources, through an XQuery parser, to its eventual execution.
*/
module XQueryInjectionFlow = TaintTracking::Global<XQueryInjectionConfig>;
from XQueryInjectionFlow::PathNode source, XQueryInjectionFlow::PathNode sink
where XQueryInjectionFlow::flowPath(source, sink)
select sink.getNode(), source, sink, "XQuery query might include code from $@.", source.getNode(),
"this user input"

View File

@@ -32,12 +32,10 @@ predicate isRmiOrJmxServerCreateMethod(Method method) {
* `map.put("jmx.remote.rmi.server.credential.types", value)` call
* to an RMI or JMX initialisation call.
*/
class SafeFlow extends DataFlow::Configuration {
SafeFlow() { this = "MapToPutCredentialstypeConfiguration" }
module SafeFlowConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node source) { putsCredentialtypesKey(source.asExpr()) }
override predicate isSource(DataFlow::Node source) { putsCredentialtypesKey(source.asExpr()) }
override predicate isSink(DataFlow::Node sink) {
predicate isSink(DataFlow::Node sink) {
exists(Call c |
isRmiOrJmxServerCreateConstructor(c.getCallee()) or
isRmiOrJmxServerCreateMethod(c.getCallee())
@@ -71,6 +69,8 @@ class SafeFlow extends DataFlow::Configuration {
}
}
module SafeFlow = DataFlow::Global<SafeFlowConfig>;
/** Gets a string describing why the application is vulnerable, depending on if the vulnerability is present due to a) a null environment b) an insecurely set environment map */
string getRmiResult(Expr e) {
// We got a Map so we have a source and a sink node
@@ -87,5 +87,5 @@ from Call c, Expr envArg
where
(isRmiOrJmxServerCreateConstructor(c.getCallee()) or isRmiOrJmxServerCreateMethod(c.getCallee())) and
envArg = c.getArgument(1) and
not any(SafeFlow conf).hasFlowToExpr(envArg)
not SafeFlow::flowToExpr(envArg)
select c, getRmiResult(envArg), envArg, envArg.toString()

View File

@@ -17,19 +17,17 @@ import java
import semmle.code.java.frameworks.android.Intent
import semmle.code.java.dataflow.FlowSources
import semmle.code.java.NumberFormatException
import DataFlow::PathGraph
import NfeLocalDoSFlow::PathGraph
/**
* Taint configuration tracking flow from untrusted inputs to number conversion calls in exported Android compononents.
*/
class NfeLocalDoSConfiguration extends TaintTracking::Configuration {
NfeLocalDoSConfiguration() { this = "NFELocalDoSConfiguration" }
module NfeLocalDoSConfig implements DataFlow::ConfigSig {
/** Holds if source is a remote flow source */
override predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource }
predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource }
/** Holds if NFE is thrown but not caught */
override predicate isSink(DataFlow::Node sink) {
predicate isSink(DataFlow::Node sink) {
exists(Expr e |
e.getEnclosingCallable().getDeclaringType().(ExportableAndroidComponent).isExported() and
throwsNfe(e) and
@@ -42,8 +40,10 @@ class NfeLocalDoSConfiguration extends TaintTracking::Configuration {
}
}
from DataFlow::PathNode source, DataFlow::PathNode sink, NfeLocalDoSConfiguration conf
where conf.hasFlowPath(source, sink)
module NfeLocalDoSFlow = TaintTracking::Global<NfeLocalDoSConfig>;
from NfeLocalDoSFlow::PathNode source, NfeLocalDoSFlow::PathNode sink
where NfeLocalDoSFlow::flowPath(source, sink)
select sink.getNode(), source, sink,
"Uncaught NumberFormatException in an exported Android component due to $@.", source.getNode(),
"user-provided value"

View File

@@ -12,7 +12,7 @@
import java
import semmle.code.java.dataflow.TaintTracking
import DataFlow::PathGraph
import HashWithoutSaltFlow::PathGraph
/**
* Gets a regular expression for matching common names of variables
@@ -138,12 +138,10 @@ class HashWithoutSaltSink extends DataFlow::ExprNode {
* Taint configuration tracking flow from an expression whose name suggests it holds password data
* to a method call that generates a hash without a salt.
*/
class HashWithoutSaltConfiguration extends TaintTracking::Configuration {
HashWithoutSaltConfiguration() { this = "HashWithoutSaltConfiguration" }
module HashWithoutSaltConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node source) { source.asExpr() instanceof PasswordVarExpr }
override predicate isSource(DataFlow::Node source) { source.asExpr() instanceof PasswordVarExpr }
override predicate isSink(DataFlow::Node sink) { sink instanceof HashWithoutSaltSink }
predicate isSink(DataFlow::Node sink) { sink instanceof HashWithoutSaltSink }
/**
* Holds if a password is concatenated with a salt then hashed together through the call `System.arraycopy(password.getBytes(), ...)`, for example,
@@ -152,7 +150,7 @@ class HashWithoutSaltConfiguration extends TaintTracking::Configuration {
* `byte[] messageDigest = md.digest(allBytes);`
* Or the password is concatenated with a salt as a string.
*/
override predicate isSanitizer(DataFlow::Node node) {
predicate isBarrier(DataFlow::Node node) {
exists(MethodAccess ma |
ma.getMethod().getDeclaringType().hasQualifiedName("java.lang", "System") and
ma.getMethod().hasName("arraycopy") and
@@ -176,6 +174,8 @@ class HashWithoutSaltConfiguration extends TaintTracking::Configuration {
}
}
from DataFlow::PathNode source, DataFlow::PathNode sink, HashWithoutSaltConfiguration cc
where cc.hasFlowPath(source, sink)
module HashWithoutSaltFlow = TaintTracking::Global<HashWithoutSaltConfig>;
from HashWithoutSaltFlow::PathNode source, HashWithoutSaltFlow::PathNode sink
where HashWithoutSaltFlow::flowPath(source, sink)
select sink, source, sink, "$@ is hashed without a salt.", source, "The password"

View File

@@ -1,53 +1,26 @@
edges
| JsonpController.java:33:32:33:68 | getParameter(...) : String | JsonpController.java:37:16:37:24 | resultStr |
| JsonpController.java:36:21:36:54 | ... + ... : String | JsonpController.java:37:16:37:24 | resultStr |
| JsonpController.java:44:32:44:68 | getParameter(...) : String | JsonpController.java:46:16:46:24 | resultStr |
| JsonpController.java:45:21:45:80 | ... + ... : String | JsonpController.java:46:16:46:24 | resultStr |
| JsonpController.java:53:32:53:68 | getParameter(...) : String | JsonpController.java:56:16:56:24 | resultStr |
| JsonpController.java:55:21:55:55 | ... + ... : String | JsonpController.java:56:16:56:24 | resultStr |
| JsonpController.java:63:32:63:68 | getParameter(...) : String | JsonpController.java:66:16:66:24 | resultStr |
| JsonpController.java:65:21:65:54 | ... + ... : String | JsonpController.java:66:16:66:24 | resultStr |
| JsonpController.java:73:32:73:68 | getParameter(...) : String | JsonpController.java:80:20:80:28 | resultStr |
| JsonpController.java:79:21:79:54 | ... + ... : String | JsonpController.java:80:20:80:28 | resultStr |
| JsonpController.java:87:32:87:68 | getParameter(...) : String | JsonpController.java:94:20:94:28 | resultStr |
| JsonpController.java:93:21:93:54 | ... + ... : String | JsonpController.java:94:20:94:28 | resultStr |
| JsonpController.java:101:32:101:68 | getParameter(...) : String | JsonpController.java:105:16:105:24 | resultStr |
| JsonpController.java:104:21:104:54 | ... + ... : String | JsonpController.java:105:16:105:24 | resultStr |
| JsonpController.java:115:21:115:54 | ... + ... : String | JsonpController.java:116:16:116:24 | resultStr |
| JsonpController.java:130:21:130:54 | ... + ... : String | JsonpController.java:131:16:131:24 | resultStr |
nodes
| JsonpController.java:33:32:33:68 | getParameter(...) : String | semmle.label | getParameter(...) : String |
| JsonpController.java:36:21:36:54 | ... + ... : String | semmle.label | ... + ... : String |
| JsonpController.java:37:16:37:24 | resultStr | semmle.label | resultStr |
| JsonpController.java:37:16:37:24 | resultStr | semmle.label | resultStr |
| JsonpController.java:44:32:44:68 | getParameter(...) : String | semmle.label | getParameter(...) : String |
| JsonpController.java:45:21:45:80 | ... + ... : String | semmle.label | ... + ... : String |
| JsonpController.java:46:16:46:24 | resultStr | semmle.label | resultStr |
| JsonpController.java:46:16:46:24 | resultStr | semmle.label | resultStr |
| JsonpController.java:53:32:53:68 | getParameter(...) : String | semmle.label | getParameter(...) : String |
| JsonpController.java:55:21:55:55 | ... + ... : String | semmle.label | ... + ... : String |
| JsonpController.java:56:16:56:24 | resultStr | semmle.label | resultStr |
| JsonpController.java:56:16:56:24 | resultStr | semmle.label | resultStr |
| JsonpController.java:63:32:63:68 | getParameter(...) : String | semmle.label | getParameter(...) : String |
| JsonpController.java:65:21:65:54 | ... + ... : String | semmle.label | ... + ... : String |
| JsonpController.java:66:16:66:24 | resultStr | semmle.label | resultStr |
| JsonpController.java:66:16:66:24 | resultStr | semmle.label | resultStr |
| JsonpController.java:73:32:73:68 | getParameter(...) : String | semmle.label | getParameter(...) : String |
| JsonpController.java:79:21:79:54 | ... + ... : String | semmle.label | ... + ... : String |
| JsonpController.java:80:20:80:28 | resultStr | semmle.label | resultStr |
| JsonpController.java:80:20:80:28 | resultStr | semmle.label | resultStr |
| JsonpController.java:87:32:87:68 | getParameter(...) : String | semmle.label | getParameter(...) : String |
| JsonpController.java:93:21:93:54 | ... + ... : String | semmle.label | ... + ... : String |
| JsonpController.java:94:20:94:28 | resultStr | semmle.label | resultStr |
| JsonpController.java:94:20:94:28 | resultStr | semmle.label | resultStr |
| JsonpController.java:101:32:101:68 | getParameter(...) : String | semmle.label | getParameter(...) : String |
| JsonpController.java:104:21:104:54 | ... + ... : String | semmle.label | ... + ... : String |
| JsonpController.java:105:16:105:24 | resultStr | semmle.label | resultStr |
| JsonpController.java:105:16:105:24 | resultStr | semmle.label | resultStr |
| JsonpController.java:115:21:115:54 | ... + ... : String | semmle.label | ... + ... : String |
| JsonpController.java:116:16:116:24 | resultStr | semmle.label | resultStr |
| JsonpController.java:130:21:130:54 | ... + ... : String | semmle.label | ... + ... : String |
| JsonpController.java:131:16:131:24 | resultStr | semmle.label | resultStr |
subpaths
#select
| JsonpController.java:37:16:37:24 | resultStr | JsonpController.java:33:32:33:68 | getParameter(...) : String | JsonpController.java:37:16:37:24 | resultStr | Jsonp response might include code from $@. | JsonpController.java:33:32:33:68 | getParameter(...) | this user input |