Skip to content

Commit 028799d

Browse files
committed
implement a simple InsufficientKeySize query
1 parent 7a9315f commit 028799d

File tree

5 files changed

+101
-0
lines changed

5 files changed

+101
-0
lines changed

javascript/ql/lib/semmle/javascript/frameworks/CryptoLibraries.qll

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,26 @@ abstract class CryptographicOperation extends Expr {
2525
*/
2626
abstract class CryptographicKey extends DataFlow::ValueNode { }
2727

28+
/**
29+
* The creation of a cryptographic key.
30+
*/
31+
abstract class CryptographicKeyCreation extends DataFlow::Node {
32+
/**
33+
* Gets the algorithm used to create the key.
34+
*/
35+
abstract CryptographicAlgorithm getAlgorithm();
36+
37+
/**
38+
* Gets the size of the key.
39+
*/
40+
abstract int getSize();
41+
42+
/**
43+
* Gets whether the key is symmetric.
44+
*/
45+
abstract predicate isSymmetricKey();
46+
}
47+
2848
/**
2949
* A key used in a cryptographic algorithm, viewed as a `CredentialsExpr`.
3050
*/
@@ -151,6 +171,39 @@ private module NodeJSCrypto {
151171
CryptographicAlgorithm getAlgorithm() { result = algorithm }
152172
}
153173

174+
private class CreateKey extends CryptographicKeyCreation, DataFlow::CallNode {
175+
boolean symmetric;
176+
177+
CreateKey() {
178+
// crypto.generateKey(type, options, callback)
179+
// crypto.generateKeyPair(type, options, callback)
180+
// crypto.generateKeyPairSync(type, options)
181+
// crypto.generateKeySync(type, options)
182+
exists(DataFlow::SourceNode mod, string keyType |
183+
keyType = "Key" and symmetric = true
184+
or
185+
keyType = "KeyPair" and symmetric = false
186+
|
187+
mod = DataFlow::moduleImport("crypto") and
188+
this = mod.getAMemberCall("generate" + keyType + ["", "Sync"])
189+
)
190+
}
191+
192+
override CryptographicAlgorithm getAlgorithm() {
193+
result.matchesName(getArgument(0).getStringValue())
194+
}
195+
196+
override int getSize() {
197+
symmetric = true and
198+
result = getOptionArgument(1, "length").getIntValue()
199+
or
200+
symmetric = false and
201+
result = getOptionArgument(1, "modulusLength").getIntValue()
202+
}
203+
204+
override predicate isSymmetricKey() { symmetric = true }
205+
}
206+
154207
private class Apply extends CryptographicOperation, MethodCallExpr {
155208
InstantiatedAlgorithm instantiation;
156209

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
/**
2+
* @name Use of a weak cryptographic key
3+
* @description Using a weak cryptographic key can allow an attacker to compromise security.
4+
* @kind problem
5+
* @problem.severity warning
6+
* @security-severity 7.5
7+
* @precision high
8+
* @id js/insufficient-key-size
9+
* @tags security
10+
* external/cwe/cwe-326
11+
*/
12+
13+
import javascript
14+
15+
from CryptographicKeyCreation key, int size, string msg, string algo
16+
where
17+
size = key.getSize() and
18+
(
19+
algo = key.getAlgorithm() + " "
20+
or
21+
not exists(key.getAlgorithm()) and algo = ""
22+
) and
23+
(
24+
size < 128 and
25+
key.isSymmetricKey() and
26+
msg =
27+
"Creation of an symmetric " + algo + "key uses " + size +
28+
" bits, which is below 128 and considered breakable."
29+
or
30+
size < 2048 and
31+
not key.isSymmetricKey() and
32+
msg =
33+
"Creation of an asymmetric " + algo + "key uses " + size +
34+
" bits, which is below 2048 and considered breakable."
35+
)
36+
select key, msg
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
| tst.js:3:14:3:71 | crypto. ... 1024 }) | Creation of an asymmetric RSA key uses 1024 bits, which is below 2048 and considered breakable. |
2+
| tst.js:7:14:7:59 | crypto. ... : 64 }) | Creation of an symmetric key uses 64 bits, which is below 128 and considered breakable. |
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Security/CWE-326/InsufficientKeySize.ql
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
const crypto = require("crypto");
2+
3+
const bad1 = crypto.generateKeyPairSync("rsa", { modulusLength: 1024 }); // NOT OK
4+
5+
const good1 = crypto.generateKeyPairSync("rsa", { modulusLength: 4096 }); // OK
6+
7+
const bad2 = crypto.generateKeySync("hmac", { length: 64 }); // NOT OK
8+
9+
const good2 = crypto.generateKeySync("aes", { length: 256 }); // OK

0 commit comments

Comments
 (0)