mirror of
https://github.com/github/codeql.git
synced 2026-04-24 16:25:15 +02:00
Swift: Split encryption queries into three parts (trivial re-organization of existing code).
This commit is contained in:
@@ -0,0 +1,7 @@
|
||||
/**
|
||||
* Provides classes and predicates for reasoning about constant password
|
||||
* vulnerabilities.
|
||||
*/
|
||||
|
||||
import swift
|
||||
import codeql.swift.dataflow.DataFlow
|
||||
62
swift/ql/lib/codeql/swift/security/ConstantPasswordQuery.qll
Normal file
62
swift/ql/lib/codeql/swift/security/ConstantPasswordQuery.qll
Normal file
@@ -0,0 +1,62 @@
|
||||
/**
|
||||
* Provides a taint tracking configuration to find constant password
|
||||
* vulnerabilities.
|
||||
*/
|
||||
|
||||
import swift
|
||||
import codeql.swift.dataflow.DataFlow
|
||||
import codeql.swift.dataflow.TaintTracking
|
||||
import codeql.swift.dataflow.FlowSteps
|
||||
import codeql.swift.security.ConstantPasswordExtensions
|
||||
|
||||
/**
|
||||
* A constant password is created through either a byte array or string literals.
|
||||
*/
|
||||
class ConstantPasswordSource extends Expr {
|
||||
ConstantPasswordSource() {
|
||||
this = any(ArrayExpr arr | arr.getType().getName() = "Array<UInt8>") or
|
||||
this instanceof StringLiteralExpr
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A class for all ways to use a constant password.
|
||||
*/
|
||||
class ConstantPasswordSink extends Expr {
|
||||
ConstantPasswordSink() {
|
||||
// `password` arg in `init` is a sink
|
||||
exists(ClassOrStructDecl c, ConstructorDecl f, CallExpr call |
|
||||
c.getName() = ["HKDF", "PBKDF1", "PBKDF2", "Scrypt"] and
|
||||
c.getAMember() = f and
|
||||
call.getStaticTarget() = f and
|
||||
call.getArgumentWithLabel("password").getExpr() = this
|
||||
)
|
||||
or
|
||||
// RNCryptor (labelled arguments)
|
||||
exists(ClassOrStructDecl c, MethodDecl f, CallExpr call |
|
||||
c.getName() = ["RNCryptor", "RNEncryptor", "RNDecryptor"] and
|
||||
c.getAMember() = f and
|
||||
call.getStaticTarget() = f and
|
||||
call.getArgumentWithLabel(["password", "withPassword", "forPassword"]).getExpr() = this
|
||||
)
|
||||
or
|
||||
// RNCryptor (unlabelled arguments)
|
||||
exists(MethodDecl f, CallExpr call |
|
||||
f.hasQualifiedName("RNCryptor", "keyForPassword(_:salt:settings:)") and
|
||||
call.getStaticTarget() = f and
|
||||
call.getArgument(0).getExpr() = this
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A taint configuration from the source of constants passwords to expressions that use
|
||||
* them to initialize password-based encryption keys.
|
||||
*/
|
||||
module ConstantPasswordConfig implements DataFlow::ConfigSig {
|
||||
predicate isSource(DataFlow::Node node) { node.asExpr() instanceof ConstantPasswordSource }
|
||||
|
||||
predicate isSink(DataFlow::Node node) { node.asExpr() instanceof ConstantPasswordSink }
|
||||
}
|
||||
|
||||
module ConstantPasswordFlow = TaintTracking::Global<ConstantPasswordConfig>;
|
||||
@@ -0,0 +1,7 @@
|
||||
/**
|
||||
* Provides classes and predicates for reasoning about use of constant salts
|
||||
* for password hashing.
|
||||
*/
|
||||
|
||||
import swift
|
||||
import codeql.swift.dataflow.DataFlow
|
||||
56
swift/ql/lib/codeql/swift/security/ConstantSaltQuery.qll
Normal file
56
swift/ql/lib/codeql/swift/security/ConstantSaltQuery.qll
Normal file
@@ -0,0 +1,56 @@
|
||||
/**
|
||||
* Provides a taint tracking configuration to find use of constant salts
|
||||
* for password hashing.
|
||||
*/
|
||||
|
||||
import swift
|
||||
import codeql.swift.dataflow.DataFlow
|
||||
import codeql.swift.dataflow.TaintTracking
|
||||
import codeql.swift.dataflow.FlowSteps
|
||||
import codeql.swift.security.ConstantSaltExtensions
|
||||
|
||||
/**
|
||||
* A constant salt is created through either a byte array or string literals.
|
||||
*/
|
||||
class ConstantSaltSource extends Expr {
|
||||
ConstantSaltSource() {
|
||||
this = any(ArrayExpr arr | arr.getType().getName() = "Array<UInt8>") or
|
||||
this instanceof StringLiteralExpr or
|
||||
this instanceof NumberLiteralExpr
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A class for all ways to use a constant salt.
|
||||
*/
|
||||
class ConstantSaltSink extends Expr {
|
||||
ConstantSaltSink() {
|
||||
// `salt` arg in `init` is a sink
|
||||
exists(ClassOrStructDecl c, ConstructorDecl f, CallExpr call |
|
||||
c.getName() = ["HKDF", "PBKDF1", "PBKDF2", "Scrypt"] and
|
||||
c.getAMember() = f and
|
||||
call.getStaticTarget() = f and
|
||||
call.getArgumentWithLabel("salt").getExpr() = this
|
||||
)
|
||||
or
|
||||
// RNCryptor
|
||||
exists(ClassOrStructDecl c, MethodDecl f, CallExpr call |
|
||||
c.getName() = ["RNCryptor", "RNEncryptor", "RNDecryptor"] and
|
||||
c.getAMember() = f and
|
||||
call.getStaticTarget() = f and
|
||||
call.getArgumentWithLabel(["salt", "encryptionSalt", "hmacSalt", "HMACSalt"]).getExpr() = this
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A taint configuration from the source of constants salts to expressions that use
|
||||
* them to initialize password-based encryption keys.
|
||||
*/
|
||||
module ConstantSaltConfig implements DataFlow::ConfigSig {
|
||||
predicate isSource(DataFlow::Node node) { node.asExpr() instanceof ConstantSaltSource }
|
||||
|
||||
predicate isSink(DataFlow::Node node) { node.asExpr() instanceof ConstantSaltSink }
|
||||
}
|
||||
|
||||
module ConstantSaltFlow = TaintTracking::Global<ConstantSaltConfig>;
|
||||
@@ -0,0 +1,7 @@
|
||||
/**
|
||||
* Provides classes and predicates for reasoning about encryption using the
|
||||
* ECB encrpytion mode.
|
||||
*/
|
||||
|
||||
import swift
|
||||
import codeql.swift.dataflow.DataFlow
|
||||
61
swift/ql/lib/codeql/swift/security/ECBEncryptionQuery.qll
Normal file
61
swift/ql/lib/codeql/swift/security/ECBEncryptionQuery.qll
Normal file
@@ -0,0 +1,61 @@
|
||||
/**
|
||||
* Provides a taint tracking configuration to find encryption using the
|
||||
* ECB encrpytion mode.
|
||||
*/
|
||||
|
||||
import swift
|
||||
import codeql.swift.dataflow.DataFlow
|
||||
import codeql.swift.dataflow.TaintTracking
|
||||
import codeql.swift.security.ECBEncryptionExtensions
|
||||
|
||||
/**
|
||||
* An `Expr` that is used to initialize the block mode of a cipher.
|
||||
*/
|
||||
abstract class BlockMode extends Expr { }
|
||||
|
||||
/**
|
||||
* An `Expr` that is used to form an `AES` cipher.
|
||||
*/
|
||||
class AES extends BlockMode {
|
||||
AES() {
|
||||
// `blockMode` arg in `AES.init` is a sink
|
||||
exists(CallExpr call |
|
||||
call.getStaticTarget()
|
||||
.(MethodDecl)
|
||||
.hasQualifiedName("AES", ["init(key:blockMode:)", "init(key:blockMode:padding:)"]) and
|
||||
call.getArgument(1).getExpr() = this
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* An `Expr` that is used to form a `Blowfish` cipher.
|
||||
*/
|
||||
class Blowfish extends BlockMode {
|
||||
Blowfish() {
|
||||
// `blockMode` arg in `Blowfish.init` is a sink
|
||||
exists(CallExpr call |
|
||||
call.getStaticTarget()
|
||||
.(MethodDecl)
|
||||
.hasQualifiedName("Blowfish", "init(key:blockMode:padding:)") and
|
||||
call.getArgument(1).getExpr() = this
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A taint configuration from the constructor of ECB mode to expressions that use
|
||||
* it to initialize a cipher.
|
||||
*/
|
||||
module EcbEncryptionConfig implements DataFlow::ConfigSig {
|
||||
predicate isSource(DataFlow::Node node) {
|
||||
exists(CallExpr call |
|
||||
call.getStaticTarget().(MethodDecl).hasQualifiedName("ECB", "init()") and
|
||||
node.asExpr() = call
|
||||
)
|
||||
}
|
||||
|
||||
predicate isSink(DataFlow::Node node) { node.asExpr() instanceof BlockMode }
|
||||
}
|
||||
|
||||
module EcbEncryptionFlow = DataFlow::Global<EcbEncryptionConfig>;
|
||||
@@ -0,0 +1,7 @@
|
||||
/**
|
||||
* Provides classes and predicates for reasoning about hard-coded encryption
|
||||
* key vulnerabilities.
|
||||
*/
|
||||
|
||||
import swift
|
||||
import codeql.swift.dataflow.DataFlow
|
||||
@@ -0,0 +1,64 @@
|
||||
/**
|
||||
* Provides a taint tracking configuration to find hard-coded encryption
|
||||
* key vulnerabilities.
|
||||
*/
|
||||
|
||||
import swift
|
||||
import codeql.swift.dataflow.DataFlow
|
||||
import codeql.swift.dataflow.TaintTracking
|
||||
import codeql.swift.security.HardcodedEncryptionKeyExtensions
|
||||
|
||||
/**
|
||||
* An `Expr` that is used to initialize a key.
|
||||
*/
|
||||
abstract class KeySource extends Expr { }
|
||||
|
||||
/**
|
||||
* A literal byte array is a key source.
|
||||
*/
|
||||
class ByteArrayLiteralSource extends KeySource {
|
||||
ByteArrayLiteralSource() { this = any(ArrayExpr arr | arr.getType().getName() = "Array<UInt8>") }
|
||||
}
|
||||
|
||||
/**
|
||||
* A string literal is a key source.
|
||||
*/
|
||||
class StringLiteralSource extends KeySource instanceof StringLiteralExpr { }
|
||||
|
||||
/**
|
||||
* A class for all ways to set a key.
|
||||
*/
|
||||
class EncryptionKeySink extends Expr {
|
||||
EncryptionKeySink() {
|
||||
// `key` arg in `init` is a sink
|
||||
exists(CallExpr call, string fName |
|
||||
call.getStaticTarget()
|
||||
.(MethodDecl)
|
||||
.hasQualifiedName([
|
||||
"AES", "HMAC", "ChaCha20", "CBCMAC", "CMAC", "Poly1305", "Blowfish", "Rabbit"
|
||||
], fName) and
|
||||
fName.matches("init(key:%") and
|
||||
call.getArgument(0).getExpr() = this
|
||||
)
|
||||
or
|
||||
// RNCryptor
|
||||
exists(ClassOrStructDecl c, MethodDecl f, CallExpr call |
|
||||
c.getFullName() = ["RNCryptor", "RNEncryptor", "RNDecryptor"] and
|
||||
c.getAMember() = f and
|
||||
call.getStaticTarget() = f and
|
||||
call.getArgumentWithLabel(["encryptionKey", "withEncryptionKey"]).getExpr() = this
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A taint configuration from the key source to expressions that use
|
||||
* it to initialize a cipher.
|
||||
*/
|
||||
module HardcodedKeyConfig implements DataFlow::ConfigSig {
|
||||
predicate isSource(DataFlow::Node node) { node.asExpr() instanceof KeySource }
|
||||
|
||||
predicate isSink(DataFlow::Node node) { node.asExpr() instanceof EncryptionKeySink }
|
||||
}
|
||||
|
||||
module HardcodedKeyFlow = TaintTracking::Global<HardcodedKeyConfig>;
|
||||
@@ -0,0 +1,7 @@
|
||||
/**
|
||||
* Provides classes and predicates for reasoning about insecure TLS
|
||||
* configurations.
|
||||
*/
|
||||
|
||||
import swift
|
||||
import codeql.swift.dataflow.DataFlow
|
||||
39
swift/ql/lib/codeql/swift/security/InsecureTLSQuery.qll
Normal file
39
swift/ql/lib/codeql/swift/security/InsecureTLSQuery.qll
Normal file
@@ -0,0 +1,39 @@
|
||||
/**
|
||||
* Provides a taint tracking configuration to find insecure TLS
|
||||
* configurations.
|
||||
*/
|
||||
|
||||
import swift
|
||||
import codeql.swift.dataflow.DataFlow
|
||||
import codeql.swift.dataflow.TaintTracking
|
||||
import codeql.swift.dataflow.FlowSources
|
||||
import codeql.swift.security.InsecureTLSExtensions
|
||||
|
||||
/**
|
||||
* A taint config to detect insecure configuration of `NSURLSessionConfiguration`
|
||||
*/
|
||||
module InsecureTlsConfig implements DataFlow::ConfigSig {
|
||||
/**
|
||||
* Holds for enum values that represent an insecure version of TLS
|
||||
*/
|
||||
predicate isSource(DataFlow::Node node) {
|
||||
node.asExpr().(MethodLookupExpr).getMember().(EnumElementDecl).getName() =
|
||||
["TLSv10", "TLSv11", "tlsProtocol10", "tlsProtocol11"]
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds for assignment of TLS-related properties of `NSURLSessionConfiguration`
|
||||
*/
|
||||
predicate isSink(DataFlow::Node node) {
|
||||
exists(AssignExpr assign |
|
||||
assign.getSource() = node.asExpr() and
|
||||
assign.getDest().(MemberRefExpr).getMember().(ConcreteVarDecl).getName() =
|
||||
[
|
||||
"tlsMinimumSupportedProtocolVersion", "tlsMinimumSupportedProtocol",
|
||||
"tlsMaximumSupportedProtocolVersion", "tlsMaximumSupportedProtocol"
|
||||
]
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
module InsecureTlsFlow = TaintTracking::Global<InsecureTlsConfig>;
|
||||
@@ -0,0 +1,7 @@
|
||||
/**
|
||||
* Provides classes and predicates for reasoning about insufficient hash
|
||||
* iteration vulnerabilities.
|
||||
*/
|
||||
|
||||
import swift
|
||||
import codeql.swift.dataflow.DataFlow
|
||||
@@ -0,0 +1,48 @@
|
||||
/**
|
||||
* Provides a taint tracking configuration to find insufficient hash
|
||||
* iteration vulnerabilities.
|
||||
*/
|
||||
|
||||
import swift
|
||||
import codeql.swift.dataflow.DataFlow
|
||||
import codeql.swift.dataflow.TaintTracking
|
||||
import codeql.swift.security.InsufficientHashIterationsQuery
|
||||
|
||||
/**
|
||||
* An `Expr` that is used to initialize a password-based encryption key.
|
||||
*/
|
||||
abstract class IterationsSource extends Expr { }
|
||||
|
||||
/**
|
||||
* A literal integer that is 120,000 or less is a source of taint for iterations.
|
||||
*/
|
||||
class IntLiteralSource extends IterationsSource instanceof IntegerLiteralExpr {
|
||||
IntLiteralSource() { this.getStringValue().toInt() < 120000 }
|
||||
}
|
||||
|
||||
/**
|
||||
* A class for all ways to set the iterations of hash function.
|
||||
*/
|
||||
class InsufficientHashIterationsSink extends Expr {
|
||||
InsufficientHashIterationsSink() {
|
||||
// `iterations` arg in `init` is a sink
|
||||
exists(ClassOrStructDecl c, ConstructorDecl f, CallExpr call |
|
||||
c.getName() = ["PBKDF1", "PBKDF2"] and
|
||||
c.getAMember() = f and
|
||||
call.getStaticTarget() = f and
|
||||
call.getArgumentWithLabel("iterations").getExpr() = this
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A dataflow configuration from the hash iterations source to expressions that use
|
||||
* it to initialize hash functions.
|
||||
*/
|
||||
module InsufficientHashIterationsConfig implements DataFlow::ConfigSig {
|
||||
predicate isSource(DataFlow::Node node) { node.asExpr() instanceof IterationsSource }
|
||||
|
||||
predicate isSink(DataFlow::Node node) { node.asExpr() instanceof InsufficientHashIterationsSink }
|
||||
}
|
||||
|
||||
module InsufficientHashIterationsFlow = TaintTracking::Global<InsufficientHashIterationsConfig>;
|
||||
@@ -0,0 +1,7 @@
|
||||
/**
|
||||
* Provides classes and predicates for reasoning about use of static
|
||||
* initialization vectors for encryption.
|
||||
*/
|
||||
|
||||
import swift
|
||||
import codeql.swift.dataflow.DataFlow
|
||||
@@ -0,0 +1,59 @@
|
||||
/**
|
||||
* Provides a taint tracking configuration to find use of static
|
||||
* initialization vectors for encryption.
|
||||
*/
|
||||
|
||||
import swift
|
||||
import codeql.swift.dataflow.DataFlow
|
||||
import codeql.swift.dataflow.TaintTracking
|
||||
import codeql.swift.security.StaticInitializationVectorExtensions
|
||||
|
||||
/**
|
||||
* A static IV is created through either a byte array or string literals.
|
||||
*/
|
||||
class StaticInitializationVectorSource extends Expr {
|
||||
StaticInitializationVectorSource() {
|
||||
this instanceof ArrayExpr or
|
||||
this instanceof StringLiteralExpr or
|
||||
this instanceof NumberLiteralExpr
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A class for all ways to set an IV.
|
||||
*/
|
||||
class EncryptionInitializationSink extends Expr {
|
||||
EncryptionInitializationSink() {
|
||||
// `iv` arg in `init` is a sink
|
||||
exists(InitializerCallExpr call |
|
||||
call.getStaticTarget()
|
||||
.hasQualifiedName([
|
||||
"AES", "ChaCha20", "Blowfish", "Rabbit", "CBC", "CFB", "GCM", "OCB", "OFB", "PCBC",
|
||||
"CCM", "CTR"
|
||||
], _) and
|
||||
call.getArgumentWithLabel("iv").getExpr() = this
|
||||
)
|
||||
or
|
||||
// RNCryptor
|
||||
exists(ClassOrStructDecl c, MethodDecl f, CallExpr call |
|
||||
c.getFullName() = ["RNCryptor", "RNEncryptor", "RNDecryptor"] and
|
||||
c.getAMember() = f and
|
||||
call.getStaticTarget() = f and
|
||||
call.getArgumentWithLabel(["iv", "IV"]).getExpr() = this
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A dataflow configuration from the source of a static IV to expressions that use
|
||||
* it to initialize a cipher.
|
||||
*/
|
||||
module StaticInitializationVectorConfig implements DataFlow::ConfigSig {
|
||||
predicate isSource(DataFlow::Node node) {
|
||||
node.asExpr() instanceof StaticInitializationVectorSource
|
||||
}
|
||||
|
||||
predicate isSink(DataFlow::Node node) { node.asExpr() instanceof EncryptionInitializationSink }
|
||||
}
|
||||
|
||||
module StaticInitializationVectorFlow = TaintTracking::Global<StaticInitializationVectorConfig>;
|
||||
@@ -0,0 +1,8 @@
|
||||
/**
|
||||
* Provides classes and predicates for reasoning about use of broken or weak
|
||||
* cryptographic hashing algorithms on sensitive data.
|
||||
*/
|
||||
|
||||
import swift
|
||||
import codeql.swift.security.SensitiveExprs
|
||||
import codeql.swift.dataflow.DataFlow
|
||||
44
swift/ql/lib/codeql/swift/security/WeakSensitiveDataHashingQuery.qll
Executable file
44
swift/ql/lib/codeql/swift/security/WeakSensitiveDataHashingQuery.qll
Executable file
@@ -0,0 +1,44 @@
|
||||
/**
|
||||
* Provides a taint tracking configuration to find use of broken or weak
|
||||
* cryptographic hashing algorithms on sensitive data.
|
||||
*/
|
||||
|
||||
import swift
|
||||
import codeql.swift.security.SensitiveExprs
|
||||
import codeql.swift.dataflow.DataFlow
|
||||
import codeql.swift.dataflow.TaintTracking
|
||||
import codeql.swift.security.WeakSensitiveDataHashingExtensions
|
||||
|
||||
module WeakHashingConfig implements DataFlow::ConfigSig {
|
||||
predicate isSource(DataFlow::Node node) { node instanceof WeakHashingConfigImpl::Source }
|
||||
|
||||
predicate isSink(DataFlow::Node node) { node instanceof WeakHashingConfigImpl::Sink }
|
||||
}
|
||||
|
||||
module WeakHashingFlow = TaintTracking::Global<WeakHashingConfig>;
|
||||
|
||||
module WeakHashingConfigImpl {
|
||||
class Source extends DataFlow::Node {
|
||||
Source() { this.asExpr() instanceof SensitiveExpr }
|
||||
}
|
||||
|
||||
abstract class Sink extends DataFlow::Node {
|
||||
abstract string getAlgorithm();
|
||||
}
|
||||
|
||||
class CryptoHash extends Sink {
|
||||
string algorithm;
|
||||
|
||||
CryptoHash() {
|
||||
exists(ApplyExpr call, FuncDecl func |
|
||||
call.getAnArgument().getExpr() = this.asExpr() and
|
||||
call.getStaticTarget() = func and
|
||||
func.getName().matches(["hash(%", "update(%"]) and
|
||||
algorithm = func.getEnclosingDecl().(ClassOrStructDecl).getName() and
|
||||
algorithm = ["MD5", "SHA1"]
|
||||
)
|
||||
}
|
||||
|
||||
override string getAlgorithm() { result = algorithm }
|
||||
}
|
||||
}
|
||||
@@ -12,61 +12,9 @@
|
||||
*/
|
||||
|
||||
import swift
|
||||
import codeql.swift.dataflow.DataFlow
|
||||
import codeql.swift.dataflow.TaintTracking
|
||||
import codeql.swift.security.StaticInitializationVectorQuery
|
||||
import StaticInitializationVectorFlow::PathGraph
|
||||
|
||||
/**
|
||||
* A static IV is created through either a byte array or string literals.
|
||||
*/
|
||||
class StaticInitializationVectorSource extends Expr {
|
||||
StaticInitializationVectorSource() {
|
||||
this instanceof ArrayExpr or
|
||||
this instanceof StringLiteralExpr or
|
||||
this instanceof NumberLiteralExpr
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A class for all ways to set an IV.
|
||||
*/
|
||||
class EncryptionInitializationSink extends Expr {
|
||||
EncryptionInitializationSink() {
|
||||
// `iv` arg in `init` is a sink
|
||||
exists(InitializerCallExpr call |
|
||||
call.getStaticTarget()
|
||||
.hasQualifiedName([
|
||||
"AES", "ChaCha20", "Blowfish", "Rabbit", "CBC", "CFB", "GCM", "OCB", "OFB", "PCBC",
|
||||
"CCM", "CTR"
|
||||
], _) and
|
||||
call.getArgumentWithLabel("iv").getExpr() = this
|
||||
)
|
||||
or
|
||||
// RNCryptor
|
||||
exists(ClassOrStructDecl c, MethodDecl f, CallExpr call |
|
||||
c.getFullName() = ["RNCryptor", "RNEncryptor", "RNDecryptor"] and
|
||||
c.getAMember() = f and
|
||||
call.getStaticTarget() = f and
|
||||
call.getArgumentWithLabel(["iv", "IV"]).getExpr() = this
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A dataflow configuration from the source of a static IV to expressions that use
|
||||
* it to initialize a cipher.
|
||||
*/
|
||||
module StaticInitializationVectorConfig implements DataFlow::ConfigSig {
|
||||
predicate isSource(DataFlow::Node node) {
|
||||
node.asExpr() instanceof StaticInitializationVectorSource
|
||||
}
|
||||
|
||||
predicate isSink(DataFlow::Node node) { node.asExpr() instanceof EncryptionInitializationSink }
|
||||
}
|
||||
|
||||
module StaticInitializationVectorFlow = TaintTracking::Global<StaticInitializationVectorConfig>;
|
||||
|
||||
// The query itself
|
||||
from
|
||||
StaticInitializationVectorFlow::PathNode sourceNode,
|
||||
StaticInitializationVectorFlow::PathNode sinkNode
|
||||
|
||||
@@ -11,64 +11,9 @@
|
||||
*/
|
||||
|
||||
import swift
|
||||
import codeql.swift.dataflow.DataFlow
|
||||
import codeql.swift.dataflow.TaintTracking
|
||||
import codeql.swift.dataflow.FlowSteps
|
||||
import codeql.swift.security.ConstantPasswordQuery
|
||||
import ConstantPasswordFlow::PathGraph
|
||||
|
||||
/**
|
||||
* A constant password is created through either a byte array or string literals.
|
||||
*/
|
||||
class ConstantPasswordSource extends Expr {
|
||||
ConstantPasswordSource() {
|
||||
this = any(ArrayExpr arr | arr.getType().getName() = "Array<UInt8>") or
|
||||
this instanceof StringLiteralExpr
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A class for all ways to use a constant password.
|
||||
*/
|
||||
class ConstantPasswordSink extends Expr {
|
||||
ConstantPasswordSink() {
|
||||
// `password` arg in `init` is a sink
|
||||
exists(ClassOrStructDecl c, ConstructorDecl f, CallExpr call |
|
||||
c.getName() = ["HKDF", "PBKDF1", "PBKDF2", "Scrypt"] and
|
||||
c.getAMember() = f and
|
||||
call.getStaticTarget() = f and
|
||||
call.getArgumentWithLabel("password").getExpr() = this
|
||||
)
|
||||
or
|
||||
// RNCryptor (labelled arguments)
|
||||
exists(ClassOrStructDecl c, MethodDecl f, CallExpr call |
|
||||
c.getName() = ["RNCryptor", "RNEncryptor", "RNDecryptor"] and
|
||||
c.getAMember() = f and
|
||||
call.getStaticTarget() = f and
|
||||
call.getArgumentWithLabel(["password", "withPassword", "forPassword"]).getExpr() = this
|
||||
)
|
||||
or
|
||||
// RNCryptor (unlabelled arguments)
|
||||
exists(MethodDecl f, CallExpr call |
|
||||
f.hasQualifiedName("RNCryptor", "keyForPassword(_:salt:settings:)") and
|
||||
call.getStaticTarget() = f and
|
||||
call.getArgument(0).getExpr() = this
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A taint configuration from the source of constants passwords to expressions that use
|
||||
* them to initialize password-based encryption keys.
|
||||
*/
|
||||
module ConstantPasswordConfig implements DataFlow::ConfigSig {
|
||||
predicate isSource(DataFlow::Node node) { node.asExpr() instanceof ConstantPasswordSource }
|
||||
|
||||
predicate isSink(DataFlow::Node node) { node.asExpr() instanceof ConstantPasswordSink }
|
||||
}
|
||||
|
||||
module ConstantPasswordFlow = TaintTracking::Global<ConstantPasswordConfig>;
|
||||
|
||||
// The query itself
|
||||
from ConstantPasswordFlow::PathNode sourceNode, ConstantPasswordFlow::PathNode sinkNode
|
||||
where ConstantPasswordFlow::flowPath(sourceNode, sinkNode)
|
||||
select sinkNode.getNode(), sourceNode, sinkNode,
|
||||
|
||||
@@ -11,66 +11,9 @@
|
||||
*/
|
||||
|
||||
import swift
|
||||
import codeql.swift.dataflow.DataFlow
|
||||
import codeql.swift.dataflow.TaintTracking
|
||||
import codeql.swift.security.HardcodedEncryptionKeyQuery
|
||||
import HardcodedKeyFlow::PathGraph
|
||||
|
||||
/**
|
||||
* An `Expr` that is used to initialize a key.
|
||||
*/
|
||||
abstract class KeySource extends Expr { }
|
||||
|
||||
/**
|
||||
* A literal byte array is a key source.
|
||||
*/
|
||||
class ByteArrayLiteralSource extends KeySource {
|
||||
ByteArrayLiteralSource() { this = any(ArrayExpr arr | arr.getType().getName() = "Array<UInt8>") }
|
||||
}
|
||||
|
||||
/**
|
||||
* A string literal is a key source.
|
||||
*/
|
||||
class StringLiteralSource extends KeySource instanceof StringLiteralExpr { }
|
||||
|
||||
/**
|
||||
* A class for all ways to set a key.
|
||||
*/
|
||||
class EncryptionKeySink extends Expr {
|
||||
EncryptionKeySink() {
|
||||
// `key` arg in `init` is a sink
|
||||
exists(CallExpr call, string fName |
|
||||
call.getStaticTarget()
|
||||
.(MethodDecl)
|
||||
.hasQualifiedName([
|
||||
"AES", "HMAC", "ChaCha20", "CBCMAC", "CMAC", "Poly1305", "Blowfish", "Rabbit"
|
||||
], fName) and
|
||||
fName.matches("init(key:%") and
|
||||
call.getArgument(0).getExpr() = this
|
||||
)
|
||||
or
|
||||
// RNCryptor
|
||||
exists(ClassOrStructDecl c, MethodDecl f, CallExpr call |
|
||||
c.getFullName() = ["RNCryptor", "RNEncryptor", "RNDecryptor"] and
|
||||
c.getAMember() = f and
|
||||
call.getStaticTarget() = f and
|
||||
call.getArgumentWithLabel(["encryptionKey", "withEncryptionKey"]).getExpr() = this
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A taint configuration from the key source to expressions that use
|
||||
* it to initialize a cipher.
|
||||
*/
|
||||
module HardcodedKeyConfig implements DataFlow::ConfigSig {
|
||||
predicate isSource(DataFlow::Node node) { node.asExpr() instanceof KeySource }
|
||||
|
||||
predicate isSink(DataFlow::Node node) { node.asExpr() instanceof EncryptionKeySink }
|
||||
}
|
||||
|
||||
module HardcodedKeyFlow = TaintTracking::Global<HardcodedKeyConfig>;
|
||||
|
||||
// The query itself
|
||||
from HardcodedKeyFlow::PathNode sourceNode, HardcodedKeyFlow::PathNode sinkNode
|
||||
where HardcodedKeyFlow::flowPath(sourceNode, sinkNode)
|
||||
select sinkNode.getNode(), sourceNode, sinkNode,
|
||||
|
||||
@@ -11,63 +11,9 @@
|
||||
*/
|
||||
|
||||
import swift
|
||||
import codeql.swift.dataflow.DataFlow
|
||||
import codeql.swift.dataflow.TaintTracking
|
||||
import codeql.swift.security.ECBEncryptionQuery
|
||||
import EcbEncryptionFlow::PathGraph
|
||||
|
||||
/**
|
||||
* An `Expr` that is used to initialize the block mode of a cipher.
|
||||
*/
|
||||
abstract class BlockMode extends Expr { }
|
||||
|
||||
/**
|
||||
* An `Expr` that is used to form an `AES` cipher.
|
||||
*/
|
||||
class AES extends BlockMode {
|
||||
AES() {
|
||||
// `blockMode` arg in `AES.init` is a sink
|
||||
exists(CallExpr call |
|
||||
call.getStaticTarget()
|
||||
.(MethodDecl)
|
||||
.hasQualifiedName("AES", ["init(key:blockMode:)", "init(key:blockMode:padding:)"]) and
|
||||
call.getArgument(1).getExpr() = this
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* An `Expr` that is used to form a `Blowfish` cipher.
|
||||
*/
|
||||
class Blowfish extends BlockMode {
|
||||
Blowfish() {
|
||||
// `blockMode` arg in `Blowfish.init` is a sink
|
||||
exists(CallExpr call |
|
||||
call.getStaticTarget()
|
||||
.(MethodDecl)
|
||||
.hasQualifiedName("Blowfish", "init(key:blockMode:padding:)") and
|
||||
call.getArgument(1).getExpr() = this
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A taint configuration from the constructor of ECB mode to expressions that use
|
||||
* it to initialize a cipher.
|
||||
*/
|
||||
module EcbEncryptionConfig implements DataFlow::ConfigSig {
|
||||
predicate isSource(DataFlow::Node node) {
|
||||
exists(CallExpr call |
|
||||
call.getStaticTarget().(MethodDecl).hasQualifiedName("ECB", "init()") and
|
||||
node.asExpr() = call
|
||||
)
|
||||
}
|
||||
|
||||
predicate isSink(DataFlow::Node node) { node.asExpr() instanceof BlockMode }
|
||||
}
|
||||
|
||||
module EcbEncryptionFlow = DataFlow::Global<EcbEncryptionConfig>;
|
||||
|
||||
// The query itself
|
||||
from EcbEncryptionFlow::PathNode sourceNode, EcbEncryptionFlow::PathNode sinkNode
|
||||
where EcbEncryptionFlow::flowPath(sourceNode, sinkNode)
|
||||
select sinkNode.getNode(), sourceNode, sinkNode,
|
||||
|
||||
@@ -12,45 +12,9 @@
|
||||
*/
|
||||
|
||||
import swift
|
||||
import codeql.swift.security.SensitiveExprs
|
||||
import codeql.swift.dataflow.DataFlow
|
||||
import codeql.swift.dataflow.TaintTracking
|
||||
import codeql.swift.security.WeakSensitiveDataHashingQuery
|
||||
import WeakHashingFlow::PathGraph
|
||||
|
||||
module WeakHashingConfig implements DataFlow::ConfigSig {
|
||||
predicate isSource(DataFlow::Node node) { node instanceof WeakHashingConfigImpl::Source }
|
||||
|
||||
predicate isSink(DataFlow::Node node) { node instanceof WeakHashingConfigImpl::Sink }
|
||||
}
|
||||
|
||||
module WeakHashingFlow = TaintTracking::Global<WeakHashingConfig>;
|
||||
|
||||
module WeakHashingConfigImpl {
|
||||
class Source extends DataFlow::Node {
|
||||
Source() { this.asExpr() instanceof SensitiveExpr }
|
||||
}
|
||||
|
||||
abstract class Sink extends DataFlow::Node {
|
||||
abstract string getAlgorithm();
|
||||
}
|
||||
|
||||
class CryptoHash extends Sink {
|
||||
string algorithm;
|
||||
|
||||
CryptoHash() {
|
||||
exists(ApplyExpr call, FuncDecl func |
|
||||
call.getAnArgument().getExpr() = this.asExpr() and
|
||||
call.getStaticTarget() = func and
|
||||
func.getName().matches(["hash(%", "update(%"]) and
|
||||
algorithm = func.getEnclosingDecl().(ClassOrStructDecl).getName() and
|
||||
algorithm = ["MD5", "SHA1"]
|
||||
)
|
||||
}
|
||||
|
||||
override string getAlgorithm() { result = algorithm }
|
||||
}
|
||||
}
|
||||
|
||||
from
|
||||
WeakHashingFlow::PathNode source, WeakHashingFlow::PathNode sink, string algorithm,
|
||||
SensitiveExpr expr
|
||||
|
||||
@@ -11,40 +11,9 @@
|
||||
*/
|
||||
|
||||
import swift
|
||||
import codeql.swift.dataflow.DataFlow
|
||||
import codeql.swift.dataflow.TaintTracking
|
||||
import codeql.swift.dataflow.FlowSources
|
||||
import codeql.swift.security.InsecureTLSQuery
|
||||
import InsecureTlsFlow::PathGraph
|
||||
|
||||
/**
|
||||
* A taint config to detect insecure configuration of `NSURLSessionConfiguration`
|
||||
*/
|
||||
module InsecureTlsConfig implements DataFlow::ConfigSig {
|
||||
/**
|
||||
* Holds for enum values that represent an insecure version of TLS
|
||||
*/
|
||||
predicate isSource(DataFlow::Node node) {
|
||||
node.asExpr().(MethodLookupExpr).getMember().(EnumElementDecl).getName() =
|
||||
["TLSv10", "TLSv11", "tlsProtocol10", "tlsProtocol11"]
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds for assignment of TLS-related properties of `NSURLSessionConfiguration`
|
||||
*/
|
||||
predicate isSink(DataFlow::Node node) {
|
||||
exists(AssignExpr assign |
|
||||
assign.getSource() = node.asExpr() and
|
||||
assign.getDest().(MemberRefExpr).getMember().(ConcreteVarDecl).getName() =
|
||||
[
|
||||
"tlsMinimumSupportedProtocolVersion", "tlsMinimumSupportedProtocol",
|
||||
"tlsMaximumSupportedProtocolVersion", "tlsMaximumSupportedProtocol"
|
||||
]
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
module InsecureTlsFlow = TaintTracking::Global<InsecureTlsConfig>;
|
||||
|
||||
from InsecureTlsFlow::PathNode sourceNode, InsecureTlsFlow::PathNode sinkNode
|
||||
where InsecureTlsFlow::flowPath(sourceNode, sinkNode)
|
||||
select sinkNode.getNode(), sourceNode, sinkNode, "This TLS configuration is insecure."
|
||||
|
||||
@@ -11,58 +11,9 @@
|
||||
*/
|
||||
|
||||
import swift
|
||||
import codeql.swift.dataflow.DataFlow
|
||||
import codeql.swift.dataflow.TaintTracking
|
||||
import codeql.swift.dataflow.FlowSteps
|
||||
import codeql.swift.security.ConstantSaltQuery
|
||||
import ConstantSaltFlow::PathGraph
|
||||
|
||||
/**
|
||||
* A constant salt is created through either a byte array or string literals.
|
||||
*/
|
||||
class ConstantSaltSource extends Expr {
|
||||
ConstantSaltSource() {
|
||||
this = any(ArrayExpr arr | arr.getType().getName() = "Array<UInt8>") or
|
||||
this instanceof StringLiteralExpr or
|
||||
this instanceof NumberLiteralExpr
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A class for all ways to use a constant salt.
|
||||
*/
|
||||
class ConstantSaltSink extends Expr {
|
||||
ConstantSaltSink() {
|
||||
// `salt` arg in `init` is a sink
|
||||
exists(ClassOrStructDecl c, ConstructorDecl f, CallExpr call |
|
||||
c.getName() = ["HKDF", "PBKDF1", "PBKDF2", "Scrypt"] and
|
||||
c.getAMember() = f and
|
||||
call.getStaticTarget() = f and
|
||||
call.getArgumentWithLabel("salt").getExpr() = this
|
||||
)
|
||||
or
|
||||
// RNCryptor
|
||||
exists(ClassOrStructDecl c, MethodDecl f, CallExpr call |
|
||||
c.getName() = ["RNCryptor", "RNEncryptor", "RNDecryptor"] and
|
||||
c.getAMember() = f and
|
||||
call.getStaticTarget() = f and
|
||||
call.getArgumentWithLabel(["salt", "encryptionSalt", "hmacSalt", "HMACSalt"]).getExpr() = this
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A taint configuration from the source of constants salts to expressions that use
|
||||
* them to initialize password-based encryption keys.
|
||||
*/
|
||||
module ConstantSaltConfig implements DataFlow::ConfigSig {
|
||||
predicate isSource(DataFlow::Node node) { node.asExpr() instanceof ConstantSaltSource }
|
||||
|
||||
predicate isSink(DataFlow::Node node) { node.asExpr() instanceof ConstantSaltSink }
|
||||
}
|
||||
|
||||
module ConstantSaltFlow = TaintTracking::Global<ConstantSaltConfig>;
|
||||
|
||||
// The query itself
|
||||
from ConstantSaltFlow::PathNode sourceNode, ConstantSaltFlow::PathNode sinkNode
|
||||
where ConstantSaltFlow::flowPath(sourceNode, sinkNode)
|
||||
select sinkNode.getNode(), sourceNode, sinkNode,
|
||||
|
||||
@@ -11,50 +11,9 @@
|
||||
*/
|
||||
|
||||
import swift
|
||||
import codeql.swift.dataflow.DataFlow
|
||||
import codeql.swift.dataflow.TaintTracking
|
||||
import codeql.swift.security.InsufficientHashIterationsQuery
|
||||
import InsufficientHashIterationsFlow::PathGraph
|
||||
|
||||
/**
|
||||
* An `Expr` that is used to initialize a password-based encryption key.
|
||||
*/
|
||||
abstract class IterationsSource extends Expr { }
|
||||
|
||||
/**
|
||||
* A literal integer that is 120,000 or less is a source of taint for iterations.
|
||||
*/
|
||||
class IntLiteralSource extends IterationsSource instanceof IntegerLiteralExpr {
|
||||
IntLiteralSource() { this.getStringValue().toInt() < 120000 }
|
||||
}
|
||||
|
||||
/**
|
||||
* A class for all ways to set the iterations of hash function.
|
||||
*/
|
||||
class InsufficientHashIterationsSink extends Expr {
|
||||
InsufficientHashIterationsSink() {
|
||||
// `iterations` arg in `init` is a sink
|
||||
exists(ClassOrStructDecl c, ConstructorDecl f, CallExpr call |
|
||||
c.getName() = ["PBKDF1", "PBKDF2"] and
|
||||
c.getAMember() = f and
|
||||
call.getStaticTarget() = f and
|
||||
call.getArgumentWithLabel("iterations").getExpr() = this
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A dataflow configuration from the hash iterations source to expressions that use
|
||||
* it to initialize hash functions.
|
||||
*/
|
||||
module InsufficientHashIterationsConfig implements DataFlow::ConfigSig {
|
||||
predicate isSource(DataFlow::Node node) { node.asExpr() instanceof IterationsSource }
|
||||
|
||||
predicate isSink(DataFlow::Node node) { node.asExpr() instanceof InsufficientHashIterationsSink }
|
||||
}
|
||||
|
||||
module InsufficientHashIterationsFlow = TaintTracking::Global<InsufficientHashIterationsConfig>;
|
||||
|
||||
// The query itself
|
||||
from
|
||||
InsufficientHashIterationsFlow::PathNode sourceNode,
|
||||
InsufficientHashIterationsFlow::PathNode sinkNode
|
||||
|
||||
Reference in New Issue
Block a user