
Дружественный к разработчикам и инженерам безопасности пакет для защиты приложений NodeJS.
Node Security Shield (NSS) — это инструмент самозащиты приложений во время выполнения (RASP) с открытым исходным кодом, предназначенный для устранения пробелов в комплексной безопасности NodeJS. Он позволяет разработчику и инженеру по безопасности указывать, к каким ресурсам может обращаться приложение.
Вдохновением послужила уязвимость Log4Shell (CVE-2021-44228), которая эксплуатируется из-за возможности приложения выполнять произвольные сетевые вызовы. Мы решили, что приложению необходим механизм, позволяющий объявлять разрешённые привилегии, чтобы усложнить эксплуатацию подобных уязвимостей с помощью дополнительных средств контроля.
Для достижения этой цели NSS (Node Security Shield) использует Политику доступа к ресурсам (RAP)
Политика доступа к ресурсам аналогична CSP (Политика безопасности контента).
Она позволяет разработчику/инженеру по безопасности указать, к каким ресурсам должно обращаться приложение. Node Security Shield обеспечивает соблюдение этой политики.
npm install nodesecurityshield
// Подключение Node Security Shield
let nodeSecurityShield = require('nodesecurityshield');
// Включение мониторинга и/или блокировки атак
nodeSecurityShield.enableAttackMonitoring("Уникальный-ID-приложения", resourceAccessPolicy, callbackFunction);
const resourceAccessPolicy = {
"outBoundRequest" : {
"blockedDomains" : ["compromised.domdog.io"],
"allowedDomains" : []
},
"executedCommand": {
"allowedCommands": ["pwd" , "(node)[](https://github.com/domdogsec/nodesecurityshield/blob/HEAD/helper%5C/)[a-z|0-9]*(.js)"]
}
};
outBoundRequest: определяет допустимое поведение для исходящих запросов
executedCommand: определяет допустимое поведение для выполнения команд
allowedCommands принимает строки. Вы можете передать регулярное выражение для разрешения шаблона команд.executedCommand.pwd разрешена к выполнению;.js внутри helper могут запускаться как процессы node..* в регулярных выражениях, так как это позволит выполнить любую команду после символа пайпа .var callbackFunction = function (violationEvent,violations,violationLimitPerMinReached) {
console.log(JSON.stringify(violationEvent,null, 4));
}
violationEvent — произошедшее нарушение RAP. Представлено как нарушение CSP.
violations — счётчик нарушений RAP. Сбрасывается в ноль каждую минуту.
violationLimitPerMinReached — значение true, если количество нарушений RAP превышает 'maxViolationsPerMinute' [опция в RAP]
Для блокировки атаки — выбросить ошибку
throw new Error("Запрос заблокирован. Он нарушает объявленную политику доступа к ресурсам.")
{
"csp-report": {
"document-uri": "https://Уникальный-ID-приложения",
"blocked-uri": "https://compromised.domdog.io:443",
"violated-directive": "connect-src",
"effective-directive": "connect-src",
"original-policy": "{\"outBoundRequest\":{\"blockedDomains\":[\"compromised.domdog.io\"],\"allowedDomains\":[]}}",
"disposition": "report",
"status-code": 200,
"script-sample": "",
"source-file": "Error\n at TLSSocket.obj.<computed> [as connect] (/mnt/c/Ironwasp/Product/NodeSecurityShield/lib/hook.js:20:25)\n at Object.connect (_tls_wrap.js:1606:13)\n at Agent.createConnection (https.js:126:22)\n at Agent.createSocket (_http_agent.js:273:26)\n at Agent.addRequest (_http_agent.js:232:10)\n at new ClientRequest (_http_client.js:302:16)\n at request (https.js:310:10)\n at Object.get (https.js:314:15)\n at /mnt/c/Ironwasp/RD/Node/SimpleVulnerableNode/routes/ssrf.js:19:19\n at Layer.handle [as handle_request] (/mnt/c/Ironwasp/RD/Node/SimpleVulnerableNode/node_modules/express/lib/router/layer.js:95:5)"
}
}
document-uri: содержит Уникальный-ID-приложения, переданный при инициализации NSSblocked-uri: домен исходящего запроса, нарушившего RAPviolated-directive: connect-src является синонимом Исходящий запрос, так же как script-src является синонимом Выполнение командыoriginal-policy: нарушенная Политика доступа к ресурсам (RAP)source-file: трассировка стека места возникновения нарушенияconst resourceAccessPolicy = {
"outBoundRequest" : {
"blockedDomains" : ["compromised.domdog.io"],
"allowedDomains" : []
},
"executedCommand": {
"allowedCommands": ["pwd" , "(node)[](https://github.com/domdogsec/nodesecurityshield/blob/HEAD/helper%5C/)[a-z|0-9]*(.js)"]
},
"reportUri": "https://ingest.sentry.io/api/6011856/security/?sentry_key=",
};
outBoundRequest: определяет допустимое поведение для исходящих запросов
executedCommand: определяет допустимое поведение для выполнения команд
allowedCommands принимает строки. Вы можете передать регулярное выражение для разрешения шаблона команд.executedCommand.pwd разрешена к выполнению;.js внутри helper могут запускаться как процессы node..* в регулярных выражениях, так как это позволит выполнить любую команду после символа пайпа .Скриншот из панели управления Sentry

const resourceAccessPolicy = {
"outBoundRequest" : {
"blockedDomains" : ["compromised.domdog.io"],
"allowedDomains" : ["domdog.io","*.domdog.io",
{
"domains": [
"domgo.at",
],
"modules": [
{
"file": "\/routes\/ssrf.js",
},
{
"file": "\/node_modules\/axios\/",
}
]
},
{
"domains": [
"cluster0-shard-00-00.lb9jm.mongodb.net",
"cluster0-shard-00-01.lb9jm.mongodb.net",
"cluster0-shard-00-02.lb9jm.mongodb.net"
],
"modules": [
{
"file": "\/node_modules\/mongodb\/"
}
]
}
]
},
"executedCommand": {
"allowedCommands": ["pwd" , "(node)[](https://github.com/domdogsec/nodesecurityshield/blob/HEAD/helper%5C/)[a-z|0-9]*(.js)"]
},
"reportUri": "https://endpoint-to-send-violations",
"maxViolationsPerMinute": 50
}
outBoundRequest: определяет допустимое поведение для исходящих запросов
executedCommand: определяет допустимое поведение для выполнения команд
allowedCommands принимает строки. Вы можете передать регулярное выражение для разрешения шаблона команд.executedCommand.pwd разрешена к выполнению;.js внутри helper могут запускаться как процессы node..* в регулярных выражениях, так как это позволит выполнить любую команду после символа пайпа .||reportUri : Отправляет нарушения на заданную конечную точку. Поскольку нарушения аналогичны нарушениям Политики безопасности контента, можно использовать любые CSP-решения для мониторинга. В приведённом выше RAP мы использовали конечную точку Sentry.|reportUri: Отправляет нарушения на заданную конечную точку. Поскольку нарушения аналогичны нарушениям Политики безопасности контента, можно использовать любые CSP-решения для мониторинга. В приведённом выше RAP мы использовали конечную точку Sentry.allowedDomain принимает объекты со следующими полями:
domain: Массив доменов, которые разрешены для указанных файлов.modules: Массив объектов, содержащих пути к файлам. Разрешены только исходящие запросы, выполняемые через эти файлы к указанным доменам.maxViolationsPerMinute: Максимальное количество нарушений, отправляемых на reportUri. Если не указано, используется значение по умолчанию (100 нарушений).