CVE-2025-14868

Career Section <= 1.6 - Cross-Site Request Forgery to Arbitrary File Deletion

highImproper Limitation of a Pathname to a Restricted Directory ('Path Traversal')
8.8
CVSS Score
8.8
CVSS Score
high
Severity
1.7
Patched in
0d
Time to patch

Description

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.

CVSS Vector Breakdown

CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H
Attack Vector
Network
Attack Complexity
Low
Privileges Required
None
User Interaction
Required
Scope
Unchanged
High
Confidentiality
High
Integrity
High
Availability

Technical Details

Affected versions<=1.6
PublishedApril 15, 2026
Last updatedApril 15, 2026
Affected plugincareer-section

What Changed in the Fix

Changes introduced in v1.7

Loading patch diff...

Source Code

WordPress.org SVN
Research Plan
Verified by PoC

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. ### 1. Vulnerability Summary The `appform_options_page_html` function in `include/top_level_menu.php` fails to validate user…

Show full research plan

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.

1. Vulnerability Summary

The appform_options_page_html function in include/top_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 (../), an attacker can delete arbitrary files on the server by tricking an administrator into submitting a forged request.

2. Attack Vector Analysis

  • Vulnerable Endpoint: /wp-admin/admin.php?page=appform
  • Vulnerable Parameter: delete_file (POST)
  • Trigger Parameter: delete_id (POST) must be set to enter the vulnerable code block.
  • Authentication: Requires a session with manage_options capability (typically Administrator). This is exploited via CSRF.
  • Vector: Path Traversal (../) leading to Arbitrary File Deletion.

3. Code Flow

  1. Entry Point: The administrator visits wp-admin/admin.php?page=appform or is forced to submit a POST request to it via CSRF.
  2. Hook: The csaf_options_page function (in include/top_level_menu.php) registers the appform_options_page_html callback for the appform submenu page.
  3. Vulnerable Logic: Inside appform_options_page_html():
    • The function checks if isset( $_POST['delete_id'] ).
    • It initializes the WordPress filesystem: WP_Filesystem().
    • It defines the target directory: $target_dir_location = $wp_filesystem->wp_content_dir() . 'uploads/cs_applicant_submission_files/';.
    • It captures the filename: $file_path = $target_dir_location . sanitize_text_field($_POST['delete_file']);.
    • It executes the deletion: wp_delete_file( $file_path );.
  4. Sink: wp_delete_file() (a WordPress wrapper for unlink()).

4. Nonce Acquisition Strategy

This vulnerability is specifically caused by the absence of nonce validation.

  • Reviewing include/top_level_menu.php, the "Delete" form used for submissions does not include a nonce field.
  • 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.
  • The vulnerable code block processing delete_id and delete_file does not call check_admin_referer() or wp_verify_nonce().
  • Conclusion: No nonce is required to exploit this endpoint.

5. Exploitation Strategy

The goal is to delete a sensitive file (e.g., wp-config.php) or a test file in the WordPress root.

Step-by-Step Plan:

  1. Identify Path: The target directory is wp-content/uploads/cs_applicant_submission_files/.
  2. Calculate Traversal: To reach the WordPress root (where wp-config.php resides) from the target directory:
    • .. -> wp-content/uploads/
    • ../.. -> wp-content/
    • ../../../ -> WordPress root directory.
  3. Construct Payload: delete_file=../../../wp-config.php.
  4. Formulate Request:
    • Method: POST
    • URL: http://localhost:8080/wp-admin/admin.php?page=appform
    • Body: delete_id=1&delete_file=../../../wp-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).

6. Test Data Setup

  1. Ensure the "Career Section" plugin is installed and active.
  2. Create a canary file in the WordPress root to safely test deletion:
    wp eval "file_put_contents(ABSPATH . 'pwn.txt', 'test');"
  3. Ensure an administrator user exists (standard in test environments).

7. Expected Results

  1. The HTTP request will return a 200 OK response containing the message: "Application permanently deleted." (added via add_settings_error in the code).
  2. The file pwn.txt (or wp-config.php) will be removed from the server.

