security fix exploits, memory leak fix

This commit is contained in:
Sebastian Hildebrandt 2020-05-19 14:56:58 +02:00
parent bafcb0f93c
commit f89a2ec63f
4 changed files with 127 additions and 84 deletions

View File

@ -34,17 +34,17 @@ function inetChecksite(url, callback) {
return new Promise((resolve) => {
process.nextTick(() => {
const urlSanitized = util.sanitizeShellString(url).toLowerCase();
let result = {
url: url,
url: urlSanitized,
ok: false,
status: 404,
ms: -1
};
if (url) {
url = url.toLowerCase();
if (urlSanitized) {
let t = Date.now();
if (_linux || _freebsd || _openbsd || _netbsd || _darwin || _sunos) {
let args = ' -I --connect-timeout 5 -m 5 ' + url + ' 2>/dev/null | head -n 1 | cut -d " " -f2';
let args = ' -I --connect-timeout 5 -m 5 ' + urlSanitized + ' 2>/dev/null | head -n 1 | cut -d " " -f2';
let cmd = 'curl';
exec(cmd + args, function (error, stdout) {
let statusCode = parseInt(stdout.toString());
@ -56,9 +56,9 @@ function inetChecksite(url, callback) {
});
}
if (_windows) { // if this is stable, this can be used for all OS types
const http = (url.startsWith('https:') ? require('https') : require('http'));
const http = (urlSanitized.startsWith('https:') ? require('https') : require('http'));
try {
http.get(url, (res) => {
http.get(urlSanitized, (res) => {
const statusCode = res.statusCode;
result.status = statusCode || 404;
@ -108,19 +108,20 @@ function inetLatency(host, callback) {
}
host = host || '8.8.8.8';
const hostSanitized = util.sanitizeShellString(host);
return new Promise((resolve) => {
process.nextTick(() => {
let cmd;
if (_linux || _freebsd || _openbsd || _netbsd || _darwin) {
if (_linux) {
cmd = 'ping -c 2 -w 3 ' + host + ' | grep rtt';
cmd = 'ping -c 2 -w 3 ' + hostSanitized + ' | grep rtt';
}
if (_freebsd || _openbsd || _netbsd) {
cmd = 'ping -c 2 -t 3 ' + host + ' | grep round-trip';
cmd = 'ping -c 2 -t 3 ' + hostSanitized + ' | grep round-trip';
}
if (_darwin) {
cmd = 'ping -c 2 -t 3 ' + host + ' | grep avg';
cmd = 'ping -c 2 -t 3 ' + hostSanitized + ' | grep avg';
}
exec(cmd, function (error, stdout) {
@ -139,7 +140,7 @@ function inetLatency(host, callback) {
});
}
if (_sunos) {
exec('ping -s -a ' + host + ' 56 2 | grep avg', { timeout: 3000 }, function (error, stdout) {
exec('ping -s -a ' + hostSanitized + ' 56 2 | grep avg', { timeout: 3000 }, function (error, stdout) {
let result = -1;
if (!error) {
const line = stdout.toString().split('=');
@ -157,7 +158,7 @@ function inetLatency(host, callback) {
if (_windows) {
let result = -1;
try {
exec('ping ' + host + ' -n 1', util.execOptsWin, function (error, stdout) {
exec('ping ' + hostSanitized + ' -n 1', util.execOptsWin, function (error, stdout) {
if (!error) {
let lines = stdout.toString().split('\r\n');
lines.shift();

View File

@ -572,13 +572,13 @@ function getLinuxIfaceDHCPstatus(iface, connectionName, DHCPNics) {
let dhcStatus = resultFormat.split(' ').slice(1).toString();
switch (dhcStatus) {
case 'auto':
result = true;
break;
case 'auto':
result = true;
break;
default:
result = false;
break;
default:
result = false;
break;
}
return result;
} catch (e) {
@ -1018,8 +1018,10 @@ function networkStatsSingle(iface) {
return new Promise((resolve) => {
process.nextTick(() => {
const ifaceSanitized = util.sanitizeShellString(iface);
let result = {
iface: iface,
iface: ifaceSanitized,
operstate: 'unknown',
rx_bytes: 0,
rx_dropped: 0,
@ -1041,17 +1043,17 @@ function networkStatsSingle(iface) {
let tx_errors = 0;
let cmd, lines, stats;
if (!_network[iface] || (_network[iface] && !_network[iface].ms) || (_network[iface] && _network[iface].ms && Date.now() - _network[iface].ms >= 500)) {
if (!_network[ifaceSanitized] || (_network[ifaceSanitized] && !_network[ifaceSanitized].ms) || (_network[ifaceSanitized] && _network[ifaceSanitized].ms && Date.now() - _network[ifaceSanitized].ms >= 500)) {
if (_linux) {
if (fs.existsSync('/sys/class/net/' + iface)) {
if (fs.existsSync('/sys/class/net/' + ifaceSanitized)) {
cmd =
'cat /sys/class/net/' + iface + '/operstate; ' +
'cat /sys/class/net/' + iface + '/statistics/rx_bytes; ' +
'cat /sys/class/net/' + iface + '/statistics/tx_bytes; ' +
'cat /sys/class/net/' + iface + '/statistics/rx_dropped; ' +
'cat /sys/class/net/' + iface + '/statistics/rx_errors; ' +
'cat /sys/class/net/' + iface + '/statistics/rx_dropped; ' +
'cat /sys/class/net/' + iface + '/statistics/tx_errors; ';
'cat /sys/class/net/' + ifaceSanitized + '/operstate; ' +
'cat /sys/class/net/' + ifaceSanitized + '/statistics/rx_bytes; ' +
'cat /sys/class/net/' + ifaceSanitized + '/statistics/tx_bytes; ' +
'cat /sys/class/net/' + ifaceSanitized + '/statistics/rx_dropped; ' +
'cat /sys/class/net/' + ifaceSanitized + '/statistics/rx_errors; ' +
'cat /sys/class/net/' + ifaceSanitized + '/statistics/rx_dropped; ' +
'cat /sys/class/net/' + ifaceSanitized + '/statistics/tx_errors; ';
exec(cmd, function (error, stdout) {
if (!error) {
lines = stdout.toString().split('\n');
@ -1063,7 +1065,7 @@ function networkStatsSingle(iface) {
tx_dropped = parseInt(lines[5], 10);
tx_errors = parseInt(lines[6], 10);
result = calcNetworkSpeed(iface, rx_bytes, tx_bytes, operstate, rx_dropped, rx_errors, tx_dropped, tx_errors);
result = calcNetworkSpeed(ifaceSanitized, rx_bytes, tx_bytes, operstate, rx_dropped, rx_errors, tx_dropped, tx_errors);
}
resolve(result);
@ -1073,7 +1075,7 @@ function networkStatsSingle(iface) {
}
}
if (_freebsd || _openbsd || _netbsd) {
cmd = 'netstat -ibndI ' + iface;
cmd = 'netstat -ibndI ' + ifaceSanitized;
exec(cmd, function (error, stdout) {
if (!error) {
lines = stdout.toString().split('\n');
@ -1089,18 +1091,18 @@ function networkStatsSingle(iface) {
operstate = 'up';
}
}
result = calcNetworkSpeed(iface, rx_bytes, tx_bytes, operstate, rx_dropped, rx_errors, tx_dropped, tx_errors);
result = calcNetworkSpeed(ifaceSanitized, rx_bytes, tx_bytes, operstate, rx_dropped, rx_errors, tx_dropped, tx_errors);
}
resolve(result);
});
}
if (_darwin) {
cmd = 'ifconfig ' + iface + ' | grep "status"';
cmd = 'ifconfig ' + ifaceSanitized + ' | grep "status"';
exec(cmd, function (error, stdout) {
result.operstate = (stdout.toString().split(':')[1] || '').trim();
result.operstate = (result.operstate || '').toLowerCase();
result.operstate = (result.operstate === 'active' ? 'up' : (result.operstate === 'inactive' ? 'down' : 'unknown'));
cmd = 'netstat -bdI ' + iface;
cmd = 'netstat -bdI ' + ifaceSanitized;
exec(cmd, function (error, stdout) {
if (!error) {
lines = stdout.toString().split('\n');
@ -1116,7 +1118,7 @@ function networkStatsSingle(iface) {
tx_dropped = parseInt(stats[11]);
tx_errors = parseInt(stats[8]);
result = calcNetworkSpeed(iface, rx_bytes, tx_bytes, result.operstate, rx_dropped, rx_errors, tx_dropped, tx_errors);
result = calcNetworkSpeed(ifaceSanitized, rx_bytes, tx_bytes, result.operstate, rx_dropped, rx_errors, tx_dropped, tx_errors);
}
}
resolve(result);
@ -1125,7 +1127,7 @@ function networkStatsSingle(iface) {
}
if (_windows) {
let perfData = [];
let ifaceName = iface;
let ifaceName = ifaceSanitized;
// Performance Data
util.wmic('path Win32_PerfRawData_Tcpip_NetworkInterface Get name,BytesReceivedPersec,BytesSentPersec,BytesTotalPersec,PacketsOutboundDiscarded,PacketsOutboundErrors,PacketsReceivedDiscarded,PacketsReceivedErrors /value').then((stdout, error) => {
@ -1141,11 +1143,11 @@ function networkStatsSingle(iface) {
tx_bytes = 0;
perfData.forEach(detail => {
interfaces.forEach(det => {
if ((det.iface.toLowerCase() === iface.toLowerCase() ||
det.mac.toLowerCase() === iface.toLowerCase() ||
det.ip4.toLowerCase() === iface.toLowerCase() ||
det.ip6.toLowerCase() === iface.toLowerCase() ||
(det.ifaceName.replace(/[()\[\] ]+/g, '').toLowerCase() === iface.replace(/[()\[\] ]+/g, '').toLowerCase()) &&
if ((det.iface.toLowerCase() === ifaceSanitized.toLowerCase() ||
det.mac.toLowerCase() === ifaceSanitized.toLowerCase() ||
det.ip4.toLowerCase() === ifaceSanitized.toLowerCase() ||
det.ip6.toLowerCase() === ifaceSanitized.toLowerCase() ||
(det.ifaceName.replace(/[()\[\] ]+/g, '').toLowerCase() === ifaceSanitized.replace(/[()\[\] ]+/g, '').toLowerCase()) &&
det.ifaceName.replace(/[()\[\] ]+/g, '').toLowerCase() === detail.name)) {
ifaceName = det.iface;
rx_bytes = detail.rx_bytes;
@ -1167,12 +1169,12 @@ function networkStatsSingle(iface) {
});
}
} else {
result.rx_bytes = _network[iface].rx_bytes;
result.tx_bytes = _network[iface].tx_bytes;
result.rx_sec = _network[iface].rx_sec;
result.tx_sec = _network[iface].tx_sec;
result.ms = _network[iface].last_ms;
result.operstate = _network[iface].operstate;
result.rx_bytes = _network[ifaceSanitized].rx_bytes;
result.tx_bytes = _network[ifaceSanitized].tx_bytes;
result.rx_sec = _network[ifaceSanitized].rx_sec;
result.tx_sec = _network[ifaceSanitized].tx_sec;
result.ms = _network[ifaceSanitized].last_ms;
result.operstate = _network[ifaceSanitized].operstate;
resolve(result);
}
});

View File

@ -31,26 +31,26 @@ const _openbsd = (_platform === 'openbsd');
const _netbsd = (_platform === 'netbsd');
const _sunos = (_platform === 'sunos');
let _processes_cpu = {
const _processes_cpu = {
all: 0,
list: {},
list: [],
ms: 0,
result: {}
};
let _services_cpu = {
const _services_cpu = {
all: 0,
list: {},
list: [],
ms: 0,
result: {}
};
let _process_cpu = {
const _process_cpu = {
all: 0,
list: {},
list: [],
ms: 0,
result: {}
};
let _winStatusValues = {
const _winStatusValues = {
'0': 'unknown',
'1': 'other',
'2': 'ready',
@ -98,28 +98,32 @@ function services(srv, callback) {
return new Promise((resolve) => {
process.nextTick(() => {
if (srv) {
srv = srv.trim().toLowerCase().replace(/,+/g, ' ').replace(/ +/g, ' ').replace(/ +/g, '|');
let srvs = srv.split('|');
let srvString = util.sanitizeShellString(srv);
srvString = srvString.trim().toLowerCase().replace(/,+/g, ' ').replace(/ +/g, ' ').replace(/ +/g, '|');
if (srvString === '') {
srvString = '*';
}
let srvs = srvString.split('|');
let result = [];
let dataSrv = [];
let allSrv = [];
if (_linux || _freebsd || _openbsd || _netbsd || _darwin) {
if ((_linux || _freebsd || _openbsd || _netbsd) && srv === '*') {
srv = '';
if ((_linux || _freebsd || _openbsd || _netbsd) && srvString === '*') {
srvString = '';
let tmpsrv = execSync('service --status-all 2> /dev/null').toString().split('\n');
for (const s of tmpsrv) {
const parts = s.split(']');
if (parts.length === 2) {
srv += (srv !== '' ? '|' : '') + parts[1].trim();
srvString += (srvString !== '' ? '|' : '') + parts[1].trim();
allSrv.push({ name: parts[1].trim(), running: parts[0].indexOf('+') > 0 });
}
}
srvs = srv.split('|');
srvs = srvString.split('|');
}
let comm = (_darwin) ? 'ps -caxo pcpu,pmem,pid,command' : 'ps -axo pcpu,pmem,pid,command';
if (srv !== '' && srvs.length > 0) {
exec(comm + ' | grep -v grep | grep -iE "' + srv + '"', { maxBuffer: 1024 * 20000 }, function (error, stdout) {
if (srvString !== '' && srvs.length > 0) {
exec(comm + ' | grep -v grep | grep -iE "' + srvString + '"', { maxBuffer: 1024 * 20000 }, function (error, stdout) {
if (!error) {
let lines = stdout.toString().replace(/ +/g, ' ').replace(/,+/g, '.').split('\n');
srvs.forEach(function (srv) {
@ -167,7 +171,7 @@ function services(srv, callback) {
let curr_processes = stdout.toString().split('\n');
// first line (all - /proc/stat)
let all = parseProcStat(curr_processes.shift());
let all = parseProcStat(curr_processes.shift()).slice();
// process
let list_new = {};
@ -202,9 +206,11 @@ function services(srv, callback) {
// store old values
_services_cpu.all = all;
_services_cpu.list = list_new;
// _services_cpu.list = list_new;
_services_cpu.list = list_new.slice();
_services_cpu.ms = Date.now() - _services_cpu.ms;
_services_cpu.result = result;
// _services_cpu.result = result;
_services_cpu.result = Object.assign({}, result);
if (callback) { callback(result); }
resolve(result);
});
@ -213,7 +219,7 @@ function services(srv, callback) {
resolve(result);
}
} else {
exec('ps -o comm | grep -v grep | egrep "' + srv + '"', { maxBuffer: 1024 * 20000 }, function (error, stdout) {
exec('ps -o comm | grep -v grep | egrep "' + srvString + '"', { maxBuffer: 1024 * 20000 }, function (error, stdout) {
if (!error) {
let lines = stdout.toString().replace(/ +/g, ' ').replace(/,+/g, '.').split('\n');
srvs.forEach(function (srv) {
@ -263,12 +269,12 @@ function services(srv, callback) {
let started = util.getValue(lines, 'Started', '=', true);
let startMode = util.getValue(lines, 'StartMode', '=', true);
let pid = util.getValue(lines, 'ProcessId', '=', true);
if (srv === '*' || srvs.indexOf(srvName) >= 0) {
if (srvString === '*' || srvs.indexOf(srvName) >= 0) {
result.push({
name: srvName,
running: (started === 'TRUE'),
startmode: startMode,
pids: [ pid],
pids: [pid],
pcpu: 0,
pmem: 0
});
@ -276,7 +282,7 @@ function services(srv, callback) {
}
}
}
if (srv !== '*') {
if (srvString !== '*') {
let srvsMissing = srvs.filter(function (e) {
return dataSrv.indexOf(e) === -1;
});
@ -609,7 +615,7 @@ function processes(callback) {
if (_sunos) cmd = 'ps -Ao pid,ppid,pcpu,pmem,pri,vsz,rss,nice,stime,s,tty,user,comm';
exec(cmd, { maxBuffer: 1024 * 20000 }, function (error, stdout) {
if (!error) {
result.list = parseProcesses(stdout.toString().split('\n'));
result.list = (parseProcesses(stdout.toString().split('\n'))).slice();
result.all = result.list.length;
result.running = result.list.filter(function (e) {
return e.state === 'running';
@ -663,9 +669,11 @@ function processes(callback) {
// store old values
_processes_cpu.all = all;
_processes_cpu.list = list_new;
// _processes_cpu.list = list_new;
_processes_cpu.list = list_new.slice();
_processes_cpu.ms = Date.now() - _processes_cpu.ms;
_processes_cpu.result = result;
// _processes_cpu.result = result;
_processes_cpu.result = Object.assign({}, result);
if (callback) { callback(result); }
resolve(result);
});
@ -683,7 +691,7 @@ function processes(callback) {
let lines = stdout.toString().split('\n');
lines.shift();
result.list = parseProcesses2(lines);
result.list = parseProcesses2(lines).slice();
result.all = result.list.length;
result.running = result.list.filter(function (e) {
return e.state === 'running';
@ -703,8 +711,7 @@ function processes(callback) {
});
}
});
}
if (_windows) {
} else if (_windows) {
try {
util.wmic('process get /value').then((stdout, error) => {
if (!error) {
@ -786,9 +793,11 @@ function processes(callback) {
}
// store old values
_processes_cpu.all = allcpuu + allcpus;
_processes_cpu.list = list_new;
// _processes_cpu.list = list_new;
_processes_cpu.list = list_new.slice();
_processes_cpu.ms = Date.now() - _processes_cpu.ms;
_processes_cpu.result = result;
// _processes_cpu.result = result;
_processes_cpu.result = Object.assign({}, result);
}
if (callback) {
callback(result);
@ -799,6 +808,9 @@ function processes(callback) {
if (callback) { callback(result); }
resolve(result);
}
} else {
if (callback) { callback(result); }
resolve(result);
}
} else {
if (callback) { callback(_processes_cpu.result); }
@ -825,14 +837,16 @@ function processLoad(proc, callback) {
return new Promise((resolve) => {
process.nextTick(() => {
const procSanitized = util.sanitizeShellString(proc);
let result = {
'proc': proc,
'proc': procSanitized,
'pid': -1,
'cpu': 0,
'mem': 0
};
if (proc) {
if (procSanitized) {
if (_windows) {
try {
util.wmic('process get /value').then((stdout, error) => {
@ -861,7 +875,7 @@ function processLoad(proc, callback) {
pcpuu: 0,
pcpus: 0,
});
if (name.toLowerCase().indexOf(proc.toLowerCase()) >= 0) {
if (name.toLowerCase().indexOf(procSanitized.toLowerCase()) >= 0) {
if (result.pid === -1) {
result = {
proc: name,
@ -898,9 +912,11 @@ function processLoad(proc, callback) {
}
// store old values
_process_cpu.all = allcpuu + allcpus;
_process_cpu.list = list_new;
// _process_cpu.list = list_new;
_process_cpu.list = list_new.slice();
_process_cpu.ms = Date.now() - _process_cpu.ms;
_process_cpu.result = result;
// _process_cpu.result = result;
_process_cpu.result = Object.assign({}, result);
if (callback) {
callback(result);
}
@ -914,7 +930,7 @@ function processLoad(proc, callback) {
}
if (_darwin || _linux) {
exec('ps -axo pid,pcpu,pmem,comm | grep -i ' + proc + ' | grep -v grep', { maxBuffer: 1024 * 20000 }, function (error, stdout) {
exec('ps -axo pid,pcpu,pmem,comm | grep -i ' + procSanitized + ' | grep -v grep', { maxBuffer: 1024 * 20000 }, function (error, stdout) {
if (!error) {
let lines = stdout.toString().split('\n');
@ -934,7 +950,7 @@ function processLoad(proc, callback) {
});
result = {
'proc': proc,
'proc': procSanitized,
'pid': pid,
'pids': pids,
'cpu': parseFloat((cpu / lines.length).toFixed(2)),
@ -980,9 +996,11 @@ function processLoad(proc, callback) {
result.cpu = Math.round(result.cpu * 100) / 100;
_process_cpu.all = all;
_process_cpu.list = list_new;
// _process_cpu.list = list_new;
_process_cpu.list = list_new.slice();
_process_cpu.ms = Date.now() - _process_cpu.ms;
_process_cpu.result = result;
// _process_cpu.result = result;
_process_cpu.result = Object.assign({}, result);
if (callback) { callback(result); }
resolve(result);
});

View File

@ -485,6 +485,27 @@ function countLines(lines, startingWith) {
return uniqueLines.length;
}
function sanitizeShellString(str) {
let result = str;
result = result.replace(/>/g, "");
result = result.replace(/</g, "");
result = result.replace(/\*/g, "");
result = result.replace(/\?/g, "");
result = result.replace(/\[/g, "");
result = result.replace(/\]/g, "");
result = result.replace(/\|/g, "");
result = result.replace(/\`/g, "");
result = result.replace(/$/g, "");
result = result.replace(/;/g, "");
result = result.replace(/&/g, "");
result = result.replace(/\)/g, "");
result = result.replace(/\(/g, "");
result = result.replace(/\$/g, "");
result = result.replace(/#/g, "");
result = result.replace(/\\/g, "");
return result
}
function noop() { }
exports.toInt = toInt;
@ -511,3 +532,4 @@ exports.countLines = countLines;
exports.noop = noop;
exports.isRaspberry = isRaspberry;
exports.isRaspbian = isRaspbian;
exports.sanitizeShellString = sanitizeShellString;