Merge pull request #12723 from michaelnebel/csharp/refactordataflow2

C#: Re-factor queries to use the new API.
This commit is contained in:
Michael Nebel
2023-04-13 12:32:22 +02:00
committed by GitHub
22 changed files with 289 additions and 77 deletions

View File

@@ -90,8 +90,12 @@ class ExternalApiDataNode extends DataFlow::Node {
/** DEPRECATED: Alias for ExternalApiDataNode */ /** DEPRECATED: Alias for ExternalApiDataNode */
deprecated class ExternalAPIDataNode = ExternalApiDataNode; deprecated class ExternalAPIDataNode = ExternalApiDataNode;
/** A configuration for tracking flow from `RemoteFlowSource`s to `ExternalApiDataNode`s. */ /**
class UntrustedDataToExternalApiConfig extends TaintTracking::Configuration { * DEPRECATED: Use `RemoteSourceToExternalApi` instead.
*
* A configuration for tracking flow from `RemoteFlowSource`s to `ExternalApiDataNode`s.
*/
deprecated class UntrustedDataToExternalApiConfig extends TaintTracking::Configuration {
UntrustedDataToExternalApiConfig() { this = "UntrustedDataToExternalAPIConfig" } UntrustedDataToExternalApiConfig() { this = "UntrustedDataToExternalAPIConfig" }
override predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource } override predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource }
@@ -99,17 +103,25 @@ class UntrustedDataToExternalApiConfig extends TaintTracking::Configuration {
override predicate isSink(DataFlow::Node sink) { sink instanceof ExternalApiDataNode } override predicate isSink(DataFlow::Node sink) { sink instanceof ExternalApiDataNode }
} }
/** A configuration for tracking flow from `RemoteFlowSource`s to `ExternalApiDataNode`s. */
private module RemoteSourceToExternalApiConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource }
predicate isSink(DataFlow::Node sink) { sink instanceof ExternalApiDataNode }
}
/** A module for tracking flow from `RemoteFlowSource`s to `ExternalApiDataNode`s. */
module RemoteSourceToExternalApi = TaintTracking::Global<RemoteSourceToExternalApiConfig>;
/** DEPRECATED: Alias for UntrustedDataToExternalApiConfig */ /** DEPRECATED: Alias for UntrustedDataToExternalApiConfig */
deprecated class UntrustedDataToExternalAPIConfig = UntrustedDataToExternalApiConfig; deprecated class UntrustedDataToExternalAPIConfig = UntrustedDataToExternalApiConfig;
/** A node representing untrusted data being passed to an external API. */ /** A node representing untrusted data being passed to an external API. */
class UntrustedExternalApiDataNode extends ExternalApiDataNode { class UntrustedExternalApiDataNode extends ExternalApiDataNode {
private UntrustedDataToExternalApiConfig c; UntrustedExternalApiDataNode() { RemoteSourceToExternalApi::flow(_, this) }
UntrustedExternalApiDataNode() { c.hasFlow(_, this) }
/** Gets a source of untrusted data which is passed to this external API data node. */ /** Gets a source of untrusted data which is passed to this external API data node. */
DataFlow::Node getAnUntrustedSource() { c.hasFlow(result, this) } DataFlow::Node getAnUntrustedSource() { RemoteSourceToExternalApi::flow(result, this) }
} }
/** DEPRECATED: Alias for UntrustedExternalApiDataNode */ /** DEPRECATED: Alias for UntrustedExternalApiDataNode */

View File

@@ -38,9 +38,11 @@ abstract class Sink extends DataFlow::ExprNode {
abstract class Sanitizer extends DataFlow::ExprNode { } abstract class Sanitizer extends DataFlow::ExprNode { }
/** /**
* DEPRECATED: Use `HardcodedCredentials` instead.
*
* A taint-tracking configuration for hard coded credentials. * A taint-tracking configuration for hard coded credentials.
*/ */
class TaintTrackingConfiguration extends TaintTracking::Configuration { deprecated class TaintTrackingConfiguration extends TaintTracking::Configuration {
TaintTrackingConfiguration() { this = "HardcodedCredentials" } TaintTrackingConfiguration() { this = "HardcodedCredentials" }
override predicate isSource(DataFlow::Node source) { source instanceof Source } override predicate isSource(DataFlow::Node source) { source instanceof Source }
@@ -75,6 +77,56 @@ class TaintTrackingConfiguration extends TaintTracking::Configuration {
override predicate isSanitizer(DataFlow::Node node) { node instanceof Sanitizer } override predicate isSanitizer(DataFlow::Node node) { node instanceof Sanitizer }
} }
/**
* A taint-tracking configuration for hard coded credentials.
*/
private module HardcodedCredentialsConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node source) { source instanceof Source }
predicate isSink(DataFlow::Node sink) {
sink instanceof Sink and
// Ignore values that are ultimately returned by mocks, as they don't represent "real"
// credentials.
not any(ReturnedByMockObject mock).getAMemberInitializationValue() = sink.asExpr() and
not any(ReturnedByMockObject mock).getAnArgument() = sink.asExpr()
}
predicate isBarrier(DataFlow::Node node) { node instanceof Sanitizer }
}
/**
* A taint-tracking module for hard coded credentials.
*/
module HardcodedCredentials {
import TaintTracking::Global<HardcodedCredentialsConfig> as Super
import Super
/**
* Holds if data can flow from `source` to `sink`.
*
* The corresponding paths are generated from the end-points and the graph
* included in the module `PathGraph`.
*/
predicate flowPath(HardcodedCredentials::PathNode source, HardcodedCredentials::PathNode sink) {
Super::flowPath(source, sink) and
// Exclude hard-coded credentials in tests if they only flow to calls to methods with a name
// like "Add*" "Create*" or "Update*". The rationale is that hard-coded credentials within
// tests that are only used for creating or setting values within tests are unlikely to
// represent credentials to some accessible system.
not (
source.getNode().asExpr().getFile() instanceof TestFile and
exists(MethodCall createOrAddCall, string createOrAddMethodName |
createOrAddMethodName.matches("Update%") or
createOrAddMethodName.matches("Create%") or
createOrAddMethodName.matches("Add%")
|
createOrAddCall.getTarget().hasName(createOrAddMethodName) and
createOrAddCall.getAnArgument() = sink.getNode().asExpr()
)
)
}
}
/** /**
* A string literal that is not empty. * A string literal that is not empty.
*/ */

View File

@@ -25,9 +25,11 @@ abstract class Sink extends DataFlow::ExprNode { }
abstract class Sanitizer extends DataFlow::ExprNode { } abstract class Sanitizer extends DataFlow::ExprNode { }
/** /**
* DEPRECATED: Use `LdapInjection` instead.
*
* A taint-tracking configuration for unvalidated user input that is used to construct LDAP queries. * A taint-tracking configuration for unvalidated user input that is used to construct LDAP queries.
*/ */
class TaintTrackingConfiguration extends TaintTracking::Configuration { deprecated class TaintTrackingConfiguration extends TaintTracking::Configuration {
TaintTrackingConfiguration() { this = "LDAPInjection" } TaintTrackingConfiguration() { this = "LDAPInjection" }
override predicate isSource(DataFlow::Node source) { source instanceof Source } override predicate isSource(DataFlow::Node source) { source instanceof Source }
@@ -37,6 +39,32 @@ class TaintTrackingConfiguration extends TaintTracking::Configuration {
override predicate isSanitizer(DataFlow::Node node) { node instanceof Sanitizer } override predicate isSanitizer(DataFlow::Node node) { node instanceof Sanitizer }
} }
/**
* A taint-tracking configuration for unvalidated user input that is used to construct LDAP queries.
*/
module LdapInjectionConfig implements DataFlow::ConfigSig {
/**
* Holds if `source` is a relevant data flow source.
*/
predicate isSource(DataFlow::Node source) { source instanceof Source }
/**
* Holds if `sink` is a relevant data flow sink.
*/
predicate isSink(DataFlow::Node sink) { sink instanceof Sink }
/**
* Holds if data flow through `node` is prohibited. This completely removes
* `node` from the data flow graph.
*/
predicate isBarrier(DataFlow::Node node) { node instanceof Sanitizer }
}
/**
* A taint-tracking configuration for unvalidated user input that is used to construct LDAP queries.
*/
module LdapInjection = TaintTracking::Global<LdapInjectionConfig>;
/** A source of remote user input. */ /** A source of remote user input. */
class RemoteSource extends Source instanceof RemoteFlowSource { } class RemoteSource extends Source instanceof RemoteFlowSource { }

View File

@@ -25,9 +25,11 @@ abstract class Sink extends DataFlow::ExprNode { }
abstract class Sanitizer extends DataFlow::ExprNode { } abstract class Sanitizer extends DataFlow::ExprNode { }
/** /**
* DEPRECATED: Use `LogForging` instead.
*
* A taint-tracking configuration for untrusted user input used in log entries. * A taint-tracking configuration for untrusted user input used in log entries.
*/ */
class TaintTrackingConfiguration extends TaintTracking::Configuration { deprecated class TaintTrackingConfiguration extends TaintTracking::Configuration {
TaintTrackingConfiguration() { this = "LogForging" } TaintTrackingConfiguration() { this = "LogForging" }
override predicate isSource(DataFlow::Node source) { source instanceof Source } override predicate isSource(DataFlow::Node source) { source instanceof Source }
@@ -37,6 +39,22 @@ class TaintTrackingConfiguration extends TaintTracking::Configuration {
override predicate isSanitizer(DataFlow::Node node) { node instanceof Sanitizer } override predicate isSanitizer(DataFlow::Node node) { node instanceof Sanitizer }
} }
/**
* A taint-tracking configuration for untrusted user input used in log entries.
*/
private module LogForgingConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node source) { source instanceof Source }
predicate isSink(DataFlow::Node sink) { sink instanceof Sink }
predicate isBarrier(DataFlow::Node node) { node instanceof Sanitizer }
}
/**
* A taint-tracking module for untrusted user input used in log entries.
*/
module LogForging = TaintTracking::Global<LogForgingConfig>;
/** A source of remote user input. */ /** A source of remote user input. */
private class RemoteSource extends Source instanceof RemoteFlowSource { } private class RemoteSource extends Source instanceof RemoteFlowSource { }

