Skip to content

Commit 152d8ba

Browse files
committed
update the cryptoLibraries to use dataflow nodes
1 parent 8ade3a7 commit 152d8ba

File tree

3 files changed

+64
-66
lines changed

3 files changed

+64
-66
lines changed

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

Lines changed: 62 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,11 @@ import semmle.javascript.security.CryptoAlgorithms
88
/**
99
* An application of a cryptographic algorithm.
1010
*/
11-
abstract class CryptographicOperation extends Expr {
11+
abstract class CryptographicOperation extends DataFlow::Node {
1212
/**
1313
* Gets the input the algorithm is used on, e.g. the plain text input to be encrypted.
1414
*/
15-
abstract Expr getInput();
15+
abstract DataFlow::Node getInput();
1616

1717
/**
1818
* Gets the applied algorithm.
@@ -58,8 +58,8 @@ class CryptographicKeyCredentialsExpr extends CredentialsExpr {
5858
* A model of the asmCrypto library.
5959
*/
6060
private module AsmCrypto {
61-
private class Apply extends CryptographicOperation {
62-
Expr input;
61+
private class Apply extends CryptographicOperation instanceof DataFlow::CallNode {
62+
DataFlow::Node input;
6363
CryptographicAlgorithm algorithm; // non-functional
6464

6565
Apply() {
@@ -73,17 +73,15 @@ private module AsmCrypto {
7373
* ```
7474
*/
7575

76-
exists(DataFlow::CallNode mce | this = mce.asExpr() |
77-
exists(DataFlow::SourceNode asmCrypto, string algorithmName |
78-
asmCrypto = DataFlow::globalVarRef("asmCrypto") and
79-
algorithm.matchesName(algorithmName) and
80-
mce = asmCrypto.getAPropertyRead(algorithmName).getAMemberCall(_) and
81-
input = mce.getAnArgument().asExpr()
82-
)
76+
exists(DataFlow::SourceNode asmCrypto, string algorithmName |
77+
asmCrypto = DataFlow::globalVarRef("asmCrypto") and
78+
algorithm.matchesName(algorithmName) and
79+
this = asmCrypto.getAPropertyRead(algorithmName).getAMemberCall(_) and
80+
input = this.getAnArgument()
8381
)
8482
}
8583

86-
override Expr getInput() { result = input }
84+
override DataFlow::Node getInput() { result = input }
8785

8886
override CryptographicAlgorithm getAlgorithm() { result = algorithm }
8987
}
@@ -97,9 +95,8 @@ private module BrowserIdCrypto {
9795
Key() { this = any(Apply apply).getKey() }
9896
}
9997

100-
private class Apply extends CryptographicOperation {
98+
private class Apply extends CryptographicOperation instanceof DataFlow::MethodCallNode {
10199
CryptographicAlgorithm algorithm; // non-functional
102-
MethodCallExpr mce;
103100

104101
Apply() {
105102
/*
@@ -118,7 +115,6 @@ private module BrowserIdCrypto {
118115
* ```
119116
*/
120117

121-
this = mce and
122118
exists(
123119
DataFlow::SourceNode mod, DataFlow::Node algorithmNameNode, DataFlow::CallNode keygen,
124120
DataFlow::FunctionNode callback
@@ -128,15 +124,15 @@ private module BrowserIdCrypto {
128124
algorithmNameNode = keygen.getOptionArgument(0, "algorithm") and
129125
algorithm.matchesName(algorithmNameNode.getStringValue()) and
130126
callback = keygen.getCallback(1) and
131-
this = mod.getAMemberCall("sign").asExpr()
127+
this = mod.getAMemberCall("sign")
132128
)
133129
}
134130

135-
override Expr getInput() { result = mce.getArgument(0) }
131+
override DataFlow::Node getInput() { result = super.getArgument(0) }
136132

137133
override CryptographicAlgorithm getAlgorithm() { result = algorithm }
138134

139-
DataFlow::Node getKey() { result.asExpr() = mce.getArgument(1) }
135+
DataFlow::Node getKey() { result = super.getArgument(1) }
140136
}
141137
}
142138

@@ -217,14 +213,12 @@ private module NodeJSCrypto {
217213
override predicate isSymmetricKey() { none() }
218214
}
219215

220-
private class Apply extends CryptographicOperation, MethodCallExpr {
216+
private class Apply extends CryptographicOperation instanceof DataFlow::MethodCallNode {
221217
InstantiatedAlgorithm instantiation;
222218

223-
Apply() {
224-
this = instantiation.getAMethodCall(any(string m | m = "update" or m = "write")).asExpr()
225-
}
219+
Apply() { this = instantiation.getAMethodCall(any(string m | m = "update" or m = "write")) }
226220

227-
override Expr getInput() { result = this.getArgument(0) }
221+
override DataFlow::Node getInput() { result = super.getArgument(0) }
228222

229223
override CryptographicAlgorithm getAlgorithm() { result = instantiation.getAlgorithm() }
230224
}
@@ -260,7 +254,7 @@ private module CryptoJS {
260254
/**
261255
* Matches `CryptoJS.<algorithmName>` and `require("crypto-js/<algorithmName>")`
262256
*/
263-
private DataFlow::SourceNode getAlgorithmExpr(CryptographicAlgorithm algorithm) {
257+
private DataFlow::SourceNode getAlgorithmNode(CryptographicAlgorithm algorithm) {
264258
exists(string algorithmName | algorithm.matchesName(algorithmName) |
265259
exists(DataFlow::SourceNode mod | mod = DataFlow::moduleImport("crypto-js") |
266260
result = mod.getAPropertyRead(algorithmName) or
@@ -274,7 +268,9 @@ private module CryptoJS {
274268
)
275269
}
276270

277-
private DataFlow::CallNode getEncryptionApplication(Expr input, CryptographicAlgorithm algorithm) {
271+
private DataFlow::CallNode getEncryptionApplication(
272+
DataFlow::Node input, CryptographicAlgorithm algorithm
273+
) {
278274
/*
279275
* ```
280276
* var CryptoJS = require("crypto-js");
@@ -288,11 +284,13 @@ private module CryptoJS {
288284
* Also matches where `CryptoJS.<algorithmName>` has been replaced by `require("crypto-js/<algorithmName>")`
289285
*/
290286

291-
result = getAlgorithmExpr(algorithm).getAMemberCall("encrypt") and
292-
input = result.getArgument(0).asExpr()
287+
result = getAlgorithmNode(algorithm).getAMemberCall("encrypt") and
288+
input = result.getArgument(0)
293289
}
294290

295-
private DataFlow::CallNode getDirectApplication(Expr input, CryptographicAlgorithm algorithm) {
291+
private DataFlow::CallNode getDirectApplication(
292+
DataFlow::Node input, CryptographicAlgorithm algorithm
293+
) {
296294
/*
297295
* ```
298296
* var CryptoJS = require("crypto-js");
@@ -307,28 +305,28 @@ private module CryptoJS {
307305
* Also matches where `CryptoJS.<algorithmName>` has been replaced by `require("crypto-js/<algorithmName>")`
308306
*/
309307

310-
result = getAlgorithmExpr(algorithm).getACall() and
311-
input = result.getArgument(0).asExpr()
308+
result = getAlgorithmNode(algorithm).getACall() and
309+
input = result.getArgument(0)
312310
}
313311

314312
private class Apply extends CryptographicOperation {
315-
Expr input;
313+
DataFlow::Node input;
316314
CryptographicAlgorithm algorithm; // non-functional
317315

318316
Apply() {
319-
this = getEncryptionApplication(input, algorithm).asExpr() or
320-
this = getDirectApplication(input, algorithm).asExpr()
317+
this = getEncryptionApplication(input, algorithm) or
318+
this = getDirectApplication(input, algorithm)
321319
}
322320

323-
override Expr getInput() { result = input }
321+
override DataFlow::Node getInput() { result = input }
324322

325323
override CryptographicAlgorithm getAlgorithm() { result = algorithm }
326324
}
327325

328326
private class Key extends CryptographicKey {
329327
Key() {
330328
exists(DataFlow::SourceNode e, CryptographicAlgorithm algorithm |
331-
e = getAlgorithmExpr(algorithm)
329+
e = getAlgorithmNode(algorithm)
332330
|
333331
exists(string name |
334332
name = "encrypt" or
@@ -351,7 +349,7 @@ private module CryptoJS {
351349
CreateKey() {
352350
// var key = CryptoJS.PBKDF2(password, salt, { keySize: 8 });
353351
this =
354-
getAlgorithmExpr(any(CryptographicAlgorithm algo | algo.getName() = algorithm)).getACall() and
352+
getAlgorithmNode(any(CryptographicAlgorithm algo | algo.getName() = algorithm)).getACall() and
355353
optionArg = 2
356354
or
357355
// var key = CryptoJS.algo.PBKDF2.create({ keySize: 8 });
@@ -378,8 +376,8 @@ private module CryptoJS {
378376
* A model of the TweetNaCl library.
379377
*/
380378
private module TweetNaCl {
381-
private class Apply extends CryptographicOperation instanceof MethodCallExpr {
382-
Expr input;
379+
private class Apply extends CryptographicOperation instanceof DataFlow::CallNode {
380+
DataFlow::Node input;
383381
CryptographicAlgorithm algorithm;
384382

385383
Apply() {
@@ -400,12 +398,12 @@ private module TweetNaCl {
400398
name = "sign" and algorithm.matchesName("ed25519")
401399
|
402400
(mod = DataFlow::moduleImport("nacl") or mod = DataFlow::moduleImport("nacl-fast")) and
403-
this = mod.getAMemberCall(name).asExpr() and
401+
this = mod.getAMemberCall(name) and
404402
super.getArgument(0) = input
405403
)
406404
}
407405

408-
override Expr getInput() { result = input }
406+
override DataFlow::Node getInput() { result = input }
409407

410408
override CryptographicAlgorithm getAlgorithm() { result = algorithm }
411409
}
@@ -421,7 +419,7 @@ private module HashJs {
421419
* - `require("hash.js/lib/hash/<algorithmName>")`()
422420
* - `require("hash.js/lib/hash/sha/<sha-algorithm-suffix>")`()
423421
*/
424-
private DataFlow::CallNode getAlgorithmExpr(CryptographicAlgorithm algorithm) {
422+
private DataFlow::CallNode getAlgorithmNode(CryptographicAlgorithm algorithm) {
425423
exists(string algorithmName | algorithm.matchesName(algorithmName) |
426424
result = DataFlow::moduleMember("hash.js", algorithmName).getACall()
427425
or
@@ -438,8 +436,8 @@ private module HashJs {
438436
)
439437
}
440438

441-
private class Apply extends CryptographicOperation instanceof MethodCallExpr {
442-
Expr input;
439+
private class Apply extends CryptographicOperation instanceof DataFlow::CallNode {
440+
DataFlow::Node input;
443441
CryptographicAlgorithm algorithm; // non-functional
444442

445443
Apply() {
@@ -456,11 +454,11 @@ private module HashJs {
456454
* Also matches where `hash.<algorithmName>()` has been replaced by a more specific require a la `require("hash.js/lib/hash/sha/512")`
457455
*/
458456

459-
this = getAlgorithmExpr(algorithm).getAMemberCall("update").asExpr() and
457+
this = getAlgorithmNode(algorithm).getAMemberCall("update") and
460458
input = super.getArgument(0)
461459
}
462460

463-
override Expr getInput() { result = input }
461+
override DataFlow::Node getInput() { result = input }
464462

465463
override CryptographicAlgorithm getAlgorithm() { result = algorithm }
466464
}
@@ -492,7 +490,7 @@ private module Forge {
492490
// `require('forge').cipher.createCipher("3DES-CBC").update("secret", "key");`
493491
(createName = "createCipher" or createName = "createDecipher") and
494492
this = mod.getAPropertyRead("cipher").getAMemberCall(createName) and
495-
this.getArgument(0).asExpr().mayHaveStringValue(cipherName) and
493+
this.getArgument(0).mayHaveStringValue(cipherName) and
496494
cipherName = cipherPrefix + "-" + cipherSuffix and
497495
cipherSuffix = ["CBC", "CFB", "CTR", "ECB", "GCM", "OFB"] and
498496
algorithmName = cipherPrefix and
@@ -531,19 +529,19 @@ private module Forge {
531529
override CryptographicAlgorithm getAlgorithm() { result = algorithm }
532530
}
533531

534-
private class Apply extends CryptographicOperation instanceof MethodCallExpr {
535-
Expr input;
532+
private class Apply extends CryptographicOperation instanceof DataFlow::CallNode {
533+
DataFlow::Node input;
536534
CryptographicAlgorithm algorithm; // non-functional
537535

538536
Apply() {
539537
exists(Cipher cipher |
540-
this = cipher.getAMemberCall("update").asExpr() and
538+
this = cipher.getAMemberCall("update") and
541539
super.getArgument(0) = input and
542540
algorithm = cipher.getAlgorithm()
543541
)
544542
}
545543

546-
override Expr getInput() { result = input }
544+
override DataFlow::Node getInput() { result = input }
547545

548546
override CryptographicAlgorithm getAlgorithm() { result = algorithm }
549547
}
@@ -590,21 +588,21 @@ private module Forge {
590588
* A model of the md5 library.
591589
*/
592590
private module Md5 {
593-
private class Apply extends CryptographicOperation instanceof CallExpr {
594-
Expr input;
591+
private class Apply extends CryptographicOperation instanceof DataFlow::CallNode {
592+
DataFlow::Node input;
595593
CryptographicAlgorithm algorithm;
596594

597595
Apply() {
598596
// `require("md5")("message");`
599597
exists(DataFlow::SourceNode mod |
600598
mod = DataFlow::moduleImport("md5") and
601599
algorithm.matchesName("MD5") and
602-
this = mod.getACall().asExpr() and
600+
this = mod.getACall() and
603601
super.getArgument(0) = input
604602
)
605603
}
606604

607-
override Expr getInput() { result = input }
605+
override DataFlow::Node getInput() { result = input }
608606

609607
override CryptographicAlgorithm getAlgorithm() { result = algorithm }
610608
}
@@ -614,8 +612,8 @@ private module Md5 {
614612
* A model of the bcrypt, bcryptjs, bcrypt-nodejs libraries.
615613
*/
616614
private module Bcrypt {
617-
private class Apply extends CryptographicOperation instanceof MethodCallExpr {
618-
Expr input;
615+
private class Apply extends CryptographicOperation instanceof DataFlow::CallNode {
616+
DataFlow::Node input;
619617
CryptographicAlgorithm algorithm;
620618

621619
Apply() {
@@ -632,12 +630,12 @@ private module Bcrypt {
632630
methodName = "hashSync"
633631
) and
634632
mod = DataFlow::moduleImport(moduleName) and
635-
this = mod.getAMemberCall(methodName).asExpr() and
633+
this = mod.getAMemberCall(methodName) and
636634
super.getArgument(0) = input
637635
)
638636
}
639637

640-
override Expr getInput() { result = input }
638+
override DataFlow::Node getInput() { result = input }
641639

642640
override CryptographicAlgorithm getAlgorithm() { result = algorithm }
643641
}
@@ -647,23 +645,23 @@ private module Bcrypt {
647645
* A model of the hasha library.
648646
*/
649647
private module Hasha {
650-
private class Apply extends CryptographicOperation instanceof CallExpr {
651-
Expr input;
648+
private class Apply extends CryptographicOperation instanceof DataFlow::CallNode {
649+
DataFlow::Node input;
652650
CryptographicAlgorithm algorithm;
653651

654652
Apply() {
655653
// `require('hasha')('unicorn', { algorithm: "md5" });`
656-
exists(DataFlow::SourceNode mod, string algorithmName, Expr algorithmNameNode |
654+
exists(DataFlow::SourceNode mod, string algorithmName, DataFlow::Node algorithmNameNode |
657655
mod = DataFlow::moduleImport("hasha") and
658-
this = mod.getACall().asExpr() and
656+
this = mod.getACall() and
659657
super.getArgument(0) = input and
660658
algorithm.matchesName(algorithmName) and
661-
super.hasOptionArgument(1, "algorithm", algorithmNameNode) and
659+
super.getOptionArgument(1, "algorithm") = algorithmNameNode and
662660
algorithmNameNode.mayHaveStringValue(algorithmName)
663661
)
664662
}
665663

666-
override Expr getInput() { result = input }
664+
override DataFlow::Node getInput() { result = input }
667665

668666
override CryptographicAlgorithm getAlgorithm() { result = algorithm }
669667
}

javascript/ql/lib/semmle/javascript/security/dataflow/BrokenCryptoAlgorithmCustomizations.qll

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ module BrokenCryptoAlgorithm {
4444
WeakCryptographicOperationSink() {
4545
exists(CryptographicOperation application |
4646
application.getAlgorithm().isWeak() and
47-
this.asExpr() = application.getInput()
47+
this = application.getInput()
4848
)
4949
}
5050
}

javascript/ql/lib/semmle/javascript/security/dataflow/InsufficientPasswordHashCustomizations.qll

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ module InsufficientPasswordHash {
5050
application.getAlgorithm().isWeak() or
5151
not application.getAlgorithm() instanceof PasswordHashingAlgorithm
5252
|
53-
this.asExpr() = application.getInput()
53+
this = application.getInput()
5454
)
5555
}
5656
}

0 commit comments

Comments
 (0)