Merge branch 'main' into re-modeling

This commit is contained in:
Rasmus Wriedt Larsen
2023-11-10 16:32:50 +01:00
1463 changed files with 52896 additions and 29133 deletions

View File

@@ -1352,7 +1352,10 @@ abstract class DataFlowCall extends TDataFlowCall {
abstract ControlFlowNode getNode();
/** Gets the enclosing callable of this call. */
abstract DataFlowCallable getEnclosingCallable();
DataFlowCallable getEnclosingCallable() { result = getCallableScope(this.getScope()) }
/** Gets the scope of this node, if any. */
abstract Scope getScope();
/** Gets the location of this dataflow call. */
abstract Location getLocation();
@@ -1400,7 +1403,7 @@ class NormalCall extends ExtractedDataFlowCall, TNormalCall {
override ControlFlowNode getNode() { result = call }
override DataFlowCallable getEnclosingCallable() { result.getScope() = call.getScope() }
override Scope getScope() { result = call.getScope() }
override DataFlowCallable getCallable() { result.(DataFlowFunction).getScope() = target }
@@ -1450,7 +1453,7 @@ class PotentialLibraryCall extends ExtractedDataFlowCall, TPotentialLibraryCall
override ControlFlowNode getNode() { result = call }
override DataFlowCallable getEnclosingCallable() { result.getScope() = call.getScope() }
override Scope getScope() { result = call.getScope() }
}
/**
@@ -1474,6 +1477,8 @@ class SummaryCall extends DataFlowCall, TSummaryCall {
override DataFlowCallable getEnclosingCallable() { result.asLibraryCallable() = c }
override Scope getScope() { none() }
override DataFlowCallable getCallable() { none() }
override ArgumentNode getArgument(ArgumentPosition apos) { none() }

View File

@@ -1044,3 +1044,11 @@ class ContentApprox = Unit;
/** Gets an approximated value for content `c`. */
pragma[inline]
ContentApprox getContentApprox(Content c) { any() }
/** Helper for `.getEnclosingCallable`. */
DataFlowCallable getCallableScope(Scope s) {
result.getScope() = s
or
not exists(DataFlowCallable c | c.getScope() = s) and
result = getCallableScope(s.getEnclosingScope())
}

View File

@@ -117,14 +117,6 @@ newtype TNode =
exists(ParameterPosition ppos | ppos.isKeyword(_) | exists(callable.getParameter(ppos)))
}
/** Helper for `Node::getEnclosingCallable`. */
private DataFlowCallable getCallableScope(Scope s) {
result.getScope() = s
or
not exists(DataFlowCallable c | c.getScope() = s) and
result = getCallableScope(s.getEnclosingScope())
}
private import semmle.python.internal.CachedStages
/**

View File

@@ -128,6 +128,8 @@ private module CryptodomeModel {
this = newCall.getReturn().getMember(methodName).getACall()
}
override DataFlow::Node getInitialization() { result = newCall }
override Cryptography::CryptographicAlgorithm getAlgorithm() { result.matchesName(cipherName) }
override DataFlow::Node getAnInput() {
@@ -181,21 +183,23 @@ private module CryptodomeModel {
class CryptodomeGenericSignatureOperation extends Cryptography::CryptographicOperation::Range,
DataFlow::CallCfgNode
{
API::CallNode newCall;
string methodName;
string signatureName;
CryptodomeGenericSignatureOperation() {
methodName in ["sign", "verify"] and
this =
newCall =
API::moduleImport(["Crypto", "Cryptodome"])
.getMember("Signature")
.getMember(signatureName)
.getMember("new")
.getReturn()
.getMember(methodName)
.getACall()
.getACall() and
this = newCall.getReturn().getMember(methodName).getACall()
}
override DataFlow::Node getInitialization() { result = newCall }
override Cryptography::CryptographicAlgorithm getAlgorithm() {
result.matchesName(signatureName)
}
@@ -221,19 +225,23 @@ private module CryptodomeModel {
class CryptodomeGenericHashOperation extends Cryptography::CryptographicOperation::Range,
DataFlow::CallCfgNode
{
API::CallNode newCall;
string hashName;
CryptodomeGenericHashOperation() {
exists(API::Node hashModule |
hashModule =
API::moduleImport(["Crypto", "Cryptodome"]).getMember("Hash").getMember(hashName)
API::moduleImport(["Crypto", "Cryptodome"]).getMember("Hash").getMember(hashName) and
newCall = hashModule.getMember("new").getACall()
|
this = hashModule.getMember("new").getACall()
this = newCall
or
this = hashModule.getMember("new").getReturn().getMember("update").getACall()
this = newCall.getReturn().getMember("update").getACall()
)
}
override DataFlow::Node getInitialization() { result = newCall }
override Cryptography::CryptographicAlgorithm getAlgorithm() { result.matchesName(hashName) }
override DataFlow::Node getAnInput() { result in [this.getArg(0), this.getArgByName("data")] }

View File

@@ -209,18 +209,18 @@ private module CryptographyModel {
class CryptographyGenericCipherOperation extends Cryptography::CryptographicOperation::Range,
DataFlow::MethodCallNode
{
API::CallNode init;
string algorithmName;
string modeName;
CryptographyGenericCipherOperation() {
this =
cipherInstance(algorithmName, modeName)
.getMember(["decryptor", "encryptor"])
.getReturn()
.getMember(["update", "update_into"])
.getACall()
init =
cipherInstance(algorithmName, modeName).getMember(["decryptor", "encryptor"]).getACall() and
this = init.getReturn().getMember(["update", "update_into"]).getACall()
}
override DataFlow::Node getInitialization() { result = init }
override Cryptography::CryptographicAlgorithm getAlgorithm() {
result.matchesName(algorithmName)
}
@@ -247,19 +247,17 @@ private module CryptographyModel {
}
/** Gets a reference to a Hash instance using algorithm with `algorithmName`. */
private API::Node hashInstance(string algorithmName) {
exists(API::CallNode call | result = call.getReturn() |
call =
API::moduleImport("cryptography")
.getMember("hazmat")
.getMember("primitives")
.getMember("hashes")
.getMember("Hash")
.getACall() and
algorithmClassRef(algorithmName).getReturn().getAValueReachableFromSource() in [
call.getArg(0), call.getArgByName("algorithm")
]
)
private API::CallNode hashInstance(string algorithmName) {
result =
API::moduleImport("cryptography")
.getMember("hazmat")
.getMember("primitives")
.getMember("hashes")
.getMember("Hash")
.getACall() and
algorithmClassRef(algorithmName).getReturn().getAValueReachableFromSource() in [
result.getArg(0), result.getArgByName("algorithm")
]
}
/**
@@ -268,12 +266,16 @@ private module CryptographyModel {
class CryptographyGenericHashOperation extends Cryptography::CryptographicOperation::Range,
DataFlow::MethodCallNode
{
API::CallNode init;
string algorithmName;
CryptographyGenericHashOperation() {
this = hashInstance(algorithmName).getMember("update").getACall()
init = hashInstance(algorithmName) and
this = init.getReturn().getMember("update").getACall()
}
override DataFlow::Node getInitialization() { result = init }
override Cryptography::CryptographicAlgorithm getAlgorithm() {
result.matchesName(algorithmName)
}

View File

@@ -37,6 +37,8 @@ private module Rsa {
class RsaEncryptCall extends Cryptography::CryptographicOperation::Range, DataFlow::CallCfgNode {
RsaEncryptCall() { this = API::moduleImport("rsa").getMember("encrypt").getACall() }
override DataFlow::Node getInitialization() { result = this }
override Cryptography::CryptographicAlgorithm getAlgorithm() { result.getName() = "RSA" }
override DataFlow::Node getAnInput() {
@@ -54,6 +56,8 @@ private module Rsa {
class RsaDecryptCall extends Cryptography::CryptographicOperation::Range, DataFlow::CallCfgNode {
RsaDecryptCall() { this = API::moduleImport("rsa").getMember("decrypt").getACall() }
override DataFlow::Node getInitialization() { result = this }
override Cryptography::CryptographicAlgorithm getAlgorithm() { result.getName() = "RSA" }
override DataFlow::Node getAnInput() { result in [this.getArg(0), this.getArgByName("crypto")] }
@@ -69,6 +73,8 @@ private module Rsa {
class RsaSignCall extends Cryptography::CryptographicOperation::Range, DataFlow::CallCfgNode {
RsaSignCall() { this = API::moduleImport("rsa").getMember("sign").getACall() }
override DataFlow::Node getInitialization() { result = this }
override Cryptography::CryptographicAlgorithm getAlgorithm() {
// signature part
result.getName() = "RSA"
@@ -96,6 +102,8 @@ private module Rsa {
class RsaVerifyCall extends Cryptography::CryptographicOperation::Range, DataFlow::CallCfgNode {
RsaVerifyCall() { this = API::moduleImport("rsa").getMember("verify").getACall() }
override DataFlow::Node getInitialization() { result = this }
override Cryptography::CryptographicAlgorithm getAlgorithm() {
// note that technically there is also a hashing operation going on but we don't
// know what algorithm is used up front, since it is encoded in the signature
@@ -121,6 +129,8 @@ private module Rsa {
{
RsaComputeHashCall() { this = API::moduleImport("rsa").getMember("compute_hash").getACall() }
override DataFlow::Node getInitialization() { result = this }
override Cryptography::CryptographicAlgorithm getAlgorithm() {
exists(StrConst str, DataFlow::Node hashNameArg |
hashNameArg in [this.getArg(1), this.getArgByName("method_name")] and
@@ -144,6 +154,8 @@ private module Rsa {
class RsaSignHashCall extends Cryptography::CryptographicOperation::Range, DataFlow::CallCfgNode {
RsaSignHashCall() { this = API::moduleImport("rsa").getMember("sign_hash").getACall() }
override DataFlow::Node getInitialization() { result = this }
override Cryptography::CryptographicAlgorithm getAlgorithm() { result.getName() = "RSA" }
override DataFlow::Node getAnInput() {

View File

@@ -2747,6 +2747,8 @@ private module StdlibPrivate {
exists(this.getParameter(1, "data"))
}
override DataFlow::Node getInitialization() { result = this }
override Cryptography::CryptographicAlgorithm getAlgorithm() { result.matchesName(hashName) }
override DataFlow::Node getAnInput() { result = this.getParameter(1, "data").asSink() }
@@ -2758,12 +2760,16 @@ private module StdlibPrivate {
* A hashing operation by using the `update` method on the result of calling the `hashlib.new` function.
*/
class HashlibNewUpdateCall extends Cryptography::CryptographicOperation::Range, API::CallNode {
API::CallNode init;
string hashName;
HashlibNewUpdateCall() {
this = hashlibNewCall(hashName).getReturn().getMember("update").getACall()
init = hashlibNewCall(hashName) and
this = init.getReturn().getMember("update").getACall()
}
override DataFlow::Node getInitialization() { result = init }
override Cryptography::CryptographicAlgorithm getAlgorithm() { result.matchesName(hashName) }
override DataFlow::Node getAnInput() { result = this.getArg(0) }
@@ -2802,7 +2808,14 @@ private module StdlibPrivate {
* (such as `hashlib.md5`), by calling its' `update` method.
*/
class HashlibHashClassUpdateCall extends HashlibGenericHashOperation {
HashlibHashClassUpdateCall() { this = hashClass.getReturn().getMember("update").getACall() }
API::CallNode init;
HashlibHashClassUpdateCall() {
init = hashClass.getACall() and
this = hashClass.getReturn().getMember("update").getACall()
}
override DataFlow::Node getInitialization() { result = init }
override DataFlow::Node getAnInput() { result = this.getArg(0) }
}
@@ -2819,6 +2832,8 @@ private module StdlibPrivate {
exists([this.getArg(0), this.getArgByName("string")])
}
override DataFlow::Node getInitialization() { result = this }
override DataFlow::Node getAnInput() {
result = this.getArg(0)
or
@@ -2865,6 +2880,8 @@ private module StdlibPrivate {
exists(this.getParameter(1, "msg").asSink())
}
override DataFlow::Node getInitialization() { result = this }
override API::Node getDigestArg() { result = digestArg }
override DataFlow::Node getAnInput() { result = this.getParameter(1, "msg").asSink() }
@@ -2876,12 +2893,16 @@ private module StdlibPrivate {
* See https://docs.python.org/3.11/library/hmac.html#hmac.HMAC.update
*/
class HmacUpdateCall extends HmacCryptographicOperation {
API::CallNode init;
API::Node digestArg;
HmacUpdateCall() {
this = getHmacConstructorCall(digestArg).getReturn().getMember("update").getACall()
init = getHmacConstructorCall(digestArg) and
this = init.getReturn().getMember("update").getACall()
}
override DataFlow::Node getInitialization() { result = init }
override API::Node getDigestArg() { result = digestArg }
override DataFlow::Node getAnInput() { result = this.getParameter(0, "msg").asSink() }
@@ -2895,6 +2916,8 @@ private module StdlibPrivate {
class HmacDigestCall extends HmacCryptographicOperation {
HmacDigestCall() { this = API::moduleImport("hmac").getMember("digest").getACall() }
override DataFlow::Node getInitialization() { result = this }
override API::Node getDigestArg() { result = this.getParameter(2, "digest") }
override DataFlow::Node getAnInput() { result = this.getParameter(1, "msg").asSink() }

View File

@@ -40,6 +40,9 @@ module Cryptography {
/** Gets the algorithm used, if it matches a known `CryptographicAlgorithm`. */
CryptographicAlgorithm getAlgorithm() { result = super.getAlgorithm() }
/** Gets the data-flow node where the cryptographic algorithm used in this operation is configured. */
DataFlow::Node getInitialization() { result = super.getInitialization() }
/** Gets an input the algorithm is used on, for example the plain text input to be encrypted. */
DataFlow::Node getAnInput() { result = super.getAnInput() }
@@ -65,6 +68,9 @@ module Cryptography {
* extend `CryptographicOperation` instead.
*/
abstract class Range extends DataFlow::Node {
/** Gets the data-flow node where the cryptographic algorithm used in this operation is configured. */
abstract DataFlow::Node getInitialization();
/** Gets the algorithm used, if it matches a known `CryptographicAlgorithm`. */
abstract CryptographicAlgorithm getAlgorithm();