Skip to content

Commit 1d437dd

Browse files
authored
Merge pull request #8043 from github/esbena/sharpen-hardcoded-credentials
JS: Sharpen hardcoded credentials
2 parents 5f9bd7a + f08a140 commit 1d437dd

File tree

8 files changed

+248
-180
lines changed

8 files changed

+248
-180
lines changed

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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -214,7 +214,8 @@ module PasswordHeuristics {
214214
or
215215
exists(string normalized | normalized = password.toLowerCase() |
216216
count(normalized.charAt(_)) = 1 or
217-
normalized.regexpMatch(".*(pass|test|sample|example|secret|root|admin|user|change|auth).*")
217+
normalized
218+
.regexpMatch(".*(pass|test|sample|example|secret|root|admin|user|change|auth|fake|(my(token|password))|string|foo|bar|baz|qux|1234|3141|abcd).*")
218219
)
219220
}
220221

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

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,20 +17,26 @@ import javascript
1717
import semmle.javascript.security.dataflow.HardcodedCredentialsQuery
1818
import DataFlow::PathGraph
1919

20+
bindingset[s]
21+
predicate looksLikeATemplate(string s) { s.regexpMatch(".*((\\{\\{.*\\}\\})|(<.*>)|(\\(.*\\))).*") }
22+
2023
from Configuration cfg, DataFlow::PathNode source, DataFlow::PathNode sink, string value
2124
where
2225
cfg.hasFlowPath(source, sink) and
2326
// use source value in message if it's available
2427
if source.getNode().asExpr() instanceof ConstantString
2528
then
2629
exists(string val | val = source.getNode().getStringValue() |
27-
// exclude dummy passwords
30+
// exclude dummy passwords and templates
2831
not (
29-
sink.getNode().(Sink).(DefaultCredentialsSink).getKind() = "password" and
32+
sink.getNode().(Sink).(DefaultCredentialsSink).getKind() =
33+
["password", "credentials", "token"] and
3034
PasswordHeuristics::isDummyPassword(val)
3135
or
3236
sink.getNode().(Sink).getKind() = "authorization header" and
3337
PasswordHeuristics::isDummyAuthHeader(val)
38+
or
39+
looksLikeATemplate(val)
3440
) and
3541
value = "The hard-coded value \"" + val + "\""
3642
)

javascript/ql/test/library-tests/SensitiveActions/tests.expected

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,11 @@ cleartextPasswordExpr
1212
dummyPasswords
1313
| | true |
1414
| XXXXXXXX | true |
15-
| abcdefgh | false |
15+
| abcdefgh | true |
1616
| admin | true |
1717
| change_me | true |
1818
| example_password | true |
19+
| hgfedcba | false |
1920
| insert-auth-from-gui | true |
2021
| root | true |
2122
| sOKY6ccizpmvF*32so%Q | false |

javascript/ql/test/library-tests/SensitiveActions/tests.ql

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,8 @@ query predicate cleartextPasswordExpr(CleartextPasswordExpr e) { any() }
66
string getASamplePassword() {
77
result =
88
[
9-
"abcdefgh", "sOKY6ccizpmvF*32so%Q", "XXXXXXXX", "example_password", "change_me", "",
10-
"insert-auth-from-gui", "admin", "root"
9+
"hgfedcba", "abcdefgh", "sOKY6ccizpmvF*32so%Q", "XXXXXXXX", "example_password", "change_me",
10+
"", "insert-auth-from-gui", "admin", "root"
1111
]
1212
}
1313

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
1-
| mysql-config.json:4:16:4:25 | "abcdefgh" | Hard-coded password 'abcdefgh' in configuration file. |
1+
| mysql-config.json:4:16:4:25 | "hgfedcba" | Hard-coded password 'hgfedcba' 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. |
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"host" : "localhost",
33
"user" : "me",
4-
"password" : "abcdefgh",
4+
"password" : "hgfedcba",
55
"database" : "my_db"
66
}

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

Lines changed: 187 additions & 142 deletions
Large diffs are not rendered by default.

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

Lines changed: 45 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -5,17 +5,17 @@
55
user: 'dbuser', // NOT OK
66
host: 'database.server.com',
77
database: 'mydb',
8-
password: 'abcdefgh', // NOT OK
8+
password: 'hgfedcba', // NOT OK
99
port: 3211,
1010
});
1111
client.connect();
1212
})();
1313

1414
(function() {
15-
require("http").request({auth: "user:abcdefgh"}); // NOT OK
16-
require("https").request({auth: "user:abcdefgh"}); // NOT OK
15+
require("http").request({auth: "user:hgfedcba"}); // NOT OK
16+
require("https").request({auth: "user:hgfedcba"}); // NOT OK
1717
function getCredentials() {
18-
return "user:abcdefgh";
18+
return "user:hgfedcba";
1919
}
2020
require("http").request({auth: getCredentials()}); // NOT OK
2121
require("http").request({auth: getUnknownCredentials()}); // OK
@@ -24,37 +24,37 @@
2424
(function() {
2525
var basicAuth = require('express-basic-auth');
2626

27-
basicAuth({users: { 'admin': 'abcdefgh' }}); // NOT OK
27+
basicAuth({users: { 'admin': 'hgfedcba' }}); // NOT OK
2828
var users = {};
29-
users['unknown-admin-name'] = 'abcdefgh'; // NOT OK
29+
users['unknown-admin-name'] = 'hgfedcba'; // NOT OK
3030
basicAuth({users: users});
3131
})();
3232

3333
(function() {
3434
var basicAuth = require('basic-auth-connect');
35-
basicAuth('username', 'abcdefgh'); // NOT OK
35+
basicAuth('username', 'hgfedcba'); // NOT OK
3636
basicAuth(function(){}); // OK
3737
})();
3838

3939
(function() {
4040
var AWS = require('aws-sdk');
41-
AWS.config.update({ accessKeyId: 'username', secretAccessKey: 'abcdefgh'}); // NOT OK
42-
new AWS.Config({ accessKeyId: 'username', secretAccessKey: 'abcdefgh'}); // NOT OK
41+
AWS.config.update({ accessKeyId: 'username', secretAccessKey: 'hgfedcba'}); // NOT OK
42+
new AWS.Config({ accessKeyId: 'username', secretAccessKey: 'hgfedcba'}); // NOT OK
4343
var config = new AWS.Config();
44-
config.update({ accessKeyId: 'username', secretAccessKey: 'abcdefgh'}); // NOT OK
44+
config.update({ accessKeyId: 'username', secretAccessKey: 'hgfedcba'}); // NOT OK
4545
var o = {};
46-
o.secretAccessKey = 'abcdefgh'; // NOT OK
46+
o.secretAccessKey = 'hgfedcba'; // NOT OK
4747
config.update(o);
4848
})();
4949

5050
(function() {
5151
var request = require('request');
5252

53-
request.get(url).auth('username', 'abcdefgh'); // NOT OK
53+
request.get(url).auth('username', 'hgfedcba'); // NOT OK
5454
request.get(url, {
5555
'auth': {
5656
'user': 'username', // NOT OK
57-
'pass': 'abcdefgh' // NOT OK
57+
'pass': 'hgfedcba' // NOT OK
5858
}
5959
});
6060

@@ -66,24 +66,24 @@
6666
}
6767
});
6868

69-
request.post(url).auth('username', 'abcdefgh'); // NOT OK
70-
request.head(url).auth('username', 'abcdefgh'); // NOT OK
69+
request.post(url).auth('username', 'hgfedcba'); // NOT OK
70+
request.head(url).auth('username', 'hgfedcba'); // NOT OK
7171

72-
request(url).auth('username', 'abcdefgh'); // NOT OK
72+
request(url).auth('username', 'hgfedcba'); // NOT OK
7373
request(url, {
7474
'auth': {
7575
'user': 'username', // NOT OK
76-
'pass': 'abcdefgh' // NOT OK
76+
'pass': 'hgfedcba' // NOT OK
7777
}
7878
});
7979
})();
8080