View File

@@ -29,10 +29,12 @@ abstract class Sink extends DataFlow::ExprNode {
abstract class Sanitizer extends DataFlow::ExprNode { } abstract class Sanitizer extends DataFlow::ExprNode { }
/** /**
* DEPRECATED: Use `MissingXxmlValidation` instead.
*
* A taint-tracking configuration for untrusted user input processed as XML without validation against a * A taint-tracking configuration for untrusted user input processed as XML without validation against a
* known schema. * known schema.
*/ */
class TaintTrackingConfiguration extends TaintTracking::Configuration { deprecated class TaintTrackingConfiguration extends TaintTracking::Configuration {
TaintTrackingConfiguration() { this = "MissingXMLValidation" } TaintTrackingConfiguration() { this = "MissingXMLValidation" }
override predicate isSource(DataFlow::Node source) { source instanceof Source } override predicate isSource(DataFlow::Node source) { source instanceof Source }
@@ -42,6 +44,24 @@ class TaintTrackingConfiguration extends TaintTracking::Configuration {
override predicate isSanitizer(DataFlow::Node node) { node instanceof Sanitizer } override predicate isSanitizer(DataFlow::Node node) { node instanceof Sanitizer }
} }
/**
* A taint-tracking configuration for untrusted user input processed as XML without validation against a
* known schema.
*/
private module MissingXmlValidationConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node source) { source instanceof Source }
predicate isSink(DataFlow::Node sink) { sink instanceof Sink }
predicate isBarrier(DataFlow::Node node) { node instanceof Sanitizer }
}
/**
* A taint-tracking module for untrusted user input processed as XML without validation against a
* known schema.
*/
module MissingXmlValidation = TaintTracking::Global<MissingXmlValidationConfig>;
/** A source of remote user input. */ /** A source of remote user input. */
class RemoteSource extends Source instanceof RemoteFlowSource { } class RemoteSource extends Source instanceof RemoteFlowSource { }

View File

@@ -25,9 +25,11 @@ abstract class Sink extends DataFlow::ExprNode { }
abstract class Sanitizer extends DataFlow::ExprNode { } abstract class Sanitizer extends DataFlow::ExprNode { }
/** /**
* DEPRECATED: Use `ReDoS` instead.
*
* A taint-tracking configuration for untrusted user input used in dangerous regular expression operations. * A taint-tracking configuration for untrusted user input used in dangerous regular expression operations.
*/ */
class TaintTrackingConfiguration extends TaintTracking::Configuration { deprecated class TaintTrackingConfiguration extends TaintTracking::Configuration {
TaintTrackingConfiguration() { this = "ReDoS" } TaintTrackingConfiguration() { this = "ReDoS" }
override predicate isSource(DataFlow::Node source) { source instanceof Source } override predicate isSource(DataFlow::Node source) { source instanceof Source }
@@ -37,6 +39,22 @@ class TaintTrackingConfiguration extends TaintTracking::Configuration {
override predicate isSanitizer(DataFlow::Node node) { node instanceof Sanitizer } override predicate isSanitizer(DataFlow::Node node) { node instanceof Sanitizer }
} }
/**
* A taint-tracking configuration for untrusted user input used in dangerous regular expression operations.
*/
private module ReDoSConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node source) { source instanceof Source }
predicate isSink(DataFlow::Node sink) { sink instanceof Sink }
predicate isBarrier(DataFlow::Node node) { node instanceof Sanitizer }
}
/**
* A taint-tracking module for untrusted user input used in dangerous regular expression operations.
*/
module ReDoS = TaintTracking::Global<ReDoSConfig>;
/** A source of remote user input. */ /** A source of remote user input. */
class RemoteSource extends Source instanceof RemoteFlowSource { } class RemoteSource extends Source instanceof RemoteFlowSource { }

