mirror of
https://github.com/github/codeql.git
synced 2025-12-17 01:03:14 +01:00
Merge pull request #12829 from michaelnebel/csharp/refactordataflow4
C#: Re-factor tainttracking and dataflow configurations to use the new API.
This commit is contained in:
@@ -52,23 +52,24 @@ class IDbCommandConstructionSqlExpr extends SqlExpr, ObjectCreation {
|
||||
class DapperCommandDefinitionMethodCallSqlExpr extends SqlExpr, ObjectCreation {
|
||||
DapperCommandDefinitionMethodCallSqlExpr() {
|
||||
this.getObjectType() instanceof Dapper::CommandDefinitionStruct and
|
||||
exists(Conf c | c.hasFlow(DataFlow::exprNode(this), _))
|
||||
DapperCommandDefinitionMethodCallSql::flow(DataFlow::exprNode(this), _)
|
||||
}
|
||||
|
||||
override Expr getSql() { result = this.getArgumentForName("commandText") }
|
||||
}
|
||||
|
||||
private class Conf extends DataFlow4::Configuration {
|
||||
Conf() { this = "DapperCommandDefinitionFlowConfig" }
|
||||
|
||||
override predicate isSource(DataFlow::Node node) {
|
||||
private module DapperCommandDefitionMethodCallSqlConfig implements DataFlow::ConfigSig {
|
||||
predicate isSource(DataFlow::Node node) {
|
||||
node.asExpr().(ObjectCreation).getObjectType() instanceof Dapper::CommandDefinitionStruct
|
||||
}
|
||||
|
||||
override predicate isSink(DataFlow::Node node) {
|
||||
predicate isSink(DataFlow::Node node) {
|
||||
exists(MethodCall mc |
|
||||
mc.getTarget() = any(Dapper::SqlMapperClass c).getAQueryMethod() and
|
||||
node.asExpr() = mc.getArgumentForName("command")
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private module DapperCommandDefinitionMethodCallSql =
|
||||
DataFlow::Global<DapperCommandDefitionMethodCallSqlConfig>;
|
||||
|
||||
@@ -162,18 +162,14 @@ class XmlReaderSettingsCreation extends ObjectCreation {
|
||||
}
|
||||
}
|
||||
|
||||
private class SettingsDataFlowConfig extends DataFlow3::Configuration {
|
||||
SettingsDataFlowConfig() { this = "SettingsDataFlowConfig" }
|
||||
private module SettingsDataFlowConfig implements DataFlow::ConfigSig {
|
||||
predicate isSource(DataFlow::Node source) { source.asExpr() instanceof XmlReaderSettingsCreation }
|
||||
|
||||
override predicate isSource(DataFlow::Node source) {
|
||||
source.asExpr() instanceof XmlReaderSettingsCreation
|
||||
}
|
||||
|
||||
override predicate isSink(DataFlow::Node sink) {
|
||||
sink.asExpr() instanceof XmlReaderSettingsInstance
|
||||
}
|
||||
predicate isSink(DataFlow::Node sink) { sink.asExpr() instanceof XmlReaderSettingsInstance }
|
||||
}
|
||||
|
||||
private module SettingsDataFlow = DataFlow::Global<SettingsDataFlowConfig>;
|
||||
|
||||
/** A call to `XmlReader.Create`. */
|
||||
class XmlReaderCreateCall extends MethodCall {
|
||||
XmlReaderCreateCall() { this.getTarget() = any(SystemXmlXmlReaderClass r).getCreateMethod() }
|
||||
@@ -190,8 +186,6 @@ class XmlReaderSettingsInstance extends Expr {
|
||||
|
||||
/** Gets a possible creation point for this instance of `XmlReaderSettings`. */
|
||||
XmlReaderSettingsCreation getASettingsCreation() {
|
||||
exists(SettingsDataFlowConfig settingsFlow |
|
||||
settingsFlow.hasFlow(DataFlow::exprNode(result), DataFlow::exprNode(this))
|
||||
)
|
||||
SettingsDataFlow::flow(DataFlow::exprNode(result), DataFlow::exprNode(this))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -78,10 +78,12 @@ predicate isExponentialRegex(StringLiteral s) {
|
||||
}
|
||||
|
||||
/**
|
||||
* DEPRECATED: Use `ExponentialRegexDataflow` instead.
|
||||
*
|
||||
* A data flow configuration for tracking exponential worst case time regular expression string
|
||||
* literals to the pattern argument of a regex.
|
||||
*/
|
||||
class ExponentialRegexDataflow extends DataFlow2::Configuration {
|
||||
deprecated class ExponentialRegexDataflow extends DataFlow2::Configuration {
|
||||
ExponentialRegexDataflow() { this = "ExponentialRegex" }
|
||||
|
||||
override predicate isSource(DataFlow::Node s) { isExponentialRegex(s.asExpr()) }
|
||||
@@ -89,15 +91,27 @@ class ExponentialRegexDataflow extends DataFlow2::Configuration {
|
||||
override predicate isSink(DataFlow::Node s) { s.asExpr() = any(RegexOperation c).getPattern() }
|
||||
}
|
||||
|
||||
/**
|
||||
* A data flow configuration for tracking exponential worst case time regular expression string
|
||||
* literals to the pattern argument of a regex.
|
||||
*/
|
||||
private module ExponentialRegexDataFlowConfig implements DataFlow::ConfigSig {
|
||||
predicate isSource(DataFlow::Node s) { isExponentialRegex(s.asExpr()) }
|
||||
|
||||
predicate isSink(DataFlow::Node s) { s.asExpr() = any(RegexOperation c).getPattern() }
|
||||
}
|
||||
|
||||
module ExponentialRegexDataFlow = DataFlow::Global<ExponentialRegexDataFlowConfig>;
|
||||
|
||||
/**
|
||||
* An expression passed as the `input` to a call to a `Regex` method, where the regex appears to
|
||||
* have exponential behavior.
|
||||
*/
|
||||
class ExponentialRegexSink extends DataFlow::ExprNode, Sink {
|
||||
ExponentialRegexSink() {
|
||||
exists(ExponentialRegexDataflow regexDataflow, RegexOperation regexOperation |
|
||||
exists(RegexOperation regexOperation |
|
||||
// Exponential regex flows to the pattern argument
|
||||
regexDataflow.hasFlow(_, DataFlow::exprNode(regexOperation.getPattern()))
|
||||
ExponentialRegexDataFlow::flow(_, DataFlow::exprNode(regexOperation.getPattern()))
|
||||
|
|
||||
// This is used as an input for this pattern
|
||||
this.getExpr() = regexOperation.getInput() and
|
||||
|
||||
@@ -75,9 +75,11 @@ class JsonConvertTrackingConfig extends TaintTracking::Configuration {
|
||||
}
|
||||
|
||||
/**
|
||||
* DEPRECATED: Use `TypeNameTracking` instead.
|
||||
*
|
||||
* Tracks unsafe `TypeNameHandling` setting to `JsonConvert` call
|
||||
*/
|
||||
class TypeNameTrackingConfig extends DataFlow::Configuration {
|
||||
deprecated class TypeNameTrackingConfig extends DataFlow::Configuration {
|
||||
TypeNameTrackingConfig() { this = "TypeNameTrackingConfig" }
|
||||
|
||||
override predicate isSource(DataFlow::Node source) {
|
||||
@@ -127,6 +129,62 @@ class TypeNameTrackingConfig extends DataFlow::Configuration {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Configuration module for tracking unsafe `TypeNameHandling` setting to `JsonConvert` calls.
|
||||
*/
|
||||
private module TypeNameTrackingConfig implements DataFlow::ConfigSig {
|
||||
predicate isSource(DataFlow::Node source) {
|
||||
(
|
||||
source.asExpr() instanceof MemberConstantAccess and
|
||||
source.getType() instanceof TypeNameHandlingEnum
|
||||
or
|
||||
source.asExpr() instanceof IntegerLiteral
|
||||
) and
|
||||
source.asExpr().hasValue() and
|
||||
not source.asExpr().getValue() = "0"
|
||||
}
|
||||
|
||||
predicate isSink(DataFlow::Node sink) {
|
||||
exists(MethodCall mc, Method m, Expr expr |
|
||||
m = mc.getTarget() and
|
||||
(
|
||||
not mc.getArgument(0).hasValue() and
|
||||
m instanceof NewtonsoftJsonConvertClassDeserializeObjectMethod
|
||||
) and
|
||||
expr = mc.getAnArgument() and
|
||||
sink.asExpr() = expr and
|
||||
expr.getType() instanceof JsonSerializerSettingsClass
|
||||
)
|
||||
}
|
||||
|
||||
predicate isAdditionalFlowStep(DataFlow::Node node1, DataFlow::Node node2) {
|
||||
node1.asExpr() instanceof IntegerLiteral and
|
||||
node2.asExpr().(CastExpr).getExpr() = node1.asExpr()
|
||||
or
|
||||
node1.getType() instanceof TypeNameHandlingEnum and
|
||||
exists(PropertyWrite pw, Property p, Assignment a |
|
||||
a.getLValue() = pw and
|
||||
pw.getProperty() = p and
|
||||
p.getDeclaringType() instanceof JsonSerializerSettingsClass and
|
||||
p.hasName("TypeNameHandling") and
|
||||
(
|
||||
node1.asExpr() = a.getRValue() and
|
||||
node2.asExpr() = pw.getQualifier()
|
||||
or
|
||||
exists(ObjectInitializer oi |
|
||||
node1.asExpr() = oi.getAMemberInitializer().getRValue() and
|
||||
node2.asExpr() = oi
|
||||
)
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Configuration module for tracking unsafe `TypeNameHandling` setting to `JsonConvert` calls.
|
||||
*/
|
||||
module TypeNameTracking = DataFlow::Global<TypeNameTrackingConfig>;
|
||||
|
||||
/**
|
||||
* User input to static method or constructor call deserialization flow tracking.
|
||||
*/
|
||||
|
||||
@@ -172,26 +172,24 @@ module XmlReader {
|
||||
isNetFrameworkBefore(this.(MethodCall).getTarget().getDeclaringType(), "4.0")
|
||||
or
|
||||
// bad settings flow here
|
||||
exists(SettingsDataFlowConfig flow, ObjectCreation settings |
|
||||
flow.hasFlow(DataFlow::exprNode(settings), DataFlow::exprNode(this.getSettings())) and
|
||||
exists(ObjectCreation settings |
|
||||
SettingsDataFlow::flow(DataFlow::exprNode(settings), DataFlow::exprNode(this.getSettings())) and
|
||||
XmlSettings::dtdEnabledSettings(settings, evidence, reason)
|
||||
)
|
||||
}
|
||||
|
||||
private predicate insecureResolver(string reason, Expr evidence) {
|
||||
// bad settings flow here
|
||||
exists(SettingsDataFlowConfig flow, ObjectCreation settings |
|
||||
flow.hasFlow(DataFlow::exprNode(settings), DataFlow::exprNode(this.getSettings())) and
|
||||
exists(ObjectCreation settings |
|
||||
SettingsDataFlow::flow(DataFlow::exprNode(settings), DataFlow::exprNode(this.getSettings())) and
|
||||
XmlSettings::insecureResolverSettings(settings, evidence, reason)
|
||||
)
|
||||
// default is secure
|
||||
}
|
||||
}
|
||||
|
||||
private class SettingsDataFlowConfig extends DataFlow2::Configuration {
|
||||
SettingsDataFlowConfig() { this = "SettingsDataFlowConfig" }
|
||||
|
||||
override predicate isSource(DataFlow::Node source) {
|
||||
private module SettingsDataFlowConfig implements DataFlow::ConfigSig {
|
||||
predicate isSource(DataFlow::Node source) {
|
||||
// flow from places where we construct an XmlReaderSettings
|
||||
source
|
||||
.asExpr()
|
||||
@@ -202,10 +200,12 @@ module XmlReader {
|
||||
.hasQualifiedName("System.Xml", "XmlReaderSettings")
|
||||
}
|
||||
|
||||
override predicate isSink(DataFlow::Node sink) {
|
||||
predicate isSink(DataFlow::Node sink) {
|
||||
sink.asExpr() = any(InsecureXmlReaderCreate create).getSettings()
|
||||
}
|
||||
}
|
||||
|
||||
private module SettingsDataFlow = DataFlow::Global<SettingsDataFlowConfig>;
|
||||
}
|
||||
|
||||
/** Provides predicates related to `System.Xml.XmlTextReader`. */
|
||||
|
||||
@@ -37,19 +37,19 @@ predicate inForeachStmtBody(ForeachStmt loop, Element e) {
|
||||
)
|
||||
}
|
||||
|
||||
class LambdaDataFlowConfiguration extends DataFlow::Configuration {
|
||||
LambdaDataFlowConfiguration() { this = "LambdaDataFlowConfiguration" }
|
||||
module LambdaDataFlowConfig implements DataFlow::ConfigSig {
|
||||
predicate isSource(DataFlow::Node source) { lambdaCapturesLoopVariable(source.asExpr(), _, _) }
|
||||
|
||||
override predicate isSource(DataFlow::Node source) {
|
||||
lambdaCapturesLoopVariable(source.asExpr(), _, _)
|
||||
}
|
||||
predicate isSink(DataFlow::Node sink) { exists(getAssignmentTarget(sink.asExpr())) }
|
||||
}
|
||||
|
||||
override predicate isSink(DataFlow::Node sink) { exists(getAssignmentTarget(sink.asExpr())) }
|
||||
module LambdaDataFlow {
|
||||
private import DataFlow::Global<LambdaDataFlowConfig>
|
||||
|
||||
predicate capturesLoopVarAndIsStoredIn(
|
||||
AnonymousFunctionExpr lambda, Variable loopVar, Element storage
|
||||
) {
|
||||
exists(DataFlow::Node sink | this.hasFlow(DataFlow::exprNode(lambda), sink) |
|
||||
exists(DataFlow::Node sink | flow(DataFlow::exprNode(lambda), sink) |
|
||||
storage = getAssignmentTarget(sink.asExpr())
|
||||
) and
|
||||
exists(ForeachStmt loop | lambdaCapturesLoopVariable(lambda, loop, loopVar) |
|
||||
@@ -109,7 +109,7 @@ predicate declaredInsideLoop(ForeachStmt loop, LocalVariable v) {
|
||||
)
|
||||
}
|
||||
|
||||
from LambdaDataFlowConfiguration c, AnonymousFunctionExpr lambda, Variable loopVar, Element storage
|
||||
where c.capturesLoopVarAndIsStoredIn(lambda, loopVar, storage)
|
||||
from AnonymousFunctionExpr lambda, Variable loopVar, Element storage
|
||||
where LambdaDataFlow::capturesLoopVarAndIsStoredIn(lambda, loopVar, storage)
|
||||
select lambda, "Function which may be stored in $@ captures variable $@.", storage,
|
||||
storage.toString(), loopVar, loopVar.getName()
|
||||
|
||||
@@ -12,12 +12,10 @@
|
||||
|
||||
import csharp
|
||||
import semmle.code.csharp.dataflow.DataFlow::DataFlow
|
||||
import semmle.code.csharp.dataflow.DataFlow::DataFlow::PathGraph
|
||||
import AddCertToRootStore::PathGraph
|
||||
|
||||
class AddCertToRootStoreConfig extends DataFlow::Configuration {
|
||||
AddCertToRootStoreConfig() { this = "Adding Certificate To Root Store" }
|
||||
|
||||
override predicate isSource(DataFlow::Node source) {
|
||||
module AddCertToRootStoreConfig implements DataFlow::ConfigSig {
|
||||
predicate isSource(DataFlow::Node source) {
|
||||
exists(ObjectCreation oc | oc = source.asExpr() |
|
||||
oc.getType()
|
||||
.(RefType)
|
||||
@@ -26,7 +24,7 @@ class AddCertToRootStoreConfig extends DataFlow::Configuration {
|
||||
)
|
||||
}
|
||||
|
||||
override predicate isSink(DataFlow::Node sink) {
|
||||
predicate isSink(DataFlow::Node sink) {
|
||||
exists(MethodCall mc |
|
||||
(
|
||||
mc.getTarget()
|
||||
@@ -40,6 +38,8 @@ class AddCertToRootStoreConfig extends DataFlow::Configuration {
|
||||
}
|
||||
}
|
||||
|
||||
from DataFlow::PathNode oc, DataFlow::PathNode mc, AddCertToRootStoreConfig config
|
||||
where config.hasFlowPath(oc, mc)
|
||||
module AddCertToRootStore = DataFlow::Global<AddCertToRootStoreConfig>;
|
||||
|
||||
from AddCertToRootStore::PathNode oc, AddCertToRootStore::PathNode mc
|
||||
where AddCertToRootStore::flowPath(oc, mc)
|
||||
select mc.getNode(), oc, mc, "This certificate is added to the root certificate store."
|
||||
|
||||
@@ -11,15 +11,13 @@
|
||||
*/
|
||||
|
||||
import csharp
|
||||
import DataFlow::PathGraph
|
||||
import InsecureSqlConnection::PathGraph
|
||||
|
||||
/**
|
||||
* A data flow configuration for tracking strings passed to `SqlConnection[StringBuilder]` instances.
|
||||
*/
|
||||
class TaintTrackingConfiguration extends DataFlow::Configuration {
|
||||
TaintTrackingConfiguration() { this = "TaintTrackingConfiguration" }
|
||||
|
||||
override predicate isSource(DataFlow::Node source) {
|
||||
module InsecureSqlConnectionConfig implements DataFlow::ConfigSig {
|
||||
predicate isSource(DataFlow::Node source) {
|
||||
exists(string s | s = source.asExpr().(StringLiteral).getValue().toLowerCase() |
|
||||
s.matches("%encrypt=false%")
|
||||
or
|
||||
@@ -27,7 +25,7 @@ class TaintTrackingConfiguration extends DataFlow::Configuration {
|
||||
)
|
||||
}
|
||||
|
||||
override predicate isSink(DataFlow::Node sink) {
|
||||
predicate isSink(DataFlow::Node sink) {
|
||||
exists(ObjectCreation oc |
|
||||
oc.getRuntimeArgument(0) = sink.asExpr() and
|
||||
(
|
||||
@@ -39,8 +37,13 @@ class TaintTrackingConfiguration extends DataFlow::Configuration {
|
||||
}
|
||||
}
|
||||
|
||||
from TaintTrackingConfiguration c, DataFlow::PathNode source, DataFlow::PathNode sink
|
||||
where c.hasFlowPath(source, sink)
|
||||
/**
|
||||
* A data flow configuration for tracking strings passed to `SqlConnection[StringBuilder]` instances.
|
||||
*/
|
||||
module InsecureSqlConnection = DataFlow::Global<InsecureSqlConnectionConfig>;
|
||||
|
||||
from InsecureSqlConnection::PathNode source, InsecureSqlConnection::PathNode sink
|
||||
where InsecureSqlConnection::flowPath(source, sink)
|
||||
select sink.getNode(), source, sink,
|
||||
"$@ flows to this SQL connection and does not specify `Encrypt=True`.", source.getNode(),
|
||||
"Connection string"
|
||||
|
||||
@@ -48,12 +48,9 @@ where
|
||||
)
|
||||
or
|
||||
// JsonConvert static method call, but with additional unsafe typename tracking
|
||||
exists(
|
||||
JsonConvertTrackingConfig taintTrackingJsonConvert, TypeNameTrackingConfig typenameTracking,
|
||||
DataFlow::Node settingsCallArg
|
||||
|
|
||||
exists(JsonConvertTrackingConfig taintTrackingJsonConvert, DataFlow::Node settingsCallArg |
|
||||
taintTrackingJsonConvert.hasFlowPath(userInput, deserializeCallArg) and
|
||||
typenameTracking.hasFlow(_, settingsCallArg) and
|
||||
TypeNameTracking::flow(_, settingsCallArg) and
|
||||
deserializeCallArg.getNode().asExpr().getParent() = settingsCallArg.asExpr().getParent()
|
||||
)
|
||||
select deserializeCallArg, userInput, deserializeCallArg, "$@ flows to unsafe deserializer.",
|
||||
|
||||
@@ -38,11 +38,8 @@ where
|
||||
// there is no callback `OnAppendCookie` that sets `HttpOnly` to true
|
||||
not exists(OnAppendCookieHttpOnlyTrackingConfig config | config.hasFlowTo(_)) and
|
||||
// Passed as third argument to `IResponseCookies.Append`
|
||||
exists(
|
||||
CookieOptionsTrackingConfiguration cookieTracking, DataFlow::Node creation,
|
||||
DataFlow::Node append
|
||||
|
|
||||
cookieTracking.hasFlow(creation, append) and
|
||||
exists(DataFlow::Node creation, DataFlow::Node append |
|
||||
CookieOptionsTracking::flow(creation, append) and
|
||||
creation.asExpr() = oc and
|
||||
append.asExpr() = mc.getArgument(2)
|
||||
)
|
||||
@@ -79,8 +76,8 @@ where
|
||||
oc = c and
|
||||
oc.getType() instanceof MicrosoftAspNetCoreHttpCookieOptions and
|
||||
not isPropertySet(oc, "HttpOnly") and
|
||||
exists(CookieOptionsTrackingConfiguration cookieTracking, DataFlow::Node creation |
|
||||
cookieTracking.hasFlow(creation, _) and
|
||||
exists(DataFlow::Node creation |
|
||||
CookieOptionsTracking::flow(creation, _) and
|
||||
creation.asExpr() = oc
|
||||
)
|
||||
)
|
||||
|
||||
@@ -37,8 +37,8 @@ where
|
||||
oc = c and
|
||||
oc.getType() instanceof MicrosoftAspNetCoreHttpCookieOptions and
|
||||
not isPropertySet(oc, "Secure") and
|
||||
exists(CookieOptionsTrackingConfiguration cookieTracking, DataFlow::Node creation |
|
||||
cookieTracking.hasFlow(creation, _) and
|
||||
exists(DataFlow::Node creation |
|
||||
CookieOptionsTracking::flow(creation, _) and
|
||||
creation.asExpr() = oc
|
||||
)
|
||||
)
|
||||
@@ -82,8 +82,8 @@ where
|
||||
// there is no callback `OnAppendCookie` that sets `Secure` to true
|
||||
not exists(OnAppendCookieSecureTrackingConfig config | config.hasFlowTo(_)) and
|
||||
// the cookie option is passed to `Append`
|
||||
exists(CookieOptionsTrackingConfiguration cookieTracking, DataFlow::Node creation |
|
||||
cookieTracking.hasFlow(creation, _) and
|
||||
exists(DataFlow::Node creation |
|
||||
CookieOptionsTracking::flow(creation, _) and
|
||||
creation.asExpr() = oc
|
||||
)
|
||||
)
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
import csharp
|
||||
import semmle.code.csharp.dataflow.DataFlow2
|
||||
import semmle.code.csharp.dataflow.TaintTracking2
|
||||
import DataFlow::PathGraph
|
||||
import HashWithoutSalt::PathGraph
|
||||
|
||||
/** The C# class `Windows.Security.Cryptography.Core.HashAlgorithmProvider`. */
|
||||
class HashAlgorithmProvider extends RefType {
|
||||
@@ -120,12 +120,10 @@ predicate hasHashAncestor(MethodCall mc) {
|
||||
* 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) {
|
||||
predicate isSink(DataFlow::Node sink) {
|
||||
exists(MethodCall mc |
|
||||
sink.asExpr() = mc.getArgument(0) and
|
||||
isHashCall(mc) and
|
||||
@@ -148,7 +146,7 @@ class HashWithoutSaltConfiguration extends TaintTracking::Configuration {
|
||||
)
|
||||
}
|
||||
|
||||
override predicate isAdditionalTaintStep(DataFlow::Node node1, DataFlow::Node node2) {
|
||||
predicate isAdditionalFlowStep(DataFlow::Node node1, DataFlow::Node node2) {
|
||||
exists(MethodCall mc |
|
||||
mc.getTarget()
|
||||
.hasQualifiedName("Windows.Security.Cryptography", "CryptographicBuffer",
|
||||
@@ -166,7 +164,7 @@ class HashWithoutSaltConfiguration extends TaintTracking::Configuration {
|
||||
* `byte[] saltedPassword = sha256.ComputeHash(rawSalted);`
|
||||
* Or the password is concatenated with a salt as a string.
|
||||
*/
|
||||
override predicate isSanitizer(DataFlow::Node node) {
|
||||
predicate isBarrier(DataFlow::Node node) {
|
||||
exists(MethodCall mc |
|
||||
hasFurtherProcessing(mc) and
|
||||
mc.getAnArgument() = node.asExpr()
|
||||
@@ -194,7 +192,9 @@ class HashWithoutSaltConfiguration extends TaintTracking::Configuration {
|
||||
}
|
||||
}
|
||||
|
||||
from DataFlow::PathNode source, DataFlow::PathNode sink, HashWithoutSaltConfiguration c
|
||||
where c.hasFlowPath(source, sink)
|
||||
module HashWithoutSalt = TaintTracking::Global<HashWithoutSaltConfig>;
|
||||
|
||||
from HashWithoutSalt::PathNode source, HashWithoutSalt::PathNode sink
|
||||
where HashWithoutSalt::flowPath(source, sink)
|
||||
select sink.getNode(), source, sink, "$@ is hashed without a salt.", source.getNode(),
|
||||
"The password"
|
||||
|
||||
@@ -19,9 +19,11 @@ class TokenValidationParametersPropertySensitiveValidation extends Property {
|
||||
}
|
||||
|
||||
/**
|
||||
* DEPRECATED: Use `FalseValueFlowsToTokenValidationParametersPropertyWriteToBypassValidation` instead.
|
||||
*
|
||||
* A dataflow from a `false` value to a write sensitive property for `TokenValidationParameters`.
|
||||
*/
|
||||
class FalseValueFlowsToTokenValidationParametersPropertyWriteToBypassValidation extends DataFlow::Configuration
|
||||
deprecated class FalseValueFlowsToTokenValidationParametersPropertyWriteToBypassValidation extends DataFlow::Configuration
|
||||
{
|
||||
FalseValueFlowsToTokenValidationParametersPropertyWriteToBypassValidation() {
|
||||
this = "FalseValueFlowsToTokenValidationParametersPropertyWriteToBypassValidation"
|
||||
@@ -37,6 +39,25 @@ class FalseValueFlowsToTokenValidationParametersPropertyWriteToBypassValidation
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A dataflow configuration from a `false` value to a write sensitive property for `TokenValidationParameters`.
|
||||
*/
|
||||
private module FalseValueFlowsToTokenValidationParametersPropertyWriteToBypassValidationConfig
|
||||
implements DataFlow::ConfigSig
|
||||
{
|
||||
predicate isSource(DataFlow::Node source) {
|
||||
source.asExpr().getValue() = "false" and
|
||||
source.asExpr().getType() instanceof BoolType
|
||||
}
|
||||
|
||||
predicate isSink(DataFlow::Node sink) {
|
||||
sink.asExpr() = any(TokenValidationParametersPropertySensitiveValidation p).getAnAssignedValue()
|
||||
}
|
||||
}
|
||||
|
||||
module FalseValueFlowsToTokenValidationParametersPropertyWriteToBypassValidation =
|
||||
DataFlow::Global<FalseValueFlowsToTokenValidationParametersPropertyWriteToBypassValidationConfig>;
|
||||
|
||||
/**
|
||||
* Holds if `assemblyName` is older than version `ver`
|
||||
*/
|
||||
|
||||
@@ -16,11 +16,10 @@ import JsonWebTokenHandlerLib
|
||||
import semmle.code.csharp.commons.QualifiedName
|
||||
|
||||
from
|
||||
FalseValueFlowsToTokenValidationParametersPropertyWriteToBypassValidation config,
|
||||
DataFlow::Node source, DataFlow::Node sink,
|
||||
TokenValidationParametersPropertySensitiveValidation pw, string qualifier, string name
|
||||
where
|
||||
config.hasFlow(source, sink) and
|
||||
FalseValueFlowsToTokenValidationParametersPropertyWriteToBypassValidation::flow(source, sink) and
|
||||
sink.asExpr() = pw.getAnAssignedValue() and
|
||||
pw.hasQualifiedName(qualifier, name)
|
||||
select sink, "The security sensitive property $@ is being disabled by the following value: $@.", pw,
|
||||
|
||||
@@ -31,16 +31,16 @@ predicate unsafeDataContractTypeCreation(Expr e) {
|
||||
e.(TypeofExpr).getTypeAccess().getTarget() instanceof DataSetOrTableRelatedClass
|
||||
}
|
||||
|
||||
class Conf extends DataFlow::Configuration {
|
||||
Conf() { this = "FlowToDataSerializerConstructor" }
|
||||
module FlowToDataSerializerConstructorConfig implements DataFlow::ConfigSig {
|
||||
predicate isSource(DataFlow::Node node) { unsafeDataContractTypeCreation(node.asExpr()) }
|
||||
|
||||
override predicate isSource(DataFlow::Node node) { unsafeDataContractTypeCreation(node.asExpr()) }
|
||||
|
||||
override predicate isSink(DataFlow::Node node) { xmlSerializerConstructorArgument(node.asExpr()) }
|
||||
predicate isSink(DataFlow::Node node) { xmlSerializerConstructorArgument(node.asExpr()) }
|
||||
}
|
||||
|
||||
from Conf conf, DataFlow::Node source, DataFlow::Node sink
|
||||
where conf.hasFlow(source, sink)
|
||||
module FlowToDataSerializerConstructor = DataFlow::Global<FlowToDataSerializerConstructorConfig>;
|
||||
|
||||
from DataFlow::Node source, DataFlow::Node sink
|
||||
where FlowToDataSerializerConstructor::flow(source, sink)
|
||||
select sink,
|
||||
"Unsafe type is used in data contract serializer. Make sure $@ comes from the trusted source.",
|
||||
source, source.toString()
|
||||
|
||||
@@ -40,9 +40,11 @@ private class AuthCookieNameConfiguration extends DataFlow::Configuration {
|
||||
}
|
||||
|
||||
/**
|
||||
* DEPRECATED: Use `CookieOptionsTracking` instead.
|
||||
*
|
||||
* Tracks creation of `CookieOptions` to `IResponseCookies.Append(String, String, CookieOptions)` call as a third parameter.
|
||||
*/
|
||||
class CookieOptionsTrackingConfiguration extends DataFlow::Configuration {
|
||||
deprecated class CookieOptionsTrackingConfiguration extends DataFlow::Configuration {
|
||||
CookieOptionsTrackingConfiguration() { this = "CookieOptionsTrackingConfiguration" }
|
||||
|
||||
override predicate isSource(DataFlow::Node source) {
|
||||
@@ -57,6 +59,29 @@ class CookieOptionsTrackingConfiguration extends DataFlow::Configuration {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Configuration module tracking creation of `CookieOptions` to `IResponseCookies.Append(String, String, CookieOptions)`
|
||||
* calls as a third parameter.
|
||||
*/
|
||||
private module CookieOptionsTrackingConfig implements DataFlow::ConfigSig {
|
||||
predicate isSource(DataFlow::Node source) {
|
||||
source.asExpr().(ObjectCreation).getType() instanceof MicrosoftAspNetCoreHttpCookieOptions
|
||||
}
|
||||
|
||||
predicate isSink(DataFlow::Node sink) {
|
||||
exists(MicrosoftAspNetCoreHttpResponseCookies iResponse, MethodCall mc |
|
||||
iResponse.getAppendMethod() = mc.getTarget() and
|
||||
mc.getArgument(2) = sink.asExpr()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Tracking creation of `CookieOptions` to `IResponseCookies.Append(String, String, CookieOptions)`
|
||||
* calls as a third parameter.
|
||||
*/
|
||||
module CookieOptionsTracking = DataFlow::Global<CookieOptionsTrackingConfig>;
|
||||
|
||||
/**
|
||||
* Looks for property value of `CookiePolicyOptions` passed to `app.UseCookiePolicy` in `Startup.Configure`.
|
||||
*/
|
||||
|
||||
@@ -3,20 +3,18 @@
|
||||
*/
|
||||
|
||||
import csharp
|
||||
import DataFlow::PathGraph
|
||||
import GlobalFlow::PathGraph
|
||||
|
||||
class DataflowConfiguration extends DataFlow::Configuration {
|
||||
DataflowConfiguration() { this = "data flow configuration" }
|
||||
module GlobalFlowConfig implements DataFlow::ConfigSig {
|
||||
predicate isSource(DataFlow::Node source) { source.asExpr().(Expr).getValue() = "tainted" }
|
||||
|
||||
override predicate isSource(DataFlow::Node source) {
|
||||
source.asExpr().(Expr).getValue() = "tainted"
|
||||
}
|
||||
|
||||
override predicate isSink(DataFlow::Node sink) {
|
||||
predicate isSink(DataFlow::Node sink) {
|
||||
exists(LocalVariable v | sink.asExpr() = v.getInitializer())
|
||||
}
|
||||
}
|
||||
|
||||
from DataFlow::PathNode source, DataFlow::PathNode sink, DataflowConfiguration conf
|
||||
where conf.hasFlowPath(source, sink)
|
||||
module GlobalFlow = DataFlow::Global<GlobalFlowConfig>;
|
||||
|
||||
from GlobalFlow::PathNode source, GlobalFlow::PathNode sink
|
||||
where GlobalFlow::flowPath(source, sink)
|
||||
select source, source, sink, "$@", sink, sink.toString()
|
||||
|
||||
@@ -3,14 +3,12 @@
|
||||
*/
|
||||
|
||||
import csharp
|
||||
import DataFlow::PathGraph
|
||||
import CallSensitivity::PathGraph
|
||||
|
||||
class Conf extends DataFlow::Configuration {
|
||||
Conf() { this = "CallSensitiveFlowConf" }
|
||||
module CallSensitivityConfig implements DataFlow::ConfigSig {
|
||||
predicate isSource(DataFlow::Node src) { src.asExpr() instanceof ObjectCreation }
|
||||
|
||||
override predicate isSource(DataFlow::Node src) { src.asExpr() instanceof ObjectCreation }
|
||||
|
||||
override predicate isSink(DataFlow::Node sink) {
|
||||
predicate isSink(DataFlow::Node sink) {
|
||||
exists(MethodCall mc |
|
||||
mc.getTarget().hasName("Sink") and
|
||||
mc.getAnArgument() = sink.asExpr()
|
||||
@@ -18,6 +16,8 @@ class Conf extends DataFlow::Configuration {
|
||||
}
|
||||
}
|
||||
|
||||
from DataFlow::PathNode source, DataFlow::PathNode sink, Conf conf
|
||||
where conf.hasFlowPath(source, sink)
|
||||
module CallSensitivity = DataFlow::Global<CallSensitivityConfig>;
|
||||
|
||||
from CallSensitivity::PathNode source, CallSensitivity::PathNode sink
|
||||
where CallSensitivity::flowPath(source, sink)
|
||||
select source, source, sink, "$@", sink, sink.toString()
|
||||
|
||||
@@ -3,23 +3,23 @@
|
||||
*/
|
||||
|
||||
import csharp
|
||||
import DataFlow::PathGraph
|
||||
import ArrayFlow::PathGraph
|
||||
|
||||
class Conf extends DataFlow::Configuration {
|
||||
Conf() { this = "ArrayFlowConf" }
|
||||
module ArrayFlowConfig implements DataFlow::ConfigSig {
|
||||
predicate isSource(DataFlow::Node src) { src.asExpr() instanceof ObjectCreation }
|
||||
|
||||
override predicate isSource(DataFlow::Node src) { src.asExpr() instanceof ObjectCreation }
|
||||
|
||||
override predicate isSink(DataFlow::Node sink) {
|
||||
predicate isSink(DataFlow::Node sink) {
|
||||
exists(MethodCall mc |
|
||||
mc.getTarget().hasUndecoratedName("Sink") and
|
||||
mc.getAnArgument() = sink.asExpr()
|
||||
)
|
||||
}
|
||||
|
||||
override int fieldFlowBranchLimit() { result = 100 }
|
||||
int fieldFlowBranchLimit() { result = 100 }
|
||||
}
|
||||
|
||||
from DataFlow::PathNode source, DataFlow::PathNode sink, Conf conf
|
||||
where conf.hasFlowPath(source, sink)
|
||||
module ArrayFlow = DataFlow::Global<ArrayFlowConfig>;
|
||||
|
||||
from ArrayFlow::PathNode source, ArrayFlow::PathNode sink
|
||||
where ArrayFlow::flowPath(source, sink)
|
||||
select source, source, sink, "$@", sink, sink.toString()
|
||||
|
||||
@@ -3,17 +3,15 @@
|
||||
*/
|
||||
|
||||
import csharp
|
||||
import DataFlow::PathGraph
|
||||
import Types::PathGraph
|
||||
|
||||
class Conf extends DataFlow::Configuration {
|
||||
Conf() { this = "TypesConf" }
|
||||
|
||||
override predicate isSource(DataFlow::Node src) {
|
||||
module TypesConfig implements DataFlow::ConfigSig {
|
||||
predicate isSource(DataFlow::Node src) {
|
||||
src.asExpr() instanceof ObjectCreation or
|
||||
src.asExpr() instanceof NullLiteral
|
||||
}
|
||||
|
||||
override predicate isSink(DataFlow::Node sink) {
|
||||
predicate isSink(DataFlow::Node sink) {
|
||||
exists(MethodCall mc |
|
||||
mc.getTarget().hasUndecoratedName("Sink") and
|
||||
mc.getAnArgument() = sink.asExpr()
|
||||
@@ -21,6 +19,8 @@ class Conf extends DataFlow::Configuration {
|
||||
}
|
||||
}
|
||||
|
||||
from DataFlow::PathNode source, DataFlow::PathNode sink, Conf conf
|
||||
where conf.hasFlowPath(source, sink)
|
||||
module Types = DataFlow::Global<TypesConfig>;
|
||||
|
||||
from Types::PathNode source, Types::PathNode sink
|
||||
where Types::flowPath(source, sink)
|
||||
select source, source, sink, "$@", sink, sink.toString()
|
||||
|
||||
Reference in New Issue
Block a user