Ruby: fix some cases where we assume that a CryptographicOperation is using CBC when it is not

This commit is contained in:
Alex Ford
2022-05-17 14:54:57 +01:00
parent c620fceb82
commit f92782d4e7
7 changed files with 47 additions and 6 deletions

View File

@@ -81,6 +81,8 @@ class EncryptionAlgorithm extends MkEncryptionAlgorithm, CryptographicAlgorithm
override string getName() { result = name }
override predicate isWeak() { isWeak = true }
predicate isStreamCipher() { isStreamCipher(name) }
}
/**

View File

@@ -65,3 +65,8 @@ predicate isStrongPasswordHashingAlgorithm(string name) {
* Holds if `name` corresponds to a weak password hashing algorithm.
*/
predicate isWeakPasswordHashingAlgorithm(string name) { name = "EVPKDF" }
/**
* Holds if `name` corresponds to a stream cipher.
*/
predicate isStreamCipher(string name) { name = ["CHACHA", "RC4", "ARC4", "ARCFOUR", "RABBIT"] }

View File

@@ -81,6 +81,8 @@ class EncryptionAlgorithm extends MkEncryptionAlgorithm, CryptographicAlgorithm
override string getName() { result = name }
override predicate isWeak() { isWeak = true }
predicate isStreamCipher() { isStreamCipher(name) }
}
/**

View File

@@ -65,3 +65,8 @@ predicate isStrongPasswordHashingAlgorithm(string name) {
* Holds if `name` corresponds to a weak password hashing algorithm.
*/
predicate isWeakPasswordHashingAlgorithm(string name) { name = "EVPKDF" }
/**
* Holds if `name` corresponds to a stream cipher.
*/
predicate isStreamCipher(string name) { name = ["CHACHA", "RC4", "ARC4", "ARCFOUR", "RABBIT"] }

View File

@@ -81,6 +81,8 @@ class EncryptionAlgorithm extends MkEncryptionAlgorithm, CryptographicAlgorithm
override string getName() { result = name }
override predicate isWeak() { isWeak = true }
predicate isStreamCipher() { isStreamCipher(name) }
}
/**

View File

@@ -370,6 +370,25 @@ private int getIntArgument(DataFlow::CallNode call, int i) {
result = call.getArgument(i).asExpr().getConstantValue().getInt()
}
bindingset[blockCipherName]
private Cryptography::BlockMode getCandidateBlockModeFromCipherName(string blockCipherName) {
result = blockCipherName.splitAt("-", [1, 2]).toUpperCase()
}
/**
* Gets the block mode specified as part of a block cipher name used to
* instantiate an `OpenSSL::Cipher` instance. If the block mode is not
* explicitly specified, this defaults to "CBC".
*/
bindingset[blockCipherName]
private Cryptography::BlockMode getBlockModeFromCipherName(string blockCipherName) {
// Extract the block mode from the cipher name
result = getCandidateBlockModeFromCipherName(blockCipherName)
or
// Fall back on the OpenSSL default of CBC if the block mode is unspecified
not exists(getCandidateBlockModeFromCipherName(blockCipherName)) and result = "CBC"
}
/**
* Holds if `call` is a call to `OpenSSL::Cipher.new` that instantiates a
* `cipher` instance with mode `cipherMode`.
@@ -381,8 +400,9 @@ private predicate cipherInstantiationGeneric(
// `OpenSSL::Cipher.new('<cipherName>')`
call = cipherApi().getAnInstantiation() and
cipherName = getStringArgument(call, 0) and
// CBC is used by default
cipherMode.isBlockMode("CBC")
if cipher.getAlgorithm().isStreamCipher()
then cipherMode = TStreamCipher()
else cipherMode.isBlockMode(getBlockModeFromCipherName(cipherName))
)
}
@@ -397,12 +417,12 @@ private predicate cipherInstantiationAES(
exists(string cipherName | cipher.matchesName(cipherName) |
// `OpenSSL::Cipher::AES` instantiations
call = cipherApi().getMember("AES").getAnInstantiation() and
exists(string keyLength, string blockMode |
exists(string keyLength, Cryptography::BlockMode blockMode |
// `OpenSSL::Cipher::AES.new('<keyLength-blockMode>')
exists(string arg0 |
arg0 = getStringArgument(call, 0) and
keyLength = arg0.splitAt("-", 0) and
blockMode = arg0.splitAt("-", 1).toUpperCase()
blockMode = getBlockModeFromCipherName(arg0)
)
or
// `OpenSSL::Cipher::AES.new(<keyLength>, '<blockMode>')`
@@ -418,7 +438,7 @@ private predicate cipherInstantiationAES(
call = cipherApi().getMember(mod).getAnInstantiation() and
// Canonical representation is `AES-<keyLength>`
blockAlgo = "AES-" + mod.suffix(3) and
exists(string blockMode |
exists(Cryptography::BlockMode blockMode |
if exists(getStringArgument(call, 0))
then
// `OpenSSL::Cipher::<blockAlgo>.new('<blockMode>')`
@@ -445,7 +465,7 @@ private predicate cipherInstantiationSpecific(
// Block ciphers with dedicated modules
exists(string blockAlgo | blockAlgo = ["BF", "CAST5", "DES", "IDEA", "RC2"] |
call = cipherApi().getMember(blockAlgo).getAnInstantiation() and
exists(string blockMode |
exists(Cryptography::BlockMode blockMode |
if exists(getStringArgument(call, 0))
then
// `OpenSSL::Cipher::<blockAlgo>.new('<blockMode>')`

View File

@@ -65,3 +65,8 @@ predicate isStrongPasswordHashingAlgorithm(string name) {
* Holds if `name` corresponds to a weak password hashing algorithm.
*/
predicate isWeakPasswordHashingAlgorithm(string name) { name = "EVPKDF" }
/**
* Holds if `name` corresponds to a stream cipher.
*/
predicate isStreamCipher(string name) { name = ["CHACHA", "RC4", "ARC4", "ARCFOUR", "RABBIT"] }