CVE-2020-7778: Improper Neutralization of Special Elements used in an OS Command ('OS Command Injection') (CWE-78)
value: This affects the package systeminformation before 4.30.2. The attacker can overwrite the properties and functions of an object, which can lead to executing OS commands.
CWE description: The product constructs all or part of an OS command using externally-influenced input from an upstream component, but it does not neutralize or incorrectly neutralizes special elements that could modify the intended OS command when it is sent to a downstream component.
CVSS v3 base score: 7.3
Published: 2020-11-26T11:15Z
Repository: https://github.com/sebhildebrandt/systeminformation
Language: JavaScript
Files changed: lib/internet.js, lib/network.js, lib/util.js
Commit date: 2020-11-25 06:58:06 +0100
Commit message: security update (prototype pollution prevention)

Diff: diff --git a/lib/internet.js b/lib/internet.js
index c25f2bb..9f8ef33 100644
--- a/lib/internet.js
+++ b/lib/internet.js
@@ -33,18 +33,18 @@ function inetChecksite(url, callback) {
 
   return new Promise((resolve) => {
     process.nextTick(() => {
       let urlSanitized = '';
       const s = util.sanitizeShellString(url);
-      for (i = 0; i <= 2000; i++) {
+      for (let 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];
+            urlSanitized = urlSanitized + sl[0];
           }
         }
       }
       let result = {
         url: urlSanitized,
diff --git a/lib/network.js b/lib/network.js
index 4c5190d..c969398 100644
--- a/lib/network.js
+++ b/lib/network.js
@@ -1132,17 +1132,17 @@ function networkStatsSingle(iface) {
                 // if there is less than 2 lines, no information for this interface was found
                 if (lines.length > 1 && lines[1].trim() !== '') {
                   // skip header line
                   // use the second line because it is tied to the NIC instead of the ipv4 or ipv6 address
                   stats = lines[1].replace(/ +/g, ' ').split(' ');
-                  rx_bytes = parseInt(stats[6]);
-                  rx_dropped = parseInt(stats[11]);
-                  rx_errors = parseInt(stats[5]);
-                  tx_bytes = parseInt(stats[9]);
-                  tx_dropped = parseInt(stats[11]);
-                  tx_errors = parseInt(stats[8]);
-
+                  const offset = stats.length > 11 ? 1 : 0;
+                  rx_bytes = parseInt(stats[offset + 5]);
+                  rx_dropped = parseInt(stats[offset + 10]);
+                  rx_errors = parseInt(stats[offset + 4]);
+                  tx_bytes = parseInt(stats[offset + 8]);
+                  tx_dropped = parseInt(stats[offset + 10]);
+                  tx_errors = parseInt(stats[offset + 7]);
                   result = calcNetworkSpeed(ifaceSanitized, rx_bytes, tx_bytes, result.operstate, rx_dropped, rx_errors, tx_dropped, tx_errors);
                 }
               }
               resolve(result);
             });
diff --git a/lib/util.js b/lib/util.js
index 5f13173..facf1ec 100644
--- a/lib/util.js
+++ b/lib/util.js
@@ -490,11 +490,11 @@ function countLines(lines, startingWith) {
 }
 
 function sanitizeShellString(str) {
   const s = str || '';
   let result = '';
-  for (i = 0; i <= 2000; i++) {
+  for (let i = 0; i <= 2000; i++) {
     if (!(s[i] === undefined ||
       s[i] === '>' ||
       s[i] === '<' ||
       s[i] === '*' ||
       s[i] === '?' ||
@@ -518,19 +518,19 @@ function sanitizeShellString(str) {
   }
   return result;
 }
 
 function isPrototypePolluted() {
-  s = '1234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'
+  const 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++) {
+    for (let 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)
@@ -559,11 +559,11 @@ function isPrototypePolluted() {
     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++) {
+    for (let 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]);
     }

Vulnerable code:       for (i = 0; i <= 2000; i++) {
            urlSanitized = urlSanitized + sl[i];
                  rx_bytes = parseInt(stats[6]);
                  rx_dropped = parseInt(stats[11]);
                  rx_errors = parseInt(stats[5]);
                  tx_bytes = parseInt(stats[9]);
                  tx_dropped = parseInt(stats[11]);
                  tx_errors = parseInt(stats[8]);

  for (i = 0; i <= 2000; i++) {
  s = '1234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'
    for (i = 0; i < l; i++) {
    for (i = 0; i < l; i++) {
Fixed code:       for (let i = 0; i <= 2000; i++) {
            urlSanitized = urlSanitized + sl[0];
                  const offset = stats.length > 11 ? 1 : 0;
                  rx_bytes = parseInt(stats[offset + 5]);
                  rx_dropped = parseInt(stats[offset + 10]);
                  rx_errors = parseInt(stats[offset + 4]);
                  tx_bytes = parseInt(stats[offset + 8]);
                  tx_dropped = parseInt(stats[offset + 10]);
                  tx_errors = parseInt(stats[offset + 7]);
  for (let i = 0; i <= 2000; i++) {
  const s = '1234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'
    for (let i = 0; i < l; i++) {
    for (let i = 0; i < l; i++) {