Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Support for IAST restrictions to scan #254

Closed
wants to merge 94 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
94 commits
Select commit Hold shift + click to select a range
d0fc7cc
logger for transaction errors
sumitsuthar May 15, 2024
7ecdf28
exception report generation
sumitsuthar May 16, 2024
43f832d
hanlding to send application error json
sumitsuthar May 20, 2024
77fab60
clean up
sumitsuthar May 20, 2024
82554f8
Merge branch 'main' into error_reporting
sumitsuthar May 20, 2024
a4a6953
added accountId and jsonName update
sumitsuthar May 23, 2024
a77f3f8
minor fix
sumitsuthar May 23, 2024
54f75be
Merge branch 'error_reporting' of https://github.com/newrelic/csec-no…
sumitsuthar May 23, 2024
6199cf4
minor fix
sumitsuthar May 23, 2024
e25a838
added accountId
sumitsuthar May 23, 2024
d6007f6
handling to collect and report uncaught exception
sumitsuthar May 27, 2024
8c9785f
handling to exit the process manually
sumitsuthar May 27, 2024
c037400
updated jsonName and added type
sumitsuthar May 28, 2024
bc04e3e
minor fix
sumitsuthar May 28, 2024
5bf7fb4
fix
sumitsuthar May 28, 2024
ae36eed
Implemented exception reporting schedular
sumitsuthar May 28, 2024
2eeb747
code refactor
sumitsuthar May 28, 2024
f7a3558
Merge branch 'main' into error_reporting
sumitsuthar Jun 3, 2024
365d89b
Handling to report 5xx errors and added category
sumitsuthar Jun 5, 2024
c73b453
Updated secure cookie event generation
sumitsuthar Jun 6, 2024
864d43b
updated stacktrace to stackTrace
sumitsuthar Jun 6, 2024
669f466
Merge branch 'error_reporting' into secure_cookie_event_update
sumitsuthar Jun 7, 2024
3a0ae68
added key identifier
sumitsuthar Jul 3, 2024
fcdcf30
added key identifier
sumitsuthar Jul 12, 2024
7650496
merge fix
sumitsuthar Jul 16, 2024
ed4c88e
cleanup
sumitsuthar Jul 16, 2024
41d44c9
Merge branch 'main' into key_identifier
sumitsuthar Jul 16, 2024
e476e06
Merge branch 'main' into secure_cookie_event_update
sumitsuthar Jul 16, 2024
dcf4a10
Handlle empty data in fuzz header
sumitsuthar Jul 18, 2024
efdaf6d
updated json version
sumitsuthar Aug 5, 2024
b596a0c
added key identifier in hc
sumitsuthar Aug 7, 2024
bee36dd
Merge branch 'key_identifier' into empty_fuzz_header
sumitsuthar Aug 7, 2024
3e201ae
code cleanup
sumitsuthar Aug 7, 2024
76a0984
Merge branch 'empty_fuzz_header' into secure_cookie_event_update
sumitsuthar Aug 12, 2024
f12e724
json version update
sumitsuthar Aug 12, 2024
949c844
handling for delay and duration
sumitsuthar Aug 12, 2024
67de57b
handling to disable websocket and agent
sumitsuthar Aug 12, 2024
d355a0d
handling to disable detection category
sumitsuthar Aug 12, 2024
603b41b
minor fix
sumitsuthar Aug 12, 2024
d0fa11e
Revert "minor fix"
sumitsuthar Aug 12, 2024
a6a9862
Revert "handling to disable detection category"
sumitsuthar Aug 12, 2024
b4d9d8e
minor fix
sumitsuthar Aug 12, 2024
f8e32ea
Revert "minor fix"
sumitsuthar Aug 12, 2024
5b75921
handling to disable detection category
sumitsuthar Aug 12, 2024
b8349d5
asserts added
sumitsuthar Aug 12, 2024
acc9899
Merge branch 'restrict_iast' of https://github.com/newrelic/csec-node…
sumitsuthar Aug 12, 2024
113c705
Handling to skip APIs for event generationg
sumitsuthar Aug 13, 2024
4323313
Merge branch 'main' into restrict_iast
sumitsuthar Aug 16, 2024
147675f
skipping rxss
sumitsuthar Aug 16, 2024
31fdf29
added ws header to ignore detection category
sumitsuthar Aug 16, 2024
70115a7
disable response file hooks based on ignore detection category
sumitsuthar Aug 16, 2024
5498daf
Added cron express parsing
sumitsuthar Aug 20, 2024
1616040
handling for 0 or negative value in duration
sumitsuthar Aug 20, 2024
b13e7fd
support for always_sample_traces flag
sumitsuthar Aug 20, 2024
27c7a35
config update
sumitsuthar Aug 23, 2024
41df8ca
scan rate limit implementation
sumitsuthar Aug 28, 2024
7646a9d
minor fix
sumitsuthar Aug 30, 2024
c4a9f2e
json version update
sumitsuthar Sep 2, 2024
965e9a5
scan controllers config added
sumitsuthar Sep 2, 2024
2192610
update in scan rate limit flag
sumitsuthar Sep 6, 2024
831e805
resolved merge conflict
sumitsuthar Sep 20, 2024
54dec2f
fix for exclusion based on regex
sumitsuthar Sep 21, 2024
4c50b6e
Merge branch 'main' into restrict_iast
sumitsuthar Sep 25, 2024
6d0cd8b
added handling to log delay scan time and iast data pull request time
sumitsuthar Sep 26, 2024
ca280eb
debug log added
sumitsuthar Sep 26, 2024
b75bc16
minor fix
sumitsuthar Sep 26, 2024
09567c5
remove logger for scan delay
sumitsuthar Sep 26, 2024
5083e47
added handling to parse duration and delay to integer
sumitsuthar Oct 3, 2024
868ef8a
disable agent if cron expression is wrong
sumitsuthar Oct 3, 2024
34cbed7
calling utility to shutdonw agent
sumitsuthar Oct 3, 2024
1d4ec8a
log the delay message if the delay is greater than 0
sumitsuthar Oct 3, 2024
f792ba3
fix to log schedule config if non empty
sumitsuthar Oct 3, 2024
e3161c7
Added log for agent shutdown message
sumitsuthar Oct 3, 2024
65a2b21
minor log update
sumitsuthar Oct 3, 2024
80b4603
spell fix
sumitsuthar Oct 3, 2024
650c311
delay parsing udpate
sumitsuthar Oct 3, 2024
0782669
added logger for SA config
sumitsuthar Oct 3, 2024
d33af09
updates to main config for delay and duration
sumitsuthar Oct 3, 2024
8de9a11
log only when duration is greater than 1
sumitsuthar Oct 3, 2024
e2654da
minor space fix
sumitsuthar Oct 3, 2024
0f5c084
Handling to generate event if allow sample flag is true regardless of…
sumitsuthar Oct 4, 2024
970eda6
fix for delay flag
sumitsuthar Oct 7, 2024
a444a61
cron express fix of ?
sumitsuthar Oct 7, 2024
09fa058
fix for invocation of duration and cron
sumitsuthar Oct 7, 2024
3902546
added logger for hibernate mode
sumitsuthar Oct 7, 2024
48cab39
Handling to not start agent until the cron expression time
sumitsuthar Oct 7, 2024
6451226
fix for cron
sumitsuthar Oct 7, 2024
1e189ae
handling to store request if agent is in active mode
sumitsuthar Oct 7, 2024
3d81aa4
updated rxss detection condition
pratik-k2 Oct 8, 2024
c4c2e4d
formatting fix
sumitsuthar Oct 8, 2024
b615f14
fix for schedule with duration
sumitsuthar Oct 8, 2024
3b99d40
fix for schedule with duration
sumitsuthar Oct 8, 2024
0373daa
fix for delay as priority over schedule
sumitsuthar Oct 8, 2024
d82f1ce
minor fix for dual calling of durationConfig
sumitsuthar Oct 8, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 29 additions & 0 deletions lib/instrumentation-security/core/request-manager.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,10 @@
*/

