-
Notifications
You must be signed in to change notification settings - Fork 1.8k
Ruby: Add rb/weak-cryptographic-algorithm
query
#8421
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Ruby: Add rb/weak-cryptographic-algorithm
query
#8421
Conversation
QHelp previews: ruby/ql/src/queries/security/cwe-327/BrokenCryptoAlgorithm.qhelpUse of a broken or weak cryptographic algorithmUsing broken or weak cryptographic algorithms can leave data vulnerable to being decrypted or forged by an attacker. Many cryptographic algorithms provided by cryptography libraries are known to be weak, or flawed. Using such an algorithm means that encrypted or hashed data is less secure than it appears to be. RecommendationEnsure that you use a strong, modern cryptographic algorithm, such as AES-128 or RSA-2048. ExampleThe following code uses the require 'openssl'
class Encryptor
attr_accessor :secret_key
def encrypt_message_weak(message)
cipher = OpenSSL::Cipher.new('des') # BAD: weak encryption
cipher.encrypt
cipher.key = secret_key
cipher.update(message)
cipher.final
end
def encrypt_message_strong(message)
cipher = OpenSSL::Cipher::AES128.new # GOOD: strong encryption
cipher.encrypt
cipher.key = secret_key
cipher.update(message)
cipher.final
end
end References
|
QHelp previews: ruby/ql/src/queries/security/cwe-327/BrokenCryptoAlgorithm.qhelpUse of a broken or weak cryptographic algorithmUsing broken or weak cryptographic algorithms can leave data vulnerable to being decrypted or forged by an attacker. Many cryptographic algorithms provided by cryptography libraries are known to be weak, or flawed. Using such an algorithm means that encrypted or hashed data is less secure than it appears to be. RecommendationEnsure that you use a strong, modern cryptographic algorithm, such as AES-128 or RSA-2048. ExampleThe following code uses the require 'openssl'
class Encryptor
attr_accessor :secret_key
def encrypt_message_weak(message)
cipher = OpenSSL::Cipher.new('des') # BAD: weak encryption
cipher.encrypt
cipher.key = secret_key
cipher.update(message)
cipher.final
end
def encrypt_message_strong(message)
cipher = OpenSSL::Cipher::AES128.new # GOOD: strong encryption
cipher.encrypt
cipher.key = secret_key
cipher.update(message)
cipher.final
end
end References
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This looks good to me.
ruby/ql/lib/codeql/ruby/Concepts.qll
Outdated
@@ -762,3 +762,58 @@ module Logging { | |||
abstract DataFlow::Node getAnInput(); | |||
} | |||
} | |||
|
|||
/** | |||
* Provides models for cryptographic things. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Perhaps things
-> concepts
.
| | ||
cipher.matchesName(cipherName) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this can be moved to line 381 .
exists(string cipherName | cipher.matchesName(cipherName) |
...
or
...
)
// CBC is used by default | ||
cipherMode.isBlockMode("CBC") | ||
or | ||
// `OpenSSL::Cipher::AES` instantiations |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is quite a large block of text and I wonder if it would improve readability if split into smaller predicates.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've split this into 4 separate predicates that each cover a subset of cases, I think it's slightly clearer.
QHelp previews: ruby/ql/src/queries/security/cwe-327/BrokenCryptoAlgorithm.qhelpUse of a broken or weak cryptographic algorithmUsing broken or weak cryptographic algorithms can leave data vulnerable to being decrypted or forged by an attacker. Many cryptographic algorithms provided by cryptography libraries are known to be weak, or flawed. Using such an algorithm means that encrypted or hashed data is less secure than it appears to be. RecommendationEnsure that you use a strong, modern cryptographic algorithm, such as AES-128 or RSA-2048. ExampleThe following code uses the require 'openssl'
class Encryptor
attr_accessor :secret_key
def encrypt_message_weak(message)
cipher = OpenSSL::Cipher.new('des') # BAD: weak encryption
cipher.encrypt
cipher.key = secret_key
cipher.update(message)
cipher.final
end
def encrypt_message_strong(message)
cipher = OpenSSL::Cipher::AES128.new # GOOD: strong encryption
cipher.encrypt
cipher.key = secret_key
cipher.update(message)
cipher.final
end
end References
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry, I know you already had a review and were just looking for re-approval, but I have a couple of comments.
@@ -0,0 +1,18 @@ | |||
| broken_crypto.rb:4:8:4:34 | call to new | The cryptographic algorithm DES is broken or weak, and should not be used. | | |||
| broken_crypto.rb:8:1:8:18 | call to update | The cryptographic algorithm DES is broken or weak, and should not be used. | | |||
| broken_crypto.rb:12:8:12:43 | call to new | The cryptographic algorithm AES is broken or weak, and should not be used. | |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's a bit of a shame that this message doesn't mention the specific cipher mode that makes it weak. Would that be difficult to add?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, the inaccurate message here is not great. At the level of CryptographicOperation
, we have no concept of the block mode, so the weakness/strength of the operation is just a kind of black box. The solutions that I've considered are:
- Keeping
CryptographicAlgorithm
and the block mode separate, but introducing a properBlockMode
class with e.g. anisWeak()
predicate of its own.CryptographicOperation
could then have aBlockMode getBlockMode()
predicate rather than its ownisWeak()
predicate, and the query could check both the encryption algorithm and the block mode. - Include the block mode in the
CryptographicAlgorithm
, and add 2 predicates -isWeakEncryptionAlgorithm
andisWeakBlockMode
, to that class. ThenCryptographicOperation#isWeak()
could be removed.
I think I prefer 1
overall as it seems like the intention of the CryptographicAlgorithm
class (shared with JS and Python) is to represent the algorithm modulo any block mode. Do you have any preferences between these?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
1 sounds like a nice solution, if it's not too difficult to implement.
QHelp previews: ruby/ql/src/queries/security/cwe-327/BrokenCryptoAlgorithm.qhelpUse of a broken or weak cryptographic algorithmUsing broken or weak cryptographic algorithms can leave data vulnerable to being decrypted or forged by an attacker. Many cryptographic algorithms provided by cryptography libraries are known to be weak, or flawed. Using such an algorithm means that encrypted or hashed data is less secure than it appears to be. RecommendationEnsure that you use a strong, modern cryptographic algorithm, such as AES-128 or RSA-2048. ExampleThe following code uses the require 'openssl'
class Encryptor
attr_accessor :secret_key
def encrypt_message_weak(message)
cipher = OpenSSL::Cipher.new('des') # BAD: weak encryption
cipher.encrypt
cipher.key = secret_key
cipher.update(message)
cipher.final
end
def encrypt_message_strong(message)
cipher = OpenSSL::Cipher::AES128.new # GOOD: strong encryption
cipher.encrypt
cipher.key = secret_key
cipher.update(message)
cipher.final
end
end References
|
QHelp previews: ruby/ql/src/queries/security/cwe-327/BrokenCryptoAlgorithm.qhelpUse of a broken or weak cryptographic algorithmUsing broken or weak cryptographic algorithms can leave data vulnerable to being decrypted or forged by an attacker. Many cryptographic algorithms provided by cryptography libraries are known to be weak, or flawed. Using such an algorithm means that encrypted or hashed data is less secure than it appears to be. RecommendationEnsure that you use a strong, modern cryptographic algorithm, such as AES-128 or RSA-2048. ExampleThe following code uses the require 'openssl'
class Encryptor
attr_accessor :secret_key
def encrypt_message_weak(message)
cipher = OpenSSL::Cipher.new('des') # BAD: weak encryption
cipher.encrypt
cipher.key = secret_key
cipher.update(message)
cipher.final
end
def encrypt_message_strong(message)
cipher = OpenSSL::Cipher::AES128.new # GOOD: strong encryption
cipher.encrypt
cipher.key = secret_key
cipher.update(message)
cipher.final
end
end References
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM. I'll leave it up to you whether you address my comment about the block mode in the alert message.
I'll merge this as is and work on the block mode changes as a follow-up. |
Ports
py/weak-cryptographic-algorithm
to Ruby. Currently supportsOpenSSL
ciphers.This is generally similar, using the
Cryptography::CryptographicOperation
concept. There is a slight tweak in moving theisWeak()
predicate intoCryptographicOperation
rather than only having it onCryptographicAlgorithm
, which allows us to account for operations with ciphers that use a weak block mode (in practice, this meansECB
). TheCryptographicAlgorithm
only includes the block encryption algorithm itself, not the block mode in the context where the algorithm is used in a stream cipher.The side-effect of this is that the alert messages can currently be misleading, e.g. suggesting that the block encryption algorithm is weak when it is actually the block mode.
The best solutions to this that I can see are:
CryptographicAlgorithm
and the block mode separate, but introducing a properBlockMode
class with e.g. anisWeak()
predicate of its own.CryptographicOperation
could then have aBlockMode getBlockMode()
predicate rather than its ownisWeak()
predicate, and the query could check both the encryption algorithm and the block mode.CryptographicAlgorithm
, and add 2 predicates -isWeakEncryptionAlgorithm
andisWeakBlockMode
, to that class. ThenCryptographicOperation#isWeak()
could be removed.