8. Verification Steps

  1. Verify via CLI:
    wp eval "echo file_exists(ABSPATH . 'pwn.txt') ? 'Exists' : 'Deleted';"
  2. Check the WordPress database table to see if the row with id=1 was attempted to be deleted (optional):
    wp db query "SELECT * FROM wp_cs_applicant_submissions WHERE id=1"

9. Alternative Approaches

  • Targeting Other Files: If wp-config.php is protected by file permissions, attempt to delete index.php or a file within wp-content/plugins/career-section/index.php to prove arbitrary deletion.
  • Traversal Depth: If the environment uses a non-standard WP_CONTENT_DIR, the traversal depth might vary. Test ../../../../wp-config.php as a backup.
  • 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:
    wp db query "INSERT INTO wp_cs_applicant_submissions (id, first_name, last_name, cv) VALUES (1, 'Test', 'User', 'test.pdf')"
Research Findings

Summary

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.

Vulnerable Code

// include/top_level_menu.php L28-41
	if ( isset( $_POST['delete_id'] ) ) {
	    //delete db raw
	    global $wpdb;
	    $table_name = $wpdb->prefix . "cs_applicant_submissions";
	    $wpdb->delete( $table_name, array( 'id' => sanitize_text_field($_POST['delete_id'] )) );
	    //delete files
	    global $wp_filesystem;
	    WP_Filesystem();
	    $content_directory = $wp_filesystem->wp_content_dir() . 'uploads/';
	    $target_dir_location = $content_directory . 'cs_applicant_submission_files/';
	    $file_path = $target_dir_location.sanitize_text_field($_POST['delete_file']);  // path of the file which need to be deleted.
        wp_delete_file( $file_path ); //delete file here.

Security Fix

--- /home/deploy/wp-safety.org/data/plugin-versions/career-section/1.6/include/top_level_menu.php	2025-04-15 04:57:46.000000000 +0000
+++ /home/deploy/wp-safety.org/data/plugin-versions/career-section/1.7/include/top_level_menu.php	2026-03-04 06:22:06.000000000 +0000
@@ -25,13 +29,26 @@
 		return;
 	}
 	// check if the user have submitted the settings
-	if ( isset( $_POST['delete_id'] ) ) {
+	if ( isset( $_POST['delete_id'], $_POST['delete_applicant_nonce'] ) ) {		
+		 
+		// 1️⃣ Unsanitize POST data
+    	$delete_id   = intval( wp_unslash( $_POST['delete_id'] ) );
+    	$nonce       = sanitize_text_field(wp_unslash( $_POST['delete_applicant_nonce'] ));
+		$delete_file = sanitize_text_field(wp_unslash( $_POST['delete_file'] ?? ''));
+		$delete_file = basename($delete_file); // removes any "../" path segments
+    	
+		// 2️⃣ Verify nonce
+		if ( ! wp_verify_nonce( $nonce, 'delete_applicant_' . $delete_id ) ) {
+			wp_die( esc_html__( 'Nonce verification failed', 'career-section' ) );
+		}		
+
+
 	    //delete db raw
 	    global $wpdb;
 	    $table_name = $wpdb->prefix . "cs_applicant_submissions";
-	    $wpdb->delete( $table_name, array( 'id' => sanitize_text_field($_POST['delete_id'] )) );
+	    $wpdb->delete( $table_name, array( 'id' => sanitize_text_field($delete_id)) );
 	    //delete files
 	    global $wp_filesystem;
 	    WP_Filesystem();
 	    $content_directory = $wp_filesystem->wp_content_dir() . 'uploads/';
 	    $target_dir_location = $content_directory . 'cs_applicant_submission_files/';
-	    $file_path = $target_dir_location.sanitize_text_field($_POST['delete_file']);  // path of the file which need to be deleted.
+	    $file_path = $target_dir_location.sanitize_text_field($delete_file);  // path of the file which need to be deleted.
         wp_delete_file( $file_path ); //delete file here.

Exploit Outline

The exploit target is the plugin's administration page at '/wp-admin/admin.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., '../../../wp-config.php'). Because the plugin lacks CSRF protection (no nonce validation) and uses 'sanitize_text_field' (which does not remove '../' sequences), an authenticated administrator visiting the attacker's page will unknowingly trigger the deletion of sensitive files from the WordPress root directory.

Check if your site is affected.

Run a free security audit to detect vulnerable plugins, outdated versions, and misconfigurations.