View File

@@ -24,9 +24,11 @@ abstract class Sink extends DataFlow::ExprNode { }
abstract class Sanitizer extends DataFlow::ExprNode { } abstract class Sanitizer extends DataFlow::ExprNode { }
/** /**
* DEPRECATED: Use `RegexInjection` instead.
*
* A taint-tracking configuration for untrusted user input used to construct regular expressions. * A taint-tracking configuration for untrusted user input used to construct regular expressions.
*/ */
class TaintTrackingConfiguration extends TaintTracking::Configuration { deprecated class TaintTrackingConfiguration extends TaintTracking::Configuration {
TaintTrackingConfiguration() { this = "RegexInjection" } TaintTrackingConfiguration() { this = "RegexInjection" }
override predicate isSource(DataFlow::Node source) { source instanceof Source } override predicate isSource(DataFlow::Node source) { source instanceof Source }
@@ -36,6 +38,22 @@ class TaintTrackingConfiguration extends TaintTracking::Configuration {
override predicate isSanitizer(DataFlow::Node node) { node instanceof Sanitizer } override predicate isSanitizer(DataFlow::Node node) { node instanceof Sanitizer }
} }
/**
* A taint-tracking configuration for untrusted user input used to construct regular expressions.
*/
private module RegexInjectionConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node source) { source instanceof Source }
predicate isSink(DataFlow::Node sink) { sink instanceof Sink }
predicate isBarrier(DataFlow::Node node) { node instanceof Sanitizer }
}
/**
* A taint-tracking module for untrusted user input used to construct regular expressions.
*/
module RegexInjection = TaintTracking::Global<RegexInjectionConfig>;
/** A source of remote user input. */ /** A source of remote user input. */
class RemoteSource extends Source instanceof RemoteFlowSource { } class RemoteSource extends Source instanceof RemoteFlowSource { }

View File

@@ -24,9 +24,11 @@ abstract class Sink extends DataFlow::ExprNode { }
abstract class Sanitizer extends DataFlow::ExprNode { } abstract class Sanitizer extends DataFlow::ExprNode { }
/** /**
* DEPRECATED: Use `ResourceInjection` instead.
*
* A taint-tracking configuration for untrusted user input used in resource descriptors. * A taint-tracking configuration for untrusted user input used in resource descriptors.
*/ */
class TaintTrackingConfiguration extends TaintTracking::Configuration { deprecated class TaintTrackingConfiguration extends TaintTracking::Configuration {
TaintTrackingConfiguration() { this = "ResourceInjection" } TaintTrackingConfiguration() { this = "ResourceInjection" }
override predicate isSource(DataFlow::Node source) { source instanceof Source } override predicate isSource(DataFlow::Node source) { source instanceof Source }
@@ -36,6 +38,22 @@ class TaintTrackingConfiguration extends TaintTracking::Configuration {
override predicate isSanitizer(DataFlow::Node node) { node instanceof Sanitizer } override predicate isSanitizer(DataFlow::Node node) { node instanceof Sanitizer }
} }
/**
* A taint-tracking configuration for untrusted user input used in resource descriptors.
*/
private module ResourceInjectionConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node source) { source instanceof Source }
predicate isSink(DataFlow::Node sink) { sink instanceof Sink }
predicate isBarrier(DataFlow::Node node) { node instanceof Sanitizer }
}
/**
* A taint-tracking module for untrusted user input used in resource descriptors.
*/
module ResourceInjection = TaintTracking::Global<ResourceInjectionConfig>;
/** A source of remote user input. */ /** A source of remote user input. */
class RemoteSource extends Source instanceof RemoteFlowSource { } class RemoteSource extends Source instanceof RemoteFlowSource { }

View File

