diff --git a/CHANGELOG.md b/CHANGELOG.md index 88cfff7..06e1c09 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -72,6 +72,9 @@ For major (breaking) changes - **version 4, 3 and 2** - see end of page. | Version | Date | Comment | | -------------- | -------------- | -------- | +| 5.3.3 | 2020-02-15 | `dockerContainerStats()` fixed ID splitting | +| 5.3.2 | 2020-02-15 | `inetLatency()` `ineChecksite()` fixed possible security issue (file://) | +| 5.3.1 | 2020-02-14 | `inetLatency()` `ineChecksite()` `servcices()` `processes()` fixed possible security issue (arrays) | | 5.3.0 | 2020-02-12 | `osInfo()` added remoteSession (windows) | | 5.2.7 | 2020-02-12 | `fsStats()`, `blockDevices()` improved linux | | 5.2.6 | 2020-02-12 | `inetLatency()` fixed possible DOS intrusion | diff --git a/docs/history.html b/docs/history.html index f0e4d75..84aafea 100644 --- a/docs/history.html +++ b/docs/history.html @@ -56,6 +56,21 @@ + + 5.3.3 + 2020-02-15 + dockerContainerStats() fix correct ID splitting + + + 5.3.2 + 2020-02-15 + inetLatency() inetChecksite() fix possible security issue (file://) + + + 5.3.1 + 2020-02-14 + inetLatency() inetChecksite() services() processLoad() fix possible security issue + 5.3.0 2020-02-12 diff --git a/docs/index.html b/docs/index.html index 9e5318e..5471d4f 100644 --- a/docs/index.html +++ b/docs/index.html @@ -166,11 +166,11 @@
- Security advisory:
Update to v5.2.6
+ Security advisory:
Update to v5.3.2
systeminformation
 
-
New Version: 5.3.0
+
New Version: 5.3.3
@@ -201,7 +201,7 @@
-
13,752
+
13,833
Lines of code
@@ -209,7 +209,7 @@
Downloads last month
-
382
+
387
Dependents
diff --git a/docs/security.html b/docs/security.html index 10ebbcf..0f23f85 100644 --- a/docs/security.html +++ b/docs/security.html @@ -43,6 +43,40 @@
Security Advisories
+

Insufficient File Scheme Validation

+

Affected versions: + < 5.3.2 and < 4.34.12
+ Date: 2021-02-15
+ CVE indentifier - +

+ +

Impact

+

We had an issue that there was a possibility to run inetChecksite against local files due to improper file scheme validation. Affected commands: inetLatency(), inetChecksite().

+ +

Patch

+

Problem was fixed with additional parameter checking. Please upgrade to version >= 5.3.2 (or >= 4.34.12 if you are using version 4).

+ +

Workarround

+

If you cannot upgrade, be sure to check or sanitize service parameter strings that are passed to inetLatency(), inetChecksite() (sanitize `file://` parameter)

+
+
+

Command Injection Vulnerability

+

Affected versions: + < 5.3.1 and < 4.34.11
+ Date: 2021-02-14
+ CVE indentifier - +

+ +

Impact

+

We had an issue that there was a possibility to perform a potential command injection possibility by passing a manipulated array as a parameter to the following functions. Affected commands: inetLatency(), inetChecksite(), services(), processLoad().

+ +

Patch

+

Problem was fixed with additional parameter checking. Please upgrade to version >= 5.3.1 (or >= 4.34.11 if you are using version 4).

+ +

Workarround

+

If you cannot upgrade, be sure to check or sanitize service parameter strings that are passed to inetLatency(), inetChecksite(), services(), processLoad() (string only)

+
+

DOS Injection Vulnerability

Affected versions: < 5.2.6 and < 4.34.10
diff --git a/docs/v4/gettingstarted.html b/docs/v4/gettingstarted.html index bf6afff..a97048f 100644 --- a/docs/v4/gettingstarted.html +++ b/docs/v4/gettingstarted.html @@ -67,7 +67,7 @@

This library is supposed to be used as a node.js backend/server-side library and will definilely not work within a browser.

Installation (old version 4)

-
$ npm install systeminformation@4 —save
+
$ npm install systeminformation@4 —-save

Usage

All functions (except version and time) are implemented as asynchronous functions. Here a small example how to use them:

const si = require('systeminformation');
diff --git a/docs/v4/history.html b/docs/v4/history.html
index 67dcfe3..a933e98 100644
--- a/docs/v4/history.html
+++ b/docs/v4/history.html
@@ -83,6 +83,16 @@
                   
                 
                 
+                  
+                    4.34.12
+                    2020-02-15
+                    inetLatency() inetChecksite() fix possible security issue (file://)
+                  
+                  
+                    4.34.11
+                    2020-02-14
+                    inetLatency() inetChecksite() services() processes() possible security fix
+                  
                   
                     4.34.10
                     2020-02-12
diff --git a/docs/v4/index.html b/docs/v4/index.html
index fe94b13..6423484 100644
--- a/docs/v4/index.html
+++ b/docs/v4/index.html
@@ -165,12 +165,12 @@
 
   
- Security advisory:
Update to v4.34.10
+ Security advisory:
Update to v4.34.11
systeminformation
 
Version 4 documentation
-
Current Version: 4.34.10
+
Current Version: 4.34.12
diff --git a/docs/v4/security.html b/docs/v4/security.html index 47f66d6..78d966d 100644 --- a/docs/v4/security.html +++ b/docs/v4/security.html @@ -42,6 +42,40 @@
Security Advisories
+

Insufficient File Scheme Validation

+

Affected versions: + 4.34.12
+ Date: 2021-02-15
+ CVE indentifier - +

+ +

Impact

+

We had an issue that there was a possibility to run inetChecksite against local files due to improper file scheme validation. Affected commands: inetLatency(), inetChecksite().

+ +

Patch

+

Problem was fixed with additional parameter checking. Please upgrade to version >= 4.34.12 if you are using version 4.

+ +

Workarround

+

If you cannot upgrade, be sure to check or sanitize service parameter strings that are passed to inetLatency(), inetChecksite() (sanitize `file://` parameter)

+
+
+

Command Injection Vulnerability

+

Affected versions: + < 4.34.11
+ Date: 2021-02-14
+ CVE indentifier - +

+ +

Impact

+

We had an issue that there was a possibility to perform a potential command injection possibility by passing a manipulated array as a parameter to the following functions. Affected commands: inetLatency(), inetChecksite(), services(), processLoad().

+ +

Patch

+

Problem was fixed with additional parameter checking. Please upgrade to version >= 4.34.11 if you are using version 4.

+ +

Workarround

+

If you cannot upgrade, be sure to check or sanitize service parameter strings that are passed to inetLatency(), inetChecksite(), services(), processLoad() (string only)

+
+

DOS Injection Vulnerability

Affected versions: < 4.34.10
@@ -57,7 +91,8 @@

Workarround

If you cannot upgrade, be sure to check or sanitize service parameter strings that are passed to inetLatency() (no spaces)

- +
+

Command Injection Vulnerability

Affected versions: < 4.31.1
@@ -73,9 +108,9 @@

Workarround

If you cannot upgrade, be sure to check or sanitize service parameter strings that are passed to inetLatency()

- - -

command injection vulnerability - prototype pollution

+
+
+

Command Injection Vulnerability - prototype pollution

Affected versions: < 4.30.5
Date: 2020-11-26
@@ -90,8 +125,8 @@

Workarround

If you cannot upgrade, be sure to check or sanitize service parameter strings that are passed to inetChecksite()

- - +
+

Command Injection Vulnerability

Affected versions: < 4.27.11
diff --git a/lib/docker.js b/lib/docker.js index 24b56b2..1c2854e 100644 --- a/lib/docker.js +++ b/lib/docker.js @@ -109,6 +109,9 @@ function dockerContainers(all, callback) { callback = all; all = false; } + if (typeof all !== 'boolean' && all !== undefined) { + all = false; + } all = all || false; let result = []; @@ -185,16 +188,20 @@ function dockerContainers(all, callback) { // container inspect (for one container) function dockerContainerInspect(containerID, payload) { - containerID = containerID || ''; return new Promise((resolve) => { process.nextTick(() => { - if (containerID) { + containerID = containerID || ''; + if (typeof containerID !== 'string') { + resolve(); + } + const containerIdSanitized = (util.isPrototypePolluted() ? '' : util.sanitizeShellString(containerID, true)).trim(); + if (containerIdSanitized) { if (!_docker_socket) { _docker_socket = new DockerSocket(); } - _docker_socket.getInspect(containerID.trim(), data => { + _docker_socket.getInspect(containerIdSanitized.trim(), data => { try { resolve({ id: payload.Id, @@ -325,19 +332,39 @@ function docker_calcBlockIO(blkio_stats) { function dockerContainerStats(containerIDs, callback) { let containerArray = []; - // fallback - if only callback is given - if (util.isFunction(containerIDs) && !callback) { - callback = containerIDs; - containerArray = ['*']; - } else { - containerIDs = containerIDs || '*'; - containerIDs = containerIDs.trim().toLowerCase().replace(/,+/g, '|'); - containerArray = containerIDs.split('|'); - } - return new Promise((resolve) => { process.nextTick(() => { + // fallback - if only callback is given + if (util.isFunction(containerIDs) && !callback) { + callback = containerIDs; + containerArray = ['*']; + } else { + containerIDs = containerIDs || '*'; + if (typeof containerIDs !== 'string') { + if (callback) { callback([]); } + return resolve([]); + } + let containerIDsSanitized = ''; + containerIDsSanitized.__proto__.toLowerCase = util.stringToLower; + containerIDsSanitized.__proto__.replace = util.stringReplace; + containerIDsSanitized.__proto__.trim = util.stringTrim; + + const s = (util.isPrototypePolluted() ? '' : util.sanitizeShellString(containerIDs, true)).trim(); + for (let i = 0; i <= 2000; i++) { + if (!(s[i] === undefined)) { + s[i].__proto__.toLowerCase = util.stringToLower; + const sl = s[i].toLowerCase(); + if (sl && sl[0] && !sl[1]) { + containerIDsSanitized = containerIDsSanitized + sl[0]; + } + } + } + + containerIDsSanitized = containerIDsSanitized.trim().toLowerCase().replace(/,+/g, '|'); + containerArray = containerIDsSanitized.split('|'); + } + const result = []; const workload = []; @@ -444,17 +471,22 @@ exports.dockerContainerStats = dockerContainerStats; // container processes (for one container) function dockerContainerProcesses(containerID, callback) { - containerID = containerID || ''; let result = []; return new Promise((resolve) => { process.nextTick(() => { - if (containerID) { + containerID = containerID || ''; + if (typeof containerID !== 'string') { + resolve(result); + } + const containerIdSanitized = (util.isPrototypePolluted() ? '' : util.sanitizeShellString(containerID, true)).trim(); + + if (containerIdSanitized) { if (!_docker_socket) { _docker_socket = new DockerSocket(); } - _docker_socket.getProcesses(containerID, data => { + _docker_socket.getProcesses(containerIdSanitized, data => { /** * @namespace * @property {Array} Titles diff --git a/lib/internet.js b/lib/internet.js index 21936b6..6c4e9af 100644 --- a/lib/internet.js +++ b/lib/internet.js @@ -40,7 +40,7 @@ function inetChecksite(url, callback) { status: 404, ms: null }; - if (typeof url !== "string") { + if (typeof url !== 'string') { if (callback) { callback(result); } return resolve(result); } @@ -58,6 +58,11 @@ function inetChecksite(url, callback) { result.url = urlSanitized; try { if (urlSanitized && !util.isPrototypePolluted()) { + urlSanitized.__proto__.startsWith = util.stringStartWith; + if (urlSanitized.startsWith('file:')) { + if (callback) { callback(result); } + return resolve(result); + } 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'; @@ -131,7 +136,7 @@ function inetLatency(host, callback) { return new Promise((resolve) => { process.nextTick(() => { - if (typeof host !== "string") { + if (typeof host !== 'string') { if (callback) { callback(null); } return resolve(null); } @@ -146,6 +151,11 @@ function inetLatency(host, callback) { } } } + hostSanitized.__proto__.startsWith = util.stringStartWith; + if (hostSanitized.startsWith('file:')) { + if (callback) { callback(null); } + return resolve(null); + } let params; let filt; if (_linux || _freebsd || _openbsd || _netbsd || _darwin) { diff --git a/lib/network.js b/lib/network.js index 4e10af7..34cfa0a 100644 --- a/lib/network.js +++ b/lib/network.js @@ -973,19 +973,29 @@ function calcNetworkSpeed(iface, rx_bytes, tx_bytes, operstate, rx_dropped, rx_e function networkStats(ifaces, callback) { let ifacesArray = []; - // fallback - if only callback is given - if (util.isFunction(ifaces) && !callback) { - callback = ifaces; - ifacesArray = [getDefaultNetworkInterface()]; - } else { - ifaces = ifaces || getDefaultNetworkInterface(); - ifaces = ifaces.trim().toLowerCase().replace(/,+/g, '|'); - ifacesArray = ifaces.split('|'); - } return new Promise((resolve) => { process.nextTick(() => { + // fallback - if only callback is given + if (util.isFunction(ifaces) && !callback) { + callback = ifaces; + ifacesArray = [getDefaultNetworkInterface()]; + } else { + if (typeof ifaces !== 'string' && ifaces !== undefined) { + if (callback) { callback([]); } + return resolve([]); + } + ifaces = ifaces || getDefaultNetworkInterface(); + + ifaces.__proto__.toLowerCase = util.stringToLower; + ifaces.__proto__.replace = util.stringReplace; + ifaces.__proto__.trim = util.stringTrim; + + ifaces = ifaces.trim().toLowerCase().replace(/,+/g, '|'); + ifacesArray = ifaces.split('|'); + } + const result = []; const workload = []; diff --git a/lib/poc.js b/lib/poc.js new file mode 100644 index 0000000..98e883d --- /dev/null +++ b/lib/poc.js @@ -0,0 +1,22 @@ +let si = require('./internet'); +si.inetChecksite([]).then((a) => { + if (a.ok == false) + console.log("inetChecksite is fixed!") + else + console.log("inetChecksite is not fixed!") +}); + + +si.inetLatency([]).then((a) => { + if (a == null) + console.log("inetLatency is fixed!") + else + console.log("inetLatency is not fixed!") +}); +si = require('./processes'); +si.services([]).then((a) => { + if (typeof a == typeof []) + console.log("services is fixed!") + else + console.log("services is not fixed!") +}); diff --git a/lib/processes.js b/lib/processes.js index 772b932..83a90cc 100644 --- a/lib/processes.js +++ b/lib/processes.js @@ -99,7 +99,7 @@ function services(srv, callback) { return new Promise((resolve) => { process.nextTick(() => { - if (typeof srv !== "string") { + if (typeof srv !== 'string') { if (callback) { callback([]); } return resolve([]); } @@ -892,6 +892,13 @@ function processLoad(proc, callback) { return new Promise((resolve) => { process.nextTick(() => { + proc = proc || ''; + + if (typeof proc !== 'string') { + if (callback) { callback([]); } + return resolve([]); + } + let processesString = ''; processesString.__proto__.toLowerCase = util.stringToLower; processesString.__proto__.replace = util.stringReplace; diff --git a/lib/util.js b/lib/util.js index dd94ba2..24b3e6e 100644 --- a/lib/util.js +++ b/lib/util.js @@ -57,6 +57,7 @@ const stringToLower = new String().toLowerCase; const stringToString = new String().toString; const stringSubstr = new String().substr; const stringTrim = new String().trim; +const stringStartWith = new String().startsWith; function isFunction(functionToCheck) { let getType = {}; @@ -528,6 +529,7 @@ function sanitizeShellString(str, strict = false) { s[i] === '\'' || s[i] === '`' || s[i] === '"' || + strict && s[i] === '@' || strict && s[i] === ' ' || strict && s[i] == '{' || strict && s[i] == ')')) { @@ -939,5 +941,6 @@ exports.stringToLower = stringToLower; exports.stringToString = stringToString; exports.stringSubstr = stringSubstr; exports.stringTrim = stringTrim; +exports.stringStartWith = stringStartWith; exports.WINDIR = WINDIR; exports.getFilesInPath = getFilesInPath; diff --git a/package.json b/package.json index e9884b8..095088b 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "systeminformation", - "version": "5.3.0", + "version": "5.3.3", "description": "Simple system and OS information library", "license": "MIT", "author": "Sebastian Hildebrandt (https://plus-innovations.com)",