92 lines
3.4 KiB
JavaScript
92 lines
3.4 KiB
JavaScript
const express = require('express');
|
|
const { exec } = require('child_process');
|
|
const xml2js = require('xml2js');
|
|
const cors = require('cors');
|
|
const os = require('os');
|
|
const { promisify } = require('util');
|
|
|
|
const execAsync = promisify(exec);
|
|
|
|
const app = express();
|
|
const port = 3001;
|
|
|
|
// Use CORS to allow requests from the frontend
|
|
app.use(cors());
|
|
app.use(express.json());
|
|
|
|
// Basic validation for CIDR notation
|
|
const isValidCIDR = (cidr) => {
|
|
const cidrRegex = /^([0-9]{1,3}\.){3}[0-9]{1,3}(\/([0-9]|[1-2][0-9]|3[0-2]))$/;
|
|
return cidrRegex.test(cidr);
|
|
};
|
|
|
|
app.post('/api/scan', async (req, res) => {
|
|
const { network } = req.body;
|
|
|
|
if (!network || !isValidCIDR(network)) {
|
|
return res.status(400).json({ error: 'Invalid or missing network address in CIDR format (e.g., 192.168.1.0/24).' });
|
|
}
|
|
|
|
// Sanitize input to prevent command injection
|
|
// The regex validation is the primary defense here.
|
|
const sanitizedNetwork = network;
|
|
|
|
console.log(`[SCAN STARTED] for network: ${sanitizedNetwork}`);
|
|
|
|
// Command to find hosts with a wide range of common web ports open and output as XML.
|
|
// This is more efficient than scanning all 65535 ports.
|
|
const command = `nmap -p 80,443,3000,5000,7878,8080,8443,9000,9090,9091,9443,10000,32400,8000-8999 --open ${sanitizedNetwork} -oX -`;
|
|
|
|
try {
|
|
const { stdout, stderr } = await execAsync(command, { timeout: 300000 }); // 5 minute timeout
|
|
|
|
if (stderr) {
|
|
console.error(`[NMAP STDERR] ${stderr}`);
|
|
}
|
|
|
|
const parser = new xml2js.Parser();
|
|
const result = await parser.parseStringPromise(stdout);
|
|
const services = [];
|
|
|
|
if (result.nmaprun && result.nmaprun.host) {
|
|
result.nmaprun.host.forEach(host => {
|
|
const address = host.address[0].$.addr;
|
|
if (host.ports && host.ports[0].port) {
|
|
host.ports[0].port.forEach(portInfo => {
|
|
const port = portInfo.$.portid;
|
|
|
|
let url;
|
|
if (port === '443') {
|
|
url = `https://${address}`;
|
|
} else if (port === '80') {
|
|
url = `http://${address}`;
|
|
} else {
|
|
url = `http://${address}:${port}`;
|
|
}
|
|
|
|
const serviceName = portInfo.service && portInfo.service[0].$.name
|
|
? portInfo.service[0].$.name.replace(/-http$/, '') // Clean up names like 'http-proxy'
|
|
: `Web Service @ ${address}`;
|
|
|
|
services.push({
|
|
name: `${serviceName.charAt(0).toUpperCase() + serviceName.slice(1)} (${port})`,
|
|
url: url,
|
|
description: `Discovered service on port ${port}.`
|
|
});
|
|
});
|
|
}
|
|
});
|
|
}
|
|
|
|
console.log(`[SCAN COMPLETE] Found ${services.length} services on ${sanitizedNetwork}.`);
|
|
res.json(services);
|
|
|
|
} catch (error) {
|
|
console.error(`[SCAN FAILED] Error executing nmap:`, error);
|
|
res.status(500).json({ error: 'Failed to execute nmap scan. Is nmap installed and in your system PATH?' });
|
|
}
|
|
});
|
|
|
|
app.listen(port, () => {
|
|
console.log(`Backend server running on http://localhost:${port}`);
|
|
}); |