mirror of
https://github.com/github/codeql.git
synced 2025-12-17 01:03:14 +01:00
Merge pull request #10335 from github/redsun82/swift-weak-hashing-phase-1
Swift: first version of query targeting weak hashing
This commit is contained in:
@@ -1,17 +1,30 @@
|
|||||||
private import codeql.swift.generated.AstNode
|
private import codeql.swift.generated.AstNode
|
||||||
private import codeql.swift.elements.decl.AbstractFunctionDecl
|
private import codeql.swift.elements.decl.AbstractFunctionDecl
|
||||||
|
private import codeql.swift.elements.decl.Decl
|
||||||
private import codeql.swift.generated.ParentChild
|
private import codeql.swift.generated.ParentChild
|
||||||
|
|
||||||
private Element getEnclosingFunctionStep(Element e) {
|
private module Cached {
|
||||||
not e instanceof AbstractFunctionDecl and
|
private Element getEnclosingDeclStep(Element e) {
|
||||||
result = getImmediateParent(e)
|
not e instanceof Decl and
|
||||||
}
|
result = getImmediateParent(e)
|
||||||
|
}
|
||||||
|
|
||||||
cached
|
cached
|
||||||
private AbstractFunctionDecl getEnclosingFunctionCached(AstNode ast) {
|
Decl getEnclosingDecl(AstNode ast) { result = getEnclosingDeclStep*(getImmediateParent(ast)) }
|
||||||
result = getEnclosingFunctionStep*(getImmediateParent(ast))
|
|
||||||
|
private Element getEnclosingFunctionStep(Element e) {
|
||||||
|
not e instanceof AbstractFunctionDecl and
|
||||||
|
result = getEnclosingDecl(e)
|
||||||
|
}
|
||||||
|
|
||||||
|
cached
|
||||||
|
AbstractFunctionDecl getEnclosingFunction(AstNode ast) {
|
||||||
|
result = getEnclosingFunctionStep*(getEnclosingDecl(ast))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class AstNode extends AstNodeBase {
|
class AstNode extends AstNodeBase {
|
||||||
final AbstractFunctionDecl getEnclosingFunction() { result = getEnclosingFunctionCached(this) }
|
final AbstractFunctionDecl getEnclosingFunction() { result = Cached::getEnclosingFunction(this) }
|
||||||
|
|
||||||
|
final Decl getEnclosingDecl() { result = Cached::getEnclosingDecl(this) }
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -121,20 +121,24 @@ class SensitiveExpr extends Expr {
|
|||||||
SensitiveDataType sensitiveType;
|
SensitiveDataType sensitiveType;
|
||||||
|
|
||||||
SensitiveExpr() {
|
SensitiveExpr() {
|
||||||
// variable reference
|
(
|
||||||
this.(DeclRefExpr).getDecl().(SensitiveVarDecl).hasInfo(label, sensitiveType)
|
// variable reference
|
||||||
or
|
this.(DeclRefExpr).getDecl().(SensitiveVarDecl).hasInfo(label, sensitiveType)
|
||||||
// member variable reference
|
or
|
||||||
this.(MemberRefExpr).getMember().(SensitiveVarDecl).hasInfo(label, sensitiveType)
|
// member variable reference
|
||||||
or
|
this.(MemberRefExpr).getMember().(SensitiveVarDecl).hasInfo(label, sensitiveType)
|
||||||
// function call
|
or
|
||||||
this.(ApplyExpr).getStaticTarget().(SensitiveFunctionDecl).hasInfo(label, sensitiveType)
|
// function call
|
||||||
or
|
this.(ApplyExpr).getStaticTarget().(SensitiveFunctionDecl).hasInfo(label, sensitiveType)
|
||||||
// sensitive argument
|
or
|
||||||
exists(SensitiveArgument a |
|
// sensitive argument
|
||||||
a.hasInfo(label, sensitiveType) and
|
exists(SensitiveArgument a |
|
||||||
a.getExpr() = this
|
a.hasInfo(label, sensitiveType) and
|
||||||
)
|
a.getExpr() = this
|
||||||
|
)
|
||||||
|
) and
|
||||||
|
// do not mark as sensitive it if it is probably safe
|
||||||
|
not label.toLowerCase().regexpMatch(regexpProbablySafe())
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -146,13 +150,6 @@ class SensitiveExpr extends Expr {
|
|||||||
* Gets the type of sensitive expression this is.
|
* Gets the type of sensitive expression this is.
|
||||||
*/
|
*/
|
||||||
SensitiveDataType getSensitiveType() { result = sensitiveType }
|
SensitiveDataType getSensitiveType() { result = sensitiveType }
|
||||||
|
|
||||||
/**
|
|
||||||
* Holds if this sensitive expression might be safe because it contains
|
|
||||||
* hashed or encrypted data, or is only a reference to data that is stored
|
|
||||||
* elsewhere.
|
|
||||||
*/
|
|
||||||
predicate isProbablySafe() { label.toLowerCase().regexpMatch(regexpProbablySafe()) }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -70,12 +70,7 @@ class RealmStore extends Stored {
|
|||||||
class CleartextStorageConfig extends TaintTracking::Configuration {
|
class CleartextStorageConfig extends TaintTracking::Configuration {
|
||||||
CleartextStorageConfig() { this = "CleartextStorageConfig" }
|
CleartextStorageConfig() { this = "CleartextStorageConfig" }
|
||||||
|
|
||||||
override predicate isSource(DataFlow::Node node) {
|
override predicate isSource(DataFlow::Node node) { node.asExpr() instanceof SensitiveExpr }
|
||||||
exists(SensitiveExpr e |
|
|
||||||
node.asExpr() = e and
|
|
||||||
not e.isProbablySafe()
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
override predicate isSink(DataFlow::Node node) { node.asExpr() instanceof Stored }
|
override predicate isSink(DataFlow::Node node) { node.asExpr() instanceof Stored }
|
||||||
|
|
||||||
|
|||||||
@@ -63,12 +63,7 @@ class URL extends Transmitted {
|
|||||||
class CleartextTransmissionConfig extends TaintTracking::Configuration {
|
class CleartextTransmissionConfig extends TaintTracking::Configuration {
|
||||||
CleartextTransmissionConfig() { this = "CleartextTransmissionConfig" }
|
CleartextTransmissionConfig() { this = "CleartextTransmissionConfig" }
|
||||||
|
|
||||||
override predicate isSource(DataFlow::Node node) {
|
override predicate isSource(DataFlow::Node node) { node.asExpr() instanceof SensitiveExpr }
|
||||||
exists(SensitiveExpr e |
|
|
||||||
node.asExpr() = e and
|
|
||||||
not e.isProbablySafe()
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
override predicate isSink(DataFlow::Node node) { node.asExpr() instanceof Transmitted }
|
override predicate isSink(DataFlow::Node node) { node.asExpr() instanceof Transmitted }
|
||||||
|
|
||||||
|
|||||||
84
swift/ql/src/queries/Security/CWE-328/WeakSensitiveDataHashing.qhelp
Executable file
84
swift/ql/src/queries/Security/CWE-328/WeakSensitiveDataHashing.qhelp
Executable file
@@ -0,0 +1,84 @@
|
|||||||
|
<!DOCTYPE qhelp PUBLIC
|
||||||
|
"-//Semmle//qhelp//EN"
|
||||||
|
"qhelp.dtd">
|
||||||
|
<qhelp>
|
||||||
|
<overview>
|
||||||
|
<p>
|
||||||
|
Using a broken or weak cryptographic hash function can leave data
|
||||||
|
vulnerable, and should not be used in security related code.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
A strong cryptographic hash function should be resistant to:
|
||||||
|
</p>
|
||||||
|
<ul>
|
||||||
|
<li>
|
||||||
|
<b>Pre-image attacks</b>. If you know a hash value <code>h(x)</code>,
|
||||||
|
you should not be able to easily find the input <code>x</code>.
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<b>Collision attacks</b>. If you know a hash value <code>h(x)</code>,
|
||||||
|
you should not be able to easily find a different input
|
||||||
|
<code>y</code>
|
||||||
|
with the same hash value <code>h(x) = h(y)</code>.
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
As an example, both MD5 and SHA-1 are known to be vulnerable to collision attacks.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
Since it's OK to use a weak cryptographic hash function in a non-security
|
||||||
|
context, this query only alerts when these are used to hash sensitive
|
||||||
|
data (such as passwords, certificates, usernames).
|
||||||
|
</p>
|
||||||
|
|
||||||
|
</overview>
|
||||||
|
<recommendation>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
Ensure that you use a strong, modern cryptographic hash function, such as:
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<ul>
|
||||||
|
<li>
|
||||||
|
Argon2, scrypt, bcrypt, or PBKDF2 for passwords and other data with limited input space where
|
||||||
|
a dictionary-like attack is feasible.
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
SHA-2, or SHA-3 in other cases.
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
</recommendation>
|
||||||
|
<example>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
The following examples show a function for checking whether the hash
|
||||||
|
of a certificate matches a known value -- to prevent tampering.
|
||||||
|
|
||||||
|
In the first case the MD5 hashing algorithm is used that is known to be vulnerable to collision attacks.
|
||||||
|
</p>
|
||||||
|
<sample src="WeakSensitiveDataHashingBad.swift"/>
|
||||||
|
<p>
|
||||||
|
|
||||||
|
Here is the same function using SHA-512, which is a strong cryptographic hashing function.
|
||||||
|
</p>
|
||||||
|
<sample src="WeakSensitiveDataHashingGood.swift"/>
|
||||||
|
|
||||||
|
</example>
|
||||||
|
<references>
|
||||||
|
<li>
|
||||||
|
OWASP:
|
||||||
|
<a href="https://cheatsheetseries.owasp.org/cheatsheets/Password_Storage_Cheat_Sheet.html">Password Storage
|
||||||
|
Cheat Sheet
|
||||||
|
</a>
|
||||||
|
and
|
||||||
|
<a href="https://cheatsheetseries.owasp.org/cheatsheets/Transport_Layer_Protection_Cheat_Sheet.html#use-strong-cryptographic-hashing-algorithms">
|
||||||
|
Transport Layer Protection Cheat Sheet
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
</references>
|
||||||
|
|
||||||
|
</qhelp>
|
||||||
63
swift/ql/src/queries/Security/CWE-328/WeakSensitiveDataHashing.ql
Executable file
63
swift/ql/src/queries/Security/CWE-328/WeakSensitiveDataHashing.ql
Executable file
@@ -0,0 +1,63 @@
|
|||||||
|
/**
|
||||||
|
* @name Use of a broken or weak cryptographic hashing algorithm on sensitive data
|
||||||
|
* @description Using broken or weak cryptographic hashing algorithms can compromise security.
|
||||||
|
* @kind path-problem
|
||||||
|
* @problem.severity warning
|
||||||
|
* @security-severity 7.5
|
||||||
|
* @precision high
|
||||||
|
* @id swift/weak-sensitive-data-hashing
|
||||||
|
* @tags security
|
||||||
|
* external/cwe/cwe-327
|
||||||
|
* external/cwe/cwe-328
|
||||||
|
*/
|
||||||
|
|
||||||
|
import swift
|
||||||
|
import codeql.swift.security.SensitiveExprs
|
||||||
|
import codeql.swift.dataflow.DataFlow
|
||||||
|
import codeql.swift.dataflow.TaintTracking
|
||||||
|
import DataFlow::PathGraph
|
||||||
|
|
||||||
|
class WeakHashingConfig extends TaintTracking::Configuration {
|
||||||
|
WeakHashingConfig() { this = "WeakHashingConfig" }
|
||||||
|
|
||||||
|
override predicate isSource(DataFlow::Node node) { node instanceof WeakHashingConfig::Source }
|
||||||
|
|
||||||
|
override predicate isSink(DataFlow::Node node) { node instanceof WeakHashingConfig::Sink }
|
||||||
|
}
|
||||||
|
|
||||||
|
module WeakHashingConfig {
|
||||||
|
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().(StructDecl).getName() and
|
||||||
|
algorithm = ["MD5", "SHA1"]
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
override string getAlgorithm() { result = algorithm }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
from
|
||||||
|
WeakHashingConfig config, DataFlow::PathNode source, DataFlow::PathNode sink, string algorithm,
|
||||||
|
SensitiveExpr expr
|
||||||
|
where
|
||||||
|
config.hasFlowPath(source, sink) and
|
||||||
|
algorithm = sink.getNode().(WeakHashingConfig::Sink).getAlgorithm() and
|
||||||
|
expr = source.getNode().asExpr()
|
||||||
|
select sink.getNode(), source, sink,
|
||||||
|
"Insecure hashing algorithm (" + algorithm + ") depends on $@.", source.getNode(),
|
||||||
|
"sensitive data (" + expr.getSensitiveType() + " " + expr.getLabel() + ")"
|
||||||
5
swift/ql/src/queries/Security/CWE-328/WeakSensitiveDataHashingBad.swift
Executable file
5
swift/ql/src/queries/Security/CWE-328/WeakSensitiveDataHashingBad.swift
Executable file
@@ -0,0 +1,5 @@
|
|||||||
|
typealias Hasher = Crypto.Insecure.MD5
|
||||||
|
|
||||||
|
func checkCertificate(cert: Array[UInt8], hash: Array[UInt8]) -> Bool
|
||||||
|
return Hasher.hash(data: cert) == hash // BAD
|
||||||
|
}
|
||||||
4
swift/ql/src/queries/Security/CWE-328/WeakSensitiveDataHashingGood.swift
Executable file
4
swift/ql/src/queries/Security/CWE-328/WeakSensitiveDataHashingGood.swift
Executable file
@@ -0,0 +1,4 @@
|
|||||||
|
typealias Hasher = Crypto.SHA512
|
||||||
|
|
||||||
|
func checkCertificate(cert: Array[UInt8], hash: Array[UInt8]) -> Bool
|
||||||
|
return Hasher.hash(data: cert) == hash // GOOD
|
||||||
@@ -1,13 +1,8 @@
|
|||||||
| testCoreData.swift:48:15:48:15 | password | label:password, type:credential |
|
| testCoreData.swift:48:15:48:15 | password | label:password, type:credential |
|
||||||
| testCoreData.swift:49:15:49:15 | password_hash | isProbablySafe, label:password_hash, type:credential |
|
|
||||||
| testCoreData.swift:51:24:51:24 | password | label:password, type:credential |
|
| testCoreData.swift:51:24:51:24 | password | label:password, type:credential |
|
||||||
| testCoreData.swift:52:24:52:24 | password_hash | isProbablySafe, label:password_hash, type:credential |
|
|
||||||
| testCoreData.swift:58:15:58:15 | password | label:password, type:credential |
|
| testCoreData.swift:58:15:58:15 | password | label:password, type:credential |
|
||||||
| testCoreData.swift:59:15:59:15 | password_file | isProbablySafe, label:password_file, type:credential |
|
|
||||||
| testCoreData.swift:61:25:61:25 | password | label:password, type:credential |
|
| testCoreData.swift:61:25:61:25 | password | label:password, type:credential |
|
||||||
| testCoreData.swift:62:25:62:25 | password_file | isProbablySafe, label:password_file, type:credential |
|
|
||||||
| testCoreData.swift:64:16:64:16 | password | label:password, type:credential |
|
| testCoreData.swift:64:16:64:16 | password | label:password, type:credential |
|
||||||
| testCoreData.swift:65:16:65:16 | password_file | isProbablySafe, label:password_file, type:credential |
|
|
||||||
| testCoreData.swift:77:2:77:25 | call to doSomething(password:) | label:doSomething(password:), type:credential |
|
| testCoreData.swift:77:2:77:25 | call to doSomething(password:) | label:doSomething(password:), type:credential |
|
||||||
| testCoreData.swift:77:24:77:24 | x | label:password, type:credential |
|
| testCoreData.swift:77:24:77:24 | x | label:password, type:credential |
|
||||||
| testCoreData.swift:80:10:80:22 | call to getPassword() | label:getPassword(), type:credential |
|
| testCoreData.swift:80:10:80:22 | call to getPassword() | label:getPassword(), type:credential |
|
||||||
@@ -16,15 +11,10 @@
|
|||||||
| testCoreData.swift:92:10:92:10 | passwd | label:passwd, type:credential |
|
| testCoreData.swift:92:10:92:10 | passwd | label:passwd, type:credential |
|
||||||
| testCoreData.swift:93:10:93:10 | passwd | label:passwd, type:credential |
|
| testCoreData.swift:93:10:93:10 | passwd | label:passwd, type:credential |
|
||||||
| testRealm.swift:34:11:34:11 | myPassword | label:myPassword, type:credential |
|
| testRealm.swift:34:11:34:11 | myPassword | label:myPassword, type:credential |
|
||||||
| testRealm.swift:38:11:38:11 | myHashedPassword | isProbablySafe, label:myHashedPassword, type:credential |
|
|
||||||
| testRealm.swift:42:11:42:11 | myPassword | label:myPassword, type:credential |
|
| testRealm.swift:42:11:42:11 | myPassword | label:myPassword, type:credential |
|
||||||
| testRealm.swift:46:11:46:11 | myHashedPassword | isProbablySafe, label:myHashedPassword, type:credential |
|
|
||||||
| testRealm.swift:52:12:52:12 | myPassword | label:myPassword, type:credential |
|
| testRealm.swift:52:12:52:12 | myPassword | label:myPassword, type:credential |
|
||||||
| testRealm.swift:55:12:55:12 | myHashedPassword | isProbablySafe, label:myHashedPassword, type:credential |
|
|
||||||
| testSend.swift:29:19:29:19 | passwordPlain | label:passwordPlain, type:credential |
|
| testSend.swift:29:19:29:19 | passwordPlain | label:passwordPlain, type:credential |
|
||||||
| testSend.swift:30:19:30:19 | passwordHash | isProbablySafe, label:passwordHash, type:credential |
|
|
||||||
| testSend.swift:33:19:33:19 | passwordPlain | label:passwordPlain, type:credential |
|
| testSend.swift:33:19:33:19 | passwordPlain | label:passwordPlain, type:credential |
|
||||||
| testSend.swift:34:19:34:19 | passwordHash | isProbablySafe, label:passwordHash, type:credential |
|
|
||||||
| testSend.swift:45:13:45:13 | password | label:password, type:credential |
|
| testSend.swift:45:13:45:13 | password | label:password, type:credential |
|
||||||
| testSend.swift:46:13:46:13 | password | label:password, type:credential |
|
| testSend.swift:46:13:46:13 | password | label:password, type:credential |
|
||||||
| testSend.swift:47:17:47:17 | password | label:password, type:credential |
|
| testSend.swift:47:17:47:17 | password | label:password, type:credential |
|
||||||
@@ -32,6 +22,5 @@
|
|||||||
| testSend.swift:49:27:49:27 | password | label:password, type:credential |
|
| testSend.swift:49:27:49:27 | password | label:password, type:credential |
|
||||||
| testSend.swift:50:27:50:27 | password | label:password, type:credential |
|
| testSend.swift:50:27:50:27 | password | label:password, type:credential |
|
||||||
| testURL.swift:13:54:13:54 | passwd | label:passwd, type:credential |
|
| testURL.swift:13:54:13:54 | passwd | label:passwd, type:credential |
|
||||||
| testURL.swift:14:54:14:54 | encrypted_passwd | isProbablySafe, label:encrypted_passwd, type:credential |
|
|
||||||
| testURL.swift:16:55:16:55 | credit_card_no | label:credit_card_no, type:private information |
|
| testURL.swift:16:55:16:55 | credit_card_no | label:credit_card_no, type:private information |
|
||||||
| testURL.swift:20:22:20:22 | passwd | label:passwd, type:credential |
|
| testURL.swift:20:22:20:22 | passwd | label:passwd, type:credential |
|
||||||
|
|||||||
@@ -5,8 +5,6 @@ string describe(SensitiveExpr e) {
|
|||||||
result = "label:" + e.getLabel()
|
result = "label:" + e.getLabel()
|
||||||
or
|
or
|
||||||
result = "type:" + e.getSensitiveType().toString()
|
result = "type:" + e.getSensitiveType().toString()
|
||||||
or
|
|
||||||
e.isProbablySafe() and result = "isProbablySafe"
|
|
||||||
}
|
}
|
||||||
|
|
||||||
from SensitiveExpr e
|
from SensitiveExpr e
|
||||||
|
|||||||
@@ -0,0 +1,42 @@
|
|||||||
|
edges
|
||||||
|
| testCrypto.swift:56:47:56:47 | passwd : | testCrypto.swift:63:44:63:44 | passwd |
|
||||||
|
| testCrypto.swift:60:43:60:43 | credit_card_no : | testCrypto.swift:61:43:61:43 | credit_card_no |
|
||||||
|
| testCrypto.swift:60:43:60:43 | credit_card_no : | testCrypto.swift:61:43:61:43 | credit_card_no : |
|
||||||
|
| testCrypto.swift:60:43:60:43 | credit_card_no : | testCrypto.swift:67:44:67:44 | credit_card_no |
|
||||||
|
| testCrypto.swift:61:43:61:43 | credit_card_no : | testCrypto.swift:67:44:67:44 | credit_card_no |
|
||||||
|
nodes
|
||||||
|
| testCrypto.swift:56:47:56:47 | passwd | semmle.label | passwd |
|
||||||
|
| testCrypto.swift:56:47:56:47 | passwd : | semmle.label | passwd : |
|
||||||
|
| testCrypto.swift:60:43:60:43 | credit_card_no | semmle.label | credit_card_no |
|
||||||
|
| testCrypto.swift:60:43:60:43 | credit_card_no : | semmle.label | credit_card_no : |
|
||||||
|
| testCrypto.swift:61:43:61:43 | credit_card_no | semmle.label | credit_card_no |
|
||||||
|
| testCrypto.swift:61:43:61:43 | credit_card_no : | semmle.label | credit_card_no : |
|
||||||
|
| testCrypto.swift:63:44:63:44 | passwd | semmle.label | passwd |
|
||||||
|
| testCrypto.swift:67:44:67:44 | credit_card_no | semmle.label | credit_card_no |
|
||||||
|
| testCrypto.swift:90:23:90:23 | passwd | semmle.label | passwd |
|
||||||
|
| testCrypto.swift:94:23:94:23 | credit_card_no | semmle.label | credit_card_no |
|
||||||
|
| testCrypto.swift:99:23:99:23 | passwd | semmle.label | passwd |
|
||||||
|
| testCrypto.swift:103:23:103:23 | credit_card_no | semmle.label | credit_card_no |
|
||||||
|
| testCrypto.swift:132:32:132:32 | passwd | semmle.label | passwd |
|
||||||
|
| testCrypto.swift:136:32:136:32 | credit_card_no | semmle.label | credit_card_no |
|
||||||
|
| testCrypto.swift:141:32:141:32 | passwd | semmle.label | passwd |
|
||||||
|
| testCrypto.swift:145:32:145:32 | credit_card_no | semmle.label | credit_card_no |
|
||||||
|
subpaths
|
||||||
|
#select
|
||||||
|
| testCrypto.swift:56:47:56:47 | passwd | testCrypto.swift:56:47:56:47 | passwd | testCrypto.swift:56:47:56:47 | passwd | Insecure hashing algorithm (MD5) depends on $@. | testCrypto.swift:56:47:56:47 | passwd | sensitive data (credential passwd) |
|
||||||
|
| testCrypto.swift:60:43:60:43 | credit_card_no | testCrypto.swift:60:43:60:43 | credit_card_no | testCrypto.swift:60:43:60:43 | credit_card_no | Insecure hashing algorithm (MD5) depends on $@. | testCrypto.swift:60:43:60:43 | credit_card_no | sensitive data (private information credit_card_no) |
|
||||||
|
| testCrypto.swift:61:43:61:43 | credit_card_no | testCrypto.swift:60:43:60:43 | credit_card_no : | testCrypto.swift:61:43:61:43 | credit_card_no | Insecure hashing algorithm (MD5) depends on $@. | testCrypto.swift:60:43:60:43 | credit_card_no | sensitive data (private information credit_card_no) |
|
||||||
|
| testCrypto.swift:61:43:61:43 | credit_card_no | testCrypto.swift:61:43:61:43 | credit_card_no | testCrypto.swift:61:43:61:43 | credit_card_no | Insecure hashing algorithm (MD5) depends on $@. | testCrypto.swift:61:43:61:43 | credit_card_no | sensitive data (private information credit_card_no) |
|
||||||
|
| testCrypto.swift:63:44:63:44 | passwd | testCrypto.swift:56:47:56:47 | passwd : | testCrypto.swift:63:44:63:44 | passwd | Insecure hashing algorithm (SHA1) depends on $@. | testCrypto.swift:56:47:56:47 | passwd | sensitive data (credential passwd) |
|
||||||
|
| testCrypto.swift:63:44:63:44 | passwd | testCrypto.swift:63:44:63:44 | passwd | testCrypto.swift:63:44:63:44 | passwd | Insecure hashing algorithm (SHA1) depends on $@. | testCrypto.swift:63:44:63:44 | passwd | sensitive data (credential passwd) |
|
||||||
|
| testCrypto.swift:67:44:67:44 | credit_card_no | testCrypto.swift:60:43:60:43 | credit_card_no : | testCrypto.swift:67:44:67:44 | credit_card_no | Insecure hashing algorithm (SHA1) depends on $@. | testCrypto.swift:60:43:60:43 | credit_card_no | sensitive data (private information credit_card_no) |
|
||||||
|
| testCrypto.swift:67:44:67:44 | credit_card_no | testCrypto.swift:61:43:61:43 | credit_card_no : | testCrypto.swift:67:44:67:44 | credit_card_no | Insecure hashing algorithm (SHA1) depends on $@. | testCrypto.swift:61:43:61:43 | credit_card_no | sensitive data (private information credit_card_no) |
|
||||||
|
| testCrypto.swift:67:44:67:44 | credit_card_no | testCrypto.swift:67:44:67:44 | credit_card_no | testCrypto.swift:67:44:67:44 | credit_card_no | Insecure hashing algorithm (SHA1) depends on $@. | testCrypto.swift:67:44:67:44 | credit_card_no | sensitive data (private information credit_card_no) |
|
||||||
|
| testCrypto.swift:90:23:90:23 | passwd | testCrypto.swift:90:23:90:23 | passwd | testCrypto.swift:90:23:90:23 | passwd | Insecure hashing algorithm (MD5) depends on $@. | testCrypto.swift:90:23:90:23 | passwd | sensitive data (credential passwd) |
|
||||||
|
| testCrypto.swift:94:23:94:23 | credit_card_no | testCrypto.swift:94:23:94:23 | credit_card_no | testCrypto.swift:94:23:94:23 | credit_card_no | Insecure hashing algorithm (MD5) depends on $@. | testCrypto.swift:94:23:94:23 | credit_card_no | sensitive data (private information credit_card_no) |
|
||||||
|
| testCrypto.swift:99:23:99:23 | passwd | testCrypto.swift:99:23:99:23 | passwd | testCrypto.swift:99:23:99:23 | passwd | Insecure hashing algorithm (SHA1) depends on $@. | testCrypto.swift:99:23:99:23 | passwd | sensitive data (credential passwd) |
|
||||||
|
| testCrypto.swift:103:23:103:23 | credit_card_no | testCrypto.swift:103:23:103:23 | credit_card_no | testCrypto.swift:103:23:103:23 | credit_card_no | Insecure hashing algorithm (SHA1) depends on $@. | testCrypto.swift:103:23:103:23 | credit_card_no | sensitive data (private information credit_card_no) |
|
||||||
|
| testCrypto.swift:132:32:132:32 | passwd | testCrypto.swift:132:32:132:32 | passwd | testCrypto.swift:132:32:132:32 | passwd | Insecure hashing algorithm (MD5) depends on $@. | testCrypto.swift:132:32:132:32 | passwd | sensitive data (credential passwd) |
|
||||||
|
| testCrypto.swift:136:32:136:32 | credit_card_no | testCrypto.swift:136:32:136:32 | credit_card_no | testCrypto.swift:136:32:136:32 | credit_card_no | Insecure hashing algorithm (MD5) depends on $@. | testCrypto.swift:136:32:136:32 | credit_card_no | sensitive data (private information credit_card_no) |
|
||||||
|
| testCrypto.swift:141:32:141:32 | passwd | testCrypto.swift:141:32:141:32 | passwd | testCrypto.swift:141:32:141:32 | passwd | Insecure hashing algorithm (SHA1) depends on $@. | testCrypto.swift:141:32:141:32 | passwd | sensitive data (credential passwd) |
|
||||||
|
| testCrypto.swift:145:32:145:32 | credit_card_no | testCrypto.swift:145:32:145:32 | credit_card_no | testCrypto.swift:145:32:145:32 | credit_card_no | Insecure hashing algorithm (SHA1) depends on $@. | testCrypto.swift:145:32:145:32 | credit_card_no | sensitive data (private information credit_card_no) |
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
queries/Security/CWE-328/WeakSensitiveDataHashing.ql
|
||||||
170
swift/ql/test/query-tests/Security/CWE-328/testCrypto.swift
Normal file
170
swift/ql/test/query-tests/Security/CWE-328/testCrypto.swift
Normal file
@@ -0,0 +1,170 @@
|
|||||||
|
//codeql-extractor-options: -module-name Crypto
|
||||||
|
|
||||||
|
struct SHA256 {
|
||||||
|
static func hash<D>(data: D) -> [UInt8] {
|
||||||
|
return []
|
||||||
|
}
|
||||||
|
|
||||||
|
func update<D>(data: D) {}
|
||||||
|
func update(bufferPointer: UnsafeRawBufferPointer) {}
|
||||||
|
func finalize() -> [UInt8] { return [] }
|
||||||
|
}
|
||||||
|
|
||||||
|
struct SHA384 {
|
||||||
|
static func hash<D>(data: D) -> [UInt8] {
|
||||||
|
return []
|
||||||
|
}
|
||||||
|
|
||||||
|
func update<D>(data: D) {}
|
||||||
|
func update(bufferPointer: UnsafeRawBufferPointer) {}
|
||||||
|
func finalize() -> [UInt8] { return [] }
|
||||||
|
}
|
||||||
|
|
||||||
|
struct SHA512 {
|
||||||
|
static func hash<D>(data: D) -> [UInt8] {
|
||||||
|
return []
|
||||||
|
}
|
||||||
|
|
||||||
|
func update<D>(data: D) {}
|
||||||
|
func update(bufferPointer: UnsafeRawBufferPointer) {}
|
||||||
|
func finalize() -> [UInt8] { return [] }
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
enum Insecure {
|
||||||
|
struct MD5 {
|
||||||
|
static func hash<D>(data: D) -> [UInt8] {
|
||||||
|
return []
|
||||||
|
}
|
||||||
|
|
||||||
|
func update<D>(data: D) {}
|
||||||
|
func update(bufferPointer: UnsafeRawBufferPointer) {}
|
||||||
|
func finalize() -> [UInt8] { return [] }
|
||||||
|
}
|
||||||
|
struct SHA1 {
|
||||||
|
static func hash<D>(data: D) -> [UInt8] {
|
||||||
|
return []
|
||||||
|
}
|
||||||
|
|
||||||
|
func update<D>(data: D) {}
|
||||||
|
func update(bufferPointer: UnsafeRawBufferPointer) {}
|
||||||
|
func finalize() -> [UInt8] { return [] }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func testHashMethods(passwd : UnsafeRawBufferPointer, cert: String, encrypted_passwd : String, account_no : String, credit_card_no : String) {
|
||||||
|
var hash = Crypto.Insecure.MD5.hash(data: passwd) // BAD
|
||||||
|
hash = Crypto.Insecure.MD5.hash(data: cert) // BAD [NOT DETECTED]
|
||||||
|
hash = Crypto.Insecure.MD5.hash(data: encrypted_passwd) // GOOD (not sensitive)
|
||||||
|
hash = Crypto.Insecure.MD5.hash(data: account_no) // BAD [NOT DETECTED]
|
||||||
|
hash = Crypto.Insecure.MD5.hash(data: credit_card_no) // BAD
|
||||||
|
hash = Crypto.Insecure.MD5.hash(data: credit_card_no) // BAD
|
||||||
|
|
||||||
|
hash = Crypto.Insecure.SHA1.hash(data: passwd) // BAD
|
||||||
|
hash = Crypto.Insecure.SHA1.hash(data: cert) // BAD [NOT DETECTED]
|
||||||
|
hash = Crypto.Insecure.SHA1.hash(data: encrypted_passwd) // GOOD (not sensitive)
|
||||||
|
hash = Crypto.Insecure.SHA1.hash(data: account_no) // BAD [NOT DETECTED]
|
||||||
|
hash = Crypto.Insecure.SHA1.hash(data: credit_card_no) // BAD
|
||||||
|
|
||||||
|
hash = Crypto.SHA256.hash(data: passwd) // BAD [NOT DETECTED] not a computationally expensive hash
|
||||||
|
hash = Crypto.SHA256.hash(data: cert) // GOOD, computationally expensive hash not required
|
||||||
|
hash = Crypto.SHA256.hash(data: account_no) // GOOD, computationally expensive hash not required
|
||||||
|
hash = Crypto.SHA256.hash(data: credit_card_no) // GOOD, computationally expensive hash not required
|
||||||
|
hash = Crypto.SHA256.hash(data: credit_card_no) // GOOD, computationally expensive hash not required
|
||||||
|
|
||||||
|
hash = Crypto.SHA384.hash(data: passwd) // BAD [NOT DETECTED] not a computationally expensive hash
|
||||||
|
hash = Crypto.SHA384.hash(data: cert) // GOOD, computationally expensive hash not required
|
||||||
|
hash = Crypto.SHA384.hash(data: account_no) // GOOD, computationally expensive hash not required
|
||||||
|
hash = Crypto.SHA384.hash(data: credit_card_no) // GOOD, computationally expensive hash not required
|
||||||
|
hash = Crypto.SHA384.hash(data: credit_card_no) // GOOD, computationally expensive hash not required
|
||||||
|
|
||||||
|
hash = Crypto.SHA512.hash(data: passwd) // BAD [NOT DETECTED] not a computationally expensive hash
|
||||||
|
hash = Crypto.SHA512.hash(data: cert) // GOOD, computationally expensive hash not required
|
||||||
|
hash = Crypto.SHA512.hash(data: account_no) // GOOD, computationally expensive hash not required
|
||||||
|
hash = Crypto.SHA512.hash(data: credit_card_no) // GOOD, computationally expensive hash not required
|
||||||
|
hash = Crypto.SHA512.hash(data: credit_card_no) // GOOD, computationally expensive hash not required
|
||||||
|
}
|
||||||
|
|
||||||
|
func testMD5UpdateWithData(passwd : String, cert: String, encrypted_passwd : String, account_no : String, credit_card_no : String) {
|
||||||
|
var hash = Crypto.Insecure.MD5()
|
||||||
|
hash.update(data: passwd) // BAD
|
||||||
|
hash.update(data: cert) // BAD [NOT DETECTED]
|
||||||
|
hash.update(data: encrypted_passwd) // GOOD (not sensitive)
|
||||||
|
hash.update(data: account_no) // BAD [NOT DETECTED]
|
||||||
|
hash.update(data: credit_card_no) // BAD
|
||||||
|
}
|
||||||
|
|
||||||
|
func testSHA1UpdateWithData(passwd : String, cert: String, encrypted_passwd : String, account_no : String, credit_card_no : String) {
|
||||||
|
var hash = Crypto.Insecure.SHA1()
|
||||||
|
hash.update(data: passwd) // BAD
|
||||||
|
hash.update(data: cert) // BAD [NOT DETECTED]
|
||||||
|
hash.update(data: encrypted_passwd) // GOOD (not sensitive)
|
||||||
|
hash.update(data: account_no) // BAD [NOT DETECTED]
|
||||||
|
hash.update(data: credit_card_no) // BAD
|
||||||
|
}
|
||||||
|
|
||||||
|
func testSHA256UpdateWithData(passwd : String, cert: String, encrypted_passwd : String, account_no : String, credit_card_no : String) {
|
||||||
|
var hash = Crypto.SHA256()
|
||||||
|
hash.update(data: passwd) // BAD [NOT DETECTED] not a computationally expensive hash
|
||||||
|
hash.update(data: cert) // GOOD
|
||||||
|
hash.update(data: account_no) // GOOD
|
||||||
|
hash.update(data: credit_card_no) // GOOD
|
||||||
|
}
|
||||||
|
|
||||||
|
func testSHA384UpdateWithData(passwd : String, cert: String, encrypted_passwd : String, account_no : String, credit_card_no : String) {
|
||||||
|
var hash = Crypto.SHA384()
|
||||||
|
hash.update(data: passwd) // BAD [NOT DETECTED] not a computationally expensive hash
|
||||||
|
hash.update(data: cert) // GOOD
|
||||||
|
hash.update(data: account_no) // GOOD
|
||||||
|
hash.update(data: credit_card_no) // GOOD
|
||||||
|
}
|
||||||
|
|
||||||
|
func testSHA512UpdateWithData(passwd : String, cert: String, encrypted_passwd : String, account_no : String, credit_card_no : String) {
|
||||||
|
var hash = Crypto.SHA512()
|
||||||
|
hash.update(data: passwd) // BAD [NOT DETECTED] not a computationally expensive hash
|
||||||
|
hash.update(data: cert) // GOOD
|
||||||
|
hash.update(data: account_no) // GOOD
|
||||||
|
hash.update(data: credit_card_no) // GOOD
|
||||||
|
}
|
||||||
|
|
||||||
|
func testMD5UpdateWithUnsafeRawBufferPointer(passwd : UnsafeRawBufferPointer, cert: UnsafeRawBufferPointer, encrypted_passwd : UnsafeRawBufferPointer, account_no : UnsafeRawBufferPointer, credit_card_no : UnsafeRawBufferPointer) {
|
||||||
|
var hash = Crypto.Insecure.MD5()
|
||||||
|
hash.update(bufferPointer: passwd) // BAD
|
||||||
|
hash.update(bufferPointer: cert) // BAD [NOT DETECTED]
|
||||||
|
hash.update(bufferPointer: encrypted_passwd) // GOOD (not sensitive)
|
||||||
|
hash.update(bufferPointer: account_no) // BAD [NOT DETECTED]
|
||||||
|
hash.update(bufferPointer: credit_card_no) // BAD
|
||||||
|
}
|
||||||
|
|
||||||
|
func testSHA1UpdateWithUnsafeRawBufferPointer(passwd : UnsafeRawBufferPointer, cert: UnsafeRawBufferPointer, encrypted_passwd : UnsafeRawBufferPointer, account_no : UnsafeRawBufferPointer, credit_card_no : UnsafeRawBufferPointer) {
|
||||||
|
var hash = Crypto.Insecure.SHA1()
|
||||||
|
hash.update(bufferPointer: passwd) // BAD
|
||||||
|
hash.update(bufferPointer: cert) // BAD [NOT DETECTED]
|
||||||
|
hash.update(bufferPointer: encrypted_passwd) // GOOD (not sensitive)
|
||||||
|
hash.update(bufferPointer: account_no) // BAD [NOT DETECTED]
|
||||||
|
hash.update(bufferPointer: credit_card_no) // BAD
|
||||||
|
}
|
||||||
|
|
||||||
|
func testSHA256UpdateWithUnsafeRawBufferPointer(passwd : UnsafeRawBufferPointer, cert: UnsafeRawBufferPointer, encrypted_passwd : UnsafeRawBufferPointer, account_no : UnsafeRawBufferPointer, credit_card_no : UnsafeRawBufferPointer) {
|
||||||
|
var hash = Crypto.SHA256()
|
||||||
|
hash.update(bufferPointer: passwd) // BAD [NOT DETECTED] not a computationally expensive hash
|
||||||
|
hash.update(bufferPointer: cert) // GOOD
|
||||||
|
hash.update(bufferPointer: account_no) // GOOD
|
||||||
|
hash.update(bufferPointer: credit_card_no) // GOOD
|
||||||
|
}
|
||||||
|
|
||||||
|
func testSHA384UpdateWithUnsafeRawBufferPointer(passwd : UnsafeRawBufferPointer, cert: UnsafeRawBufferPointer, encrypted_passwd : UnsafeRawBufferPointer, account_no : UnsafeRawBufferPointer, credit_card_no : UnsafeRawBufferPointer) {
|
||||||
|
var hash = Crypto.SHA384()
|
||||||
|
hash.update(bufferPointer: passwd) // BAD [NOT DETECTED] not a computationally expensive hash
|
||||||
|
hash.update(bufferPointer: cert) // GOOD
|
||||||
|
hash.update(bufferPointer: account_no) // GOOD
|
||||||
|
hash.update(bufferPointer: credit_card_no) // GOOD
|
||||||
|
}
|
||||||
|
|
||||||
|
func testSHA512UpdateWithUnsafeRawBufferPointer(passwd : UnsafeRawBufferPointer, cert: UnsafeRawBufferPointer, encrypted_passwd : UnsafeRawBufferPointer, account_no : UnsafeRawBufferPointer, credit_card_no : UnsafeRawBufferPointer) {
|
||||||
|
var hash = Crypto.SHA512()
|
||||||
|
hash.update(bufferPointer: passwd) // BAD [NOT DETECTED] not a computationally expensive hash
|
||||||
|
hash.update(bufferPointer: cert) // GOOD
|
||||||
|
hash.update(bufferPointer: account_no) // GOOD
|
||||||
|
hash.update(bufferPointer: credit_card_no) // GOOD
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user