@@ -25,9 +25,11 @@ abstract class Sink extends DataFlow::ExprNode { }
abstract class Sanitizer extends DataFlow::ExprNode { } abstract class Sanitizer extends DataFlow::ExprNode { }
/** /**
* DEPRECATED: Use `SqlInjection` instead.
*
* A taint-tracking configuration for SQL injection vulnerabilities. * A taint-tracking configuration for SQL injection vulnerabilities.
*/ */
class TaintTrackingConfiguration extends TaintTracking::Configuration { deprecated class TaintTrackingConfiguration extends TaintTracking::Configuration {
TaintTrackingConfiguration() { this = "SqlInjection" } TaintTrackingConfiguration() { this = "SqlInjection" }
override predicate isSource(DataFlow::Node source) { source instanceof Source } override predicate isSource(DataFlow::Node source) { source instanceof Source }
@@ -37,6 +39,32 @@ class TaintTrackingConfiguration extends TaintTracking::Configuration {
override predicate isSanitizer(DataFlow::Node node) { node instanceof Sanitizer } override predicate isSanitizer(DataFlow::Node node) { node instanceof Sanitizer }
} }
/**
* A taint-tracking configuration for SQL injection vulnerabilities.
*/
module SqlInjectionConfig implements DataFlow::ConfigSig {
/**
* Holds if `source` is a relevant data flow source.
*/
predicate isSource(DataFlow::Node source) { source instanceof Source }
/**
* Holds if `sink` is a relevant data flow sink.
*/
predicate isSink(DataFlow::Node sink) { sink instanceof Sink }
/**
* Holds if data flow through `node` is prohibited. This completely removes
* `node` from the data flow graph.
*/
predicate isBarrier(DataFlow::Node node) { node instanceof Sanitizer }
}
/**
* A taint-tracking module for SQL injection vulnerabilities.
*/
module SqlInjection = TaintTracking::Global<SqlInjectionConfig>;
/** A source of remote user input. */ /** A source of remote user input. */
class RemoteSource extends Source instanceof RemoteFlowSource { } class RemoteSource extends Source instanceof RemoteFlowSource { }

View File

@@ -12,13 +12,13 @@
import csharp import csharp
import semmle.code.csharp.commons.QualifiedName import semmle.code.csharp.commons.QualifiedName
import semmle.code.csharp.security.dataflow.ExternalAPIsQuery import semmle.code.csharp.security.dataflow.ExternalAPIsQuery
import DataFlow::PathGraph import RemoteSourceToExternalApi::PathGraph
from from
UntrustedDataToExternalApiConfig config, DataFlow::PathNode source, DataFlow::PathNode sink, RemoteSourceToExternalApi::PathNode source, RemoteSourceToExternalApi::PathNode sink,
string qualifier, string name string qualifier, string name
where where
config.hasFlowPath(source, sink) and RemoteSourceToExternalApi::flowPath(source, sink) and
sink.getNode().(ExternalApiDataNode).hasQualifiedName(qualifier, name) sink.getNode().(ExternalApiDataNode).hasQualifiedName(qualifier, name)
select sink, source, sink, select sink, source, sink,
"Call to " + getQualifiedName(qualifier, name) + " with untrusted data from $@.", source, "Call to " + getQualifiedName(qualifier, name) + " with untrusted data from $@.", source,

View File

@@ -12,15 +12,21 @@
*/ */
import csharp import csharp
import semmle.code.csharp.security.dataflow.SqlInjectionQuery as SqlInjection import semmle.code.csharp.security.dataflow.SqlInjectionQuery
import semmle.code.csharp.security.dataflow.flowsources.Stored import semmle.code.csharp.security.dataflow.flowsources.Stored
import semmle.code.csharp.dataflow.DataFlow::DataFlow::PathGraph import StoredSqlInjection::PathGraph
class StoredTaintTrackingConfiguration extends SqlInjection::TaintTrackingConfiguration { module StoredSqlInjectionConfig implements DataFlow::ConfigSig {
override predicate isSource(DataFlow::Node source) { source instanceof StoredFlowSource } predicate isSource(DataFlow::Node source) { source instanceof StoredFlowSource }
predicate isSink = SqlInjectionConfig::isSink/1;
predicate isBarrier = SqlInjectionConfig::isBarrier/1;
} }
from StoredTaintTrackingConfiguration c, DataFlow::PathNode source, DataFlow::PathNode sink module StoredSqlInjection = TaintTracking::Global<StoredSqlInjectionConfig>;
where c.hasFlowPath(source, sink)
from StoredSqlInjection::PathNode source, StoredSqlInjection::PathNode sink
where StoredSqlInjection::flowPath(source, sink)
select sink.getNode(), source, sink, "This SQL query depends on a $@.", source.getNode(), select sink.getNode(), source, sink, "This SQL query depends on a $@.", source.getNode(),
"stored user-provided value" "stored user-provided value"

View File

@@ -13,7 +13,7 @@
import csharp import csharp
import semmle.code.csharp.security.dataflow.SqlInjectionQuery import semmle.code.csharp.security.dataflow.SqlInjectionQuery
import semmle.code.csharp.dataflow.DataFlow::DataFlow::PathGraph import SqlInjection::PathGraph
import semmle.code.csharp.security.dataflow.flowsources.Remote import semmle.code.csharp.security.dataflow.flowsources.Remote
import semmle.code.csharp.security.dataflow.flowsources.Local import semmle.code.csharp.security.dataflow.flowsources.Local
@@ -23,7 +23,7 @@ string getSourceType(DataFlow::Node node) {
result = node.(LocalFlowSource).getSourceType() result = node.(LocalFlowSource).getSourceType()
} }
from TaintTrackingConfiguration c, DataFlow::PathNode source, DataFlow::PathNode sink from SqlInjection::PathNode source, SqlInjection::PathNode sink
where c.hasFlowPath(source, sink) where SqlInjection::flowPath(source, sink)
select sink.getNode(), source, sink, "This query depends on $@.", source, select sink.getNode(), source, sink, "This query depends on $@.", source,
("this " + getSourceType(source.getNode())) ("this " + getSourceType(source.getNode()))