8181
(function() {
8282
const MsRest = require('ms-rest-azure');
8383

84-
MsRest.loginWithUsernamePassword('username', 'abcdefgh', function(){}); // NOT OK
84+
MsRest.loginWithUsernamePassword('username', 'hgfedcba', function(){}); // NOT OK
8585
MsRest.loginWithUsernamePassword(process.env.AZURE_USER, process.env.AZURE_PASS, function(){}); // OK
86-
MsRest.loginWithServicePrincipalSecret('username', 'abcdefgh', function(){}); // NOT OK
86+
MsRest.loginWithServicePrincipalSecret('username', 'hgfedcba', function(){}); // NOT OK
8787
})();
8888

8989
(function() {
@@ -99,26 +99,26 @@
9999
keyId: 'x2',// NOT OK
100100
storageAccount: 'x3', // NOT OK
101101
username: 'x4', // NOT OK
102-
key: 'abcdefgh', // NOT OK
103-
apiKey: 'abcdefgh', // NOT OK
104-
storageAccessKey: 'abcdefgh', // NOT OK
105-
password: 'abcdefgh', // NOT OK
106-
token: 'abcdefgh' // NOT OK
102+
key: 'hgfedcba', // NOT OK
103+
apiKey: 'hgfedcba', // NOT OK
104+
storageAccessKey: 'hgfedcba', // NOT OK
105+
password: 'hgfedcba', // NOT OK
106+
token: 'hgfedcba' // NOT OK
107107
});
108108
pkgcloud.compute.createClient({ // OK
109109
INNOCENT_DATA: '42'
110110
});
111111
pkgcloud.providers.SOME_PROVIDER.compute.createClient({
112112
username: 'x5', // NOT OK
113-
password: 'abcdefgh' // NOT OK
113+
password: 'hgfedcba' // NOT OK
114114
});
115115
pkgcloud.UNKNOWN_SERVICE.createClient({ // OK
116116
username: 'x6',
117-
password: 'abcdefgh'
117+
password: 'hgfedcba'
118118
});
119119
pkgcloud.providers.SOME_PROVIDER.UNKNOWN_SERVICE.createClient({
120120
username: 'x7', // OK
121-
password: 'abcdefgh' // OK
121+
password: 'hgfedcba' // OK
122122
});
123123
pkgcloud.compute.createClient({ // OK
124124
username: process.env.USERNAME,
@@ -127,12 +127,12 @@
127127
})();
128128

129129
(function(){
130-
require('crypto').createHmac('sha256', 'abcdefgh');
131-
require("crypto-js/aes").encrypt('my message', 'abcdefgh');
130+
require('crypto').createHmac('sha256', 'hgfedcba');
131+
require("crypto-js/aes").encrypt('my message', 'hgfedcba');
132132
})()
133133

134134
(function(){
135-
require("cookie-session")({ secret: "abcdefgh" });
135+
require("cookie-session")({ secret: "hgfedcba" });
136136
})()
137137

138138
(function(){
@@ -269,4 +269,19 @@
269269
"Content-Type": 'application/json'
270270
})
271271
});
272+
});
273+
274+
(function() {
275+
require("http").request({auth: "user:{{ INSERT_HERE }}"}); // OK
276+
require("http").request({auth: "user:token {{ INSERT_HERE }}"}); // OK
277+
require("http").request({auth: "user:( INSERT_HERE )"}); // OK
278+
require("http").request({auth: "user:{{ env.access_token }}"}); // OK
279+
require("http").request({auth: "user:abcdefgh"}); // OK
280+
require("http").request({auth: "user:12345678"}); // OK
281+
require("http").request({auth: "user:foo"}); // OK
282+
require("http").request({auth: "user:mypassword"}) // OK
283+
require("http").request({auth: "user:mytoken"}) // OK
284+
require("http").request({auth: "user:fake token"}) // OK
285+
require("http").request({auth: "user:dcba"}) // OK
286+
require("http").request({auth: "user:custom string"}) // OK
272287
});

0 commit comments

Comments
 (0)