mirror of
https://github.com/github/codeql.git
synced 2025-12-17 01:03:14 +01:00
C#: Make use of extra data flow copies
This commit is contained in:
@@ -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 }
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 }
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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 |
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 |
|
||||
|
||||
@@ -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 |
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user