Vulnerability: OS Command Injection in GenieACS In GenieACS 1.2.x before 1.2.8, the UI interface API is vulnerable to unauthenticated OS command injection via the ping host argument (lib/ui/api.ts and lib/ping.ts). The vulnerability arises from insufficient input validation combined with a missing authorization check.
Vulnerability ID: GHSA-2877-693q-pj33
CWE: CWE-78
Severity score: 9.8
Project: https://github.com/genieacs/genieacs
Published: 2022-03-07
File: lib/ping.ts
Commit message: Validate host arg passed to ping

Fixes remote code execution vulnerability reported by Alex Hordijk.
Commit author: Zaid Abdulla

Vulnerable version (before fix):
  import { platform } from "os"; import { exec } from "child_process";  export interface PingResult {   packetsTransmitted: number; export interface PingResult {   mdev: number; }  export function ping(   host: string,   callback: (err: Error, res?: PingResult, stdout?: string) => void ): void {   let cmd: string, parseRegExp1: RegExp, parseRegExp2: RegExp;   host = host.replace("[", "").replace("]", "");   switch (platform()) {     case "linux":

Fixed version (after fix):
  import { platform } from "os"; import { exec } from "child_process"; import { domainToASCII } from "url";  export interface PingResult {   packetsTransmitted: number; export interface PingResult {   mdev: number; }  function isValidHost(host: string): boolean {   // Valid chars in IPv4, IPv6, domain names   if (/^[a-zA-Z0-9\-.:[\]-]+$/.test(host)) return true;    // Check if input is an IDN convert to Punycode   // Can't merge with above because domainToASCII doesn't accept IP addresses   return /^[a-zA-Z0-9\-.:[\]-]+$/.test(domainToASCII(host)); }  export function ping(   host: string,   callback: (err: Error, res?: PingResult, stdout?: string) => void ): void {   let cmd: string, parseRegExp1: RegExp, parseRegExp2: RegExp;   // Validate input to prevent possible remote code execution   // Credit to Alex Hordijk for reporting this vulnerability   if (!isValidHost(host)) return callback(new Error("Invalid host"));   host = host.replace("[", "").replace("]", "");   switch (platform()) {     case "linux":

Patch:
patch: @@ -19,6 +19,7 @@
 
 import { platform } from "os";
 import { exec } from "child_process";
+import { domainToASCII } from "url";
 
 export interface PingResult {
   packetsTransmitted: number;
@@ -30,11 +31,23 @@ export interface PingResult {
   mdev: number;
 }
 
+function isValidHost(host: string): boolean {
+  // Valid chars in IPv4, IPv6, domain names
+  if (/^[a-zA-Z0-9\-.:[\]-]+$/.test(host)) return true;
+
+  // Check if input is an IDN convert to Punycode
+  // Can't merge with above because domainToASCII doesn't accept IP addresses
+  return /^[a-zA-Z0-9\-.:[\]-]+$/.test(domainToASCII(host));
+}
+
 export function ping(
   host: string,
   callback: (err: Error, res?: PingResult, stdout?: string) => void
 ): void {
   let cmd: string, parseRegExp1: RegExp, parseRegExp2: RegExp;
+  // Validate input to prevent possible remote code execution
+  // Credit to Alex Hordijk for reporting this vulnerability
+  if (!isValidHost(host)) return callback(new Error("Invalid host"));
   host = host.replace("[", "").replace("]", "");
   switch (platform()) {
     case "linux":
path: lib/ping.ts