
개발자와 보안 엔지니어에게 친숙한 NodeJS 애플리케이션 보안 패키지입니다.
**Node Security Shield (NSS)**는 포괄적인 NodeJS 보안의 격차를 해소하기 위해 개발자와 보안 엔지니어가 애플리케이션이 접근할 수 있는 리소스를 선언할 수 있도록 하는 오픈 소스 Runtime Application Self-Protection (RASP) 도구입니다.
애플리케이션이 임의의 네트워크 호출을 할 수 있기 때문에 악용될 수 있는 Log4Shell (CVE-2021-44228) 취약점에서 영감을 받아, 우리는 추가적인 통제를 구현하여 이러한 취약점의 악용을 더 어렵게 만들기 위해 애플리케이션이 허용하는 권한을 선언할 수 있는 메커니즘이 필요하다고 느꼈습니다.
이를 달성하기 위해 **NSS (Node Security Shield)**는 **Resource Access Policy (RAP)**를 제공합니다.
Resource Access Policy는 CSP(Content Security Policy)와 유사합니다.
개발자/보안 엔지니어가 애플리케이션이 접근해야 하는 리소스를 선언할 수 있도록 하며, Node Security Shield가 이를 강제합니다.
npm install nodesecurityshield
// Node Security Shield 불러오기
let nodeSecurityShield = require('nodesecurityshield');
// 공격 모니터링 및/또는 차단 활성화
nodeSecurityShield.enableAttackMonitoring("Unique-App-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: 나가는 요청(Outbound Requests)에 대해 허용되는 동작을 정의합니다.
blockedDomains가 allowedDomains보다 우선합니다.blockedDomains에 대해 확인된 후 allowedDomains에 대해 확인됩니다.executedCommand: 명령 실행(Command Execution)에 대해 허용되는 동작을 정의합니다.
allowedCommands 배열은 String을 허용합니다. 명령 패턴을 허용하기 위해 RegEx를 전달할 수 있습니다.executedCommand 속성이 정의된 경우 모든 명령 실행을 차단하는 것입니다.pwd 명령의 실행이 허용되고,helper 내부의 파일이 노드 프로세스로 생성(spawn)될 수 있습니다.var callbackFunction = function (violationEvent,violations,violationLimitPerMinReached) {
console.log(JSON.stringify(violationEvent,null, 4));
}
violationEvent - 발생한 RAP 위반. CSP 위반 형식으로 제공됩니다.
violations - RAP 위반 횟수. 매분 0으로 재설정됩니다.
violationLimitPerMinReached - RAP 위반 횟수가 'maxViolationsPerMinute' [RAP의 옵션]을 초과하면 true가 됩니다.
공격 차단 방법 - 오류 발생
throw new Error("Request Blocked. It violates declared Resource Access Policy.")
{
"csp-report": {
"document-uri": "https://Unique-App-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: NSS 초기화 시 전달된 Unique-App-Id를 포함합니다.blocked-uri: RAP를 위반한 나가는 요청의 도메인violated-directive: connect-src는 나가는 요청(Outbound Request)의 동의어이고, script-src는 명령 실행(Command Execution)의 동의어입니다.original-policy: 위반된 Resource Access Policy (RAP)source-file: 이 위반이 발생한 스택 추적(Stack Trace)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: 나가는 요청(Outbound Requests)에 대해 허용되는 동작을 정의합니다.
blockedDomains가 allowedDomains보다 우선합니다.blockedDomains에 대해 확인된 후 allowedDomains에 대해 확인됩니다.executedCommand: 명령 실행(Command Execution)에 대해 허용되는 동작을 정의합니다.
allowedCommands 배열은 String을 허용합니다. 명령 패턴을 허용하기 위해 RegEx를 전달할 수 있습니다.executedCommand 속성이 정의된 경우 모든 명령 실행을 차단하는 것입니다.pwd 명령의 실행이 허용되고,helper 내부의 파일이 노드 프로세스로 생성(spawn)될 수 있습니다.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: 나가는 요청(Outbound Requests)에 대해 허용되는 동작을 정의합니다.
blockedDomains가 allowedDomains보다 우선합니다.blockedDomains에 대해 확인된 후 allowedDomains에 대해 확인됩니다.executedCommand: 명령 실행(Command Execution)에 대해 허용되는 동작을 정의합니다.
allowedCommands 배열은 String을 허용합니다. 명령 패턴을 허용하기 위해 RegEx를 전달할 수 있습니다.executedCommand 속성이 정의된 경우 모든 명령 실행을 차단하는 것입니다.pwd 명령의 실행이 허용되고,helper 내부의 파일이 노드 프로세스로 생성(spawn)될 수 있습니다..js.* 사용을 피하십시오. 파이프 | 뒤에 모든 명령이 실행될 수 있기 때문입니다..js.* 사용을 피하십시오. 파이프 | 뒤에 모든 명령이 실행될 수 있기 때문입니다.reportUri : 위반을 지정된 엔드포인트로 전송합니다. 위반은 Content Security Policy 위반과 유사하므로 모든 CSP 모니터링 솔루션을 사용할 수 있습니다. 위 RAP에서는 Sentry 엔드포인트를 사용했습니다..js.* 사용을 피하십시오. 파이프 | 뒤에 모든 명령이 실행될 수 있기 때문입니다.reportUri: 위반을 지정된 엔드포인트로 전송합니다. 위반은 Content Security Policy 위반과 유사하므로 모든 CSP 모니터링 솔루션을 사용할 수 있습니다. 위 RAP에서는 Sentry 엔드포인트를 사용했습니다.allowedDomain 배열은 다음 속성을 가진 객체를 허용합니다.
domain: 제공된 파일에 대해 허용할 도메인의 배열입니다.modules: 파일 경로를 포함하는 객체의 배열입니다. 이 파일들을 통해 지정된 도메인으로 이루어지는 나가는 요청만 허용됩니다.maxViolationsPerMinute: reportUri로 전송될 최대 위반 횟수입니다. 지정하지 않으면 기본값(100건의 위반)이 사용됩니다.