13
13
*
14
14
* The classification into strong and weak are based on Wikipedia, OWASP and google (2017).
15
15
*/
16
- private module AlgorithmNames {
16
+ module AlgorithmNames {
17
17
predicate isStrongBlockMode ( string name ) { name = [ "CCM" , "GCM" ] }
18
18
19
19
predicate isWeakBlockMode ( string name ) { name = "ECB" }
@@ -59,128 +59,7 @@ private module AlgorithmNames {
59
59
predicate isWeakPasswordHashingAlgorithm ( string name ) { name = "EVPKDF" }
60
60
}
61
61
62
- bindingset [ algorithmString]
63
- private string algorithmRegex ( string algorithmString ) {
64
- // Algorithms usually appear in names surrounded by characters that are not
65
- // alphabetical characters in the same case. This handles the upper and lower
66
- // case cases.
67
- result =
68
- "((^|.*[^A-Z])(" + algorithmString + ")([^A-Z].*|$))" +
69
- // or...
70
- "|" +
71
- // For lowercase, we want to be careful to avoid being confused by camelCase
72
- // hence we require two preceding uppercase letters to be sure of a case switch,
73
- // or a preceding non-alphabetic character
74
- "((^|.*[A-Z]{2}|.*[^a-zA-Z])(" + algorithmString .toLowerCase ( ) + ")([^a-z].*|$))"
75
- }
76
-
77
- private module OpenSSL {
78
- /**
79
- * A known `OpenSSL::Cipher`. Supported ciphers depend on the version of
80
- * `OpenSSL` installed on a system. In the general case, a name will include
81
- * the cipher name, the key length, and the block encryption mode.
82
- *
83
- * Note that since the cipher name itself always comes first in these names
84
- * and always uses a "-" to demark to block mode, we can safely uppercase
85
- * these names when checking against an `algorithmRegex`.
86
- *
87
- * See https://ruby-doc.org/stdlib-3.0.1/libdoc/openssl/rdoc/OpenSSL/Cipher.html
88
- */
89
- predicate isOpenSSLCipher ( string name ) {
90
- name =
91
- [
92
- "AES-128-CBC" , "AES-128-CBC-HMAC-SHA1" , "AES-128-CFB" , "AES-128-CFB1" , "AES-128-CFB8" ,
93
- "AES-128-CTR" , "AES-128-ECB" , "AES-128-OFB" , "AES-128-XTS" , "AES-192-CBC" , "AES-192-CFB" ,
94
- "AES-192-CFB1" , "AES-192-CFB8" , "AES-192-CTR" , "AES-192-ECB" , "AES-192-OFB" , "AES-256-CBC" ,
95
- "AES-256-CBC-HMAC-SHA1" , "AES-256-CFB" , "AES-256-CFB1" , "AES-256-CFB8" , "AES-256-CTR" ,
96
- "AES-256-ECB" , "AES-256-OFB" , "AES-256-XTS" , "AES128" , "AES192" , "AES256" , "BF" , "BF-CBC" ,
97
- "BF-CFB" , "BF-ECB" , "BF-OFB" , "CAMELLIA-128-CBC" , "CAMELLIA-128-CFB" , "CAMELLIA-128-CFB1" ,
98
- "CAMELLIA-128-CFB8" , "CAMELLIA-128-ECB" , "CAMELLIA-128-OFB" , "CAMELLIA-192-CBC" ,
99
- "CAMELLIA-192-CFB" , "CAMELLIA-192-CFB1" , "CAMELLIA-192-CFB8" , "CAMELLIA-192-ECB" ,
100
- "CAMELLIA-192-OFB" , "CAMELLIA-256-CBC" , "CAMELLIA-256-CFB" , "CAMELLIA-256-CFB1" ,
101
- "CAMELLIA-256-CFB8" , "CAMELLIA-256-ECB" , "CAMELLIA-256-OFB" , "CAMELLIA128" , "CAMELLIA192" ,
102
- "CAMELLIA256" , "CAST" , "CAST-cbc" , "CAST5-CBC" , "CAST5-CFB" , "CAST5-ECB" , "CAST5-OFB" ,
103
- "ChaCha" , "DES" , "DES-CBC" , "DES-CFB" , "DES-CFB1" , "DES-CFB8" , "DES-ECB" , "DES-EDE" ,
104
- "DES-EDE-CBC" , "DES-EDE-CFB" , "DES-EDE-OFB" , "DES-EDE3" , "DES-EDE3-CBC" , "DES-EDE3-CFB" ,
105
- "DES-EDE3-CFB1" , "DES-EDE3-CFB8" , "DES-EDE3-OFB" , "DES-OFB" , "DES3" , "DESX" , "DESX-CBC" ,
106
- "GOST 28147-89" , "RC2" , "RC2-40-CBC" , "RC2-64-CBC" , "RC2-CBC" , "RC2-CFB" , "RC2-ECB" ,
107
- "RC2-OFB" , "RC4" , "RC4-40" , "RC4-HMAC-MD5" , "aes-128-cbc" , "aes-128-cbc-hmac-sha1" ,
108
- "aes-128-cfb" , "aes-128-cfb1" , "aes-128-cfb8" , "aes-128-ctr" , "aes-128-ecb" , "aes-128-gcm" ,
109
- "aes-128-ofb" , "aes-128-xts" , "aes-192-cbc" , "aes-192-cfb" , "aes-192-cfb1" , "aes-192-cfb8" ,
110
- "aes-192-ctr" , "aes-192-ecb" , "aes-192-gcm" , "aes-192-ofb" , "aes-256-cbc" ,
111
- "aes-256-cbc-hmac-sha1" , "aes-256-cfb" , "aes-256-cfb1" , "aes-256-cfb8" , "aes-256-ctr" ,
112
- "aes-256-ecb" , "aes-256-gcm" , "aes-256-ofb" , "aes-256-xts" , "aes128" , "aes192" , "aes256" ,
113
- "bf" , "bf-cbc" , "bf-cfb" , "bf-ecb" , "bf-ofb" , "blowfish" , "camellia-128-cbc" ,
114
- "camellia-128-cfb" , "camellia-128-cfb1" , "camellia-128-cfb8" , "camellia-128-ecb" ,
115
- "camellia-128-ofb" , "camellia-192-cbc" , "camellia-192-cfb" , "camellia-192-cfb1" ,
116
- "camellia-192-cfb8" , "camellia-192-ecb" , "camellia-192-ofb" , "camellia-256-cbc" ,
117
- "camellia-256-cfb" , "camellia-256-cfb1" , "camellia-256-cfb8" , "camellia-256-ecb" ,
118
- "camellia-256-ofb" , "camellia128" , "camellia192" , "camellia256" , "cast" , "cast-cbc" ,
119
- "cast5-cbc" , "cast5-cfb" , "cast5-ecb" , "cast5-ofb" , "chacha" , "des" , "des-cbc" , "des-cfb" ,
120
- "des-cfb1" , "des-cfb8" , "des-ecb" , "des-ede" , "des-ede-cbc" , "des-ede-cfb" , "des-ede-ofb" ,
121
- "des-ede3" , "des-ede3-cbc" , "des-ede3-cfb" , "des-ede3-cfb1" , "des-ede3-cfb8" ,
122
- "des-ede3-ofb" , "des-ofb" , "des3" , "desx" , "desx-cbc" , "gost89" , "gost89-cnt" , "gost89-ecb" ,
123
- "id-aes128-GCM" , "id-aes192-GCM" , "id-aes256-GCM" , "rc2" , "rc2-40-cbc" , "rc2-64-cbc" ,
124
- "rc2-cbc" , "rc2-cfb" , "rc2-ecb" , "rc2-ofb" , "rc4" , "rc4-40" , "rc4-hmac-md5"
125
- ]
126
- }
127
-
128
- predicate isWeakOpenSSLCipher ( string name ) {
129
- isOpenSSLCipher ( name ) and
130
- name .toUpperCase ( ) .regexpMatch ( getInsecureAlgorithmRegex ( ) )
131
- }
132
-
133
- predicate isStrongOpenSSLCipher ( string name ) {
134
- isOpenSSLCipher ( name ) and
135
- name .toUpperCase ( ) .regexpMatch ( getSecureAlgorithmRegex ( ) ) and
136
- // exclude algorithms that include a weak component
137
- not name .toUpperCase ( ) .regexpMatch ( getInsecureAlgorithmRegex ( ) )
138
- }
139
- }
140
-
141
62
private import AlgorithmNames
142
- private import OpenSSL
143
-
144
- private string rankedInsecureAlgorithm ( int i ) {
145
- // In this case we know these are being used for encryption, so we want to match
146
- // weak hash algorithms and block modes as well.
147
- result =
148
- rank [ i ] ( string s |
149
- isWeakEncryptionAlgorithm ( s ) or isWeakHashingAlgorithm ( s ) or isWeakBlockMode ( s )
150
- )
151
- }
152
-
153
- private string insecureAlgorithmString ( int i ) {
154
- i = 1 and result = rankedInsecureAlgorithm ( i )
155
- or
156
- result = rankedInsecureAlgorithm ( i ) + "|" + insecureAlgorithmString ( i - 1 )
157
- }
158
-
159
- /**
160
- * Gets the regular expression used for matching strings that look like they
161
- * contain an algorithm that is known to be insecure.
162
- */
163
- private string getInsecureAlgorithmRegex ( ) {
164
- result = algorithmRegex ( insecureAlgorithmString ( max ( int i | exists ( rankedInsecureAlgorithm ( i ) ) ) ) )
165
- }
166
-
167
- private string rankedSecureAlgorithm ( int i ) {
168
- result = rank [ i ] ( string s | isStrongEncryptionAlgorithm ( s ) )
169
- }
170
-
171
- private string secureAlgorithmString ( int i ) {
172
- i = 1 and result = rankedSecureAlgorithm ( i )
173
- or
174
- result = rankedSecureAlgorithm ( i ) + "|" + secureAlgorithmString ( i - 1 )
175
- }
176
-
177
- /**
178
- * Gets a regular expression for matching strings that look like they
179
- * contain an algorithm that is known to be secure.
180
- */
181
- string getSecureAlgorithmRegex ( ) {
182
- result = algorithmRegex ( secureAlgorithmString ( max ( int i | exists ( rankedSecureAlgorithm ( i ) ) ) ) )
183
- }
184
63
185
64
/**
186
65
* A cryptographic algorithm.
@@ -200,11 +79,6 @@ private newtype TCryptographicAlgorithm =
200
79
isStrongPasswordHashingAlgorithm ( name ) and isWeak = false
201
80
or
202
81
isWeakPasswordHashingAlgorithm ( name ) and isWeak = true
203
- } or
204
- MkOpenSSLCipher ( string name , boolean isWeak ) {
205
- isStrongOpenSSLCipher ( name ) and isWeak = false
206
- or
207
- isWeakOpenSSLCipher ( name ) and isWeak = true
208
82
}
209
83
210
84
/**
@@ -277,18 +151,3 @@ class PasswordHashingAlgorithm extends MkPasswordHashingAlgorithm, Cryptographic
277
151
278
152
override predicate isWeak ( ) { isWeak = true }
279
153
}
280
-
281
- /**
282
- * A known OpenSSL cipher. This may include information about the block
283
- * encryption mode, which can affect if the cipher is marked as being weak.
284
- */
285
- class OpenSSLCipher extends MkOpenSSLCipher , CryptographicAlgorithm {
286
- string name ;
287
- boolean isWeak ;
288
-
289
- OpenSSLCipher ( ) { this = MkOpenSSLCipher ( name , isWeak ) }
290
-
291
- override string getName ( ) { result = name }
292
-
293
- override predicate isWeak ( ) { isWeak = true }
294
- }
0 commit comments