Merge pull request #12763 from jketema/swift-configsig-3

Swift: Update final two queries to use `DataFlow::ConfigSig`
This commit is contained in:
Jeroen Ketema
2023-04-05 12:49:00 +02:00
committed by GitHub
5 changed files with 106 additions and 34 deletions

View File

@@ -13,7 +13,7 @@ import codeql.swift.security.CleartextStorageDatabaseExtensions
* A taint configuration from sensitive information to expressions that are
* transmitted over a network.
*/
class CleartextStorageConfig extends TaintTracking::Configuration {
deprecated class CleartextStorageConfig extends TaintTracking::Configuration {
CleartextStorageConfig() { this = "CleartextStorageConfig" }
override predicate isSource(DataFlow::Node node) { node.asExpr() instanceof SensitiveExpr }
@@ -48,3 +48,44 @@ class CleartextStorageConfig extends TaintTracking::Configuration {
super.allowImplicitRead(node, c)
}
}
/**
* A taint configuration from sensitive information to expressions that are
* transmitted over a network.
*/
module CleartextStorageConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node node) { node.asExpr() instanceof SensitiveExpr }
predicate isSink(DataFlow::Node node) { node instanceof CleartextStorageDatabaseSink }
predicate isBarrier(DataFlow::Node sanitizer) {
sanitizer instanceof CleartextStorageDatabaseSanitizer
}
predicate isAdditionalFlowStep(DataFlow::Node nodeFrom, DataFlow::Node nodeTo) {
any(CleartextStorageDatabaseAdditionalTaintStep s).step(nodeFrom, nodeTo)
}
predicate isBarrierIn(DataFlow::Node node) {
// make sources barriers so that we only report the closest instance
isSource(node)
}
predicate allowImplicitRead(DataFlow::Node node, DataFlow::ContentSet c) {
// flow out from fields of an `NSManagedObject` or `RealmSwiftObject` at the sink,
// for example in `realmObj.data = sensitive`.
isSink(node) and
exists(NominalTypeDecl d, Decl cx |
d.getType().getABaseType*().getUnderlyingType().getName() =
["NSManagedObject", "RealmSwiftObject"] and
cx.asNominalTypeDecl() = d and
c.getAReadContent().(DataFlow::Content::FieldContent).getField() = cx.getAMember()
)
}
}
/**
* Detect taint flow of sensitive information to expressions that are
* transmitted over a network.
*/
module CleartextStorageFlow = TaintTracking::Global<CleartextStorageConfig>;

View File

