C#: Make use of extra data flow copies

This commit is contained in:
Tom Hvitved
2019-08-05 16:03:01 +02:00
parent 081ee9944d
commit 6749bbd438
10 changed files with 16 additions and 66 deletions

View File

@@ -5,6 +5,7 @@
import csharp
private import semmle.code.csharp.frameworks.System
private import semmle.code.csharp.frameworks.system.Text
private import semmle.code.csharp.dataflow.DataFlow2
/** A method that formats a string, for example `string.Format()`. */
class FormatMethod extends Method {
@@ -175,7 +176,7 @@ class InvalidFormatString extends StringLiteral {
private module FormatFlow {
private import semmle.code.csharp.dataflow.DataFlow
private class FormatConfiguration extends DataFlow::Configuration {
private class FormatConfiguration extends DataFlow2::Configuration {
FormatConfiguration() { this = "format" }
override predicate isSource(DataFlow::Node n) { n.asExpr() instanceof StringLiteral }

View File

@@ -2,6 +2,7 @@
import csharp
private import semmle.code.csharp.frameworks.System
private import semmle.code.csharp.dataflow.DataFlow2
/** The `System.Xml` namespace. */
class SystemXmlNamespace extends Namespace {
@@ -162,7 +163,7 @@ class XmlReaderSettingsCreation extends ObjectCreation {
}
}
private class SettingsDataFlowConfig extends DataFlow::Configuration {
private class SettingsDataFlowConfig extends DataFlow2::Configuration {
SettingsDataFlowConfig() { this = "SettingsDataFlowConfig" }
override predicate isSource(DataFlow::Node source) {

View File

@@ -6,6 +6,7 @@
import csharp
module ReDoS {
private import semmle.code.csharp.dataflow.DataFlow2
import semmle.code.csharp.dataflow.flowsources.Remote
import semmle.code.csharp.frameworks.system.text.RegularExpressions
import semmle.code.csharp.security.Sanitizers
@@ -33,23 +34,9 @@ module ReDoS {
override predicate isSource(DataFlow::Node source) { source instanceof Source }
override predicate isSink(DataFlow::Node sink) {
sink instanceof Sink
or
// Unfortunately, we cannot add `ExponentialRegexSink` as
// a sub class of `Sink`, as that results in bad aggregate
// recursion. Therefore, we overestimate the sinks here
// and make the restriction later by overriding
// `hasFlowPath()` below.
sink.asExpr() = any(RegexOperation ro).getInput()
}
override predicate isSink(DataFlow::Node sink) { sink instanceof Sink }
override predicate isSanitizer(DataFlow::Node node) { node instanceof Sanitizer }
override predicate hasFlowPath(DataFlow::PathNode source, DataFlow::PathNode sink) {
super.hasFlowPath(source, sink) and
(sink.getNode() instanceof Sink or sink.getNode() instanceof ExponentialRegexSink)
}
}
/** A source of remote user input. */
@@ -81,7 +68,7 @@ module ReDoS {
* A data flow configuration for tracking exponential worst case time regular expression string
* literals to the pattern argument of a regex.
*/
class ExponentialRegexDataflow extends DataFlow::Configuration {
class ExponentialRegexDataflow extends DataFlow2::Configuration {
ExponentialRegexDataflow() { this = "ExponentialRegex" }
override predicate isSource(DataFlow::Node s) { isExponentialRegex(s.asExpr()) }
@@ -93,7 +80,7 @@ module ReDoS {
* An expression passed as the `input` to a call to a `Regex` method, where the regex appears to
* have exponential behaviour.
*/
class ExponentialRegexSink extends DataFlow::ExprNode {
class ExponentialRegexSink extends DataFlow::ExprNode, Sink {
ExponentialRegexSink() {
exists(ExponentialRegexDataflow regexDataflow, RegexOperation regexOperation |
// Exponential regex flows to the pattern argument

View File

@@ -31,31 +31,15 @@ module XMLEntityInjection {
}
class InsecureXMLSink extends Sink {
InsecureXMLSink() {
// Unfortunately, we cannot use
// ```
// exists(InsecureXML::InsecureXmlProcessing r | r.isUnsafe(reason) | this = r.getAnArgument())
// ```
// in the charpred, as that results in bad aggregate
// recursion. Therefore, we overestimate the sinks here
// and make the restriction later by overriding
// `hasFlowPath()` below.
this.getExpr() = any(MethodCall mc |
mc.getTarget().hasQualifiedName("System.Xml.XmlReader.Create") or
mc.getTarget().hasQualifiedName("System.Xml.XmlDocument.Load") or
mc.getTarget().hasQualifiedName("System.Xml.XmlDocument.LoadXml")
).getAnArgument()
or
this.getExpr() = any(ObjectCreation oc |
oc.getObjectType().(ValueOrRefType).hasQualifiedName("System.Xml.XmlTextReader")
).getAnArgument()
}
private string reason;
override string getReason() {
exists(InsecureXML::InsecureXmlProcessing r | r.isUnsafe(result) |
InsecureXMLSink() {
exists(InsecureXML::InsecureXmlProcessing r | r.isUnsafe(reason) |
this.getExpr() = r.getAnArgument()
)
}
override string getReason() { result = reason }
}
/**

View File

@@ -146,6 +146,8 @@ module InsecureXML {
}
module XmlReader {
private import semmle.code.csharp.dataflow.DataFlow2
class InsecureXmlReaderCreate extends InsecureXmlProcessing, MethodCall {
InsecureXmlReaderCreate() { this.getTarget().hasQualifiedName("System.Xml.XmlReader.Create") }
@@ -188,7 +190,7 @@ module InsecureXML {
}
}
private class SettingsDataFlowConfig extends DataFlow::Configuration {
private class SettingsDataFlowConfig extends DataFlow2::Configuration {
SettingsDataFlowConfig() { this = "SettingsDataFlowConfig" }
override predicate isSource(DataFlow::Node source) {

View File

@@ -4,10 +4,6 @@ edges
| MissingXMLValidation.cs:14:34:14:56 | access to property QueryString | MissingXMLValidation.cs:29:26:29:58 | object creation of type StringReader |
| MissingXMLValidation.cs:14:34:14:56 | access to property QueryString | MissingXMLValidation.cs:37:26:37:58 | object creation of type StringReader |
| MissingXMLValidation.cs:14:34:14:56 | access to property QueryString | MissingXMLValidation.cs:47:26:47:58 | object creation of type StringReader |
| MissingXMLValidation.cs:22:42:22:64 | object creation of type XmlReaderSettings | MissingXMLValidation.cs:23:61:23:72 | access to local variable badSettings1 |
| MissingXMLValidation.cs:27:42:27:64 | object creation of type XmlReaderSettings | MissingXMLValidation.cs:29:61:29:72 | access to local variable badSettings2 |
| MissingXMLValidation.cs:32:42:32:64 | object creation of type XmlReaderSettings | MissingXMLValidation.cs:37:61:37:72 | access to local variable goodSettings |
| MissingXMLValidation.cs:40:42:40:64 | object creation of type XmlReaderSettings | MissingXMLValidation.cs:47:61:47:72 | access to local variable badSettings3 |
#select
| MissingXMLValidation.cs:18:26:18:58 | object creation of type StringReader | MissingXMLValidation.cs:14:34:14:56 | access to property QueryString | MissingXMLValidation.cs:18:26:18:58 | object creation of type StringReader | $@ flows to here and is processed as XML without validation because there is no 'XmlReaderSettings' instance specifying schema validation. | MissingXMLValidation.cs:14:34:14:56 | access to property QueryString | User-provided value |
| MissingXMLValidation.cs:23:26:23:58 | object creation of type StringReader | MissingXMLValidation.cs:14:34:14:56 | access to property QueryString | MissingXMLValidation.cs:23:26:23:58 | object creation of type StringReader | $@ flows to here and is processed as XML without validation because the 'XmlReaderSettings' instance does not specify the 'ValidationType' as 'Schema'. | MissingXMLValidation.cs:14:34:14:56 | access to property QueryString | User-provided value |

View File

@@ -1,8 +1,6 @@
edges
| UncontrolledFormatString.cs:11:23:11:45 | access to property QueryString | UncontrolledFormatString.cs:14:23:14:26 | access to local variable path |
| UncontrolledFormatString.cs:11:23:11:45 | access to property QueryString | UncontrolledFormatString.cs:17:46:17:49 | access to local variable path |
| UncontrolledFormatString.cs:20:23:20:38 | "Do not do this" | UncontrolledFormatString.cs:20:23:20:38 | "Do not do this" |
| UncontrolledFormatString.cs:23:46:23:61 | "Do not do this" | UncontrolledFormatString.cs:23:46:23:61 | "Do not do this" |
| UncontrolledFormatString.cs:31:23:31:31 | access to property Text | UncontrolledFormatString.cs:31:23:31:31 | access to property Text |
| UncontrolledFormatStringBad.cs:9:25:9:47 | access to property QueryString | UncontrolledFormatStringBad.cs:12:39:12:44 | access to local variable format |
#select

View File

@@ -1,5 +1,4 @@
edges
| Test.cs:13:50:13:72 | access to property QueryString | Test.cs:13:50:13:84 | access to indexer |
| Test.cs:18:38:18:60 | object creation of type XmlReaderSettings | Test.cs:23:55:23:62 | access to local variable settings |
#select
| Test.cs:13:50:13:84 | access to indexer | Test.cs:13:50:13:72 | access to property QueryString | Test.cs:13:50:13:84 | access to indexer | $@ flows to here and is loaded insecurely as XML (DTD processing is enabled with an insecure resolver). | Test.cs:13:50:13:72 | access to property QueryString | User-provided value |

View File

@@ -1,26 +1,9 @@
edges
| ExponentialRegex.cs:9:55:9:83 | "^(([a-z])+.)+[A-Z]([a-z])+$" | ExponentialRegex.cs:24:19:24:34 | access to field JAVA_CLASS_REGEX |
| ExponentialRegex.cs:9:55:9:83 | "^(([a-z])+.)+[A-Z]([a-z])+$" | ExponentialRegex.cs:24:19:24:34 | access to field JAVA_CLASS_REGEX |
| ExponentialRegex.cs:9:55:9:83 | "^(([a-z])+.)+[A-Z]([a-z])+$" | ExponentialRegex.cs:26:32:26:47 | access to field JAVA_CLASS_REGEX |
| ExponentialRegex.cs:9:55:9:83 | "^(([a-z])+.)+[A-Z]([a-z])+$" | ExponentialRegex.cs:26:32:26:47 | access to field JAVA_CLASS_REGEX |
| ExponentialRegex.cs:9:55:9:83 | "^(([a-z])+.)+[A-Z]([a-z])+$" | ExponentialRegex.cs:30:32:30:47 | access to field JAVA_CLASS_REGEX |
| ExponentialRegex.cs:13:28:13:50 | access to property QueryString | ExponentialRegex.cs:17:40:17:48 | access to local variable userInput |
| ExponentialRegex.cs:13:28:13:50 | access to property QueryString | ExponentialRegex.cs:18:42:18:50 | access to local variable userInput |
| ExponentialRegex.cs:13:28:13:50 | access to property QueryString | ExponentialRegex.cs:21:139:21:147 | access to local variable userInput |
| ExponentialRegex.cs:13:28:13:50 | access to property QueryString | ExponentialRegex.cs:24:43:24:51 | access to local variable userInput |
| ExponentialRegex.cs:13:28:13:50 | access to property QueryString | ExponentialRegex.cs:26:21:26:29 | access to local variable userInput |
| ExponentialRegex.cs:13:28:13:50 | access to property QueryString | ExponentialRegex.cs:28:47:28:55 | access to local variable userInput |
| ExponentialRegex.cs:13:28:13:50 | access to property QueryString | ExponentialRegex.cs:29:90:29:98 | access to local variable userInput |
| ExponentialRegex.cs:13:28:13:50 | access to property QueryString | ExponentialRegex.cs:30:21:30:29 | access to local variable userInput |
| ExponentialRegex.cs:13:28:13:50 | access to property QueryString | ExponentialRegex.cs:32:57:32:65 | access to local variable userInput |
| ExponentialRegex.cs:17:19:17:31 | "^([a-z]+)+$" | ExponentialRegex.cs:17:19:17:31 | "^([a-z]+)+$" |
| ExponentialRegex.cs:18:19:18:31 | "^([a-z]*)*$" | ExponentialRegex.cs:18:19:18:31 | "^([a-z]*)*$" |
| ExponentialRegex.cs:21:19:21:130 | "^([a-zA-Z0-9])(([\\-.]\|[_]+)?([a-zA-Z0-9]+))*(@){1}[a-z0-9]+[.]{1}(([a-z]{2,3})\|([a-z]{2,3}[.]{1}[a-z]{2,3}))$" | ExponentialRegex.cs:21:19:21:130 | "^([a-zA-Z0-9])(([\\-.]\|[_]+)?([a-zA-Z0-9]+))*(@){1}[a-z0-9]+[.]{1}(([a-z]{2,3})\|([a-z]{2,3}[.]{1}[a-z]{2,3}))$" |
| ExponentialRegex.cs:24:19:24:34 | access to field JAVA_CLASS_REGEX | ExponentialRegex.cs:26:32:26:47 | access to field JAVA_CLASS_REGEX |
| ExponentialRegex.cs:24:19:24:34 | access to field JAVA_CLASS_REGEX | ExponentialRegex.cs:26:32:26:47 | access to field JAVA_CLASS_REGEX |
| ExponentialRegex.cs:24:19:24:34 | access to field JAVA_CLASS_REGEX | ExponentialRegex.cs:30:32:30:47 | access to field JAVA_CLASS_REGEX |
| ExponentialRegex.cs:26:32:26:47 | access to field JAVA_CLASS_REGEX | ExponentialRegex.cs:30:32:30:47 | access to field JAVA_CLASS_REGEX |
| ExponentialRegex.cs:29:19:29:31 | "^([a-z]+)+$" | ExponentialRegex.cs:29:19:29:31 | "^([a-z]+)+$" |
#select
| ExponentialRegex.cs:17:40:17:48 | access to local variable userInput | ExponentialRegex.cs:13:28:13:50 | access to property QueryString | ExponentialRegex.cs:17:40:17:48 | access to local variable userInput | $@ flows to regular expression operation with dangerous regex. | ExponentialRegex.cs:13:28:13:50 | access to property QueryString | User-provided value |
| ExponentialRegex.cs:18:42:18:50 | access to local variable userInput | ExponentialRegex.cs:13:28:13:50 | access to property QueryString | ExponentialRegex.cs:18:42:18:50 | access to local variable userInput | $@ flows to regular expression operation with dangerous regex. | ExponentialRegex.cs:13:28:13:50 | access to property QueryString | User-provided value |

View File

@@ -1,4 +1,3 @@
edges
| ExponentialRegex.cs:15:28:15:50 | access to property QueryString | ExponentialRegex.cs:18:40:18:48 | access to local variable userInput |
| ExponentialRegex.cs:18:19:18:31 | "^([a-z]+)+$" | ExponentialRegex.cs:18:19:18:31 | "^([a-z]+)+$" |
#select