const requestMap = new Map();
const API = require("../../nr-security-api");
const NRAgent = API.getNRAgent();
const logger = API.getLogger();
const regexPatterns = NRAgent && NRAgent.config.security.exclude_from_iast_scan.api

/**
* Utility to get request by transaction Id
Expand All @@ -20,7 +24,32 @@ function getRequestFromId(id) {
* @param {*} requestData
*/
function setRequest(id, requestData) {
if (API.getSecAgent().status.getStatus() != 'active') {
return;
}
requestMap.set(id, requestData);
try {
const stringToMatch = requestData.url;
const filteredString = stringToMatch.split('?')[0];
let isRegexMatchestoURL = false;
for (let index = 0; index < regexPatterns.length; index++) {
const regex = new RegExp(regexPatterns[index], 'gm');
const matchResult = filteredString.match(regex);
if (matchResult && matchResult.length > 0) {
const data = matchResult[0];
if (filteredString === data) {
isRegexMatchestoURL = true;
}
}
}
if (isRegexMatchestoURL) {
requestMap.delete(id);
logger.debug("Excluding URL %s from IAST processing due to ignore API setting", filteredString);
}
} catch (error) {
logger.debug("Error while processing API regex for restriction", error);
}

}

/**
Expand Down
7 changes: 5 additions & 2 deletions lib/instrumentation-security/hooks/express/nr-express.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,11 @@ module.exports = function initialize(shim, express) {
if (express.Router.use) {
wrapExpress4(shim, express)
}
expressFileHook(shim, express && express.response, 'download')
expressFileHook(shim, express && express.response, 'sendFile')
if(API && API.getNRAgent() && !API.getNRAgent().config.security.exclude_from_iast_scan.iast_detection_category.invalid_file_access){
expressFileHook(shim, express && express.response, 'download')
expressFileHook(shim, express && express.response, 'sendFile')
}

}

/**
Expand Down
6 changes: 4 additions & 2 deletions lib/instrumentation-security/hooks/fs/nr-fs.js
Original file line number Diff line number Diff line change
Expand Up @@ -94,8 +94,10 @@ const promiseFunctionProbableToFI = [
* @param {*} moduleName
*/
function initialize(shim, mod, moduleName) {


if(API && API.getNRAgent() && API.getNRAgent().config.security.exclude_from_iast_scan.iast_detection_category.invalid_file_access){
logger.warn('invalid_file_access detection is disabled');
return;
}
logger.info(`Instrumenting ${moduleName}`);
requireHook.initialize(shim)
const binding = process.binding("fs");
Expand Down
8 changes: 6 additions & 2 deletions lib/instrumentation-security/hooks/http/nr-http.js
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,10 @@ function setupRequestMapCleanup() {
* @param {*} moduleName
*/
function outboundHook(shim, mod, method, moduleName) {
if (API && API.getNRAgent() && API.getNRAgent().config.security.exclude_from_iast_scan.iast_detection_category.ssrf) {
logger.warn('ssrf detection is disabled');
return;
}
logger.debug(`Instrumenting ${moduleName}.${method}`);
shim.wrap(mod, method, function makeRequestWrapper(shim, fn) {
if (!shim.isFunction(fn)) {
Expand Down Expand Up @@ -176,7 +180,7 @@ function parseFuzzheaders(requestData, transactionId) {
if (additionalData.length >= 8) {
let encryptedData = additionalData[6].trim();
let hashVerifier = additionalData[7].trim();

if (lodash.isEmpty(encryptedData) || lodash.isEmpty(hashVerifier)) {
return;
}
Expand Down Expand Up @@ -292,7 +296,7 @@ function emitHook(shim, mod, moduleName) {
const resp = arguments[2];

if (arguments[0] == 'request') {
if (NRAgent && NRAgent.config.security.detection.rxss.enabled) {
if (NRAgent && !NRAgent.config.security.exclude_from_iast_scan.iast_detection_category.rxss && NRAgent.config.security.detection.rxss.enabled) {
responseHook(resp, req, shim);
}

Expand Down
4 changes: 4 additions & 0 deletions lib/instrumentation-security/hooks/ldap/nr-ldap.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,10 @@ const logger = API.getLogger();
* @param {*} moduleName
*/
function initialize(shim, mod, moduleName){
if(API && API.getNRAgent() && API.getNRAgent().config.security.exclude_from_iast_scan.iast_detection_category.ldap_injection){
logger.warn('ldap_injection detection is disabled');
return;
}
logger.info('Instrumenting '+ moduleName )

if(moduleName==='ldapjs' || moduleName==='ldapts'){
Expand Down
4 changes: 4 additions & 0 deletions lib/instrumentation-security/hooks/mongodb/nr-mongodb.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,10 @@ module.exports = initialize;
* @param {Shim} shim
*/
function initialize(shim, mongodb, moduleName) {
if(API && API.getNRAgent() && API.getNRAgent().config.security.exclude_from_iast_scan.iast_detection_category.nosql_injection){
logger.warn('nosql_injection detection is disabled');
return;
}
logger.info(`Instrumenting ${moduleName}`);
if (!mongodb) {
return;
Expand Down
4 changes: 4 additions & 0 deletions lib/instrumentation-security/hooks/mysql/nr-mysql.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,10 @@ module.exports = initialize;
*/
function initialize(shim, mysql, moduleName) {
modName = moduleName;
if(API && API.getNRAgent() && API.getNRAgent().config.security.exclude_from_iast_scan.iast_detection_category.sql_injection){
logger.warn('sql_injection detection is disabled');
return;
}
logger.info("Instrumenting", moduleName);
if (shim._moduleRoot.includes("mysql2")) {
promiseInitialize(shim, mysql, moduleName);
Expand Down
4 changes: 4 additions & 0 deletions lib/instrumentation-security/hooks/native/nr-childProcess.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,10 @@ const { NR_CSEC_FUZZ_REQUEST_ID } = require('../../core/constants');
const logger = API.getLogger();

function initialize(shim, childProcess, moduleName) {
if(API && API.getNRAgent() && API.getNRAgent().config.security.exclude_from_iast_scan.iast_detection_category.command_injection){
logger.warn('command_injection detection is disabled');
return;
}
logger.info('Instrumenting child_process');
execFileHook(shim, childProcess, moduleName);
spawnHook(shim, childProcess, moduleName);
Expand Down
4 changes: 4 additions & 0 deletions lib/instrumentation-security/hooks/postgres/nr-postgres.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,10 @@ const logger = API.getLogger();
const { NR_CSEC_FUZZ_REQUEST_ID } = require('../../core/constants');

module.exports = function initialize(shim, pgsql, moduleName) {
if(API && API.getNRAgent() && API.getNRAgent().config.security.exclude_from_iast_scan.iast_detection_category.sql_injection){
logger.warn('sql_injection detection is disabled');
return;
}
logger.info('Instrumenting '+ moduleName)
// allows for native wrapping to not happen if not necessary
// when env var is true
Expand Down
4 changes: 4 additions & 0 deletions lib/instrumentation-security/hooks/undici/nr-undici.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,10 @@ const url = require('url');
* @param {*} moduleName
*/
function initialize(shim, mod, moduleName) {
if(API && API.getNRAgent() && API.getNRAgent().config.security.exclude_from_iast_scan.iast_detection_category.ssrf){
logger.warn('ssrf detection is disabled');
return;
}
logger.info('Instrumenting ' + moduleName);
fetchHook(shim, mod, "fetch");
let util = shim.require('./lib/core/util');
Expand Down
4 changes: 4 additions & 0 deletions lib/instrumentation-security/hooks/xpath/nr-xpath.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,10 @@ const logger = API.getLogger();
* @param {*} moduleName
*/
function initialize(shim, mod, moduleName){
if(API && API.getNRAgent() && API.getNRAgent().config.security.exclude_from_iast_scan.iast_detection_category.xpath_injection){
logger.warn('xpath_injection detection is disabled');
return;
}
logger.info('Instrumenting '+ moduleName)

if(moduleName==='xpath'){
Expand Down
47 changes: 42 additions & 5 deletions lib/nr-security-agent/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ const njsAgentConstants = require('./lib/core/sec-agent-constants');
const NRLogger = API.newrelic.shim.logger.child({ component: 'security-agent' });
NRLogger.info("Starting New Relic Node.js Security Agent ");
try {
if (NRAgent.config.security.enabled){
if (NRAgent.config.security.enabled) {
require('../instrumentation-security');
}
} catch (error) {
Expand Down Expand Up @@ -117,11 +117,48 @@ function initialize() {
if (NRAgent) {
NRAgent.on('started', () => {
NRLogger.info("Started New Relic Node.js Security Agent");
logger.info('NR Agent started with agent_run_id:', NRAgent.config.run_id, NRAgent.config.account_id);
if (Agent.getAgent().status.getStatus() != 'connecting') {
Agent.getAgent().delayed = false;
wsClient.obeyReconnect();
return;
}
if (NRAgent.config.security.enabled || !NRAgent.config.high_security) {
wsClient.initialize();
logger.info('NR Agent started with agent_run_id:', NRAgent.config.run_id, NRAgent.config.account_id);
Agent.getAgent().status.setStatus('connecting');
Agent.setNRAgent(NRAgent);
let delayFromConfig = parseInt(NRAgent.config.security.scan_schedule.delay);
let delay = delayFromConfig;
if (isNaN(delay) || delay < 0) {
delay = 0;
}
NRAgent.config.security.scan_schedule.delay = delay;
const allowSampling = NRAgent.config.security.scan_schedule.always_sample_traces;

if (delay > 0) {
logger.debug("IAST delay is set to:", delay);
logger.info("Security Agent delay scan time is set to:", commonUtils.getScheduledScanTime(delay))
Agent.getAgent().delayed = true;
setTimeout(() => {
Agent.getAgent().delayed = false;
logger.info("IAST scanning delay of %s minutes over", delay);
commonUtils.executeCronSchedule();
commonUtils.honourDurationConfiguration();
}, delay * 60000);
}
logger.info("Security Agent is running with config:", JSON.stringify(NRAgent.config.security));
if (allowSampling) {
wsClient.initialize();
Agent.getAgent().status.setStatus('connecting');
Agent.setNRAgent(NRAgent);
}
setTimeout(() => {
if (commonUtils.honourCronExpression() && !allowSampling) {
return;
}
if (!allowSampling) {
wsClient.initialize();
Agent.getAgent().status.setStatus('connecting');
Agent.setNRAgent(NRAgent);
}
}, delay * 60000);
}
else {
logger.warn("security.enabled flag is set to false");
Expand Down
3 changes: 3 additions & 0 deletions lib/nr-security-agent/lib/core/Auth-headers.js
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ function AuthHeaders() {
authHeaders["NR-CSEC-IAST-DATA-TRANSFER-MODE"] = "PULL";
authHeaders['NR-CSEC-ENTITY-NAME'] = metadata['entity.name'] ? metadata['entity.name'] : '';
authHeaders['NR-CSEC-ENTITY-GUID'] = metadata['entity.guid'] ? metadata['entity.guid'] : '';
authHeaders['NR-CSEC-IGNORED-VUL-CATEGORIES'] = commonUtils.listSkipDetectionCategory();
} catch (error) {
logger.error("Exception in preparing auth headers:", error);
const logMessage = new LogMessage.logMessage("SEVERE", 'Exception in preparing auth headers', __filename, error);
Expand Down Expand Up @@ -76,6 +77,8 @@ function getInstance() {
return authHeaders;
}



module.exports = {
getInstance
};
3 changes: 3 additions & 0 deletions lib/nr-security-agent/lib/core/agent.js
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ function Agent(applicationInfo, logger, client, status) {
this.logger = logger;
this.status = status;
this.wsStatus = 0;
this.delayed = false;
}

Agent.prototype = {};
Expand Down Expand Up @@ -96,6 +97,7 @@ Agent.prototype.setAgentStatus = function setAgentStatus(status) {
Agent.eventEmitter.emit(EVENTS.AGENT_STATUS_UPDATED_EVENT, status);
};


Agent.EVENTS = EVENTS;

Agent.eventEmitter = new EventEmitter();
Expand Down Expand Up @@ -138,6 +140,7 @@ Agent.setNRAgent = function setNRAgent(agent) {
}
};


module.exports = {
Agent
};
Loading
Loading