Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit f92782d

Browse files
committed
Ruby: fix some cases where we assume that a CryptographicOperation is using CBC when it is not
1 parent c620fce commit f92782d

7 files changed

Lines changed: 47 additions & 6 deletions

File tree

javascript/ql/lib/semmle/javascript/security/CryptoAlgorithms.qll

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,8 @@ class EncryptionAlgorithm extends MkEncryptionAlgorithm, CryptographicAlgorithm
8181
override string getName() { result = name }
8282

8383
override predicate isWeak() { isWeak = true }
84+
85+
predicate isStreamCipher() { isStreamCipher(name) }
8486
}
8587

8688
/**

javascript/ql/lib/semmle/javascript/security/internal/CryptoAlgorithmNames.qll

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,3 +65,8 @@ predicate isStrongPasswordHashingAlgorithm(string name) {
6565
* Holds if `name` corresponds to a weak password hashing algorithm.
6666
*/
6767
predicate isWeakPasswordHashingAlgorithm(string name) { name = "EVPKDF" }
68+
69+
/**
70+
* Holds if `name` corresponds to a stream cipher.
71+
*/
72+
predicate isStreamCipher(string name) { name = ["CHACHA", "RC4", "ARC4", "ARCFOUR", "RABBIT"] }

python/ql/lib/semmle/python/concepts/CryptoAlgorithms.qll

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,8 @@ class EncryptionAlgorithm extends MkEncryptionAlgorithm, CryptographicAlgorithm
8181
override string getName() { result = name }
8282

8383
override predicate isWeak() { isWeak = true }
84+
85+
predicate isStreamCipher() { isStreamCipher(name) }
8486
}
8587

8688
/**

python/ql/lib/semmle/python/concepts/internal/CryptoAlgorithmNames.qll

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,3 +65,8 @@ predicate isStrongPasswordHashingAlgorithm(string name) {
6565
* Holds if `name` corresponds to a weak password hashing algorithm.
6666
*/
6767
predicate isWeakPasswordHashingAlgorithm(string name) { name = "EVPKDF" }
68+
69+
/**
70+
* Holds if `name` corresponds to a stream cipher.
71+
*/
72+
predicate isStreamCipher(string name) { name = ["CHACHA", "RC4", "ARC4", "ARCFOUR", "RABBIT"] }

ruby/ql/lib/codeql/ruby/security/CryptoAlgorithms.qll

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,8 @@ class EncryptionAlgorithm extends MkEncryptionAlgorithm, CryptographicAlgorithm
8181
override string getName() { result = name }
8282

8383
override predicate isWeak() { isWeak = true }
84+
85+
predicate isStreamCipher() { isStreamCipher(name) }
8486
}
8587

8688
/**

ruby/ql/lib/codeql/ruby/security/OpenSSL.qll

Lines changed: 26 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -370,6 +370,25 @@ private int getIntArgument(DataFlow::CallNode call, int i) {
370370
result = call.getArgument(i).asExpr().getConstantValue().getInt()
371371
}
372372

373+
bindingset[blockCipherName]
374+
private Cryptography::BlockMode getCandidateBlockModeFromCipherName(string blockCipherName) {
375+
result = blockCipherName.splitAt("-", [1, 2]).toUpperCase()
376+
}
377+
378+
/**
379+
* Gets the block mode specified as part of a block cipher name used to
380+
* instantiate an `OpenSSL::Cipher` instance. If the block mode is not
381+
* explicitly specified, this defaults to "CBC".
382+
*/
383+
bindingset[blockCipherName]
384+
private Cryptography::BlockMode getBlockModeFromCipherName(string blockCipherName) {
385+
// Extract the block mode from the cipher name
386+
result = getCandidateBlockModeFromCipherName(blockCipherName)
387+
or
388+
// Fall back on the OpenSSL default of CBC if the block mode is unspecified
389+
not exists(getCandidateBlockModeFromCipherName(blockCipherName)) and result = "CBC"
390+
}
391+
373392
/**
374393
* Holds if `call` is a call to `OpenSSL::Cipher.new` that instantiates a
375394
* `cipher` instance with mode `cipherMode`.
@@ -381,8 +400,9 @@ private predicate cipherInstantiationGeneric(
381400
// `OpenSSL::Cipher.new('<cipherName>')`
382401
call = cipherApi().getAnInstantiation() and
383402
cipherName = getStringArgument(call, 0) and
384-
// CBC is used by default
385-
cipherMode.isBlockMode("CBC")
403+
if cipher.getAlgorithm().isStreamCipher()
404+
then cipherMode = TStreamCipher()
405+
else cipherMode.isBlockMode(getBlockModeFromCipherName(cipherName))
386406
)
387407
}
388408

@@ -397,12 +417,12 @@ private predicate cipherInstantiationAES(
397417
exists(string cipherName | cipher.matchesName(cipherName) |
398418
// `OpenSSL::Cipher::AES` instantiations
399419
call = cipherApi().getMember("AES").getAnInstantiation() and
400-
exists(string keyLength, string blockMode |
420+
exists(string keyLength, Cryptography::BlockMode blockMode |
401421
// `OpenSSL::Cipher::AES.new('<keyLength-blockMode>')
402422
exists(string arg0 |
403423
arg0 = getStringArgument(call, 0) and
404424
keyLength = arg0.splitAt("-", 0) and
405-
blockMode = arg0.splitAt("-", 1).toUpperCase()
425+
blockMode = getBlockModeFromCipherName(arg0)
406426
)
407427
or
408428
// `OpenSSL::Cipher::AES.new(<keyLength>, '<blockMode>')`
@@ -418,7 +438,7 @@ private predicate cipherInstantiationAES(
418438
call = cipherApi().getMember(mod).getAnInstantiation() and
419439
// Canonical representation is `AES-<keyLength>`
420440
blockAlgo = "AES-" + mod.suffix(3) and
421-
exists(string blockMode |
441+
exists(Cryptography::BlockMode blockMode |
422442
if exists(getStringArgument(call, 0))
423443
then
424444
// `OpenSSL::Cipher::<blockAlgo>.new('<blockMode>')`
@@ -445,7 +465,7 @@ private predicate cipherInstantiationSpecific(
445465
// Block ciphers with dedicated modules
446466
exists(string blockAlgo | blockAlgo = ["BF", "CAST5", "DES", "IDEA", "RC2"] |
447467
call = cipherApi().getMember(blockAlgo).getAnInstantiation() and
448-
exists(string blockMode |
468+
exists(Cryptography::BlockMode blockMode |
449469
if exists(getStringArgument(call, 0))
450470
then
451471
// `OpenSSL::Cipher::<blockAlgo>.new('<blockMode>')`

ruby/ql/lib/codeql/ruby/security/internal/CryptoAlgorithmNames.qll

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,3 +65,8 @@ predicate isStrongPasswordHashingAlgorithm(string name) {
6565
* Holds if `name` corresponds to a weak password hashing algorithm.
6666
*/
6767
predicate isWeakPasswordHashingAlgorithm(string name) { name = "EVPKDF" }
68+
69+
/**
70+
* Holds if `name` corresponds to a stream cipher.
71+
*/
72+
predicate isStreamCipher(string name) { name = ["CHACHA", "RC4", "ARC4", "ARCFOUR", "RABBIT"] }

0 commit comments

Comments
 (0)