CVE-2024-21488: Improper Neutralization of Special Elements used in a Command ('Command Injection') (CWE-77)
value: Versions of the package network before 0.7.0 are vulnerable to Arbitrary Command Injection due to use of the child_process exec function without input sanitization. If (attacker-controlled) user input is given to the mac_address_for function of the package, it is possible for the attacker to execute arbitrary commands on the operating system that this package is being run on.
CWE description: The product constructs all or part of a command using externally-influenced input from an upstream component, but it does not neutralize or incorrectly neutralizes special elements that could modify the intended command when it is sent to a downstream component.
CVSS v3 base score: 9.8
Published: 2024-01-30T05:15Z
Repository: https://github.com/tomas/network
Language: JavaScript
Files changed: lib/linux.js
Commit date: 2024-01-23 22:30:44 -0300
Commit message: Validate nic name under linux
Diff: diff --git a/lib/linux.js b/lib/linux.js
index 2347dcc..08de844 100644
--- a/lib/linux.js
+++ b/lib/linux.js
@@ -11,40 +11,53 @@ function trim_exec(cmd, cb) {
     else
       cb(err)
   })
 }
 
+function ensure_valid_nic(str) {
+  if (str.match(/[^\w]/))
+    throw new Error("Invalid nic name given: " + str);
+}
+
 // If no wifi, then there is no error but cbed get's a null in second param.
 exports.get_active_network_interface_name = function(cb) {
   var cmd = "netstat -rn | grep UG | awk '{print $NF}'";
-  exec(cmd, function(err, stdout) {
+  exec(cmd, function(err, stdout, stderr) {
     if (err) return cb(err);
 
+    if (stderr.toString().match('not found')) {
+      return cb(new Error('Command failed: ' + stderr.toString().trim()))
+    }
+
     var raw = stdout.toString().trim().split('\n');
     if (raw.length === 0 || raw === [''])
       return cb(new Error('No active network interface found.'));
 
     cb(null, raw[0]);
   });
 };
 
 exports.interface_type_for = function(nic_name, cb) {
+  ensure_valid_nic(nic_name);
   exec('cat /proc/net/wireless | grep ' + nic_name, function(err, out) {
     return cb(null, err ? 'Wired' : 'Wireless')
   })
 };
 
 exports.mac_address_for = function(nic_name, cb) {
+  ensure_valid_nic(nic_name);
   var cmd = 'cat /sys/class/net/' + nic_name + '/address';
   trim_exec(cmd, cb);
 };
 
 exports.gateway_ip_for = function(nic_name, cb) {
+  ensure_valid_nic(nic_name);
   trim_exec("ip r | grep " + nic_name + " | grep default | cut -d ' ' -f 3 | head -n1", cb);
 };
 
 exports.netmask_for = function(nic_name, cb) {
+  ensure_valid_nic(nic_name);
   var cmd = "ifconfig " + nic_name + " 2> /dev/null | egrep 'netmask|Mask:' | awk '{print $4}' | sed 's/Mask://'";
   trim_exec(cmd, cb);
 };
 
 exports.get_network_interfaces_list = function(cb) {

Vulnerable code:   exec(cmd, function(err, stdout) {
Fixed code: function ensure_valid_nic(str) {
  if (str.match(/[^\w]/))
    throw new Error("Invalid nic name given: " + str);
}

  exec(cmd, function(err, stdout, stderr) {
    if (stderr.toString().match('not found')) {
      return cb(new Error('Command failed: ' + stderr.toString().trim()))
    }

  ensure_valid_nic(nic_name);
  ensure_valid_nic(nic_name);
  ensure_valid_nic(nic_name);
  ensure_valid_nic(nic_name);