Skip to content

Commit 0e2d2f8

Browse files
author
Esben Sparre Andreasen
committed
JS: whitelist some hardcoded dummy-passwords in two queries
1 parent aa3f4a7 commit 0e2d2f8

File tree

7 files changed

+65
-5
lines changed

7 files changed

+65
-5
lines changed

javascript/ql/src/Security/CWE-313/PasswordInConfigurationFile.ql

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313

1414
import javascript
1515
import semmle.javascript.RestrictedLocations
16+
import semmle.javascript.security.SensitiveActions
1617

1718
/**
1819
* Holds if some JSON or YAML file contains a property with name `key`
@@ -56,7 +57,8 @@ where
5657
key.toLowerCase() = "password" and
5758
pwd = val and
5859
// exclude interpolations of environment variables
59-
not val.regexpMatch("\\$.*|%.*%")
60+
not val.regexpMatch("\\$.*|%.*%") and
61+
not PasswordHeuristics::isDummyPassword(val)
6062
or
6163
key.toLowerCase() != "readme" and
6264
// look for `password=...`, but exclude `password=;`, `password="$(...)"`,

javascript/ql/src/Security/CWE-798/HardcodedCredentials.ql

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,21 @@ where
2222
// use source value in message if it's available
2323
if source.getNode().asExpr() instanceof ConstantString
2424
then
25-
value = "The hard-coded value \"" + source.getNode().getStringValue() +
26-
"\""
25+
exists(string val, Sink sinkNode |
26+
sinkNode = sink.getNode().(Sink) and
27+
val = source.getNode().getStringValue()
28+
|
29+
(
30+
(
31+
sinkNode.(DefaultCredentialsSink).getKind() = "password" or
32+
sinkNode.(DefaultCredentialsSink).getKind() = "key"
33+
)
34+
implies
35+
// exclude dummy passwords
36+
not PasswordHeuristics::isDummyPassword(val)
37+
) and
38+
value = "The hard-coded value \"" + val + "\""
39+
)
2740
else value = "This hard-coded value"
2841
select source.getNode(), source, sink, value + " is used as $@.", sink.getNode(),
2942
sink.getNode().(Sink).getKind()

javascript/ql/src/semmle/javascript/security/SensitiveActions.qll

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -245,3 +245,21 @@ class CleartextPasswordExpr extends SensitiveExpr {
245245

246246
override SensitiveExpr::Classification getClassification() { none() }
247247
}
248+
249+
/**
250+
* Provides heuristics for classifying passwords.
251+
*/
252+
module PasswordHeuristics {
253+
/**
254+
* Holds if `password` looks like a deliberately weak password that the user should change.
255+
*/
256+
bindingset[password]
257+
predicate isDummyPassword(string password) {
258+
password.length() < 4
259+
or
260+
exists(string normalized | normalized = password.toLowerCase() |
261+
count(normalized.charAt(_)) = 1 or
262+
normalized.regexpMatch(".*(pass|test|sample|example|secret|root|admin|user|change|auth).*")
263+
)
264+
}
265+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
| | true |
2+
| XXXXXXXX | true |
3+
| abcdefgh | false |
4+
| admin | true |
5+
| change_me | true |
6+
| example_password | true |
7+
| insert-auth-from-gui | true |
8+
| root | true |
9+
| sOKY6ccizpmvF*32so%Q | false |
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
import javascript
2+
import semmle.javascript.security.SensitiveActions
3+
4+
string getASamplePassword() {
5+
result = "abcdefgh" or
6+
result = "sOKY6ccizpmvF*32so%Q" or
7+
result = "XXXXXXXX" or
8+
result = "example_password" or
9+
result = "change_me" or
10+
result = "" or
11+
result = "insert-auth-from-gui" or
12+
result = "admin" or
13+
result = "root"
14+
}
15+
16+
from string password, boolean isDummy
17+
where
18+
password = getASamplePassword() and
19+
if PasswordHeuristics::isDummyPassword(password) then isDummy = true else isDummy = false
20+
select password, isDummy
Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
11
| mysql-config.json:4:16:4:25 | "abcdefgh" | Hard-coded password 'abcdefgh' in configuration file. |
22
| tst4.json:2:10:2:38 | "script ... ecret'" | Hard-coded password ''secret'' in configuration file. |
33
| tst7.yml:2:9:2:6 | \| | Hard-coded password 'abc' in configuration file. |
4-
| tst.yml:7:11:7:19 | change_me | Hard-coded password 'change_me' in configuration file. |

javascript/ql/test/query-tests/Security/CWE-798/HardcodedCredentials.expected

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -106,4 +106,3 @@ edges
106106
| HardcodedCredentials.js:130:44:130:53 | 'abcdefgh' | HardcodedCredentials.js:130:44:130:53 | 'abcdefgh' | HardcodedCredentials.js:130:44:130:53 | 'abcdefgh' | The hard-coded value "abcdefgh" is used as $@. | HardcodedCredentials.js:130:44:130:53 | 'abcdefgh' | key |
107107
| HardcodedCredentials.js:131:52:131:61 | 'abcdefgh' | HardcodedCredentials.js:131:52:131:61 | 'abcdefgh' | HardcodedCredentials.js:131:52:131:61 | 'abcdefgh' | The hard-coded value "abcdefgh" is used as $@. | HardcodedCredentials.js:131:52:131:61 | 'abcdefgh' | key |
108108
| HardcodedCredentials.js:135:41:135:50 | "abcdefgh" | HardcodedCredentials.js:135:41:135:50 | "abcdefgh" | HardcodedCredentials.js:135:41:135:50 | "abcdefgh" | The hard-coded value "abcdefgh" is used as $@. | HardcodedCredentials.js:135:41:135:50 | "abcdefgh" | key |
109-
| HardcodedCredentials.js:160:38:160:48 | "change_me" | HardcodedCredentials.js:160:38:160:48 | "change_me" | HardcodedCredentials.js:160:38:160:48 | "change_me" | The hard-coded value "change_me" is used as $@. | HardcodedCredentials.js:160:38:160:48 | "change_me" | key |

0 commit comments

Comments
 (0)