diff --git a/CHANGELOG.md b/CHANGELOG.md index 6e4e41ec..703c71b2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -30,6 +30,8 @@ For major (breaking) changes - version 3 and 2 see end of page. | Version | Date | Comment | | -------------- | -------------- | -------- | +| 4.30.2 | 2020-11-25 | security update (prototype pollution prevention) | +| 4.30.1 | 2020-11-12 | updated docs | | 4.30.0 | 2020-11-12 | `get()` possibility to provide params | | 4.29.3 | 2020-11-09 | `blockdevices()` catch errors adapted for just one line | | 4.29.2 | 2020-11-09 | `blockdevices()` catch errors | diff --git a/docs/history.html b/docs/history.html index 4b5c158a..efa636ce 100644 --- a/docs/history.html +++ b/docs/history.html @@ -83,6 +83,16 @@

Full version history

+ + 4.30.2 + 2020-11-25 + security update (prototype pollution prevention) + + + 4.30.1 + 2020-11-12 + updated docs + 4.30.0 2020-11-11 diff --git a/docs/index.html b/docs/index.html index 80cc8648..3a3d21f5 100644 --- a/docs/index.html +++ b/docs/index.html @@ -168,7 +168,7 @@
systeminformation
-
Current Version: 4.30.0
+
Current Version: 4.30.2
diff --git a/lib/internet.js b/lib/internet.js index ac81e365..c25f2bb9 100644 --- a/lib/internet.js +++ b/lib/internet.js @@ -33,21 +33,26 @@ function inetChecksite(url, callback) { return new Promise((resolve) => { process.nextTick(() => { - - let urlSanitized = util.sanitizeShellString(url).toLowerCase(); - urlSanitized = urlSanitized.replace(/ /g, ''); - urlSanitized = urlSanitized.replace(/\$/g, ''); - urlSanitized = urlSanitized.replace(/\(/g, ''); - urlSanitized = urlSanitized.replace(/\)/g, ''); - urlSanitized = urlSanitized.replace(/{/g, ''); - urlSanitized = urlSanitized.replace(/}/g, ''); + let urlSanitized = ''; + const s = util.sanitizeShellString(url); + for (i = 0; i <= 2000; i++) { + if (!(s[i] === undefined || + s[i] === ' ' || + s[i] === '{' || + s[i] === '}')) { + const sl = s[i].toLowerCase(); + if (sl[0] && !sl[1]) { + urlSanitized = urlSanitized + sl[i]; + } + } + } let result = { url: urlSanitized, ok: false, status: 404, ms: -1 }; - if (urlSanitized) { + if (urlSanitized && !util.isPrototypePolluted()) { let t = Date.now(); if (_linux || _freebsd || _openbsd || _netbsd || _darwin || _sunos) { let args = ' -I --connect-timeout 5 -m 5 ' + urlSanitized + ' 2>/dev/null | head -n 1 | cut -d " " -f2'; @@ -114,7 +119,7 @@ function inetLatency(host, callback) { } host = host || '8.8.8.8'; - const hostSanitized = util.sanitizeShellString(host); + const hostSanitized = util.isPrototypePolluted() ? '8.8.8.8' : util.sanitizeShellString(host); return new Promise((resolve) => { process.nextTick(() => { diff --git a/lib/network.js b/lib/network.js index e134ecda..4c5190d6 100644 --- a/lib/network.js +++ b/lib/network.js @@ -1041,7 +1041,7 @@ function networkStatsSingle(iface) { return new Promise((resolve) => { process.nextTick(() => { - const ifaceSanitized = util.sanitizeShellString(iface); + const ifaceSanitized = util.isPrototypePolluted() ? '---' : util.sanitizeShellString(iface); let result = { iface: ifaceSanitized, diff --git a/lib/processes.js b/lib/processes.js index c4234423..b9422603 100644 --- a/lib/processes.js +++ b/lib/processes.js @@ -103,6 +103,9 @@ function services(srv, callback) { if (srvString === '') { srvString = '*'; } + if (util.isPrototypePolluted() && srvString !== '*') { + srvString = '------'; + } let srvs = srvString.split('|'); let result = []; let dataSrv = []; @@ -837,7 +840,7 @@ function processLoad(proc, callback) { return new Promise((resolve) => { process.nextTick(() => { - const procSanitized = util.sanitizeShellString(proc); + const procSanitized = util.isPrototypePolluted() ? '' : util.sanitizeShellString(proc); let result = { 'proc': procSanitized, diff --git a/lib/util.js b/lib/util.js index a986badf..5f13173b 100644 --- a/lib/util.js +++ b/lib/util.js @@ -490,29 +490,87 @@ function countLines(lines, startingWith) { } function sanitizeShellString(str) { - let result = str || ''; - result = result.replace(/>/g, ''); - result = result.replace(/' || + s[i] === '<' || + s[i] === '*' || + s[i] === '?' || + s[i] === '[' || + s[i] === ']' || + s[i] === '|' || + s[i] === '˚' || + s[i] === '$' || + s[i] === ';' || + s[i] === '&' || + s[i] === '(' || + s[i] === ')' || + s[i] === ']' || + s[i] === '#' || + s[i] === '\\' || + s[i] === '\t' || + s[i] === '\n' || + s[i] === '"')) { + result = result + s[i]; + } + } return result; } +function isPrototypePolluted() { + s = '1234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ' + let notPolluted = true; + let st = ''; + notPolluted = notPolluted || !(s.length === 62) + const ms = Date.now(); + if (typeof ms === 'number' && ms > 1600000000000) { + const l = ms % 100 + 15; + let c = 0; + for (i = 0; i < l; i++) { + const r = Math.random() * 61.99999999 + 1; + const rs = parseInt(Math.floor(r).toString(), 10) + const rs2 = parseInt(r.toString().split('.')[0], 10); + const q = Math.random() * 61.99999999 + 1; + const qs = parseInt(Math.floor(q).toString(), 10) + const qs2 = parseInt(q.toString().split('.')[0], 10); + notPolluted = notPolluted && !(r === q); + notPolluted = notPolluted && rs === rs2 && qs === qs2; + st += s[rs - 1]; + } + notPolluted = notPolluted && st.length === l; + // string manipulation + let p = Math.random() * l * 0.9999999999; + let stm = st.substr(0, p) + ' ' + st.substr(p, 2000); + let sto = stm.replace(/ /g, ''); + notPolluted = notPolluted && st === sto; + p = Math.random() * l * 0.9999999999; + stm = st.substr(0, p) + '{' + st.substr(p, 2000); + sto = stm.replace(/{/g, ''); + notPolluted = notPolluted && st === sto; + p = Math.random() * l * 0.9999999999; + stm = st.substr(0, p) + '*' + st.substr(p, 2000); + sto = stm.replace(/\*/g, ''); + notPolluted = notPolluted && st === sto; + p = Math.random() * l * 0.9999999999; + stm = st.substr(0, p) + '$' + st.substr(p, 2000); + sto = stm.replace(/\$/g, ''); + notPolluted = notPolluted && st === sto; + + // lower + const stl = st.toLowerCase(); + notPolluted = notPolluted && (stl.length === l) && stl[l - 1] && !(stl[l]) + for (i = 0; i < l; i++) { + const s1 = st[i]; + const s2 = stl[i]; + const s1l = s1.toLowerCase(); + notPolluted = notPolluted && s1l[0] === s2 && s1l[0] && !(s1l[1]); + } + } + return !notPolluted; +} + function hex2bin(hex) { return ("00000000" + (parseInt(hex, 16)).toString(2)).substr(-8); } @@ -747,4 +805,5 @@ exports.noop = noop; exports.isRaspberry = isRaspberry; exports.isRaspbian = isRaspbian; exports.sanitizeShellString = sanitizeShellString; +exports.isPrototypePolluted = isPrototypePolluted; exports.decodePiCpuinfo = decodePiCpuinfo;