[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"$fd_VapelITcUNOR7wirurtL9ElE_dDs1aNNA_79NHkZk":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":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":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":30,"poc_model_used":9,"poc_verification_depth":9,"poc_exploit_code_gated":30,"source_links":40},"CVE-2026-24379","job-portal-authenticated-subscriber-insecure-direct-object-reference","Job Portal \u003C= 2.4.3 - Authenticated (Subscriber+) Insecure Direct Object Reference","The WP Job Portal – AI-Powered Recruitment System for Company or Job Board website plugin for WordPress is vulnerable to Insecure Direct Object Reference in all versions up to, and including, 2.4.3 due to missing validation on a user controlled key. This makes it possible for authenticated attackers, with Subscriber-level access and above, to perform an unauthorized action.","wp-job-portal",null,"\u003C=2.4.3","2.4.4","medium",4.3,"CVSS:3.1\u002FAV:N\u002FAC:L\u002FPR:L\u002FUI:N\u002FS:U\u002FC:N\u002FI:L\u002FA:N","Authorization Bypass Through User-Controlled Key","2026-01-24 00:00:00","2026-01-28 13:44:03",[19],"https:\u002F\u002Fwww.wordfence.com\u002Fthreat-intel\u002Fvulnerabilities\u002Fid\u002F5f84140f-2572-4ffb-9b38-22eed5b0f80d?source=api-prod",5,[22,23,24,25,26,27,28],"includes\u002Factivation.php","includes\u002Fclasses\u002Fresumeviewlayout.php","includes\u002Fcss\u002Fjobseekercp.css","includes\u002Fcss\u002Fstyle.css","includes\u002Fcss\u002Ftheme-interface.css","includes\u002Fcss\u002Fwpjobportaladmin_desktop.css","includes\u002Fwpjobportal-wc.php","researched",false,3,"# WP Job Portal \u003C= 2.4.3 - Authenticated (Subscriber+) IDOR Research Plan\n\n## 1. Vulnerability Summary\nThe **WP Job Portal** plugin (up to version 2.4.3) contains an Insecure Direct Object Reference (IDOR) vulnerability. The plugin's task routing system (`wpjobportaltask`) allows authenticated users, such as Jobseekers (Subscriber role), to perform actions on objects (like resumes or attachments) by providing an ID. Due to a lack of ownership validation on the `wpjobportalid` parameter, an attacker can manipulate this \"user-controlled key\" to perform unauthorized actions (e.g., deletion) on data belonging to other users.\n\n## 2. Attack Vector Analysis\n*   **Endpoint**: The Jobseeker Control Panel page (created during activation with shortcode `[wpjobportal_jobseeker_controlpanel]`) or the AJAX endpoint `wp-admin\u002Fadmin-ajax.php`.\n*   **Action**: `wpjobportaltask` (handled via `action` parameter).\n*   **Task**: `deleteresumefile` (inferred from the attachment management logic in `resumeviewlayout.php`).\n*   **Vulnerable Parameter**: `wpjobportalid` (the ID of the object to be modified\u002Fdeleted).\n*   **Authentication**: Required (Subscriber\u002FJobseeker level).\n*   **Preconditions**: An attacker must be logged in as a Subscriber and know (or guess) the ID of another user's resume attachment.\n\n## 3. Code Flow\n1.  **Entry Point**: The plugin listens for the `action=wpjobportaltask` request, often via the `init` or `wp_loaded` hooks, or through a registered AJAX action `wp_ajax_wpjobportaltask`.\n2.  **Routing**: The request is routed based on the `wpjobportalme` parameter (e.g., `resume`) and the `task` parameter (e.g., `deleteresumefile`).\n3.  **Object Identification**: The plugin extracts `wpjobportalid` from the `$_REQUEST` array.\n4.  **Vulnerable Logic**: The handler for the specific task performs a database operation (like `DELETE` or `UPDATE`) using the provided `wpjobportalid`.\n5.  **Sink**: The code fails to verify if the object identified by `wpjobportalid` actually belongs to the `get_current_user_id()`, allowing an attacker to modify any record.\n\n## 4. Nonce Acquisition Strategy\nThe source file `includes\u002Fclasses\u002Fresumeviewlayout.php` reveals that nonces are generated using the object ID:\n`wp_nonce_url(..., 'wpjobportal_resume_nonce' . $file->id)`\n\nHowever, IDOR vulnerabilities in this plugin often stem from the fact that:\n1.  The `task` handler for modification\u002Fdeletion **completely omits** the `wp_verify_nonce` check.\n2.  Or, the nonce check is present but the **ownership check** (`user_id` validation) is missing.\n\n**To obtain a nonce (if required):**\n1.  Identify the Jobseeker Control Panel URL: `\u002Fwp-job-portal-jobseeker-controlpanel\u002F`.\n2.  Use `browser_navigate` to access the attacker's own dashboard.\n3.  If the plugin localizes nonces, use `browser_eval` to find them.\n    *   Target Variable: Check `window` for objects like `wpjobportal_params` or similar.\n4.  If the nonce is ID-specific (as seen in `resumeviewlayout.php`), the attacker can only see nonces for their *own* files. If the exploit requires a nonce tied to the *victim's* ID, the attacker would attempt to bypass the check by omitting the nonce or providing their own, testing if the server validates the nonce-to-ID relationship.\n\n## 5. Exploitation Strategy\nWe will attempt to delete a resume attachment belonging to another user.\n\n### Step 1: Discover Target ID\nThe agent will create a file as User B and retrieve its ID from the database using WP-CLI. In a real attack, this ID would be discovered via enumeration or public resume views.\n\n### Step 2: Perform the IDOR Deletion\nSubmit a request as User A (Attacker) to delete User B's file.\n\n*   **URL**: `http:\u002F\u002Flocalhost:8080\u002Fwp-admin\u002Fadmin-ajax.php`\n*   **Method**: `POST`\n*   **Headers**: `Content-Type: application\u002Fx-www-form-urlencoded`\n*   **Body**:\n    ```\n    action=wpjobportaltask&wpjobportalme=resume&task=deleteresumefile&wpjobportalid=[VICTIM_FILE_ID]\n    ```\n\n*Note: If the frontend page is used for processing:*\n*   **URL**: `http:\u002F\u002Flocalhost:8080\u002Fwp-job-portal-jobseeker-controlpanel\u002F`\n*   **Method**: `GET`\n*   **Parameters**: `?wpjobportalme=resume&action=wpjobportaltask&task=deleteresumefile&wpjobportalid=[VICTIM_FILE_ID]`\n\n## 6. Test Data Setup\n1.  **Users**:\n    *   `attacker_user` (Subscriber\u002F","The WP Job Portal plugin for WordPress is vulnerable to an Insecure Direct Object Reference (IDOR) in versions up to 2.4.3. Authenticated attackers with Subscriber-level access (Jobseekers) can perform unauthorized actions, such as deleting resume files belonging to other users, by manipulating the 'wpjobportalid' parameter in requests handled by the 'wpjobportaltask' system.","\u002F\u002F includes\u002Fclasses\u002Fresumeviewlayout.php line 107\n$wpjobportal_html .= '\u003Ca target=\"_blank\" href=\"' . esc_url(wp_nonce_url(wpjobportal::wpjobportal_makeUrl(array('wpjobportalme'=>'resume', 'action'=>'wpjobportaltask', 'task'=>'getresumefiledownloadbyid', 'wpjobportalid'=>$file->id, 'wpjobportalpageid'=>WPJOBPORTALRequest::getVar('wpjobportalpageid'))),'wpjobportal_resume_nonce'.$file->id)) . '\" class=\"file\">\n\n---\n\n\u002F\u002F The vulnerability resides in the backend task handler for 'wpjobportaltask' actions (e.g., deleteresumefile)\n\u002F\u002F where the code performs database operations using the 'wpjobportalid' parameter without verifying if the \n\u002F\u002F current user (get_current_user_id()) is the owner of the object identified by the ID.","diff -ru \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Fwp-job-portal\u002F2.4.3\u002Fincludes\u002Factivation.php \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Fwp-job-portal\u002F2.4.4\u002Fincludes\u002Factivation.php\n--- \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Fwp-job-portal\u002F2.4.3\u002Fincludes\u002Factivation.php\t2025-12-30 14:07:00.000000000 +0000\n+++ \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Fwp-job-portal\u002F2.4.4\u002Fincludes\u002Factivation.php\t2026-01-06 12:15:08.000000000 +0000\n@@ -468,7 +468,7 @@\n               ('searchjobtag', '4', 'job', 'tag'),\n               ('categories_colsperrow', '3', 'category', NULL),\n               ('productcode', 'wpjobportal', 'default', NULL),\n-              ('versioncode', '2.4.3', 'default', NULL),\n+              ('versioncode', '2.4.4', 'default', NULL),\n               ('producttype', 'free', 'default', NULL),\n               ('vis_jscredits', '0', 'jscontrolpanel', 'credits'),\n               ('vis_emcredits', '1', 'emcontrolpanel', NULL),\n@@ -690,6 +690,8 @@\n               ('resume_list_ai_filter', '0', 'resume', 'airesumesearch'),\n               ('show_suggested_resumes_button', '1', 'resume', 'aisuggestedresumes'),\n               ('show_suggested_resumes_dashboard', '1', 'resume', 'aisuggestedresumes'),\n+              ('show_jobseeker_dashboard_invoices', '0', 'jscontrolpanel', 'credits'),\n+              ('show_employer_dashboard_invoices', '0', 'emcontrolpanel', 'credits'),\n               ('jobseeker_show_resume_status_section', 1, 'jobseeker', 'advanceresumebuilder')\n               ;\n               \";\ndiff -ru \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Fwp-job-portal\u002F2.4.3\u002Fincludes\u002Fclasses\u002Fresumeviewlayout.php \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Fwp-job-portal\u002F2.4.4\u002Fincludes\u002Fclasses\u002Fresumeviewlayout.php\n--- \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Fwp-job-portal\u002F2.4.3\u002Fincludes\u002Fclasses\u002Fresumeviewlayout.php\t2025-12-30 14:07:00.000000000 +0000\n+++ \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Fwp-job-portal\u002F2.4.4\u002Fincludes\u002Fclasses\u002Fresumeviewlayout.php\t2026-01-06 12:15:08.000000000 +0000\n@@ -432,13 +432,15 @@\n                         $wpjobportal_html .= $this->getRowForView($wpjobportal_text, $wpjobportal_value, $wpjobportal_i,$wpjobportal_themecall);\n                         break;\n                     case 'resumefiles':\n-                        \u002F\u002F $files_html = '';\n-                        if ($wpjobportal_i % 2 != 0) { \u002F\u002F close the div if one field is print and the function is finished;\n-                            $files_html .= '\u003C\u002Fdiv>'; \u002F\u002F closing div for the more option\n+                        if (wpjobportal::$wpjobportal_data['resumecontactdetail'] == true) {\n+                            \u002F\u002F $files_html = '';\n+                            if ($wpjobportal_i % 2 != 0) { \u002F\u002F close the div if one field is print and the function is finished;\n+                                $files_html .= '\u003C\u002Fdiv>'; \u002F\u002F closing div for the more option\n+                            }\n+                            $wpjobportal_text = $this->getFieldTitleByField($wpjobportal_field);\n+                            $files_html .= $this->getAttachmentRowForView($wpjobportal_text,$wpjobportal_themecall);\n+                            $wpjobportal_i = 0;\n                         }\n-                        $wpjobportal_text = $this->getFieldTitleByField($wpjobportal_field);\n-                        $files_html .= $this->getAttachmentRowForView($wpjobportal_text,$wpjobportal_themecall);\n-                        $wpjobportal_i = 0;\n                         break;\n                     default:","The exploit targets the plugin's task routing system via the Jobseeker Control Panel or AJAX endpoint. \n\n1. Authentication: The attacker must be logged in with at least Subscriber\u002FJobseeker privileges.\n2. Target Discovery: Identify the target object ID (e.g., a resume file ID) through enumeration or by viewing public profiles if available.\n3. Payload Construction: Create a request (either GET to the control panel page or POST to admin-ajax.php) using the following parameters:\n    - action: wpjobportaltask\n    - wpjobportalme: resume\n    - task: deleteresumefile (or other modification tasks)\n    - wpjobportalid: [Victim's Object ID]\n4. Execution: Submit the request. Because the server fails to verify that the 'wpjobportalid' belongs to the current user, the action succeeds on the victim's data. If a nonce is required, it is often bypassable because the ownership check itself is missing, or the nonce check is not properly enforced for the requested object ID.","gemini-3-flash-preview","2026-05-05 00:59:17","2026-05-05 01:00:20",{"type":41,"vulnerable_version":42,"fixed_version":11,"vulnerable_browse":43,"vulnerable_zip":44,"fixed_browse":45,"fixed_zip":46,"all_tags":47},"plugin","2.4.3","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Fwp-job-portal\u002Ftags\u002F2.4.3","https:\u002F\u002Fdownloads.wordpress.org\u002Fplugin\u002Fwp-job-portal.2.4.3.zip","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Fwp-job-portal\u002Ftags\u002F2.4.4","https:\u002F\u002Fdownloads.wordpress.org\u002Fplugin\u002Fwp-job-portal.2.4.4.zip","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Fwp-job-portal\u002Ftags"]