@@ -7,47 +7,63 @@ import swift
import codeql.swift.dataflow.DataFlow
import codeql.swift.dataflow.ExternalFlow
private newtype TStringType =
TString() or
TNsString() or
TStringUtf8() or
TStringUtf16() or
TStringUnicodeScalars()
/**
* A type of Swift string encoding. This class is used as a flow state for
* the string length conflation taint tracking configuration.
*/
class StringType extends string {
class StringType extends TStringType {
string name;
string singular;
string equivClass;
TStringType equivClass;
string csvLabel;
StringType() {
this = "String" and
this = TString() and
name = "String" and
singular = "a String" and
equivClass = "String" and
equivClass = this and
csvLabel = "string-length"
or
this = "NSString" and
this = TNsString() and
name = "NSString" and
singular = "an NSString" and
equivClass = "NSString" and
equivClass = this and
csvLabel = "nsstring-length"
or
this = "String.utf8" and
this = TStringUtf8() and
name = "String.utf8" and
singular = "a String.utf8" and
equivClass = "String.utf8" and
equivClass = this and
csvLabel = "string-utf8-length"
or
this = "String.utf16" and
this = TStringUtf16() and
name = "String.utf16" and
singular = "a String.utf16" and
equivClass = "NSString" and
equivClass = TNsString() and
csvLabel = "string-utf16-length"
or
this = "String.unicodeScalars" and
this = TStringUnicodeScalars() and
name = "String.unicodeScalars" and
singular = "a String.unicodeScalars" and
equivClass = "String.unicodeScalars" and
equivClass = this and
csvLabel = "string-unicodescalars-length"
}
/** Gets a textual representation of this string type. */
string toString() { result = name }
/**
* Gets the equivalence class for this string type. If these are equal,
* they should be treated as equivalent.
*/
string getEquivClass() { result = equivClass }
StringType getEquivClass() { result = equivClass }
/**
* Gets text for the singular form of this string type.
@@ -130,15 +146,15 @@ private class ExtraStringLengthConflationSource extends StringLengthConflationSo
(
// result of a call to `String.utf8.count`
typeName = "String.UTF8View" and
stringType = "String.utf8"
stringType = TStringUtf8()
or
// result of a call to `String.utf16.count`
typeName = "String.UTF16View" and
stringType = "String.utf16"
stringType = TStringUtf16()
or
// result of a call to `String.unicodeScalars.count`
typeName = "String.UnicodeScalarView" and
stringType = "String.unicodeScalars"
stringType = TStringUnicodeScalars()
) and
memberRef.getBase().getType().(NominalType).getName() = typeName and
memberRef.getMember().(VarDecl).getName() = "count" and

View File

@@ -9,31 +9,46 @@ import codeql.swift.dataflow.TaintTracking
import codeql.swift.security.StringLengthConflationExtensions
/**
* A configuration for tracking string lengths originating from source that is
* a `String` or an `NSString` object, to a sink of a different kind that
* A configuration for tracking string lengths originating from a source that
* is a `String` or an `NSString` object, to a sink of a different kind that
* expects an incompatible measure of length.
*/
class StringLengthConflationConfiguration extends TaintTracking::Configuration {
StringLengthConflationConfiguration() { this = "StringLengthConflationConfiguration" }
module StringLengthConflationConfig implements DataFlow::StateConfigSig {
class FlowState = StringType;
override predicate isSource(DataFlow::Node node, string flowstate) {
predicate isSource(DataFlow::Node node, FlowState flowstate) {
flowstate = node.(StringLengthConflationSource).getStringType()
}
override predicate isSink(DataFlow::Node node, string flowstate) {
predicate isSink(DataFlow::Node node, FlowState flowstate) {
// Permit any *incorrect* flowstate, as those are the results the query
// should report.
exists(string correctFlowState |
exists(FlowState correctFlowState |
correctFlowState = node.(StringLengthConflationSink).getCorrectStringType() and
flowstate.(StringType).getEquivClass() != correctFlowState.(StringType).getEquivClass()
flowstate.getEquivClass() != correctFlowState.getEquivClass()
)
}
override predicate isSanitizer(DataFlow::Node sanitizer) {
predicate isBarrier(DataFlow::Node sanitizer) {
sanitizer instanceof StringLengthConflationSanitizer
}
override predicate isAdditionalTaintStep(DataFlow::Node nodeFrom, DataFlow::Node nodeTo) {
predicate isBarrier(DataFlow::Node sanitizer, FlowState flowstate) { none() }
predicate isAdditionalFlowStep(DataFlow::Node nodeFrom, DataFlow::Node nodeTo) {
any(StringLengthConflationAdditionalTaintStep s).step(nodeFrom, nodeTo)
}
predicate isAdditionalFlowStep(
DataFlow::Node nodeFrom, FlowState flowstateFrom, DataFlow::Node nodeTo, FlowState flowStateTo
) {
none()
}
}
/**
* Detect taint flow of string lengths originating from a source that is
* a `String` or an `NSString` object, to a sink of a different kind that
* expects an incompatible measure of length.
*/
module StringLengthConflationFlow = TaintTracking::GlobalWithState<StringLengthConflationConfig>;

View File

@@ -13,14 +13,14 @@
import swift
import codeql.swift.dataflow.DataFlow
import codeql.swift.security.StringLengthConflationQuery
import DataFlow::PathGraph
import StringLengthConflationFlow::PathGraph
from
StringLengthConflationConfiguration config, DataFlow::PathNode source, DataFlow::PathNode sink,
StringLengthConflationFlow::PathNode source, StringLengthConflationFlow::PathNode sink,
StringType sourceType, StringType sinkType, string message
where
config.hasFlowPath(source, sink) and
config.isSource(source.getNode(), sourceType) and
StringLengthConflationFlow::flowPath(source, sink) and
StringLengthConflationConfig::isSource(source.getNode(), sourceType) and
sinkType = sink.getNode().(StringLengthConflationSink).getCorrectStringType() and
message =
"This " + sourceType + " length is used in " + sinkType.getSingular() +

View File

@@ -14,7 +14,7 @@
import swift
import codeql.swift.dataflow.DataFlow
import codeql.swift.security.CleartextStorageDatabaseQuery
import DataFlow::PathGraph
import CleartextStorageFlow::PathGraph
/**
* Gets a prettier node to use in the results.
@@ -27,10 +27,10 @@ DataFlow::Node cleanupNode(DataFlow::Node n) {
}
from
CleartextStorageConfig config, DataFlow::PathNode sourceNode, DataFlow::PathNode sinkNode,
CleartextStorageFlow::PathNode sourceNode, CleartextStorageFlow::PathNode sinkNode,
DataFlow::Node cleanSink
where
config.hasFlowPath(sourceNode, sinkNode) and
CleartextStorageFlow::flowPath(sourceNode, sinkNode) and
cleanSink = cleanupNode(sinkNode.getNode())
select cleanSink, sourceNode, sinkNode,
"This operation stores '" + cleanSink.toString() +