@newrelic/security-agent 0.0.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.
Files changed (87) hide show
  1. package/CHANGELOG.md +0 -0
  2. package/CONTRIBUTING.md +23 -0
  3. package/LICENSE +43 -0
  4. package/README.md +98 -0
  5. package/THIRD_PARTY_NOTICES.md +2909 -0
  6. package/index.js +24 -0
  7. package/lib/instrumentation-security/core/constants.js +66 -0
  8. package/lib/instrumentation-security/core/event-constants.js +49 -0
  9. package/lib/instrumentation-security/core/request-manager.js +73 -0
  10. package/lib/instrumentation-security/core/route-manager.js +30 -0
  11. package/lib/instrumentation-security/core/sec-trace.js +134 -0
  12. package/lib/instrumentation-security/core/sec-utils.js +212 -0
  13. package/lib/instrumentation-security/core/security-metadata.js +34 -0
  14. package/lib/instrumentation-security/core/stack-trace.js +156 -0
  15. package/lib/instrumentation-security/hooks/director/nr-director.js +98 -0
  16. package/lib/instrumentation-security/hooks/express/nr-express.js +106 -0
  17. package/lib/instrumentation-security/hooks/fastify/nr-fastify.js +155 -0
  18. package/lib/instrumentation-security/hooks/fs/nr-fs.js +391 -0
  19. package/lib/instrumentation-security/hooks/hapi/nr-hapi.js +131 -0
  20. package/lib/instrumentation-security/hooks/http/nr-http.js +461 -0
  21. package/lib/instrumentation-security/hooks/koa/@koa/nr-@koa-router.js +110 -0
  22. package/lib/instrumentation-security/hooks/ldap/nr-ldap.js +81 -0
  23. package/lib/instrumentation-security/hooks/mongodb/common.js +239 -0
  24. package/lib/instrumentation-security/hooks/mongodb/constants.js +91 -0
  25. package/lib/instrumentation-security/hooks/mongodb/nr-mongodb.js +49 -0
  26. package/lib/instrumentation-security/hooks/mongodb/v2-mongo.js +91 -0
  27. package/lib/instrumentation-security/hooks/mongodb/v3-mongo.js +36 -0
  28. package/lib/instrumentation-security/hooks/mongodb/v4-mongo.js +17 -0
  29. package/lib/instrumentation-security/hooks/mysql/nr-mysql.js +232 -0
  30. package/lib/instrumentation-security/hooks/native/nr-childProcess.js +131 -0
  31. package/lib/instrumentation-security/hooks/postgres/nr-postgres.js +131 -0
  32. package/lib/instrumentation-security/hooks/require/nr-require.js +93 -0
  33. package/lib/instrumentation-security/hooks/restify/nr-restify.js +104 -0
  34. package/lib/instrumentation-security/hooks/xpath/nr-xpath.js +91 -0
  35. package/lib/instrumentation-security/index.js +171 -0
  36. package/lib/nr-security-agent/index.js +170 -0
  37. package/lib/nr-security-agent/lib/core/Auth-headers.js +58 -0
  38. package/lib/nr-security-agent/lib/core/ContainerProperties.js +42 -0
  39. package/lib/nr-security-agent/lib/core/ECSProperties.js +34 -0
  40. package/lib/nr-security-agent/lib/core/FuzzFailEvent.js +27 -0
  41. package/lib/nr-security-agent/lib/core/LinkingMetadata.js +21 -0
  42. package/lib/nr-security-agent/lib/core/LogMessage.js +47 -0
  43. package/lib/nr-security-agent/lib/core/PodProperties.js +36 -0
  44. package/lib/nr-security-agent/lib/core/Policy.js +105 -0
  45. package/lib/nr-security-agent/lib/core/agent-status.js +56 -0
  46. package/lib/nr-security-agent/lib/core/agent.js +146 -0
  47. package/lib/nr-security-agent/lib/core/applicationinfo.js +634 -0
  48. package/lib/nr-security-agent/lib/core/commonUtils.js +411 -0
  49. package/lib/nr-security-agent/lib/core/connections/aws-lambda-client.js +55 -0
  50. package/lib/nr-security-agent/lib/core/connections/restclient.js +20 -0
  51. package/lib/nr-security-agent/lib/core/connections/websocket/index.js +25 -0
  52. package/lib/nr-security-agent/lib/core/connections/websocket/response/collecotor-policy-error-handler.js +18 -0
  53. package/lib/nr-security-agent/lib/core/connections/websocket/response/collector-policy-handler.js +20 -0
  54. package/lib/nr-security-agent/lib/core/connections/websocket/response/fuzz-request-handler.js +171 -0
  55. package/lib/nr-security-agent/lib/core/connections/websocket/response/index.js +47 -0
  56. package/lib/nr-security-agent/lib/core/connections/websocket/response/no-op-handler.js +12 -0
  57. package/lib/nr-security-agent/lib/core/connections/websocket/response/startup-handshake-handler.js +27 -0
  58. package/lib/nr-security-agent/lib/core/connections/websocket/response/unsupported-agent-handler.js +18 -0
  59. package/lib/nr-security-agent/lib/core/connections/websocket/response/ws-reconnect.js +14 -0
  60. package/lib/nr-security-agent/lib/core/connections/websocket/websocket.js +443 -0
  61. package/lib/nr-security-agent/lib/core/event.js +186 -0
  62. package/lib/nr-security-agent/lib/core/health-check.js +159 -0
  63. package/lib/nr-security-agent/lib/core/json-file-handler.js +66 -0
  64. package/lib/nr-security-agent/lib/core/jsonValidator.js +149 -0
  65. package/lib/nr-security-agent/lib/core/lambda-delegated-task-service.js +90 -0
  66. package/lib/nr-security-agent/lib/core/logging.js +176 -0
  67. package/lib/nr-security-agent/lib/core/sec-agent-constants.js +173 -0
  68. package/lib/nr-security-agent/lib/core/sec-util.js +166 -0
  69. package/lib/nr-security-agent/lib/core/sha-size-util.js +338 -0
  70. package/lib/nr-security-agent/lib/core/sha_worker.js +24 -0
  71. package/lib/nr-security-agent/lib/core/startup-config.js +29 -0
  72. package/lib/nr-security-agent/lib/core/statusUtils.js +157 -0
  73. package/lib/nr-security-agent/lib/core/timeunit.js +44 -0
  74. package/lib/nr-security-agent/lib/core/websocket-client.js +335 -0
  75. package/lib/nr-security-agent/lib/core/worker-entities.js +82 -0
  76. package/lib/nr-security-agent/lib/core/worker.js +148 -0
  77. package/lib/nr-security-agent/lib/core/xss-utils.js +297 -0
  78. package/lib/nr-security-agent/lib/models/lambda-delegated-task/constants.js +12 -0
  79. package/lib/nr-security-agent/lib/models/lambda-delegated-task/index.js +15 -0
  80. package/lib/nr-security-agent/lib/models/lambda-delegated-task/lambda-delegated-sha-calculation.js +37 -0
  81. package/lib/nr-security-agent/lib/models/lambda-delegated-task/lambda-delegated-task-base.js +50 -0
  82. package/lib/nr-security-agent/lib/models/lambda-delegated-task/lambda-delegated-task-type.js +17 -0
  83. package/lib/nr-security-agent/resources/cert.pem +31 -0
  84. package/lib/nr-security-agent/resources/config.js +19 -0
  85. package/lib/nr-security-agent/resources/default-policy.yaml +36 -0
  86. package/lib/nr-security-api/index.js +111 -0
  87. package/package.json +95 -0
