We read every piece of feedback, and take your input very seriously.
To see all available qualifiers, see our documentation.
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
/* * NodeJS <-> NMAP interface * Author: John Horton * Purpose: Create an interface for NodeJS applications to make use of NMAP installed on the local system. */ const child_process = require('child_process'); const execSync = child_process.execSync; const exec = child_process.exec; const spawn = child_process.spawn; const fs = require('fs'); const EventEmitter = require('events').EventEmitter; const os = require('os'); const Queue = require('queued-up'); 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 === 'open') }) newHost.openPorts = openPorts.map((portItem) => { // console.log(JSON.stringify(portItem, null, 4)) const port = parseInt(portItem.$.portid) const protocol = portItem.$.protocol const service = portItem.service[0].$.name const tunnel = portItem.service[0].$.tunnel const method = portItem.service[0].$.method const product = portItem.service[0].$.tunnel let portObject = {} if(port) portObject.port = port if(protocol) portObject.protocol = protocol if(service) portObject.service = service if(tunnel) portObject.tunnel = tunnel if(method) portObject.method = method if(product) portObject.product = product 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, runAsRoot = false) { super(); this.runAsRoot = runAsRoot 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() { let begin if(this.runAsRoot) { begin= "sudo -u nmap ".concat(nmap.nmapLocation) } else { begin = nmap.nmapLocation } this.startTimer(); this.child = spawn(begin, 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; results = convertRawJsonToScanResults(this.rawJSON, (err) => { this.emit('error', "Error converting raw json to cleans can results: " + err + ": " + this.rawJSON); }); this.scanComplete(results); } }); } } class StealthScan extends NmapScan { constructor(range) { super(range, '-sS', true); } } class QuickScan extends NmapScan { constructor(range) { super(range, '-sP'); } } class OsAndPortScan extends NmapScan { constructor(range) { super(range, '-O'); } } class QueuedScan extends EventEmitter { constructor(scanClass, range, args, action = () => {}) { super(); this.scanResults = []; this.scanTime = 0; this.currentScan; this.runActionOnError = false; this.saveErrorsToResults = false; this.singleScanTimeout = 0; this.saveNotFoundToResults = false; this._queue = new Queue((host) => { if (args !== null) { this.currentScan = new scanClass(host, args); } else { this.currentScan = new scanClass(host); } if (this.singleScanTimeout !== 0) { this.currentScan.scanTimeout = this.singleScanTimeout; } this.currentScan.on('complete', (data) => { this.scanTime += this.currentScan.scanTime; if (data[0]) { data[0].scanTime = this.currentScan.scanTime; this.scanResults = this.scanResults.concat(data); } else if (this.saveNotFoundToResults) { data[0] = { error: "Host not found", scanTime: this.currentScan.scanTime } this.scanResults = this.scanResults.concat(data); } action(data); this._queue.done(); }); this.currentScan.on('error', (err) => { this.scanTime += this.currentScan.scanTime; let data = { error: err, scanTime: this.currentScan.scanTime } if (this.saveErrorsToResults) { this.scanResults = this.scanResults.concat(data); } if (this.runActionOnError) { action(data); } this._queue.done(); }); this.currentScan.startScan(); }); this._queue.add(this.rangeFormatter(range)); this._queue.on('complete', () => { this.emit('complete', this.scanResults); }); } rangeFormatter(range) { let outputRange = []; if (!Array.isArray(range)) { range = range.split(' '); } for (let i = 0; i < range.length; i++) { let input = range[i]; let temprange = range[i]; if (countCharacterOccurence(input, ".") === 3 && input.match(new RegExp("-", "g")) !== null && !input.match(/^[a-zA-Z]+$/) && input.match(new RegExp("-", "g")).length === 1 ) { let firstIP = input.slice(0, input.indexOf("-")); let network; let lastNumber = input.slice(input.indexOf("-") + 1); let firstNumber; let newRange = []; for (let j = firstIP.length - 1; j > -1; j--) { if (firstIP.charAt(j) === ".") { firstNumber = firstIP.slice(j + 1); network = firstIP.slice(0, j + 1); break; } } for (let iter = firstNumber; iter <= lastNumber; iter++) { newRange.push(network + iter); } //replace the range/host string with array temprange = newRange; } outputRange = outputRange.concat(temprange); } function countCharacterOccurence(input, character) { let num = 0; for (let k = 0; k < input.length; k++) { if (input.charAt(k) === character) { num++; } } return num; } return outputRange; } startRunScan(index = 0) { this.scanResults = []; this._queue.run(0); } startShiftScan() { this.scanResults = []; this._queue.shiftRun(); } pause() { this._queue.pause(); } resume() { this._queue.resume(); } next(iterations = 1) { return this._queue.next(iterations); } shift(iterations = 1) { return this._queue.shift(iterations); } results() { return this.scanResults; } shiftResults() { this._queue.shiftResults(); return this.scanResults.shift(); } index() { return this._queue.index(); } queue(newQueue) { if (Array.isArray(newQueue)) { return this._queue.queue(newQueue); } else { return this._queue.queue(); } } percentComplete() { return Math.round(((this._queue.index() + 1) / this._queue.queue().length) * 100); } } class QueuedNmapScan extends QueuedScan { constructor(range, additionalArguments, actionFunction = () => {}) { super(NmapScan, range, additionalArguments, actionFunction); } } class QueuedQuickScan extends QueuedScan { constructor(range, actionFunction = () => {}) { super(QuickScan, range, null, actionFunction); } } class QueuedOsAndPortScan extends QueuedScan { constructor(range, actionFunction = () => {}) { super(OsAndPortScan, range, null, actionFunction); } } let nmap = { nmapLocation: "nmap", NmapScan, QuickScan, OsAndPortScan, QueuedScan, StealthScan, QueuedNmapScan, QueuedQuickScan, QueuedOsAndPortScan, } module.exports = nmap;
The text was updated successfully, but these errors were encountered:
I suggest, that doing root scan would be provided with nmap user, that's nologin user...
It's easier...
Sorry, something went wrong.
No branches or pull requests
The text was updated successfully, but these errors were encountered: