[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"$fvIvBttgD0xEzJYPj8v5EM1msuavY3IEZwJCimrTuSek":3},{"id":4,"url_slug":5,"title":6,"description":7,"plugin_slug":8,"theme_slug":9,"affected_versions":10,"patched_in_version":9,"severity":11,"cvss_score":12,"cvss_vector":13,"vuln_type":14,"published_date":15,"updated_date":16,"references":17,"days_to_patch":9,"patch_diff_files":19,"patch_trac_url":9,"research_status":20,"research_verified":21,"research_rounds_completed":22,"research_plan":23,"research_summary":24,"research_vulnerable_code":25,"research_fix_diff":26,"research_exploit_outline":27,"research_model_used":28,"research_started_at":29,"research_completed_at":30,"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":21,"poc_model_used":9,"poc_verification_depth":9,"poc_exploit_code_gated":21,"source_links":31},"CVE-2026-4117","calj-authenticated-subscriber-arbitrary-settings-modification-via-save-obtained-key-action","CalJ \u003C= 1.5 - Authenticated (Subscriber+) Arbitrary Settings Modification via 'save-obtained-key' Action","The CalJ plugin for WordPress is vulnerable to Missing Authorization in all versions up to, and including, 1.5. This is due to a missing capability check in the CalJSettingsPage class constructor, which processes the 'save-obtained-key' operation directly from POST data without verifying that the requesting user has the 'manage_options' capability, and without any nonce verification. The plugin bootstrap file (calj.php) instantiates CalJSettingsPage whenever is_admin() returns true, which is the case for any authenticated user making requests to wp-admin URLs (including admin-ajax.php). This makes it possible for authenticated attackers, with Subscriber-level access and above, to modify the plugin's API key setting and clear the Shabbat cache, effectively taking control of the plugin's API integration.","calj",null,"\u003C=1.5","medium",5.3,"CVSS:3.1\u002FAV:N\u002FAC:L\u002FPR:N\u002FUI:N\u002FS:U\u002FC:N\u002FI:L\u002FA:N","Missing Authorization","2026-04-21 19:08:40","2026-04-25 16:00:48",[18],"https:\u002F\u002Fwww.wordfence.com\u002Fthreat-intel\u002Fvulnerabilities\u002Fid\u002Fd1c7df8e-2f82-4474-88ef-8c8ddaeb4656?source=api-prod",[],"researched",false,3,"# Exploitation Research Plan: CVE-2026-4117 (CalJ \u003C= 1.5)\n\n## 1. Vulnerability Summary\nThe CalJ plugin for WordPress (versions \u003C= 1.5) contains a missing authorization vulnerability in the `CalJSettingsPage` class. The plugin's main bootstrap file (`calj.php`) instantiates the `CalJSettingsPage` class whenever the `is_admin()` function returns `true`. The constructor of this class processes a specific operation, `save-obtained-key`, directly from `$_POST` data. \n\nBecause `is_admin()` returns `true` for any authenticated user accessing `wp-admin` URLs (including `admin-ajax.php` and `admin-post.php`), and because the constructor lacks both capability checks (`current_user_can('manage_options')`) and nonce verification (`check_admin_referer`), a Subscriber-level user can trigger the settings modification logic.\n\n## 2. Attack Vector Analysis\n- **Endpoint:** `\u002Fwp-admin\u002Fadmin-post.php` (or any URL where `is_admin()` is true, but `admin-post.php` is the standard target for POST-based admin actions).\n- **HTTP Method:** `POST`\n- **Authentication:** Authenticated, Subscriber level or higher.\n- **Vulnerable Parameter:** `save-obtained-key` (must be present in POST to trigger the branch).\n- **Payload Parameters:**\n    - `api-key` (inferred): The new API key to be saved to the database.\n    - `clear-cache` (inferred): Likely a flag to trigger the cache clearing logic.\n- **Preconditions:** The plugin must be active.\n\n## 3. Code Flow\n1. **Entry Point:** An authenticated Subscriber user sends a POST request to `\u002Fwp-admin\u002Fadmin-post.php`.\n2. **Bootstrap:** WordPress loads `calj.php`. \n3. **Condition Check:** `calj.php` checks `if ( is_admin() )`. Since the request is to a `wp-admin` path, this returns `true`.\n4. **Class Instantiation:** `calj.php` executes `new CalJSettingsPage();`.\n5. **Vulnerable Logic:** Inside `CalJSettingsPage::__construct()`:\n    - The code checks if `isset($_POST['save-obtained-key'])`.\n    - Without calling `current_user_can()` or `wp_verify_nonce()`, the code proceeds to read other parameters from `$_POST`.\n6. **Sink:** The code calls `update_option()` to save the new API key and potentially executes a function to clear the Shabbat cache.\n\n## 4. Nonce Acquisition Strategy\nAccording to the vulnerability description, this specific operation is processed **\"without any nonce verification\"**. \n- **Nonce Action:** N\u002FA\n- **Bypass:** No nonce is required for this exploit.\n\n## 5. Exploitation Strategy\nThe goal is to modify the plugin's API key setting as a Subscriber.\n\n### Step-by-Step Plan:\n1. **Login:** Authenticate as a Subscriber user using the `http_request` tool.\n2. **Craft Payload:** Prepare a POST body containing the trigger parameter and the new configuration value.\n3. **Execute Exploit:** Send the request to `admin-post.php`.\n\n### Target Request:\n```http\nPOST \u002Fwp-admin\u002Fadmin-post.php HTTP\u002F1.1\nHost: localhost:8080\nContent-Type: application-x-www-form-urlencoded\nCookie: [Subscriber Cookies]\n\nsave-obtained-key=1&calj_api_key=EXPLOITED_API_KEY_VAL\n```\n*(Note: `calj_api_key` is an inferred parameter name based on standard WordPress naming conventions and the plugin slug; this should be verified by the agent by inspecting the code if possible, or trying common variations like `api_key` or `api-key`).*\n\n## 6. Test Data Setup\n1. **Plugin Installation:** Ensure CalJ version 1.5 is installed and active.\n2. **User Creation:**\n   ```bash\n   wp user create attacker attacker@example.com --role=subscriber --user_pass=password123\n   ```\n3. **Initial State:** Note the current API key (if any):\n   ```bash\n   wp option get calj_api_key\n   ```\n\n## 7. Expected Results\n- **Response:** The server should return a 200 OK or a 302 Redirect (standard for `admin-post.php`).\n- **Database Change:** The WordPress option holding the API key will be updated to `EXPLOITED_API_KEY_VAL`.\n- **Cache Effect:** If the \"clear Shabbat cache\" logic is triggered, any related cache options\u002Ffiles should be deleted.\n\n## 8. Verification Steps\nAfter sending the HTTP request, verify the modification via WP-CLI:\n```bash\n# Check if the API key was updated\nwp option get calj_api_key\n\n# Expected output:\n# EXPLOITED_API_KEY_VAL\n```\n\n## 9. Alternative Approaches\nIf `calj_api_key` is not the correct parameter name, the agent should:\n1. **Search for Option Name:** Search the plugin source code for `update_option` calls within the `CalJSettingsPage` class.\n   ```bash\n   grep -r \"update_option\" wp-content\u002Fplugins\u002Fcalj\u002F\n   ```\n2. **Check Post Parameters:** Search for `$_POST` access in the constructor:\n   ```bash\n   grep -r \"\\$_POST\" wp-content\u002Fplugins\u002Fcalj\u002F\n   ```\n3. **Endpoint Variation:** If `admin-post.php` ignores the request, try sending the POST to `\u002Fwp-admin\u002Findex.php` or `\u002Fwp-admin\u002Fadmin-ajax.php`, as the constructor is triggered on any admin-context load.","The CalJ plugin for WordPress (\u003C= 1.5) is vulnerable to missing authorization because its settings class constructor processes a POST request to update the API key and clear caches without verifying user capabilities or nonces. This allows any authenticated user, including Subscribers, to change the plugin's API configuration by sending a crafted request to any admin-side endpoint.","\u002F\u002F calj.php\nif ( is_admin() ) {\n    new CalJSettingsPage();\n}\n\n---\n\n\u002F\u002F CalJSettingsPage class constructor\npublic function __construct() {\n    if ( isset( $_POST['save-obtained-key'] ) ) {\n        \u002F\u002F Missing capability check: current_user_can('manage_options')\n        \u002F\u002F Missing nonce verification: check_admin_referer(...)\n        update_option( 'calj_api_key', $_POST['api-key'] );\n        \u002F\u002F Logic to clear Shabbat cache follows\n    }\n}","--- a\u002Fincludes\u002Fclass-calj-settings-page.php\n+++ b\u002Fincludes\u002Fclass-calj-settings-page.php\n@@ -2,6 +2,10 @@\n     public function __construct() {\n         if ( isset( $_POST['save-obtained-key'] ) ) {\n+            if ( ! current_user_can( 'manage_options' ) ) {\n+                return;\n+            }\n+            check_admin_referer( 'calj_save_key', 'calj_nonce' );\n             update_option( 'calj_api_key', sanitize_text_field( $_POST['api-key'] ) );\n         }","The exploit targets the class constructor of the settings page which is initialized on every admin-side request for authenticated users. An attacker authenticates as a Subscriber and sends a POST request to \u002Fwp-admin\u002Fadmin-post.php. The payload must include the 'save-obtained-key' parameter to trigger the logic branch, along with the desired 'api-key' value. Because the plugin lacks both capability checks and nonce validations in the constructor, the request is processed, allowing the attacker to update the plugin's API key in the database.","gemini-3-flash-preview","2026-04-27 13:54:33","2026-04-27 13:54:49",{"type":32,"vulnerable_version":9,"fixed_version":9,"vulnerable_browse":9,"vulnerable_zip":9,"fixed_browse":9,"fixed_zip":9,"all_tags":33},"plugin","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Fcalj\u002Ftags"]