@@ -0,0 +1,232 @@
1
+ /*
2
+ * Copyright 2023 New Relic Corporation. All rights reserved.
3
+ * SPDX-License-Identifier: Apache-2.0
4
+ */
5
+
6
+ const requestManager = require("../../core/request-manager");
7
+
8
+ const async_hooks = require("async_hooks");
9
+ const secUtils = require('../../core/sec-utils');
10
+ const API = require("../../../nr-security-api");
11
+ const securityMetaData = require('../../core/security-metadata');
12
+ const { EVENT_TYPE, EVENT_CATEGORY } = require('../../core/event-constants');
13
+ const { NR_CSEC_FUZZ_REQUEST_ID } = require('../../core/constants');
14
+ const logger = API.getLogger();
15
+
16
+ module.exports = initialize;
17
+
18
+ /**
19
+ * Entry point of mysql and msyql2 module hooks
20
+ * @param {*} shim
21
+ * @param {*} mysql
22
+ * @param {*} moduleName
23
+ */
24
+ function initialize(shim, mysql, moduleName) {
25
+ logger.info("Instrumenting", moduleName);
26
+ if (shim._moduleRoot.includes("mysql2")) {
27
+ promiseInitialize(shim, mysql, moduleName);
28
+ } else {
29
+ callbackInitialize(shim, mysql, moduleName);
30
+ }
31
+ }
32
+
33
+ /**
34
+ * Wrapper for mysql module hooks
35
+ * @param {*} shim
36
+ * @param {*} mysql
37
+ * @param {*} moduleName
38
+ */
39
+ function callbackInitialize(shim, mysql, moduleName) {
40
+ shim.__wrappedPoolConnection = false;
41
+
42
+ shim.wrapReturn(mysql, "createConnection", wrapCreateConnection);
43
+ function wrapCreateConnection(shim, fn, fnName, connection) {
44
+ if (wrapQueryable(shim, connection, false)) {
45
+ const connProto = Object.getPrototypeOf(connection);
46
+ shim.unwrap(mysql, "createConnection");
47
+ }
48
+ }
49
+
50
+ shim.wrapReturn(mysql, "createPool", wrapCreatePool);
51
+ function wrapCreatePool(shim, fn, fnName, pool) {
52
+ if (wrapQueryable(shim, pool, true) && wrapGetConnection(shim, pool)) {
53
+ shim.unwrap(mysql, "createPool");
54
+ }
55
+ }
56
+
57
+ shim.wrapReturn(mysql, "createPoolCluster", wrapCreatePoolCluster);
58
+ function wrapCreatePoolCluster(shim, fn, fnName, poolCluster) {
59
+ const proto = Object.getPrototypeOf(poolCluster);
60
+ shim.wrapReturn(proto, "of", wrapPoolClusterOf);
61
+ function wrapPoolClusterOf(shim, of, _n, poolNamespace) {
62
+ if (wrapGetConnection(shim, poolNamespace)) {
63
+ shim.unwrap(proto, "of");
64
+ }
65
+ }
66
+ if (wrapGetConnection(shim, poolCluster)) {
67
+ shim.unwrap(mysql, "createPoolCluster");
68
+ }
69
+ }
70
+ }
71
+
72
+ /**
73
+ * Wrapper for mysql2 module hooks
74
+ * @param {*} shim
75
+ */
76
+ function promiseInitialize(shim) {
77
+ const callbackAPI = shim.require("./index");
78
+ if (callbackAPI && !shim.isWrapped(callbackAPI.createConnection)) {
79
+ callbackInitialize(shim, callbackAPI);
80
+ }
81
+ }
82
+
83
+ /**
84
+ * Wrapper to hook connection obejct.
85
+ * @param {*} shim
86
+ * @param {*} connectable
87
+ * @returns
88
+ */
89
+ function wrapGetConnection(shim, connectable) {
90
+ if (
91
+ !connectable ||
92
+ !connectable.getConnection ||
93
+ shim.isWrapped(connectable.getConnection)
94
+ ) {
95
+ return false;
96
+ }
97
+
98
+ const proto = Object.getPrototypeOf(connectable);
99
+ shim.wrap(proto, "getConnection", function doWrapGetConnection(shim, fn) {
100
+ return function wrappedGetConnection() {
101
+ const args = shim.toArray(arguments);
102
+ const cbIdx = args.length - 1;
103
+
104
+ if (shim.isFunction(args[cbIdx]) && !shim.isWrapped(args[cbIdx])) {
105
+ let cb = args[cbIdx];
106
+ if (!shim.__wrappedPoolConnection) {
107
+ cb = shim.wrap(cb, wrapGetConnectionCallback);
108
+ }
109
+ args[cbIdx] = shim.bindSegment(cb);
110
+ }
111
+ return fn.apply(this, args);
112
+ };
113
+ });
114
+
115
+ return true;
116
+ }
117
+
118
+ function wrapGetConnectionCallback(shim, cb) {
119
+ return function wrappedGetConnectionCallback(err, conn) {
120
+ try {
121
+ if (!err && wrapQueryable(shim, conn, false)) {
122
+ // Leave getConnection wrapped in order to maintain TX state, but we can
123
+ // simplify the wrapping of its callback in future calls.
124
+ shim.__wrappedPoolConnection = true;
125
+ }
126
+ } catch (_err) { }
127
+ return cb.apply(this, arguments);
128
+ };
129
+ }
130
+
131
+ /**
132
+ * Wrapper to hook query function.
133
+ * @param {*} shim
134
+ * @param {*} queryable
135
+ * @param {*} isPoolQuery
136
+ * @returns
137
+ */
138
+ function wrapQueryable(shim, queryable, isPoolQuery) {
139
+ if (!queryable || !queryable.query || shim.isWrapped(queryable.query)) {
140
+ return false;
141
+ }
142
+ const proto = Object.getPrototypeOf(queryable);
143
+ queryHook(shim, proto, "query", isPoolQuery);
144
+ if (queryable.execute) {
145
+ queryHook(shim, proto, "execute", isPoolQuery);
146
+ }
147
+ return true;
148
+ }
149
+
150
+ /**
151
+ * Utility to extract query from the intercepted args
152
+ * @param {*} shim
153
+ * @param {*} args
154
+ * @returns
155
+ */
156
+ function extractQueryArgs(shim, args) {
157
+ let rawQuery = "";
158
+ let param = [];
159
+
160
+ // Figure out the query parameter.
161
+ if (shim.isString(args[0])) {
162
+ // query(sql [, values], callback)
163
+ rawQuery = args[0];
164
+ } else {
165
+ // query(opts [, values], callback)
166
+ rawQuery = args[0].sql;
167
+ }
168
+ // Then determine the query values and callback parameters.
169
+ if (shim.isArray(args[1])) {
170
+ // query({opts|sql}, values, callback)
171
+ param = args[1];
172
+ }
173
+ else if (args[1] && typeof args[1] == 'object') {
174
+ param = args[1];
175
+ param = Object.values(param)
176
+ }
177
+ return {
178
+ rawQuery: rawQuery,
179
+ param: param,
180
+ };
181
+ }
182
+ /**
183
+ * Wrapper to wrap query function.
184
+ * @param {*} shim
185
+ * @param {*} mod
186
+ * @param {*} method
187
+ */
188
+ function queryHook(shim, mod, method, isPoolQuery) {
189
+
190
+ shim.wrap(mod, method, function makeQueryWrapper(shim, fn) {
191
+ return function queryWrapper() {
192
+ const parameters = extractQueryArgs(shim, arguments);
193
+ shim.interceptedArgs = parameters;
194
+ const request = requestManager.getRequest(shim);
195
+ if (request && !isPoolQuery) {
196
+ const traceObject = secUtils.getTraceObject(shim);
197
+ traceObject.sourceMethod = method;
198
+ const secMetadata = securityMetaData.getSecurityMetaData(request, parameters, traceObject, secUtils.getExecutionId(), EVENT_TYPE.DB_COMMAND, EVENT_CATEGORY.MYSQL)
199
+ const secEvent = API.generateSecEvent(secMetadata);
200
+ API.sendEvent(secEvent);
201
+ if (request.headers[NR_CSEC_FUZZ_REQUEST_ID]) {
202
+ callbackHook(shim, arguments, arguments.length - 1, secEvent);
203
+ }
204
+ }
205
+ return fn.apply(this, arguments);
206
+ };
207
+ });
208
+ }
209
+
210
+
211
+ /**
212
+ * Callback hook to generate exit event
213
+ * @param {*} shim
214
+ * @param {*} mod
215
+ * @param {*} fun
216
+ * @param {*} secEvent
217
+ */
218
+ function callbackHook(shim, mod, fun, secEvent) {
219
+ shim.secEvent = secEvent;
220
+ shim.wrap(mod, fun, function callbackWrapper(shim, fn) {
221
+ if (!shim.isFunction(fn)) {
222
+ return fn;
223
+ }
224
+ return function wrapper() {
225
+ if ((arguments[0] === null || arguments[0] === undefined) && shim.secEvent) {
226
+ API.generateExitEvent(shim.secEvent);
227
+ delete shim.secEvent;
228
+ }
229
+ return fn.apply(this, arguments);
230
+ }
231
+ })
232
+ }
@@ -0,0 +1,131 @@
1
+ /*
2
+ * Copyright 2023 New Relic Corporation. All rights reserved.
3
+ * SPDX-License-Identifier: Apache-2.0
4
+ */
5
+
6
+ module.exports = initialize;
7
+ const requestManager = require("../../core/request-manager");
8
+ const secUtils = require("../../core/sec-utils");
9
+ const API = require("../../../nr-security-api");
10
+ const securityMetaData = require('../../core/security-metadata');
11
+ const { EVENT_TYPE, EVENT_CATEGORY } = require('../../core/event-constants');
12
+ const { NR_CSEC_FUZZ_REQUEST_ID } = require('../../core/constants');
13
+ const logger = API.getLogger();
14
+
15
+ function initialize(shim, childProcess, moduleName) {
16
+ logger.info('Instrumenting child_process');
17
+ execFileHook(shim, childProcess, moduleName);
18
+ spawnHook(shim, childProcess, moduleName);
19
+ spawnSyncHook(shim, process.binding("spawn_sync"), moduleName);
20
+ }
21
+ /**
22
+ * Wrapper to hook childProcess.execFile()
23
+ * @param {*} shim
24
+ * @param {*} childProcess
25
+ * @param {*} moduleName
26
+ */
27
+ function execFileHook(shim, childProcess, moduleName) {
28
+ shim.wrap(childProcess, "execFile", function makeWrapper(shim, fn) {
29
+ return function wrapper() {
30
+ const interceptedArgs = [arguments[0]];
31
+ shim.interceptedArgs = interceptedArgs;
32
+ const request = requestManager.getRequest(shim);
33
+ if (request) {
34
+ const traceObject = secUtils.getTraceObject(shim);
35
+ const secMetadata = securityMetaData.getSecurityMetaData(request, interceptedArgs, traceObject, secUtils.getExecutionId(), EVENT_TYPE.SYSTEM_COMMAND, EVENT_CATEGORY.SYS)
36
+ const secEvent = API.generateSecEvent(secMetadata);
37
+ API.sendEvent(secEvent);
38
+ if (request.headers[NR_CSEC_FUZZ_REQUEST_ID]) {
39
+ callbackHook(shim, arguments, arguments.length - 1, secEvent);
40
+ }
41
+
42
+ }
43
+
44
+ return fn.apply(this, arguments);
45
+ };
46
+ });
47
+ }
48
+
49
+ /**
50
+ * Function to wrap childProcess.spawnSync()
51
+ * @param {*} shim
52
+ * @param {*} childProcess
53
+ * @param {*} moduleName
54
+ */
55
+ function spawnSyncHook(shim, childProcess, moduleName) {
56
+ shim.wrap(childProcess, "spawn", function makeWrapper(shim, fn) {
57
+ return function wrapper() {
58
+ const interceptedArgs = arguments[0].args;
59
+ shim.interceptedArgs = interceptedArgs;
60
+ const request = requestManager.getRequest(shim);
61
+ if (request) {
62
+ const traceObject = secUtils.getTraceObject(shim);
63
+ const secMetadata = securityMetaData.getSecurityMetaData(request, interceptedArgs, traceObject, secUtils.getExecutionId(), EVENT_TYPE.SYSTEM_COMMAND, EVENT_CATEGORY.SYS)
64
+ this.secEvent = API.generateSecEvent(secMetadata);
65
+ API.sendEvent(this.secEvent);
66
+ }
67
+ const result = fn.apply(this, arguments);
68
+
69
+ if(result && result.status==0 && request && request.headers[NR_CSEC_FUZZ_REQUEST_ID]){
70
+ API.generateExitEvent(this.secEvent);
71
+ delete this.secEvent
72
+ }
73
+ return result;
74
+ };
75
+ });
76
+ }
77
+
78
+ /**
79
+ * Function to wrap childProcess.spawn()
80
+ * @param {*} shim
81
+ * @param {*} childProcess
82
+ * @param {*} moduleName
83
+ */
84
+ function spawnHook(shim, childProcess, moduleName) {
85
+ shim.wrap(childProcess, "spawn", function makeWrapper(shim, fn) {
86
+ return function wrapper() {
87
+ let param = [];
88
+ param.push(arguments[0]);
89
+ if (arguments[1]) {
90
+ param.push(arguments[1].toString());
91
+
92
+ }
93
+ const interceptedArgs = param;
94
+ shim.interceptedArgs = interceptedArgs;
95
+ const request = requestManager.getRequest(shim);
96
+ if (request) {
97
+ const traceObject = secUtils.getTraceObject(shim);
98
+ const secMetadata = securityMetaData.getSecurityMetaData(request, interceptedArgs, traceObject, secUtils.getExecutionId(), EVENT_TYPE.SYSTEM_COMMAND, EVENT_CATEGORY.SYS)
99
+ const secEvent = API.generateSecEvent(secMetadata);
100
+ API.sendEvent(secEvent);
101
+ if (request.headers[NR_CSEC_FUZZ_REQUEST_ID]) {
102
+ callbackHook(shim, arguments, arguments.length - 1, secEvent);
103
+ }
104
+ }
105
+ return fn.apply(this, arguments);
106
+ };
107
+ });
108
+ }
109
+
110
+ /**
111
+ * Callback hook to generate exit event
112
+ * @param {*} shim
113
+ * @param {*} mod
114
+ * @param {*} fun
115
+ * @param {*} secEvent
116
+ */
117
+ function callbackHook(shim, mod, fun, secEvent) {
118
+ shim.secEvent = secEvent;
119
+ shim.wrap(mod, fun, function callbackWrapper(shim, fn) {
120
+ if (!shim.isFunction(fn)) {
121
+ return fn;
122
+ }
123
+ return function wrapper(secEvent) {
124
+ if ((arguments[0] === null || arguments[0] === undefined) && shim.secEvent) {
125
+ API.generateExitEvent(shim.secEvent);
126
+ delete shim.secEvent;
127
+ }
128
+ return fn.apply(this, arguments);
129
+ }
130
+ })
131
+ }
@@ -0,0 +1,131 @@
1
+ /*
2
+ * Copyright 2023 New Relic Corporation. All rights reserved.
3
+ * SPDX-License-Identifier: Apache-2.0
4
+ */
5
+
6
+
7
+ 'use strict'
8
+
9
+ const requestManager = require('../../core/request-manager');
10
+ const secUtils = require('../../core/sec-utils');
11
+ const API = require("../../../nr-security-api");
12
+ const securityMetaData = require('../../core/security-metadata');
13
+ const { EVENT_TYPE, EVENT_CATEGORY } = require('../../core/event-constants');
14
+ const logger = API.getLogger();
15
+ const { NR_CSEC_FUZZ_REQUEST_ID } = require('../../core/constants');
16
+
17
+ module.exports = function initialize(shim, pgsql, moduleName) {
18
+ logger.info('Instrumenting '+ moduleName)
19
+ // allows for native wrapping to not happen if not necessary
20
+ // when env var is true
21
+ if (process.env.NODE_PG_FORCE_NATIVE) {
22
+ return instrumentPGNative(pgsql)
23
+ }
24
+
25
+ // wrapping for native
26
+ function instrumentPGNative(pg) {
27
+ shim.wrapReturn(pg, 'Client', clientFactoryWrapper)
28
+ shim.wrapClass(pg, 'Pool', { post: poolPostConstructor, es6: true })
29
+ }
30
+
31
+ function poolPostConstructor(shim) {
32
+ if (!shim.isWrapped(this.Client)) {
33
+ shim.wrapClass(this, 'Client', clientPostConstructor)
34
+ }
35
+ }
36
+
37
+ function clientFactoryWrapper(shim, fn, fnName, client) {
38
+ clientPostConstructor.call(client, shim)
39
+ }
40
+
41
+ function clientPostConstructor(shim) {
42
+ queryHook(shim, this, 'query');
43
+ }
44
+
45
+ // The pg module defines "native" getter which sets up the native client lazily
46
+ // (only when called). We replace the getter, so that we can instrument the native
47
+ // client. The original getter replaces itself with the instance of the native
48
+ // client, so only instrument if the getter exists (otherwise assume already
49
+ // instrumented).
50
+ const origGetter = pgsql.__lookupGetter__('native')
51
+ if (origGetter) {
52
+ delete pgsql.native
53
+ pgsql.__defineGetter__('native', function getNative() {
54
+ const temp = origGetter()
55
+ if (temp != null) {
56
+ instrumentPGNative(temp)
57
+ }
58
+ return temp
59
+ })
60
+ }
61
+
62
+ queryHook(shim, pgsql && pgsql.Client && pgsql.Client.prototype, 'query');
63
+ }
64
+
65
+
66
+
67
+ function queryHook(shim, mod, method){
68
+ shim.wrap(mod, method, function makeQueryWrapper(shim, fn){
69
+ return function queryWrapper(){
70
+ const request = requestManager.getRequest(shim);
71
+ const sqlArgs = [];
72
+ if (typeof arguments[0] === 'object') {
73
+ if ((arguments[0] && arguments[0].constructor && arguments[0].constructor.name == 'Cursor') || (arguments[0] && arguments[0].text && arguments[0].values)) {
74
+ sqlArgs.push(arguments[0].text);
75
+ if (Array.isArray(arguments[0].values)) {
76
+ sqlArgs.push(arguments[0].values);
77
+ }
78
+ } else if (arguments[0] && arguments[0].constructor && arguments[0].constructor.name == 'QueryStream' && arguments[0].cursor) {
79
+ sqlArgs.push(arguments[0].cursor.text);
80
+ if (Array.isArray(arguments[0].cursor.values)) {
81
+ sqlArgs.push(arguments[0].cursor.values);
82
+ }
83
+ }
84
+ else if(arguments[0] && arguments[0].text){
85
+ sqlArgs.push(arguments[0].text);
86
+ }
87
+ } else {
88
+ for (let i = 0; i < arguments.length; i++) {
89
+ if (typeof arguments[i] !== 'function') {
90
+ sqlArgs.push(arguments[i]);
91
+ }
92
+ }
93
+ }
94
+ shim.interceptedArgs = sqlArgs;
95
+ if (request) {
96
+ const traceObject = secUtils.getTraceObject(shim);
97
+ const secMetadata = securityMetaData.getSecurityMetaData(request, sqlArgs, traceObject, secUtils.getExecutionId(), EVENT_TYPE.DB_COMMAND, EVENT_CATEGORY.POSTGRES)
98
+ const secEvent = API.generateSecEvent(secMetadata);
99
+ API.sendEvent(secEvent);
100
+ if (request.headers[NR_CSEC_FUZZ_REQUEST_ID]) {
101
+ callbackHook(shim, arguments, arguments.length - 1, secEvent);
102
+ }
103
+ }
104
+ return fn.apply(this, arguments);
105
+ }
106
+ })
107
+
108
+ }
109
+
110
+ /**
111
+ * Callback hook to generate exit event
112
+ * @param {*} shim
113
+ * @param {*} mod
114
+ * @param {*} fun
115
+ * @param {*} secEvent
116
+ */
117
+ function callbackHook(shim, mod, fun, secEvent) {
118
+ shim.secEvent = secEvent;
119
+ shim.wrap(mod, fun, function callbackWrapper(shim, fn) {
120
+ if (!shim.isFunction(fn)) {
121
+ return fn;
122
+ }
123
+ return function wrapper() {
124
+ if ((arguments[0] === null || arguments[0] === undefined) && shim.secEvent) {
125
+ API.generateExitEvent(shim.secEvent);
126
+ delete shim.secEvent;
127
+ }
128
+ return fn.apply(this, arguments);
129
+ }
130
+ })
131
+ }
@@ -0,0 +1,93 @@
1
+ /*
2
+ * Copyright 2023 New Relic Corporation. All rights reserved.
3
+ * SPDX-License-Identifier: Apache-2.0
4
+ */
5
+
6
+ const requestManager = require('../../core/request-manager');
7
+ const secUtils = require("../../core/sec-utils");
8
+ const API = require("../../../nr-security-api");
9
+ const securityMetaData = require('../../core/security-metadata');
10
+ const { EVENT_TYPE, EVENT_CATEGORY } = require('../../core/event-constants');
11
+ const { STRING } = require('../../core/constants')
12
+ const logger = API.getLogger();
13
+ const Module = require('module');
14
+ const refDirRegEx = /^(\.\/)|^(\.\.\/)/g;
15
+ const path = require('path');
16
+ const CSEC = 'nr-security-agent';
17
+
18
+ /**
19
+ * Entry point for xpath module hook
20
+ * @param {*} shim
21
+ * @param {*} mod
22
+ * @param {*} moduleName
23
+ */
24
+ function initialize(shim) {
25
+
26
+ const original_load = Module._load;
27
+ logger.info('Instrumenting Module._load');
28
+
29
+ Module._load = function (request, parent) {
30
+
31
+ let moduleName = arguments[0];
32
+
33
+ if (arguments[0].match(refDirRegEx) && arguments[1] && arguments[1].path) {
34
+ moduleName = path.resolve(arguments[1].path, arguments[0]);
35
+ }
36
+
37
+ let flag = false;
38
+ if (moduleName && typeof (moduleName) === STRING && !moduleName.includes(CSEC)) {
39
+ flag = true;
40
+ }
41
+ else if (parent && parent.id && typeof (parent.id) === STRING && moduleName.includes(CSEC) && parent.id.includes(CSEC)) {
42
+ flag = false;
43
+ }
44
+ else if (parent && parent.id && moduleName && typeof (moduleName) === STRING && moduleName.includes(CSEC) && parent.id.includes(CSEC)) {
45
+ flag = false;
46
+ }
47
+ if (flag) {
48
+ requireHook(shim, moduleName, parent);
49
+ }
50
+
51
+ return original_load.apply(this, arguments);
52
+
53
+ }
54
+
55
+ }
56
+
57
+ function requireHook(shim, moduleName, parent) {
58
+ try {
59
+ let request = requestManager.getRequest(shim);
60
+ let fallback = false;
61
+ if (!request) {
62
+ fallback = true;
63
+ let values = [...requestManager.requestMap.values()];
64
+ if (values.length > 0) {
65
+ request = values[values.length - 1];
66
+ }
67
+ }
68
+ if (request) {
69
+ const interceptedArgs = [moduleName];
70
+ let traceObject;
71
+ if (!fallback) {
72
+ traceObject = secUtils.getTraceObject(shim);
73
+ }
74
+ else {
75
+ traceObject = secUtils.getTraceObjectFallback(request);
76
+ }
77
+ const secMetadata = securityMetaData.getSecurityMetaData(request, interceptedArgs, traceObject, secUtils.getExecutionId(), EVENT_TYPE.FILE_OPERATION, EVENT_CATEGORY.FILE)
78
+ const secEvent = API.generateSecEvent(secMetadata);
79
+ API.sendEvent(secEvent);
80
+ }
81
+ } catch (error) {
82
+
83
+ }
84
+
85
+
86
+
87
+ }
88
+
89
+
90
+ module.exports = {
91
+ initialize
92
+ }
93
+
@@ -0,0 +1,104 @@
1
+ /*
2
+ * Copyright 2023 New Relic Corporation. All rights reserved.
3
+ * SPDX-License-Identifier: Apache-2.0
4
+ */
5
+
6
+ module.exports = initialize
7
+ const requestManager = require('../../core/request-manager');
8
+ const secUtils = require('../../core/sec-utils');
9
+ const { ATTHERATE, DOUBLE_DOLLAR } = require('../../core/constants');
10
+ const lodash = require('lodash');
11
+ const routeManager = require('../../core/route-manager');
12
+ const url = require('url');
13
+ const API = require("../../../nr-security-api");
14
+ const logger = API.getLogger();
15
+
16
+ /**
17
+ * Entry point of restify module hook.
18
+ * Wrapper for registryRadix module
19
+ * @param {*} shim
20
+ * @param {*} mod
21
+ * @param {*} moduleName
22
+ */
23
+ function initialize(shim, mod, moduleName) {
24
+ logger.info('Instrumenting Restify');
25
+ try {
26
+ const registryRadix = shim.require("./lib/routerRegistryRadix");
27
+
28
+ //routerRadix hook
29
+ shim.wrap(registryRadix && registryRadix.prototype, 'add', function makeWrapper(shim, fn) {
30
+ return function wrapper() {
31
+ if (arguments[0]) {
32
+ try {
33
+ const method = lodash.upperCase(arguments[0].method);
34
+ const path = arguments[0].path;
35
+ const key = method + ATTHERATE + path;
36
+ const stakTrace = secUtils.traceElementForRoute();
37
+ const splittedStack = stakTrace[0].split(DOUBLE_DOLLAR);
38
+ routeManager.setRoute(key, splittedStack[0]);
39
+ } catch (error) {
40
+
41
+ }
42
+ }
43
+ return fn.apply(this, arguments);
44
+ }
45
+ })
46
+
47
+ const router = shim.require("./lib/router");
48
+
49
+ shim.wrap(router && router.prototype, 'lookup', function lookupWrapper(shim, fn) {
50
+ return function wrappedLookup() {
51
+ const result = fn.apply(this, arguments);
52
+ extractParams(shim, arguments[0]);
53
+ return result;
54
+ }
55
+ })
56
+ } catch (error) {
57
+ }
58
+
59
+ }
60
+
61
+ /**
62
+ * Utilty to extract path params and query params  
63
+ * @param {*} shim
64
+ * @param {*} req
65
+ */
66
+ function extractParams(shim, req) {
67
+ const segment = shim.getActiveSegment();
68
+ if (segment && segment.transaction) {
69
+
70
+ let request = requestManager.getRequestFromId(segment.transaction.id);
71
+ if (req.params && request) {
72
+ try {
73
+ Object.keys(req.params).forEach(function (key) {
74
+ if (req.params[key]) {
75
+ if (!request.parameterMap[key]) {
76
+ request.parameterMap[key] = new Array(req.params[key].toString());
77
+ requestManager.setRequest(segment.transaction.id, request);
78
+ }
79
+ }
80
+ });
81
+ } catch (error) {
82
+
83
+ }
84
+ }
85
+ if (req.query && request) {
86
+ try {
87
+ const url_parts = url.parse(req.url, true);
88
+ const query = url_parts.query;
89
+ Object.keys(query).forEach(function (key) {
90
+ if (query[key]) {
91
+ request.parameterMap[key] = new Array(query[key].toString());
92
+ requestManager.setRequest(segment.transaction.id, request);
93
+ }
94
+ });
95
+ } catch (error) {
96
+
97
+ }
98
+ }
99
+ if (req.route && req.route.path && request) {
100
+ request.uri = req.route.path;
101
+ requestManager.setRequest(segment.transaction.id, request);
102
+ }
103
+ }
104
+ }