View File

@@ -13,9 +13,9 @@
import csharp import csharp
import semmle.code.csharp.security.dataflow.LDAPInjectionQuery import semmle.code.csharp.security.dataflow.LDAPInjectionQuery
import semmle.code.csharp.dataflow.DataFlow::DataFlow::PathGraph import LdapInjection::PathGraph
from TaintTrackingConfiguration c, DataFlow::PathNode source, DataFlow::PathNode sink from LdapInjection::PathNode source, LdapInjection::PathNode sink
where c.hasFlowPath(source, sink) where LdapInjection::flowPath(source, sink)
select sink.getNode(), source, sink, "This LDAP query depends on a $@.", source.getNode(), select sink.getNode(), source, sink, "This LDAP query depends on a $@.", source.getNode(),
"user-provided value" "user-provided value"

View File

@@ -14,13 +14,19 @@
import csharp import csharp
import semmle.code.csharp.security.dataflow.LDAPInjectionQuery import semmle.code.csharp.security.dataflow.LDAPInjectionQuery
import semmle.code.csharp.security.dataflow.flowsources.Stored import semmle.code.csharp.security.dataflow.flowsources.Stored
import semmle.code.csharp.dataflow.DataFlow::DataFlow::PathGraph import StoredLdapInjection::PathGraph
class StoredTaintTrackingConfiguration extends TaintTrackingConfiguration { module StoredLdapInjectionConfig implements DataFlow::ConfigSig {
override predicate isSource(DataFlow::Node source) { source instanceof StoredFlowSource } predicate isSource(DataFlow::Node source) { source instanceof StoredFlowSource }
predicate isSink = LdapInjectionConfig::isSink/1;
predicate isBarrier = LdapInjectionConfig::isBarrier/1;
} }
from StoredTaintTrackingConfiguration c, DataFlow::PathNode source, DataFlow::PathNode sink module StoredLdapInjection = TaintTracking::Global<StoredLdapInjectionConfig>;
where c.hasFlowPath(source, sink)
from StoredLdapInjection::PathNode source, StoredLdapInjection::PathNode sink
where StoredLdapInjection::flowPath(source, sink)
select sink.getNode(), source, sink, "This LDAP query depends on a $@.", source.getNode(), select sink.getNode(), source, sink, "This LDAP query depends on a $@.", source.getNode(),
"stored (potentially user-provided) value" "stored (potentially user-provided) value"

View File

@@ -13,9 +13,9 @@
import csharp import csharp
import semmle.code.csharp.security.dataflow.ResourceInjectionQuery import semmle.code.csharp.security.dataflow.ResourceInjectionQuery
import semmle.code.csharp.dataflow.DataFlow::DataFlow::PathGraph import ResourceInjection::PathGraph
from TaintTrackingConfiguration c, DataFlow::PathNode source, DataFlow::PathNode sink from ResourceInjection::PathNode source, ResourceInjection::PathNode sink
where c.hasFlowPath(source, sink) where ResourceInjection::flowPath(source, sink)
select sink.getNode(), source, sink, "This resource descriptor depends on a $@.", source.getNode(), select sink.getNode(), source, sink, "This resource descriptor depends on a $@.", source.getNode(),
"user-provided value" "user-provided value"

View File

@@ -13,10 +13,10 @@
import csharp import csharp
import semmle.code.csharp.security.dataflow.MissingXMLValidationQuery import semmle.code.csharp.security.dataflow.MissingXMLValidationQuery
import semmle.code.csharp.dataflow.DataFlow::DataFlow::PathGraph import MissingXmlValidation::PathGraph
from TaintTrackingConfiguration c, DataFlow::PathNode source, DataFlow::PathNode sink from MissingXmlValidation::PathNode source, MissingXmlValidation::PathNode sink
where c.hasFlowPath(source, sink) where MissingXmlValidation::flowPath(source, sink)
select sink.getNode(), source, sink, select sink.getNode(), source, sink,
"This XML processing depends on a $@ without validation because " + "This XML processing depends on a $@ without validation because " +
sink.getNode().(Sink).getReason(), source.getNode(), "user-provided value" sink.getNode().(Sink).getReason(), source.getNode(), "user-provided value"

