Skip to content
6 changes: 4 additions & 2 deletions lib/instrumentation-security/core/event-constants.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,8 @@ const EVENT_TYPE = {
UNVALIDATED_REDIRECT: 'UNVALIDATED_REDIRECT',
REFLECTED_XSS: 'REFLECTED_XSS',
XPATH: 'XPATH',
LDAP: 'LDAP'
LDAP: 'LDAP',
CACHING_DATA_STORE: 'CACHING_DATA_STORE'
}
const EVENT_CATEGORY = {
MYSQL: 'MYSQL',
Expand All @@ -40,7 +41,8 @@ const EVENT_CATEGORY = {
UNVALIDATED_REDIRECT: 'UNVALIDATED_REDIRECT',
REFLECTED_XSS: 'REFLECTED_XSS',
XPATH: 'XPATH',
LDAP: 'LDAP'
LDAP: 'LDAP',
MEMCACHED: 'MEMCACHED'
}

module.exports = {
Expand Down
104 changes: 104 additions & 0 deletions lib/instrumentation-security/hooks/memcached/nr-memcached.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
/*
* Copyright 2023 New Relic Corporation. All rights reserved.
* SPDX-License-Identifier: Apache-2.0
*/

'use strict'

const requestManager = require('../../core/request-manager');
const secUtils = require('../../core/sec-utils');
const API = require("../../../nr-security-api");
const securityMetaData = require('../../core/security-metadata');
const { EVENT_TYPE, EVENT_CATEGORY } = require('../../core/event-constants');
const logger = API.getLogger();
const { NR_CSEC_FUZZ_REQUEST_ID } = require('../../core/constants');

const OperationMap = {
'set': 'write',
'get': 'read',
'gets': 'read',
'replace': 'update',
'add': 'write',
'cas': 'write',
'append': 'write',
'prepend': 'write',
'delete': 'delete',
'touch': 'update',
'incr': 'update',
'decr': 'update',
'version': 'read',
'flush_all': 'delete',
'stats': 'read',
'stats settings': 'read',
'stats slabs': 'read',
'stats items': 'read',
'stats cachedump': 'read'

}

module.exports = function initialize(shim, memcached, moduleName, additionalMod) {
logger.info('Instrumenting ' + moduleName)
let utils;
if (additionalMod) {
utils = additionalMod;
}
else {
utils = shim.require('./lib/utils');
}
validateArgHook(shim, utils, 'validateArg');
}


function prepareSecurityArgs(args) {
const obj = args[0];
let parameters = Object.create(null);
try {
if (obj) {
parameters.mode = obj['type'];
let params = [];
params.push(obj['key'].toString());
if (obj['value']) {
params.push(obj['value']);
}
parameters.arguments = params;
parameters.type = OperationMap[parameters.mode]? OperationMap[parameters.mode]: 'unknown';
}
} catch (error) {
logger.debug("Error in preparing memcached parameters:", error);
}

return parameters;
}

/**
* Wrapper to hook validateArg method
* @param {*} shim
* @param {*} mod
* @param {*} method
*/
function validateArgHook(shim, mod, method) {
shim.wrap(mod, method, function makeQueryWrapper(shim, fn) {
return function queryWrapper() {
let params = prepareSecurityArgs(arguments);
shim.interceptedArgs = params;
const request = requestManager.getRequest(shim);

if (request) {
const traceObject = secUtils.getTraceObject(shim);
traceObject.sourceMethod = method;
const secMetadata = securityMetaData.getSecurityMetaData(request, params, traceObject, secUtils.getExecutionId(), EVENT_TYPE.CACHING_DATA_STORE, EVENT_CATEGORY.MEMCACHED)
const secEvent = API.generateSecEvent(secMetadata);
this.secEvent = secEvent;
API.sendEvent(secEvent);
}

const result = fn.apply(this, arguments);
if (result && request && request.headers[NR_CSEC_FUZZ_REQUEST_ID]) {
API.generateExitEvent(this.secEvent);
delete this.secEvent
}
return result;
};
});
}

9 changes: 8 additions & 1 deletion lib/instrumentation-security/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -190,7 +190,14 @@ newrelic.instrumentWebframework({
}
})


newrelic.instrumentDatastore({
moduleName: 'memcached',
isEsm: true,
onRequire: require('./hooks/memcached/nr-memcached'),
onError: function intrumentErrorHandler(err) {
logger.error(err.message, err.stack)
}
})



Expand Down
98 changes: 98 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@
"eslint-plugin-promise": "^4.3.1",
"eslint-plugin-sonarjs": "^0.15.0",
"koa": "^2.14.1",
"memcached": "^2.2.2",
"mongodb": "^4.13.0",
"mongodb-memory-server": "^8.11.2",
"mongodb2": "npm:mongodb@^2.2.36",
Expand Down
Loading