@contrast/agent 4.8.0 → 4.10.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/VERSION +1 -1
- package/bin/linux/contrast-service +0 -0
- package/bin/mac/contrast-service +0 -0
- package/bin/windows/contrast-service.exe +0 -0
- package/bootstrap.js +12 -2
- package/esm.mjs +33 -0
- package/lib/assess/index.js +2 -0
- package/lib/assess/models/source-event.js +6 -0
- package/lib/assess/policy/rules.json +29 -0
- package/lib/assess/policy/signatures.json +6 -0
- package/lib/assess/propagators/JSON/stringify.js +77 -7
- package/lib/assess/propagators/joi/any.js +48 -0
- package/lib/assess/propagators/joi/index.js +2 -0
- package/lib/assess/propagators/joi/object.js +61 -0
- package/lib/assess/propagators/joi/string-base.js +16 -0
- package/lib/assess/propagators/mongoose/helpers.js +36 -1
- package/lib/assess/propagators/mongoose/index.js +1 -0
- package/lib/assess/propagators/mongoose/map.js +19 -31
- package/lib/assess/propagators/mongoose/mixed.js +71 -0
- package/lib/assess/propagators/mongoose/string.js +8 -0
- package/lib/assess/sinks/rethinkdb-nosql-injection.js +142 -0
- package/lib/assess/sources/event-handler.js +307 -0
- package/lib/assess/sources/index.js +93 -5
- package/lib/assess/spdy/index.js +23 -0
- package/lib/assess/spdy/sinks/index.js +23 -0
- package/lib/assess/spdy/sinks/xss.js +84 -0
- package/lib/assess/technologies/index.js +2 -1
- package/lib/constants.js +2 -1
- package/lib/contrast.js +6 -6
- package/lib/core/arch-components/index.js +1 -0
- package/lib/core/arch-components/mongodb.js +22 -18
- package/lib/core/arch-components/mysql.js +25 -15
- package/lib/core/arch-components/postgres.js +40 -12
- package/lib/core/arch-components/sqlite3.js +3 -5
- package/lib/core/arch-components/util.js +49 -0
- package/lib/core/config/options.js +37 -1
- package/lib/core/exclusions/exclusion.js +2 -5
- package/lib/core/express/index.js +28 -2
- package/lib/core/express/utils.js +8 -3
- package/lib/core/fastify/index.js +2 -1
- package/lib/core/hapi/index.js +2 -1
- package/lib/core/koa/index.js +9 -1
- package/lib/core/rewrite/callees.js +16 -0
- package/lib/core/rewrite/import-declaration.js +71 -0
- package/lib/core/rewrite/index.js +9 -7
- package/lib/core/rewrite/injections.js +5 -1
- package/lib/hooks/frameworks/index.js +2 -0
- package/lib/hooks/frameworks/spdy.js +87 -0
- package/lib/hooks/http.js +11 -0
- package/lib/protect/restify/sources.js +35 -0
- package/lib/protect/rules/nosqli/nosql-injection-rule.js +30 -16
- package/lib/protect/rules/nosqli/nosql-scanner/index.js +1 -1
- package/lib/protect/rules/nosqli/nosql-scanner/rethinkdbscanner.js +26 -0
- package/lib/protect/sinks/index.js +2 -0
- package/lib/protect/sinks/mongodb.js +1 -3
- package/lib/protect/sinks/rethinkdb.js +47 -0
- package/lib/reporter/translations/to-protobuf/dtm/trace-event/index.js +4 -4
- package/lib/util/source-map.js +3 -3
- package/package.json +18 -12
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
/**
|
|
2
|
+
Copyright: 2022 Contrast Security, Inc
|
|
3
|
+
Contact: support@contrastsecurity.com
|
|
4
|
+
License: Commercial
|
|
5
|
+
|
|
6
|
+
NOTICE: This Software and the patented inventions embodied within may only be
|
|
7
|
+
used as part of Contrast Security’s commercial offerings. Even though it is
|
|
8
|
+
made available through public repositories, use of this Software is subject to
|
|
9
|
+
the applicable End User Licensing Agreement found at
|
|
10
|
+
https://www.contrastsecurity.com/enduser-terms-0317a or as otherwise agreed
|
|
11
|
+
between Contrast Security and the End User. The Software may not be reverse
|
|
12
|
+
engineered, modified, repackaged, sold, redistributed or otherwise used in a
|
|
13
|
+
way not consistent with the End User License Agreement.
|
|
14
|
+
*/
|
|
15
|
+
'use strict';
|
|
16
|
+
|
|
17
|
+
const t = require('@babel/types');
|
|
18
|
+
const _ = require('lodash');
|
|
19
|
+
|
|
20
|
+
const IMPORT_META_URL_MEMBER_EXPRESSION = t.memberExpression(
|
|
21
|
+
t.memberExpression(t.identifier('import'), t.identifier('meta')),
|
|
22
|
+
t.identifier('url')
|
|
23
|
+
);
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Appends calls to our own instrumentable import methods, providing access to
|
|
27
|
+
* the imported modules.
|
|
28
|
+
* ```
|
|
29
|
+
* import x from 'mod';
|
|
30
|
+
* // becomes:
|
|
31
|
+
* import x from 'mod';
|
|
32
|
+
* ContrastMethods.__importDefault(x, 'mod', import.meta.url);
|
|
33
|
+
*
|
|
34
|
+
* import * as x from 'mod';
|
|
35
|
+
* // becomes:
|
|
36
|
+
* import x from 'mod';
|
|
37
|
+
* ContrastMethods.__importNamespace(x, 'mod', import.meta.url);
|
|
38
|
+
*
|
|
39
|
+
* import { foo, bar as baz } from 'mod';;
|
|
40
|
+
* // becomes
|
|
41
|
+
* ContrastMethods.__import(foo, 'foo', 'mod', import.meta.url);
|
|
42
|
+
* ContrastMethods.__import(baz, 'bar', 'mod', import.meta.url);
|
|
43
|
+
* ```
|
|
44
|
+
* @param {import('@babel/traverse').NodePath<import('@babel/types').ImportDeclaration>} path
|
|
45
|
+
* @param {import('.').State} state
|
|
46
|
+
*/
|
|
47
|
+
module.exports = function ImportDeclaration(path, state) {
|
|
48
|
+
const { source, specifiers } = path.node;
|
|
49
|
+
|
|
50
|
+
path.insertAfter(
|
|
51
|
+
specifiers.map((importSpec) => {
|
|
52
|
+
const spec = _.find(state.specs, { type: importSpec.type });
|
|
53
|
+
if (!spec || !state.callees[spec.name]) return;
|
|
54
|
+
|
|
55
|
+
const args = [importSpec.local];
|
|
56
|
+
|
|
57
|
+
if (t.isImportSpecifier(importSpec)) {
|
|
58
|
+
args.push(
|
|
59
|
+
t.isIdentifier(importSpec.imported)
|
|
60
|
+
? t.stringLiteral(importSpec.imported.name)
|
|
61
|
+
: importSpec.imported
|
|
62
|
+
);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
args.push(source);
|
|
66
|
+
args.push(IMPORT_META_URL_MEMBER_EXPRESSION);
|
|
67
|
+
|
|
68
|
+
return t.callExpression(state.callees[spec.name], args);
|
|
69
|
+
})
|
|
70
|
+
);
|
|
71
|
+
};
|
|
@@ -18,23 +18,24 @@ const { default: generate } = require('@babel/generator');
|
|
|
18
18
|
const { parse } = require('@babel/parser');
|
|
19
19
|
const { default: traverse } = require('@babel/traverse');
|
|
20
20
|
|
|
21
|
+
const RewriteDeadzones = require('../../assess/deadzones/rewrite');
|
|
22
|
+
const { util: sourceMapUtility } = require('../../util/source-map');
|
|
21
23
|
const Scopes = require('../async-storage/scopes');
|
|
22
24
|
const logger = require('../logger')('contrast:rewrite');
|
|
23
|
-
const RewriteDeadzones = require('../../assess/deadzones/rewrite');
|
|
24
|
-
const logRewrite = require('./log');
|
|
25
|
-
const RewriteLog = require('./rewrite-log');
|
|
26
|
-
const isContrastMethod = require('./is-contrast-method');
|
|
27
|
-
const functionWrap = require('./function-wrap');
|
|
28
|
-
const prependGlobals = require('./prepend-globals');
|
|
29
25
|
const AssignmentExpression = require('./assignment-expression');
|
|
30
26
|
const BinaryExpression = require('./binary-expression');
|
|
31
27
|
const CallExpression = require('./call-expression');
|
|
32
28
|
const CatchClause = require('./catch-clause');
|
|
29
|
+
const functionWrap = require('./function-wrap');
|
|
30
|
+
const ImportDeclaration = require('./import-declaration');
|
|
31
|
+
const isContrastMethod = require('./is-contrast-method');
|
|
32
|
+
const logRewrite = require('./log');
|
|
33
33
|
const MemberExpression = require('./member-expression');
|
|
34
34
|
const ObjectProperty = require('./object-property');
|
|
35
|
+
const prependGlobals = require('./prepend-globals');
|
|
36
|
+
const RewriteLog = require('./rewrite-log');
|
|
35
37
|
const SwitchStatement = require('./switch-statement');
|
|
36
38
|
const TemplateLiteral = require('./template-literal');
|
|
37
|
-
const sourceMapUtility = require('../../util/source-map').util;
|
|
38
39
|
|
|
39
40
|
/**
|
|
40
41
|
* @typedef {Object} State
|
|
@@ -105,6 +106,7 @@ class Rewriter {
|
|
|
105
106
|
BinaryExpression,
|
|
106
107
|
CallExpression,
|
|
107
108
|
CatchClause,
|
|
109
|
+
ImportDeclaration,
|
|
108
110
|
MemberExpression,
|
|
109
111
|
ObjectProperty,
|
|
110
112
|
SwitchStatement,
|
|
@@ -100,7 +100,11 @@ const ContrastMethods = new Injection(null, 'ContrastMethods', {
|
|
|
100
100
|
},
|
|
101
101
|
__contrastEval: function __contrastEval(str) {
|
|
102
102
|
return str;
|
|
103
|
-
}
|
|
103
|
+
},
|
|
104
|
+
// TODO: NODE-2020
|
|
105
|
+
__importDefault(mod, source, url) {},
|
|
106
|
+
__importNamespace(mod, source, url) {},
|
|
107
|
+
__import(mod, spec, source, url) {}
|
|
104
108
|
});
|
|
105
109
|
|
|
106
110
|
ContrastMethods.enable();
|
|
@@ -16,6 +16,7 @@ Copyright: 2022 Contrast Security, Inc
|
|
|
16
16
|
|
|
17
17
|
const Http = require('./http');
|
|
18
18
|
const Http2 = require('./http2');
|
|
19
|
+
const Spdy = require('./spdy');
|
|
19
20
|
const Hapi16 = require('./hapi16');
|
|
20
21
|
|
|
21
22
|
module.exports = function(agent) {
|
|
@@ -23,5 +24,6 @@ module.exports = function(agent) {
|
|
|
23
24
|
new Http(agent);
|
|
24
25
|
new Http(agent, 'https');
|
|
25
26
|
new Http2(agent);
|
|
27
|
+
new Spdy(agent);
|
|
26
28
|
new Hapi16(agent);
|
|
27
29
|
};
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
/**
|
|
2
|
+
Copyright: 2022 Contrast Security, Inc
|
|
3
|
+
Contact: support@contrastsecurity.com
|
|
4
|
+
License: Commercial
|
|
5
|
+
|
|
6
|
+
NOTICE: This Software and the patented inventions embodied within may only be
|
|
7
|
+
used as part of Contrast Security’s commercial offerings. Even though it is
|
|
8
|
+
made available through public repositories, use of this Software is subject to
|
|
9
|
+
the applicable End User Licensing Agreement found at
|
|
10
|
+
https://www.contrastsecurity.com/enduser-terms-0317a or as otherwise agreed
|
|
11
|
+
between Contrast Security and the End User. The Software may not be reverse
|
|
12
|
+
engineered, modified, repackaged, sold, redistributed or otherwise used in a
|
|
13
|
+
way not consistent with the End User License Agreement.
|
|
14
|
+
*/
|
|
15
|
+
'use strict';
|
|
16
|
+
|
|
17
|
+
const {
|
|
18
|
+
PATCH_TYPES,
|
|
19
|
+
HTTP_RESPONSE_HOOKED_METHOD_KEYS,
|
|
20
|
+
SINK_TYPES
|
|
21
|
+
} = require('../../constants');
|
|
22
|
+
const patcher = require('../patcher');
|
|
23
|
+
const HttpFramework = require('./http');
|
|
24
|
+
const { isString } = require('../../util/is-string');
|
|
25
|
+
const { emitSendEvent } = require('../../hooks/frameworks/common');
|
|
26
|
+
const agentEmitter = require('../../agent-emitter');
|
|
27
|
+
|
|
28
|
+
class SpdyFramework extends HttpFramework {
|
|
29
|
+
/**
|
|
30
|
+
* @param {Agent} agent
|
|
31
|
+
*/
|
|
32
|
+
constructor(agent) {
|
|
33
|
+
super(agent, 'spdy');
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* @param {import('spdy')} spdy
|
|
38
|
+
* @returns {import('spdy')}
|
|
39
|
+
*/
|
|
40
|
+
onRequire(spdy) {
|
|
41
|
+
patcher.patch(spdy, 'createServer', {
|
|
42
|
+
name: `${this.id}.createServer`,
|
|
43
|
+
patchType: PATCH_TYPES.FRAMEWORK,
|
|
44
|
+
alwaysRun: true,
|
|
45
|
+
post: ({ args, result }) => {
|
|
46
|
+
this.handleServerCreate(args, result);
|
|
47
|
+
}
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
patcher.patch(spdy.response, 'push', {
|
|
51
|
+
name: 'spdy.response.push',
|
|
52
|
+
patchType: PATCH_TYPES.FRAMEWORK,
|
|
53
|
+
pre(data) {
|
|
54
|
+
agentEmitter.emit(
|
|
55
|
+
HTTP_RESPONSE_HOOKED_METHOD_KEYS.PUSH,
|
|
56
|
+
data.args[0],
|
|
57
|
+
SINK_TYPES.RESPONSE_BODY
|
|
58
|
+
);
|
|
59
|
+
|
|
60
|
+
const body = data.args[0];
|
|
61
|
+
if (isString(body)) {
|
|
62
|
+
emitSendEvent(body.valueOf());
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
return spdy;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Emits a create event for the new Server instance.
|
|
72
|
+
* @param {any[]} args The arguments passed to the Server constructor
|
|
73
|
+
* @param {import('net').Server} server The http Server instance
|
|
74
|
+
*/
|
|
75
|
+
handleServerCreate(args, server) {
|
|
76
|
+
super.handleServerCreate(args, server);
|
|
77
|
+
|
|
78
|
+
patcher.patch(server, 'listen', {
|
|
79
|
+
name: `${this.id}.SpdyFramework.listen`,
|
|
80
|
+
patchType: PATCH_TYPES.FRAMEWORK,
|
|
81
|
+
alwaysRun: true,
|
|
82
|
+
pre: ({ args, obj }) => this.handleServerListen(args, obj)
|
|
83
|
+
});
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
module.exports = SpdyFramework;
|
package/lib/hooks/http.js
CHANGED
|
@@ -195,5 +195,16 @@ module.exports = (agent) => {
|
|
|
195
195
|
}
|
|
196
196
|
});
|
|
197
197
|
});
|
|
198
|
+
|
|
199
|
+
moduleHook.resolve({ name: 'spdy' }, (spdy) => {
|
|
200
|
+
patcher.patch(spdy, 'createServer', {
|
|
201
|
+
name: `create-server-spdy-hooks`,
|
|
202
|
+
patchType: PATCH_TYPES.MISC,
|
|
203
|
+
alwaysRun: true,
|
|
204
|
+
post({ result }) {
|
|
205
|
+
hookServer(result, agent);
|
|
206
|
+
}
|
|
207
|
+
});
|
|
208
|
+
});
|
|
198
209
|
};
|
|
199
210
|
module.exports.hookServer = hookServer;
|
|
@@ -21,6 +21,8 @@ const {
|
|
|
21
21
|
} = require('../../constants');
|
|
22
22
|
const { emitSourceEvent } = require('../../hooks/frameworks/common');
|
|
23
23
|
const agentEmitter = require('../../agent-emitter');
|
|
24
|
+
const patcher = require('../../hooks/patcher');
|
|
25
|
+
const { PATCH_TYPES } = require('../../constants');
|
|
24
26
|
const {
|
|
25
27
|
utils,
|
|
26
28
|
constants: { EVENTS }
|
|
@@ -39,6 +41,39 @@ class RestifyProtectSources {
|
|
|
39
41
|
EVENTS.CREATE_SERVER,
|
|
40
42
|
this.registerUrlParamsHandler.bind(this)
|
|
41
43
|
);
|
|
44
|
+
agentEmitter.on(
|
|
45
|
+
EVENTS.RESTIFY_EXPORT,
|
|
46
|
+
this.registerQueryParamsHandler.bind(this)
|
|
47
|
+
);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Patches query parser middleware to wrap the callback argument. Once this
|
|
53
|
+
* wrapped callback is invoked w/out error we know we can proxy `req.query`.
|
|
54
|
+
* @param {object} restify
|
|
55
|
+
*/
|
|
56
|
+
registerQueryParamsHandler(restify) {
|
|
57
|
+
const {
|
|
58
|
+
plugins: { queryParser: origQueryParser }
|
|
59
|
+
} = restify;
|
|
60
|
+
|
|
61
|
+
if (origQueryParser) {
|
|
62
|
+
patcher.patch(restify.plugins, 'queryParser', {
|
|
63
|
+
name: 'restify.plugins',
|
|
64
|
+
patchType: PATCH_TYPES.FRAMEWORK,
|
|
65
|
+
alwaysRun: true,
|
|
66
|
+
post(data) {
|
|
67
|
+
patcher.patch(data, 'result', {
|
|
68
|
+
name: 'restify.plugins.queryParser',
|
|
69
|
+
patchType: PATCH_TYPES.PROTECT_SOURCE,
|
|
70
|
+
alwaysRun: true,
|
|
71
|
+
post(data) {
|
|
72
|
+
decorateRequest({ query: get(data.args[0], 'query') });
|
|
73
|
+
}
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
});
|
|
42
77
|
}
|
|
43
78
|
}
|
|
44
79
|
|
|
@@ -26,9 +26,11 @@ const brackets = /\[(.{1,1024}?)\]/;
|
|
|
26
26
|
const child = /\[(.{1,1024}?)\]/g;
|
|
27
27
|
|
|
28
28
|
const MONGODB = 'mongodb';
|
|
29
|
+
const RETHINKDB = 'rethinkdb';
|
|
29
30
|
|
|
30
31
|
const ScannerKit = new Map([
|
|
31
|
-
[MONGODB, () => require('../nosqli/nosql-scanner').create('MongoDB')]
|
|
32
|
+
[MONGODB, () => require('../nosqli/nosql-scanner').create('MongoDB')],
|
|
33
|
+
[RETHINKDB, () => require('../nosqli/nosql-scanner').create('RethinkDB')]
|
|
32
34
|
]);
|
|
33
35
|
const SubstringFinder = require('../base-scanner/substring-finder');
|
|
34
36
|
|
|
@@ -144,27 +146,14 @@ class NoSqlInjectionRule extends require('../') {
|
|
|
144
146
|
_documentType === constants.INPUT_TYPES.PARAMETER_NAME &&
|
|
145
147
|
_documentPath.length <= 1024
|
|
146
148
|
) {
|
|
147
|
-
|
|
148
|
-
const parent = segment
|
|
149
|
-
? _documentPath.slice(0, segment.index)
|
|
150
|
-
: _documentPath;
|
|
151
|
-
|
|
152
|
-
pathArray.push('query');
|
|
153
|
-
|
|
154
|
-
if (parent) {
|
|
155
|
-
pathArray.push(parent);
|
|
156
|
-
}
|
|
157
|
-
while ((segment = child.exec(_documentPath))) {
|
|
158
|
-
pathArray.push(segment[1]);
|
|
159
|
-
}
|
|
160
|
-
pathArray.pop();
|
|
149
|
+
this.buildPathArray(_documentPath, pathArray);
|
|
161
150
|
} else {
|
|
162
151
|
// only qs params and body are "expandable"
|
|
163
152
|
pathArray.push('body', ..._documentPath.split('.'));
|
|
164
153
|
}
|
|
165
154
|
|
|
166
155
|
let data;
|
|
167
|
-
let curr = ctx.
|
|
156
|
+
let curr = ctx.request;
|
|
168
157
|
|
|
169
158
|
for (const path of pathArray) {
|
|
170
159
|
if (curr) {
|
|
@@ -175,6 +164,31 @@ class NoSqlInjectionRule extends require('../') {
|
|
|
175
164
|
return data;
|
|
176
165
|
}
|
|
177
166
|
|
|
167
|
+
buildPathArray(documentPath, pathArray) {
|
|
168
|
+
const documentPathArray = documentPath.split('.');
|
|
169
|
+
|
|
170
|
+
pathArray.push('query');
|
|
171
|
+
documentPathArray.forEach((dotSegment) => {
|
|
172
|
+
let lastChar;
|
|
173
|
+
let bracketSegment = brackets.exec(dotSegment);
|
|
174
|
+
let parent = bracketSegment
|
|
175
|
+
? dotSegment.slice(0, bracketSegment.index)
|
|
176
|
+
: dotSegment;
|
|
177
|
+
if (parent) {
|
|
178
|
+
lastChar = parent.slice(-1);
|
|
179
|
+
parent = lastChar === ']' ? parent.slice(0, -1) : parent;
|
|
180
|
+
pathArray.push(parent);
|
|
181
|
+
}
|
|
182
|
+
while ((bracketSegment = child.exec(dotSegment))) {
|
|
183
|
+
lastChar = bracketSegment[1].slice(-1);
|
|
184
|
+
const segment =
|
|
185
|
+
lastChar === ']' ? bracketSegment[1].slice(0, -1) : bracketSegment[1];
|
|
186
|
+
pathArray.push(segment);
|
|
187
|
+
}
|
|
188
|
+
});
|
|
189
|
+
pathArray.pop();
|
|
190
|
+
}
|
|
191
|
+
|
|
178
192
|
getScanner(id) {
|
|
179
193
|
if (!ScannerKit.has(id)) {
|
|
180
194
|
throw new Error(`Unknown NoSQL scanner: ${id}`);
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
Copyright: 2022 Contrast Security, Inc
|
|
3
|
+
Contact: support@contrastsecurity.com
|
|
4
|
+
License: Commercial
|
|
5
|
+
|
|
6
|
+
NOTICE: This Software and the patented inventions embodied within may only be
|
|
7
|
+
used as part of Contrast Security’s commercial offerings. Even though it is
|
|
8
|
+
made available through public repositories, use of this Software is subject to
|
|
9
|
+
the applicable End User Licensing Agreement found at
|
|
10
|
+
https://www.contrastsecurity.com/enduser-terms-0317a or as otherwise agreed
|
|
11
|
+
between Contrast Security and the End User. The Software may not be reverse
|
|
12
|
+
engineered, modified, repackaged, sold, redistributed or otherwise used in a
|
|
13
|
+
way not consistent with the End User License Agreement.
|
|
14
|
+
*/
|
|
15
|
+
/**
|
|
16
|
+
* RethinkDB scanner module
|
|
17
|
+
* @module lib/protect/rules/nosql/nosql-scanner/RethinkDBScanner
|
|
18
|
+
*/
|
|
19
|
+
|
|
20
|
+
'use strict';
|
|
21
|
+
|
|
22
|
+
const { BaseScanner } = require('../../base-scanner');
|
|
23
|
+
|
|
24
|
+
class RethinkDBScanner extends BaseScanner {}
|
|
25
|
+
|
|
26
|
+
module.exports = RethinkDBScanner;
|
|
@@ -29,6 +29,7 @@ const MongoDBSink = require('./mongodb');
|
|
|
29
29
|
const MySQLSink = require('./mysql');
|
|
30
30
|
const NodeSerializeSink = require('./node-serialize');
|
|
31
31
|
const PostgresSink = require('./postgres');
|
|
32
|
+
const RethinkDBSink = require('./rethinkdb');
|
|
32
33
|
const SequelizeSink = require('./sequelize');
|
|
33
34
|
const Sqlite3Sink = require('./sqlite3');
|
|
34
35
|
const VMSink = require('./vm');
|
|
@@ -46,6 +47,7 @@ module.exports = function init(agent) {
|
|
|
46
47
|
new MySQLSink(agent).install({ ModuleHook });
|
|
47
48
|
new NodeSerializeSink(agent).install({ ModuleHook });
|
|
48
49
|
new PostgresSink(agent).install({ ModuleHook });
|
|
50
|
+
new RethinkDBSink(agent).install({ ModuleHook });
|
|
49
51
|
new SequelizeSink(agent).install({ ModuleHook });
|
|
50
52
|
new VMSink(agent).install({ ModuleHook });
|
|
51
53
|
new Sqlite3Sink(agent).install({ ModuleHook });
|
|
@@ -21,8 +21,6 @@ const BaseSensor = require('../../hooks/frameworks/base');
|
|
|
21
21
|
const patcher = require('../../hooks/patcher');
|
|
22
22
|
const { PATCH_TYPES } = require('../../constants');
|
|
23
23
|
const { emitSinkEvent } = require('../../hooks/frameworks/common');
|
|
24
|
-
const agentEmitter = require('../../agent-emitter');
|
|
25
|
-
const SinkEvent = require('../models/sink-event');
|
|
26
24
|
|
|
27
25
|
const { SINK_TYPES } = constants;
|
|
28
26
|
const ID = 'mongodb';
|
|
@@ -37,7 +35,7 @@ function getCursorQueryData(args, version) {
|
|
|
37
35
|
}
|
|
38
36
|
|
|
39
37
|
if (_.isString(query)) {
|
|
40
|
-
return query.toString()
|
|
38
|
+
return query.toString();
|
|
41
39
|
}
|
|
42
40
|
|
|
43
41
|
if (query['$where']) {
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
/**
|
|
2
|
+
Copyright: 2022 Contrast Security, Inc
|
|
3
|
+
Contact: support@contrastsecurity.com
|
|
4
|
+
License: Commercial
|
|
5
|
+
|
|
6
|
+
NOTICE: This Software and the patented inventions embodied within may only be
|
|
7
|
+
used as part of Contrast Security’s commercial offerings. Even though it is
|
|
8
|
+
made available through public repositories, use of this Software is subject to
|
|
9
|
+
the applicable End User Licensing Agreement found at
|
|
10
|
+
https://www.contrastsecurity.com/enduser-terms-0317a or as otherwise agreed
|
|
11
|
+
between Contrast Security and the End User. The Software may not be reverse
|
|
12
|
+
engineered, modified, repackaged, sold, redistributed or otherwise used in a
|
|
13
|
+
way not consistent with the End User License Agreement.
|
|
14
|
+
*/
|
|
15
|
+
'use strict';
|
|
16
|
+
|
|
17
|
+
const constants = require('../../constants');
|
|
18
|
+
const BaseSensor = require('../../hooks/frameworks/base');
|
|
19
|
+
const patcher = require('../../hooks/patcher');
|
|
20
|
+
const { PATCH_TYPES } = require('../../constants');
|
|
21
|
+
const { emitSinkEvent } = require('../../hooks/frameworks/common');
|
|
22
|
+
|
|
23
|
+
const { SINK_TYPES } = constants;
|
|
24
|
+
const ID = 'rethinkdb';
|
|
25
|
+
|
|
26
|
+
class RethinkDBSensor extends BaseSensor {
|
|
27
|
+
constructor(agent) {
|
|
28
|
+
super({ id: ID, agent });
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
install({ ModuleHook }) {
|
|
32
|
+
ModuleHook.resolve({ name: 'rethinkdb' }, (rethinkdb) => {
|
|
33
|
+
patcher.patch(rethinkdb, 'js', {
|
|
34
|
+
alwaysRun: true,
|
|
35
|
+
name: 'rethinkdb',
|
|
36
|
+
patchType: PATCH_TYPES.PROTECT_SINK,
|
|
37
|
+
pre: (data) => {
|
|
38
|
+
emitSinkEvent(data.args[0], SINK_TYPES.NOSQL_QUERY, ID);
|
|
39
|
+
}
|
|
40
|
+
});
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
return this;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
module.exports = RethinkDBSensor;
|
|
@@ -48,9 +48,9 @@ module.exports = function TraceEvent(event = {}) {
|
|
|
48
48
|
16: ret, // 17 ret
|
|
49
49
|
17: args, // 18 args
|
|
50
50
|
18: stack, // 19 stack
|
|
51
|
-
19: eventSources, //
|
|
52
|
-
20: event.source, //
|
|
53
|
-
21: event.target, //
|
|
54
|
-
22: taintRanges //
|
|
51
|
+
19: eventSources, // 20 event_sources
|
|
52
|
+
20: event.source, // 21 source
|
|
53
|
+
21: event.target, // 22 target
|
|
54
|
+
22: taintRanges // 23 taint_ranges
|
|
55
55
|
});
|
|
56
56
|
};
|
package/lib/util/source-map.js
CHANGED
|
@@ -156,9 +156,9 @@ class SourceMapUtility {
|
|
|
156
156
|
* @returns {string} fixed filename with full path
|
|
157
157
|
*/
|
|
158
158
|
replaceSource(original, source) {
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
159
|
+
return original === source
|
|
160
|
+
? original
|
|
161
|
+
: original.replace(path.basename(original), source);
|
|
162
162
|
}
|
|
163
163
|
}
|
|
164
164
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@contrast/agent",
|
|
3
|
-
"version": "4.
|
|
3
|
+
"version": "4.10.1",
|
|
4
4
|
"description": "Node.js security instrumentation by Contrast Security",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"security",
|
|
@@ -19,7 +19,13 @@
|
|
|
19
19
|
"Griffin Yourick",
|
|
20
20
|
"Ati Ok",
|
|
21
21
|
"Pat McClory",
|
|
22
|
-
"Michael Woytowitz"
|
|
22
|
+
"Michael Woytowitz",
|
|
23
|
+
"Jacob Kaplan",
|
|
24
|
+
"Yulia Tenincheva",
|
|
25
|
+
"Bruce MacNaughton",
|
|
26
|
+
"Krasen Penchev",
|
|
27
|
+
"Ivaylo Grahlyov",
|
|
28
|
+
"Yavor Stoychev"
|
|
23
29
|
],
|
|
24
30
|
"scripts": {
|
|
25
31
|
"docs": "jsdoc -c ../.jsdoc.json",
|
|
@@ -72,10 +78,10 @@
|
|
|
72
78
|
"@babel/types": "^7.12.1",
|
|
73
79
|
"@contrast/distringuish-prebuilt": "^2.2.0",
|
|
74
80
|
"@contrast/flat": "^4.1.1",
|
|
75
|
-
"@contrast/fn-inspect": "^2.4.
|
|
81
|
+
"@contrast/fn-inspect": "^2.4.4",
|
|
76
82
|
"@contrast/heapdump": "^1.1.0",
|
|
77
|
-
"@contrast/protobuf-api": "^3.2.
|
|
78
|
-
"@contrast/require-hook": "^2.0.
|
|
83
|
+
"@contrast/protobuf-api": "^3.2.3",
|
|
84
|
+
"@contrast/require-hook": "^2.0.8",
|
|
79
85
|
"@contrast/synchronous-source-maps": "^1.1.0",
|
|
80
86
|
"amqp-connection-manager": "^3.2.2",
|
|
81
87
|
"amqplib": "^0.8.0",
|
|
@@ -83,7 +89,7 @@
|
|
|
83
89
|
"bluebird": "^3.5.3",
|
|
84
90
|
"builtin-modules": "^3.2.0",
|
|
85
91
|
"cls-hooked": "^4.2.2",
|
|
86
|
-
"commander": "^
|
|
92
|
+
"commander": "^8.3.0",
|
|
87
93
|
"content-security-policy-parser": "^0.2.0",
|
|
88
94
|
"cookie": "^0.3.1",
|
|
89
95
|
"crc-32": "^1.0.0",
|
|
@@ -109,7 +115,7 @@
|
|
|
109
115
|
"@bmacnaughton/string-generator": "^1.0.0",
|
|
110
116
|
"@contrast/eslint-config": "^2.0.1",
|
|
111
117
|
"@contrast/fake-module": "file:test/mock/contrast-fake",
|
|
112
|
-
"@contrast/screener-service": "^1.12.
|
|
118
|
+
"@contrast/screener-service": "^1.12.9",
|
|
113
119
|
"@hapi/boom": "file:test/mock/boom",
|
|
114
120
|
"@hapi/hapi": "file:test/mock/hapi",
|
|
115
121
|
"@ls-lint/ls-lint": "^1.8.1",
|
|
@@ -125,8 +131,8 @@
|
|
|
125
131
|
"codecov": "^3.7.0",
|
|
126
132
|
"config": "^3.3.3",
|
|
127
133
|
"csv-writer": "^1.2.0",
|
|
128
|
-
"deasync": "^0.1.
|
|
129
|
-
"dustjs-linkedin": "^3.0.
|
|
134
|
+
"deasync": "^0.1.24",
|
|
135
|
+
"dustjs-linkedin": "^3.0.1",
|
|
130
136
|
"ejs": "^3.1.6",
|
|
131
137
|
"escape-html": "^1.0.3",
|
|
132
138
|
"eslint": "^8.2.0",
|
|
@@ -142,13 +148,13 @@
|
|
|
142
148
|
"husky": "^6.0.0",
|
|
143
149
|
"inquirer": "^8.1.2",
|
|
144
150
|
"joi": "^17.4.0",
|
|
145
|
-
"jsdoc": "^3.6.
|
|
151
|
+
"jsdoc": "^3.6.10",
|
|
146
152
|
"libxmljs": "file:test/mock/libxmljs",
|
|
147
153
|
"libxmljs2": "file:test/mock/libxmljs2",
|
|
148
154
|
"lint-staged": "^12.0.2",
|
|
149
155
|
"madge": "^4.0.1",
|
|
150
156
|
"marsdb": "file:test/mock/marsdb",
|
|
151
|
-
"mocha": "^9.
|
|
157
|
+
"mocha": "^9.2.0",
|
|
152
158
|
"mochawesome": "^7.0.1",
|
|
153
159
|
"mongodb": "file:test/mock/mongodb",
|
|
154
160
|
"mongodb-npm": "npm:mongodb@^3.6.5",
|
|
@@ -156,7 +162,7 @@
|
|
|
156
162
|
"mustache": "^3.0.1",
|
|
157
163
|
"mysql": "file:test/mock/mysql",
|
|
158
164
|
"nock": "^12.0.3",
|
|
159
|
-
"node-fetch": "^2.6.
|
|
165
|
+
"node-fetch": "^2.6.7",
|
|
160
166
|
"node-serialize": "file:test/mock/node-serialize",
|
|
161
167
|
"npm-license-crawler": "^0.2.1",
|
|
162
168
|
"nyc": "^15.1.0",
|