diff --git a/.eslintrc b/.eslintrc index e46882a..88f1e28 100644 --- a/.eslintrc +++ b/.eslintrc @@ -8,8 +8,8 @@ "parserOptions": { "ecmaVersion": 2018 }, - "extends": "eslint:recommended", - "plugins": ["prettier"], + "extends": ["eslint:recommended", "plugin:security/recommended"], + "plugins": ["prettier", "security"], "rules": { "prettier/prettier": "error", "indent": ["error", 4], diff --git a/.travis.yml b/.travis.yml index bae4b4d..b6e4450 100644 --- a/.travis.yml +++ b/.travis.yml @@ -14,9 +14,9 @@ jobs: - echo -en "travis_fold:start:Docker_Build\r" - docker build -t $REPO:$TAG --build-arg="BUILD_DATE=$(date --rfc-3339=seconds)" --build-arg=VERSION=$TRAVIS_TAG --build-arg=COMMIT_ID=$TRAVIS_COMMIT --build-arg=BRANCH=$TRAVIS_BRANCH --build-arg=REPOSITORY_URL="https://github.com/secureCodeBox/scanner-infrastructure-nmap" . - echo -en "travis_fold:end:Docker_Build\r" -deploy: - - provider: script - skip_cleanup: true - script: bash .travis/deployDockerHub.sh - on: - all_branches: true + deploy: + - provider: script + skip_cleanup: true + script: bash .travis/deployDockerHub.sh + on: + all_branches: true diff --git a/index.js b/index.js index 38dc8f8..8be2f7c 100644 --- a/index.js +++ b/index.js @@ -26,14 +26,15 @@ const scanner = new ScannerScaffolding(worker, { topic: 'nmap_portscan', async testScannerFunctionality() { try { - await testRun(); + const { version } = await testRun(); + + return { + version, + testRun: 'successful', + }; } catch (error) { return { version: 'unkown', testRun: 'failed' }; } - return { - version: 'unkown', - testRun: 'successful', - }; }, }); diff --git a/lib/__mocks__/portscan.js b/lib/__mocks__/portscan.js index a513080..11ff146 100644 --- a/lib/__mocks__/portscan.js +++ b/lib/__mocks__/portscan.js @@ -24,24 +24,33 @@ module.exports = jest.fn(() => ip: '127.0.0.1', mac: null, openPorts: [ - { port: 631, protocol: 'tcp', service: 'ipp', method: 'table' }, + { + port: 631, + protocol: 'tcp', + service: 'ipp', + method: 'table', + state: 'open', + }, { port: 7778, protocol: 'tcp', service: 'interwise', method: 'table', + state: 'open', }, { port: 8080, protocol: 'tcp', service: 'http-proxy', method: 'table', + state: 'open', }, { port: 9200, protocol: 'tcp', service: 'wap-wsp', method: 'table', + state: 'open', }, ], osNmap: null, diff --git a/lib/node-nmap.js b/lib/node-nmap.js new file mode 100644 index 0000000..25168f7 --- /dev/null +++ b/lib/node-nmap.js @@ -0,0 +1,262 @@ +/* + * Vendored version of node-nmap (original license MIT) + * Original Author: + * NodeJS <-> NMAP interface + * Author: John Horton + * Purpose: Create an interface for NodeJS applications to make use of NMAP installed on the local system. + */ + +// eslint-disable-next-line security/detect-child-process +const { spawn } = require('child_process'); +const EventEmitter = require('events').EventEmitter; +const xml2js = require('xml2js'); + +/** + * + * @param {*} xmlInput + * @param {*} onFailure + * @returns {host[]} - Array of hosts + */ +function convertRawJsonToScanResults(xmlInput) { + let tempHostList = []; + + if (!xmlInput.nmaprun.host) { + //onFailure("There was a problem with the supplied NMAP XML"); + return tempHostList; + } + + xmlInput = xmlInput.nmaprun.host; + + tempHostList = xmlInput.map(host => { + const newHost = { + hostname: null, + ip: null, + mac: null, + openPorts: null, + osNmap: null, + }; + + //Get hostname + if (host.hostnames && host.hostnames[0] !== '\r\n' && host.hostnames[0] !== '\n') { + newHost.hostname = host.hostnames[0].hostname[0].$.name; + } + + //get addresses + host.address.forEach(address => { + const addressType = address.$.addrtype; + const addressAdress = address.$.addr; + const addressVendor = address.$.vendor; + + if (addressType === 'ipv4') { + newHost.ip = addressAdress; + } else if (addressType === 'mac') { + newHost.mac = addressAdress; + newHost.vendor = addressVendor; + } + }); + + //get ports + if (host.ports && host.ports[0].port) { + const portList = host.ports[0].port; + + const openPorts = portList.filter(port => { + return port.state[0].$.state !== 'closed'; + }); + + newHost.openPorts = openPorts.map(portItem => { + // console.log(JSON.stringify(portItem, null, 4)) + + const port = parseInt(portItem.$.portid, 10); + const protocol = portItem.$.protocol; + const service = portItem.service[0].$.name; + const serviceProduct = portItem.service[0].$.product; + const serviceVersion = portItem.service[0].$.version; + + const tunnel = portItem.service[0].$.tunnel; + const method = portItem.service[0].$.method; + const product = portItem.service[0].$.tunnel; + + const state = portItem.state[0].$.state; + + let scriptOutputs = null; + + if (portItem.script) { + scriptOutputs = portItem.script.reduce((carry, { $: scriptRes }) => { + carry[scriptRes.id] = scriptRes.output; + return carry; + }, {}); + } + + let portObject = {}; + if (port) portObject.port = port; + if (protocol) portObject.protocol = protocol; + if (service) portObject.service = service; + if (serviceProduct) portObject.serviceProduct = serviceProduct; + if (serviceVersion) portObject.serviceVersion = serviceVersion; + + if (tunnel) portObject.tunnel = tunnel; + if (method) portObject.method = method; + if (product) portObject.product = product; + + if (state) portObject.state = state; + + if (scriptOutputs) portObject.scriptOutputs = scriptOutputs; + + return portObject; + }); + } + + if (host.os && host.os[0].osmatch && host.os[0].osmatch[0].$.name) { + newHost.osNmap = host.os[0].osmatch[0].$.name; + } + return newHost; + }); + + return tempHostList; +} + +class NmapScan extends EventEmitter { + constructor(range, inputArguments) { + super(); + this.nmapVersion = null; + this.command = []; + this.nmapoutputXML = ''; + this.timer; + this.range = []; + this.arguments = ['-oX', '-']; + this.rawData = ''; + this.rawJSON; + this.child; + this.cancelled = false; + this.scanTime = 0; + this.error = null; + this.scanResults; + this.scanTimeout = 0; + this.commandConstructor(range, inputArguments); + this.initializeChildProcess(); + } + + startTimer() { + this.timer = setInterval(() => { + this.scanTime += 10; + if (this.scanTime >= this.scanTimeout && this.scanTimeout !== 0) { + this.killChild(); + } + }, 10); + } + + stopTimer() { + clearInterval(this.timer); + } + + commandConstructor(range, additionalArguments) { + if (additionalArguments) { + if (!Array.isArray(additionalArguments)) { + additionalArguments = additionalArguments.split(' '); + } + this.command = this.arguments.concat(additionalArguments); + } else { + this.command = this.arguments; + } + + if (!Array.isArray(range)) { + range = range.split(' '); + } + this.range = range; + this.command = this.command.concat(this.range); + } + + killChild() { + this.cancelled = true; + if (this.child) { + this.child.kill(); + } + } + + initializeChildProcess() { + this.startTimer(); + this.child = spawn(nmap.nmapLocation, this.command); + process.on('SIGINT', this.killChild); + process.on('uncaughtException', this.killChild); + process.on('exit', this.killChild); + this.child.stdout.on('data', data => { + if (data.indexOf('percent') > -1) { + // console.log(data.toString()); + } else { + this.rawData += data; + } + }); + + this.child.on('error', err => { + this.killChild(); + if (err.code === 'ENOENT') { + this.emit('error', 'NMAP not found at command location: ' + nmap.nmapLocation); + } else { + this.emit('error', err.Error); + } + }); + + this.child.stderr.on('data', err => { + this.error = err.toString(); + }); + + this.child.on('close', () => { + process.removeListener('SIGINT', this.killChild); + process.removeListener('uncaughtException', this.killChild); + process.removeListener('exit', this.killChild); + + if (this.error) { + this.emit('error', this.error); + } else if (this.cancelled === true) { + this.emit('error', 'Over scan timeout ' + this.scanTimeout); + } else { + this.rawDataHandler(this.rawData); + } + }); + } + + startScan() { + this.child.stdin.end(); + } + + cancelScan() { + this.killChild(); + this.emit('error', 'Scan cancelled'); + } + + scanComplete(results) { + this.scanResults = results; + this.stopTimer(); + this.emit('complete', this.scanResults); + } + + rawDataHandler(data) { + let results; + //turn NMAP's xml output into a json object + xml2js.parseString(data, (err, result) => { + if (err) { + this.emit('error', 'Error converting XML to JSON in xml2js: ' + err); + } else { + this.rawJSON = result; + this.nmapVersion = result.nmaprun.$.version; + results = convertRawJsonToScanResults(this.rawJSON, err => { + this.emit( + 'error', + 'Error converting raw json to cleans can results: ' + + err + + ': ' + + this.rawJSON + ); + }); + this.scanComplete(results); + } + }); + } +} + +let nmap = { + nmapLocation: 'nmap', + NmapScan, +}; + +module.exports = nmap; diff --git a/lib/portscan.js b/lib/portscan.js index 42a233b..f0b1ccb 100644 --- a/lib/portscan.js +++ b/lib/portscan.js @@ -16,13 +16,15 @@ * limitations under the License. * / */ -const nodeNmap = require('node-nmap'); +const nodeNmap = require('./node-nmap'); function portscan(target, params) { return new Promise((resolve, reject) => { const nmapscan = new nodeNmap.NmapScan(target, params); - nmapscan.on('complete', hosts => resolve({ hosts, raw: nmapscan.rawData })); + nmapscan.on('complete', hosts => + resolve({ hosts, raw: nmapscan.rawData, version: nmapscan.nmapVersion }) + ); nmapscan.on('error', reject); nmapscan.startScan(); diff --git a/package-lock.json b/package-lock.json index 5d67280..7eb665a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1539,6 +1539,15 @@ "prettier-linter-helpers": "^1.0.0" } }, + "eslint-plugin-security": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-security/-/eslint-plugin-security-1.4.0.tgz", + "integrity": "sha512-xlS7P2PLMXeqfhyf3NpqbvbnW04kN8M9NtmhpR3XGyOvt/vNKS7XPXT5EDbwKW9vCjWH4PpfQvgD/+JgN0VJKA==", + "dev": true, + "requires": { + "safe-regex": "^1.1.0" + } + }, "eslint-scope": { "version": "4.0.3", "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-4.0.3.tgz", @@ -2055,25 +2064,29 @@ "dependencies": { "abbrev": { "version": "1.1.1", - "bundled": true, + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", + "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==", "dev": true, "optional": true }, "ansi-regex": { "version": "2.1.1", - "bundled": true, + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", "dev": true, "optional": true }, "aproba": { "version": "1.2.0", - "bundled": true, + "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", + "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==", "dev": true, "optional": true }, "are-we-there-yet": { "version": "1.1.5", - "bundled": true, + "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.5.tgz", + "integrity": "sha512-5hYdAkZlcG8tOLujVDTgCT+uPX0VnpAH28gWsLfzpXYm7wP6mp5Q/gYyR7YQ0cKVJcXJnl3j2kpBan13PtQf6w==", "dev": true, "optional": true, "requires": { @@ -2083,13 +2096,15 @@ }, "balanced-match": { "version": "1.0.0", - "bundled": true, + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", "dev": true, "optional": true }, "brace-expansion": { "version": "1.1.11", - "bundled": true, + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", "dev": true, "optional": true, "requires": { @@ -2099,37 +2114,43 @@ }, "chownr": { "version": "1.1.1", - "bundled": true, + "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.1.tgz", + "integrity": "sha512-j38EvO5+LHX84jlo6h4UzmOwi0UgW61WRyPtJz4qaadK5eY3BTS5TY/S1Stc3Uk2lIM6TPevAlULiEJwie860g==", "dev": true, "optional": true }, "code-point-at": { "version": "1.1.0", - "bundled": true, + "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", + "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=", "dev": true, "optional": true }, "concat-map": { "version": "0.0.1", - "bundled": true, + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", "dev": true, "optional": true }, "console-control-strings": { "version": "1.1.0", - "bundled": true, + "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", + "integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=", "dev": true, "optional": true }, "core-util-is": { "version": "1.0.2", - "bundled": true, + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", "dev": true, "optional": true }, "debug": { "version": "4.1.1", - "bundled": true, + "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", + "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", "dev": true, "optional": true, "requires": { @@ -2138,25 +2159,29 @@ }, "deep-extend": { "version": "0.6.0", - "bundled": true, + "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", + "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", "dev": true, "optional": true }, "delegates": { "version": "1.0.0", - "bundled": true, + "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", + "integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=", "dev": true, "optional": true }, "detect-libc": { "version": "1.0.3", - "bundled": true, + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-1.0.3.tgz", + "integrity": "sha1-+hN8S9aY7fVc1c0CrFWfkaTEups=", "dev": true, "optional": true }, "fs-minipass": { "version": "1.2.5", - "bundled": true, + "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-1.2.5.tgz", + "integrity": "sha512-JhBl0skXjUPCFH7x6x61gQxrKyXsxB5gcgePLZCwfyCGGsTISMoIeObbrvVeP6Xmyaudw4TT43qV2Gz+iyd2oQ==", "dev": true, "optional": true, "requires": { @@ -2165,13 +2190,15 @@ }, "fs.realpath": { "version": "1.0.0", - "bundled": true, + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", "dev": true, "optional": true }, "gauge": { "version": "2.7.4", - "bundled": true, + "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz", + "integrity": "sha1-LANAXHU4w51+s3sxcCLjJfsBi/c=", "dev": true, "optional": true, "requires": { @@ -2187,7 +2214,8 @@ }, "glob": { "version": "7.1.3", - "bundled": true, + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.3.tgz", + "integrity": "sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ==", "dev": true, "optional": true, "requires": { @@ -2201,13 +2229,15 @@ }, "has-unicode": { "version": "2.0.1", - "bundled": true, + "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", + "integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=", "dev": true, "optional": true }, "iconv-lite": { "version": "0.4.24", - "bundled": true, + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", "dev": true, "optional": true, "requires": { @@ -2216,7 +2246,8 @@ }, "ignore-walk": { "version": "3.0.1", - "bundled": true, + "resolved": "https://registry.npmjs.org/ignore-walk/-/ignore-walk-3.0.1.tgz", + "integrity": "sha512-DTVlMx3IYPe0/JJcYP7Gxg7ttZZu3IInhuEhbchuqneY9wWe5Ojy2mXLBaQFUQmo0AW2r3qG7m1mg86js+gnlQ==", "dev": true, "optional": true, "requires": { @@ -2225,7 +2256,8 @@ }, "inflight": { "version": "1.0.6", - "bundled": true, + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", "dev": true, "optional": true, "requires": { @@ -2235,19 +2267,22 @@ }, "inherits": { "version": "2.0.3", - "bundled": true, + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", "dev": true, "optional": true }, "ini": { "version": "1.3.5", - "bundled": true, + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.5.tgz", + "integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==", "dev": true, "optional": true }, "is-fullwidth-code-point": { "version": "1.0.0", - "bundled": true, + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", "dev": true, "optional": true, "requires": { @@ -2256,13 +2291,15 @@ }, "isarray": { "version": "1.0.0", - "bundled": true, + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", "dev": true, "optional": true }, "minimatch": { "version": "3.0.4", - "bundled": true, + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", "dev": true, "optional": true, "requires": { @@ -2271,13 +2308,15 @@ }, "minimist": { "version": "0.0.8", - "bundled": true, + "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", + "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", "dev": true, "optional": true }, "minipass": { "version": "2.3.5", - "bundled": true, + "resolved": "https://registry.npmjs.org/minipass/-/minipass-2.3.5.tgz", + "integrity": "sha512-Gi1W4k059gyRbyVUZQ4mEqLm0YIUiGYfvxhF6SIlk3ui1WVxMTGfGdQ2SInh3PDrRTVvPKgULkpJtT4RH10+VA==", "dev": true, "optional": true, "requires": { @@ -2287,7 +2326,8 @@ }, "minizlib": { "version": "1.2.1", - "bundled": true, + "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-1.2.1.tgz", + "integrity": "sha512-7+4oTUOWKg7AuL3vloEWekXY2/D20cevzsrNT2kGWm+39J9hGTCBv8VI5Pm5lXZ/o3/mdR4f8rflAPhnQb8mPA==", "dev": true, "optional": true, "requires": { @@ -2296,7 +2336,8 @@ }, "mkdirp": { "version": "0.5.1", - "bundled": true, + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", + "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", "dev": true, "optional": true, "requires": { @@ -2305,13 +2346,15 @@ }, "ms": { "version": "2.1.1", - "bundled": true, + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", + "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", "dev": true, "optional": true }, "needle": { "version": "2.3.0", - "bundled": true, + "resolved": "https://registry.npmjs.org/needle/-/needle-2.3.0.tgz", + "integrity": "sha512-QBZu7aAFR0522EyaXZM0FZ9GLpq6lvQ3uq8gteiDUp7wKdy0lSd2hPlgFwVuW1CBkfEs9PfDQsQzZghLs/psdg==", "dev": true, "optional": true, "requires": { @@ -2322,7 +2365,8 @@ }, "node-pre-gyp": { "version": "0.12.0", - "bundled": true, + "resolved": "https://registry.npmjs.org/node-pre-gyp/-/node-pre-gyp-0.12.0.tgz", + "integrity": "sha512-4KghwV8vH5k+g2ylT+sLTjy5wmUOb9vPhnM8NHvRf9dHmnW/CndrFXy2aRPaPST6dugXSdHXfeaHQm77PIz/1A==", "dev": true, "optional": true, "requires": { @@ -2340,7 +2384,8 @@ }, "nopt": { "version": "4.0.1", - "bundled": true, + "resolved": "https://registry.npmjs.org/nopt/-/nopt-4.0.1.tgz", + "integrity": "sha1-0NRoWv1UFRk8jHUFYC0NF81kR00=", "dev": true, "optional": true, "requires": { @@ -2350,13 +2395,15 @@ }, "npm-bundled": { "version": "1.0.6", - "bundled": true, + "resolved": "https://registry.npmjs.org/npm-bundled/-/npm-bundled-1.0.6.tgz", + "integrity": "sha512-8/JCaftHwbd//k6y2rEWp6k1wxVfpFzB6t1p825+cUb7Ym2XQfhwIC5KwhrvzZRJu+LtDE585zVaS32+CGtf0g==", "dev": true, "optional": true }, "npm-packlist": { "version": "1.4.1", - "bundled": true, + "resolved": "https://registry.npmjs.org/npm-packlist/-/npm-packlist-1.4.1.tgz", + "integrity": "sha512-+TcdO7HJJ8peiiYhvPxsEDhF3PJFGUGRcFsGve3vxvxdcpO2Z4Z7rkosRM0kWj6LfbK/P0gu3dzk5RU1ffvFcw==", "dev": true, "optional": true, "requires": { @@ -2366,7 +2413,8 @@ }, "npmlog": { "version": "4.1.2", - "bundled": true, + "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz", + "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==", "dev": true, "optional": true, "requires": { @@ -2378,19 +2426,22 @@ }, "number-is-nan": { "version": "1.0.1", - "bundled": true, + "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", + "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=", "dev": true, "optional": true }, "object-assign": { "version": "4.1.1", - "bundled": true, + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", "dev": true, "optional": true }, "once": { "version": "1.4.0", - "bundled": true, + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", "dev": true, "optional": true, "requires": { @@ -2399,19 +2450,22 @@ }, "os-homedir": { "version": "1.0.2", - "bundled": true, + "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", + "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=", "dev": true, "optional": true }, "os-tmpdir": { "version": "1.0.2", - "bundled": true, + "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", + "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=", "dev": true, "optional": true }, "osenv": { "version": "0.1.5", - "bundled": true, + "resolved": "https://registry.npmjs.org/osenv/-/osenv-0.1.5.tgz", + "integrity": "sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g==", "dev": true, "optional": true, "requires": { @@ -2421,19 +2475,22 @@ }, "path-is-absolute": { "version": "1.0.1", - "bundled": true, + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", "dev": true, "optional": true }, "process-nextick-args": { "version": "2.0.0", - "bundled": true, + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.0.tgz", + "integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw==", "dev": true, "optional": true }, "rc": { "version": "1.2.8", - "bundled": true, + "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", + "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", "dev": true, "optional": true, "requires": { @@ -2445,7 +2502,8 @@ "dependencies": { "minimist": { "version": "1.2.0", - "bundled": true, + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", "dev": true, "optional": true } @@ -2453,7 +2511,8 @@ }, "readable-stream": { "version": "2.3.6", - "bundled": true, + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", + "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", "dev": true, "optional": true, "requires": { @@ -2468,7 +2527,8 @@ }, "rimraf": { "version": "2.6.3", - "bundled": true, + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz", + "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==", "dev": true, "optional": true, "requires": { @@ -2477,43 +2537,50 @@ }, "safe-buffer": { "version": "5.1.2", - "bundled": true, + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", "dev": true, "optional": true }, "safer-buffer": { "version": "2.1.2", - "bundled": true, + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", "dev": true, "optional": true }, "sax": { "version": "1.2.4", - "bundled": true, + "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz", + "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==", "dev": true, "optional": true }, "semver": { "version": "5.7.0", - "bundled": true, + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.0.tgz", + "integrity": "sha512-Ya52jSX2u7QKghxeoFGpLwCtGlt7j0oY9DYb5apt9nPlJ42ID+ulTXESnt/qAQcoSERyZ5sl3LDIOw0nAn/5DA==", "dev": true, "optional": true }, "set-blocking": { "version": "2.0.0", - "bundled": true, + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", "dev": true, "optional": true }, "signal-exit": { "version": "3.0.2", - "bundled": true, + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz", + "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=", "dev": true, "optional": true }, "string-width": { "version": "1.0.2", - "bundled": true, + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", "dev": true, "optional": true, "requires": { @@ -2524,7 +2591,8 @@ }, "string_decoder": { "version": "1.1.1", - "bundled": true, + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", "dev": true, "optional": true, "requires": { @@ -2533,7 +2601,8 @@ }, "strip-ansi": { "version": "3.0.1", - "bundled": true, + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", "dev": true, "optional": true, "requires": { @@ -2542,13 +2611,15 @@ }, "strip-json-comments": { "version": "2.0.1", - "bundled": true, + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=", "dev": true, "optional": true }, "tar": { "version": "4.4.8", - "bundled": true, + "resolved": "https://registry.npmjs.org/tar/-/tar-4.4.8.tgz", + "integrity": "sha512-LzHF64s5chPQQS0IYBn9IN5h3i98c12bo4NCO7e0sGM2llXQ3p2FGC5sdENN4cTW48O915Sh+x+EXx7XW96xYQ==", "dev": true, "optional": true, "requires": { @@ -2563,13 +2634,15 @@ }, "util-deprecate": { "version": "1.0.2", - "bundled": true, + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", "dev": true, "optional": true }, "wide-align": { "version": "1.1.3", - "bundled": true, + "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.3.tgz", + "integrity": "sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA==", "dev": true, "optional": true, "requires": { @@ -2578,13 +2651,15 @@ }, "wrappy": { "version": "1.0.2", - "bundled": true, + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", "dev": true, "optional": true }, "yallist": { "version": "3.0.3", - "bundled": true, + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.0.3.tgz", + "integrity": "sha512-S+Zk8DEWE6oKpV+vI3qWkaK+jSbIK86pCwe2IF/xwIpQ8jEuxpw9NyaGjmp9+BoJv5FV2piqCDcoCtStppiq2A==", "dev": true, "optional": true } @@ -4152,15 +4227,6 @@ "integrity": "sha1-jZ2+KJZKSsVxLpExZCEHxx6Q7EA=", "dev": true }, - "node-nmap": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/node-nmap/-/node-nmap-4.0.0.tgz", - "integrity": "sha512-VJGebpYsfqmUm46+Fq0qp1Y9VXGXZ7/WL03tHGy1oJHHxaJ2DvYLMjuYWYHDV0pgUL+e5/9rCN/QEsx3+fU9TA==", - "requires": { - "queued-up": "^2.0.2", - "xml2js": "^0.4.15" - } - }, "node-notifier": { "version": "5.4.0", "resolved": "https://registry.npmjs.org/node-notifier/-/node-notifier-5.4.0.tgz", @@ -4638,11 +4704,6 @@ "resolved": "https://registry.npmjs.org/qs/-/qs-6.7.0.tgz", "integrity": "sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ==" }, - "queued-up": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/queued-up/-/queued-up-2.0.2.tgz", - "integrity": "sha1-EindqVqWhI/EMuymsQ7Yb1XNFoY=" - }, "range-parser": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", diff --git a/package.json b/package.json index e69d2a5..14dafc7 100644 --- a/package.json +++ b/package.json @@ -19,12 +19,13 @@ "dependencies": { "@securecodebox/scanner-scaffolding": "^2.2.5", "lodash": "^4.17.13", - "node-nmap": "^4.0.0", - "uuid": "^3.3.2" + "uuid": "^3.3.2", + "xml2js": "^0.4.19" }, "devDependencies": { "eslint": "^6.0.0", "eslint-plugin-prettier": "^3.1.0", + "eslint-plugin-security": "^1.4.0", "jest": "^24.8.0", "prettier": "^1.18.2" } diff --git a/src/__snapshots__/nmap.test.js.snap b/src/__snapshots__/nmap.test.js.snap index bffd4ff..752a2e9 100644 --- a/src/__snapshots__/nmap.test.js.snap +++ b/src/__snapshots__/nmap.test.js.snap @@ -20,15 +20,16 @@ Object { "protocol": "tcp", "scripts": null, "service": "ipp", + "serviceProduct": null, + "serviceVersion": null, + "state": "open", }, "category": "Open Port", "description": "Port 631 is open using tcp protocol.", - "hint": null, "id": "49bf7fd3-8512-4d73-a28f-608e493cd726", "location": "tcp://127.0.0.1:631", "name": "ipp", "osi_layer": "NETWORK", - "reference": null, "severity": "INFORMATIONAL", }, Object { @@ -42,15 +43,16 @@ Object { "protocol": "tcp", "scripts": null, "service": "interwise", + "serviceProduct": null, + "serviceVersion": null, + "state": "open", }, "category": "Open Port", "description": "Port 7778 is open using tcp protocol.", - "hint": null, "id": "49bf7fd3-8512-4d73-a28f-608e493cd726", "location": "tcp://127.0.0.1:7778", "name": "interwise", "osi_layer": "NETWORK", - "reference": null, "severity": "INFORMATIONAL", }, Object { @@ -64,15 +66,16 @@ Object { "protocol": "tcp", "scripts": null, "service": "http-proxy", + "serviceProduct": null, + "serviceVersion": null, + "state": "open", }, "category": "Open Port", "description": "Port 8080 is open using tcp protocol.", - "hint": null, "id": "49bf7fd3-8512-4d73-a28f-608e493cd726", "location": "tcp://127.0.0.1:8080", "name": "http-proxy", "osi_layer": "NETWORK", - "reference": null, "severity": "INFORMATIONAL", }, Object { @@ -86,15 +89,30 @@ Object { "protocol": "tcp", "scripts": null, "service": "wap-wsp", + "serviceProduct": null, + "serviceVersion": null, + "state": "open", }, "category": "Open Port", "description": "Port 9200 is open using tcp protocol.", - "hint": null, "id": "49bf7fd3-8512-4d73-a28f-608e493cd726", "location": "tcp://127.0.0.1:9200", "name": "wap-wsp", "osi_layer": "NETWORK", - "reference": null, + "severity": "INFORMATIONAL", + }, + Object { + "attributes": Object { + "hostname": "localhost", + "ip_address": "127.0.0.1", + "operating_system": null, + }, + "category": "Host", + "description": "Found a host", + "id": "49bf7fd3-8512-4d73-a28f-608e493cd726", + "location": "localhost", + "name": "Host: localhost", + "osi_layer": "NETWORK", "severity": "INFORMATIONAL", }, Object { @@ -108,15 +126,16 @@ Object { "protocol": "tcp", "scripts": null, "service": "ipp", + "serviceProduct": null, + "serviceVersion": null, + "state": "open", }, "category": "Open Port", "description": "Port 631 is open using tcp protocol.", - "hint": null, "id": "49bf7fd3-8512-4d73-a28f-608e493cd726", "location": "tcp://127.0.0.1:631", "name": "ipp", "osi_layer": "NETWORK", - "reference": null, "severity": "INFORMATIONAL", }, Object { @@ -130,15 +149,16 @@ Object { "protocol": "tcp", "scripts": null, "service": "interwise", + "serviceProduct": null, + "serviceVersion": null, + "state": "open", }, "category": "Open Port", "description": "Port 7778 is open using tcp protocol.", - "hint": null, "id": "49bf7fd3-8512-4d73-a28f-608e493cd726", "location": "tcp://127.0.0.1:7778", "name": "interwise", "osi_layer": "NETWORK", - "reference": null, "severity": "INFORMATIONAL", }, Object { @@ -152,15 +172,16 @@ Object { "protocol": "tcp", "scripts": null, "service": "http-proxy", + "serviceProduct": null, + "serviceVersion": null, + "state": "open", }, "category": "Open Port", "description": "Port 8080 is open using tcp protocol.", - "hint": null, "id": "49bf7fd3-8512-4d73-a28f-608e493cd726", "location": "tcp://127.0.0.1:8080", "name": "http-proxy", "osi_layer": "NETWORK", - "reference": null, "severity": "INFORMATIONAL", }, Object { @@ -174,15 +195,30 @@ Object { "protocol": "tcp", "scripts": null, "service": "wap-wsp", + "serviceProduct": null, + "serviceVersion": null, + "state": "open", }, "category": "Open Port", "description": "Port 9200 is open using tcp protocol.", - "hint": null, "id": "49bf7fd3-8512-4d73-a28f-608e493cd726", "location": "tcp://127.0.0.1:9200", "name": "wap-wsp", "osi_layer": "NETWORK", - "reference": null, + "severity": "INFORMATIONAL", + }, + Object { + "attributes": Object { + "hostname": "localhost", + "ip_address": "127.0.0.1", + "operating_system": null, + }, + "category": "Host", + "description": "Found a host", + "id": "49bf7fd3-8512-4d73-a28f-608e493cd726", + "location": "localhost", + "name": "Host: localhost", + "osi_layer": "NETWORK", "severity": "INFORMATIONAL", }, ], @@ -207,15 +243,16 @@ Object { "protocol": "tcp", "scripts": null, "service": "ipp", + "serviceProduct": null, + "serviceVersion": null, + "state": "open", }, "category": "Open Port", "description": "Port 631 is open using tcp protocol.", - "hint": null, "id": "49bf7fd3-8512-4d73-a28f-608e493cd726", "location": "tcp://127.0.0.1:631", "name": "ipp", "osi_layer": "NETWORK", - "reference": null, "severity": "INFORMATIONAL", }, Object { @@ -229,15 +266,16 @@ Object { "protocol": "tcp", "scripts": null, "service": "interwise", + "serviceProduct": null, + "serviceVersion": null, + "state": "open", }, "category": "Open Port", "description": "Port 7778 is open using tcp protocol.", - "hint": null, "id": "49bf7fd3-8512-4d73-a28f-608e493cd726", "location": "tcp://127.0.0.1:7778", "name": "interwise", "osi_layer": "NETWORK", - "reference": null, "severity": "INFORMATIONAL", }, Object { @@ -251,15 +289,16 @@ Object { "protocol": "tcp", "scripts": null, "service": "http-proxy", + "serviceProduct": null, + "serviceVersion": null, + "state": "open", }, "category": "Open Port", "description": "Port 8080 is open using tcp protocol.", - "hint": null, "id": "49bf7fd3-8512-4d73-a28f-608e493cd726", "location": "tcp://127.0.0.1:8080", "name": "http-proxy", "osi_layer": "NETWORK", - "reference": null, "severity": "INFORMATIONAL", }, Object { @@ -273,15 +312,30 @@ Object { "protocol": "tcp", "scripts": null, "service": "wap-wsp", + "serviceProduct": null, + "serviceVersion": null, + "state": "open", }, "category": "Open Port", "description": "Port 9200 is open using tcp protocol.", - "hint": null, "id": "49bf7fd3-8512-4d73-a28f-608e493cd726", "location": "tcp://127.0.0.1:9200", "name": "wap-wsp", "osi_layer": "NETWORK", - "reference": null, + "severity": "INFORMATIONAL", + }, + Object { + "attributes": Object { + "hostname": "localhost", + "ip_address": "127.0.0.1", + "operating_system": null, + }, + "category": "Host", + "description": "Found a host", + "id": "49bf7fd3-8512-4d73-a28f-608e493cd726", + "location": "localhost", + "name": "Host: localhost", + "osi_layer": "NETWORK", "severity": "INFORMATIONAL", }, ], @@ -308,15 +362,16 @@ Object { "protocol": "tcp", "scripts": null, "service": "ipp", + "serviceProduct": null, + "serviceVersion": null, + "state": "open", }, "category": "Open Port", "description": "Port 631 is open using tcp protocol.", - "hint": null, "id": "49bf7fd3-8512-4d73-a28f-608e493cd726", "location": "tcp://127.0.0.1:631", "name": "ipp", "osi_layer": "NETWORK", - "reference": null, "severity": "INFORMATIONAL", }, Object { @@ -330,15 +385,16 @@ Object { "protocol": "tcp", "scripts": null, "service": "interwise", + "serviceProduct": null, + "serviceVersion": null, + "state": "open", }, "category": "Open Port", "description": "Port 7778 is open using tcp protocol.", - "hint": null, "id": "49bf7fd3-8512-4d73-a28f-608e493cd726", "location": "tcp://127.0.0.1:7778", "name": "interwise", "osi_layer": "NETWORK", - "reference": null, "severity": "INFORMATIONAL", }, Object { @@ -352,15 +408,16 @@ Object { "protocol": "tcp", "scripts": null, "service": "http-proxy", + "serviceProduct": null, + "serviceVersion": null, + "state": "open", }, "category": "Open Port", "description": "Port 8080 is open using tcp protocol.", - "hint": null, "id": "49bf7fd3-8512-4d73-a28f-608e493cd726", "location": "tcp://127.0.0.1:8080", "name": "http-proxy", "osi_layer": "NETWORK", - "reference": null, "severity": "INFORMATIONAL", }, Object { @@ -374,15 +431,30 @@ Object { "protocol": "tcp", "scripts": null, "service": "wap-wsp", + "serviceProduct": null, + "serviceVersion": null, + "state": "open", }, "category": "Open Port", "description": "Port 9200 is open using tcp protocol.", - "hint": null, "id": "49bf7fd3-8512-4d73-a28f-608e493cd726", "location": "tcp://127.0.0.1:9200", "name": "wap-wsp", "osi_layer": "NETWORK", - "reference": null, + "severity": "INFORMATIONAL", + }, + Object { + "attributes": Object { + "hostname": "localhost", + "ip_address": "127.0.0.1", + "operating_system": null, + }, + "category": "Host", + "description": "Found a host", + "id": "49bf7fd3-8512-4d73-a28f-608e493cd726", + "location": "localhost", + "name": "Host: localhost", + "osi_layer": "NETWORK", "severity": "INFORMATIONAL", }, ], diff --git a/src/__test_data__/empty-ports-xml.test.xml b/src/__test_data__/empty-ports-xml.test.xml deleted file mode 100644 index 2723830..0000000 --- a/src/__test_data__/empty-ports-xml.test.xml +++ /dev/null @@ -1,21 +0,0 @@ - - - - - - - - - - -
- - - - - - - - - - diff --git a/src/__test_data__/results-xml.test.xml b/src/__test_data__/results-xml.test.xml deleted file mode 100644 index 2f4f9af..0000000 --- a/src/__test_data__/results-xml.test.xml +++ /dev/null @@ -1,168 +0,0 @@ - - - - - - - - - - -
- - - - - - - - - - - - - - - - - - -