View File

@@ -13,9 +13,9 @@
import csharp import csharp
import semmle.code.csharp.security.dataflow.LogForgingQuery import semmle.code.csharp.security.dataflow.LogForgingQuery
import semmle.code.csharp.dataflow.DataFlow::DataFlow::PathGraph import LogForging::PathGraph
from TaintTrackingConfiguration c, DataFlow::PathNode source, DataFlow::PathNode sink from LogForging::PathNode source, LogForging::PathNode sink
where c.hasFlowPath(source, sink) where LogForging::flowPath(source, sink)
select sink.getNode(), source, sink, "This log entry depends on a $@.", source.getNode(), select sink.getNode(), source, sink, "This log entry depends on a $@.", source.getNode(),
"user-provided value" "user-provided value"

View File

@@ -16,11 +16,11 @@
import csharp import csharp
import semmle.code.csharp.security.dataflow.ReDoSQuery import semmle.code.csharp.security.dataflow.ReDoSQuery
import semmle.code.csharp.frameworks.system.text.RegularExpressions import semmle.code.csharp.frameworks.system.text.RegularExpressions
import semmle.code.csharp.dataflow.DataFlow::DataFlow::PathGraph import ReDoS::PathGraph
from TaintTrackingConfiguration c, DataFlow::PathNode source, DataFlow::PathNode sink from ReDoS::PathNode source, ReDoS::PathNode sink
where where
c.hasFlowPath(source, sink) and ReDoS::flowPath(source, sink) and
// No global timeout set // No global timeout set
not exists(RegexGlobalTimeout r) and not exists(RegexGlobalTimeout r) and
( (

View File

@@ -16,11 +16,11 @@
import csharp import csharp
import semmle.code.csharp.security.dataflow.RegexInjectionQuery import semmle.code.csharp.security.dataflow.RegexInjectionQuery
import semmle.code.csharp.frameworks.system.text.RegularExpressions import semmle.code.csharp.frameworks.system.text.RegularExpressions
import semmle.code.csharp.dataflow.DataFlow::DataFlow::PathGraph import RegexInjection::PathGraph
from TaintTrackingConfiguration c, DataFlow::PathNode source, DataFlow::PathNode sink from RegexInjection::PathNode source, RegexInjection::PathNode sink
where where
c.hasFlowPath(source, sink) and RegexInjection::flowPath(source, sink) and
// No global timeout set // No global timeout set
not exists(RegexGlobalTimeout r) not exists(RegexGlobalTimeout r)
select sink.getNode(), source, sink, "This regular expression is constructed from a $@.", select sink.getNode(), source, sink, "This regular expression is constructed from a $@.",

View File

@@ -15,7 +15,7 @@
import csharp import csharp
import semmle.code.csharp.frameworks.system.Data import semmle.code.csharp.frameworks.system.Data
import semmle.code.csharp.security.dataflow.HardcodedCredentialsQuery import semmle.code.csharp.security.dataflow.HardcodedCredentialsQuery
import semmle.code.csharp.dataflow.DataFlow::DataFlow::PathGraph import ConnectionString::PathGraph
/** /**
* A string literal containing a username or password field. * A string literal containing a username or password field.
@@ -29,24 +29,24 @@ class ConnectionStringPasswordOrUsername extends NonEmptyStringLiteral {
/** /**
* A taint-tracking configuration for tracking string literals to a `ConnectionString` property. * A taint-tracking configuration for tracking string literals to a `ConnectionString` property.
*/ */
class ConnectionStringTaintTrackingConfiguration extends TaintTracking::Configuration { module ConnectionStringConfig implements DataFlow::ConfigSig {
ConnectionStringTaintTrackingConfiguration() { this = "connectionstring" } predicate isSource(DataFlow::Node source) { source instanceof ConnectionStringPasswordOrUsername }
override predicate isSource(DataFlow::Node source) { predicate isSink(DataFlow::Node sink) {
source instanceof ConnectionStringPasswordOrUsername
}
override predicate isSink(DataFlow::Node sink) {
sink.asExpr() = sink.asExpr() =
any(SystemDataConnectionClass connection).getConnectionStringProperty().getAnAssignedValue() any(SystemDataConnectionClass connection).getConnectionStringProperty().getAnAssignedValue()
} }
override predicate isSanitizer(DataFlow::Node node) { node instanceof StringFormatSanitizer } predicate isBarrier(DataFlow::Node node) { node instanceof StringFormatSanitizer }
} }
from /**
ConnectionStringTaintTrackingConfiguration c, DataFlow::PathNode source, DataFlow::PathNode sink * A taint-tracking module for tracking string literals to a `ConnectionString` property.
where c.hasFlowPath(source, sink) */
module ConnectionString = TaintTracking::Global<ConnectionStringConfig>;
from ConnectionString::PathNode source, ConnectionString::PathNode sink
where ConnectionString::flowPath(source, sink)
select source.getNode(), source, sink, select source.getNode(), source, sink,
"'ConnectionString' property includes hard-coded credentials set in $@.", "'ConnectionString' property includes hard-coded credentials set in $@.",
any(Call call | call.getAnArgument() = sink.getNode().asExpr()) as call, call.toString() any(Call call | call.getAnArgument() = sink.getNode().asExpr()) as call, call.toString()

View File

@@ -14,15 +14,15 @@
import csharp import csharp
import semmle.code.csharp.security.dataflow.HardcodedCredentialsQuery import semmle.code.csharp.security.dataflow.HardcodedCredentialsQuery
import semmle.code.csharp.dataflow.DataFlow::DataFlow::PathGraph import HardcodedCredentials::PathGraph
from from
TaintTrackingConfiguration c, Source source, Sink sink, DataFlow::PathNode sourcePath, Source source, Sink sink, HardcodedCredentials::PathNode sourcePath,
DataFlow::PathNode sinkPath, string value HardcodedCredentials::PathNode sinkPath, string value
where where
source = sourcePath.getNode() and source = sourcePath.getNode() and
sink = sinkPath.getNode() and sink = sinkPath.getNode() and
c.hasFlowPath(sourcePath, sinkPath) and HardcodedCredentials::flowPath(sourcePath, sinkPath) and
// Print the source value if it's available // Print the source value if it's available
if exists(source.asExpr().getValue()) if exists(source.asExpr().getValue())
then value = "The hard-coded value \"" + source.asExpr().getValue() + "\"" then value = "The hard-coded value \"" + source.asExpr().getValue() + "\""

View File

@@ -1,19 +1,7 @@
edges edges
| HardcodedCredentials.cs:47:30:47:60 | array creation of type Byte[] : Byte[] | HardcodedCredentials.cs:50:13:50:23 | access to local variable rawCertData |
nodes nodes
| HardcodedCredentials.cs:15:25:15:36 | "myPa55word" | semmle.label | "myPa55word" |
| HardcodedCredentials.cs:31:19:31:28 | "username" | semmle.label | "username" |
| HardcodedCredentials.cs:45:39:45:53 | "myNewPa55word" | semmle.label | "myNewPa55word" |
| HardcodedCredentials.cs:47:30:47:60 | array creation of type Byte[] : Byte[] | semmle.label | array creation of type Byte[] : Byte[] |
| HardcodedCredentials.cs:50:13:50:23 | access to local variable rawCertData | semmle.label | access to local variable rawCertData |
| HardcodedCredentials.cs:51:13:51:24 | "myPa55word" | semmle.label | "myPa55word" |
| HardcodedCredentials.cs:54:48:54:63 | "Password=12345" | semmle.label | "Password=12345" | | HardcodedCredentials.cs:54:48:54:63 | "Password=12345" | semmle.label | "Password=12345" |
| HardcodedCredentials.cs:56:49:56:63 | "User Id=12345" | semmle.label | "User Id=12345" | | HardcodedCredentials.cs:56:49:56:63 | "User Id=12345" | semmle.label | "User Id=12345" |
| HardcodedCredentials.cs:74:31:74:42 | "myusername" | semmle.label | "myusername" |
| HardcodedCredentials.cs:74:45:74:56 | "mypassword" | semmle.label | "mypassword" |
| TestHardcodedCredentials.cs:21:31:21:42 | "myusername" | semmle.label | "myusername" |
| TestHardcodedCredentials.cs:21:45:21:56 | "mypassword" | semmle.label | "mypassword" |
| TestHardcodedCredentials.cs:26:19:26:28 | "username" | semmle.label | "username" |
subpaths subpaths
#select #select
| HardcodedCredentials.cs:54:48:54:63 | "Password=12345" | HardcodedCredentials.cs:54:48:54:63 | "Password=12345" | HardcodedCredentials.cs:54:48:54:63 | "Password=12345" | 'ConnectionString' property includes hard-coded credentials set in $@. | HardcodedCredentials.cs:54:30:54:64 | object creation of type SqlConnection | object creation of type SqlConnection | | HardcodedCredentials.cs:54:48:54:63 | "Password=12345" | HardcodedCredentials.cs:54:48:54:63 | "Password=12345" | HardcodedCredentials.cs:54:48:54:63 | "Password=12345" | 'ConnectionString' property includes hard-coded credentials set in $@. | HardcodedCredentials.cs:54:30:54:64 | object creation of type SqlConnection | object creation of type SqlConnection |