[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"$fbw42LVGYaOYGuUyVSb-jxWNuIXSSLrafFwVvptr-W5M":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":24,"research_verified":25,"research_rounds_completed":26,"research_plan":27,"research_summary":28,"research_vulnerable_code":29,"research_fix_diff":30,"research_exploit_outline":31,"research_model_used":32,"research_started_at":33,"research_completed_at":34,"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":25,"poc_model_used":9,"poc_verification_depth":9,"poc_exploit_code_gated":25,"source_links":35},"CVE-2026-25323","osm-openstreetmap-missing-authorization","OSM – OpenStreetMap \u003C= 6.1.12 - Missing Authorization","The OSM – OpenStreetMap plugin for WordPress is vulnerable to unauthorized access due to a missing capability check on a function in all versions up to, and including, 6.1.12. This makes it possible for authenticated attackers, with Contributor-level access and above, to perform an unauthorized action.","osm",null,"\u003C=6.1.12","6.1.13","medium",4.3,"CVSS:3.1\u002FAV:N\u002FAC:L\u002FPR:L\u002FUI:N\u002FS:U\u002FC:N\u002FI:L\u002FA:N","Missing Authorization","2026-01-29 00:00:00","2026-05-04 15:40:16",[19],"https:\u002F\u002Fwww.wordfence.com\u002Fthreat-intel\u002Fvulnerabilities\u002Fid\u002Fd3af34f4-72c5-43a4-9ca1-0729455298c5?source=api-prod",96,[22,23],"osm.php","readme.txt","researched",false,3,"# Exploitation Research Plan - CVE-2026-25323 (OSM - OpenStreetMap)\n\n## 1. Vulnerability Summary\nThe **OSM – OpenStreetMap** plugin for WordPress (up to 6.1.12) contains a missing authorization vulnerability in its AJAX handling logic. Specifically, the function `saveGeotagAndPic` (and potentially associated registration hooks) verifies a nonce but fails to perform a capability check (e.g., `current_user_can( 'edit_post', $post_id )`). This allows authenticated users with Contributor-level privileges to modify geographical metadata (geotags) for any post or page on the site, regardless of ownership or status.\n\n## 2. Attack Vector Analysis\n- **Endpoint**: `\u002Fwp-admin\u002Fadmin-ajax.php`\n- **Action**: `osm_save_geotag` (inferred from function name `saveGeotagAndPic` and plugin naming conventions)\n- **Parameters**: \n    - `action`: `osm_save_geotag` (inferred)\n    - `lat`: Latitude (e.g., `51.5074`)\n    - `lon`: Longitude (e.g., `-0.1278`)\n    - `icon`: Icon filename (e.g., `marker_blue.png`)\n    - `post_id`: The ID of the target post to modify.\n    - `geotag_nonce`: The CSRF token for the action.\n- **Authentication**: Authenticated (Contributor level or higher).\n- **Preconditions**: The attacker must be logged in as a Contributor and obtain a valid nonce for the `osm_geotag_nonce` action.\n\n## 3. Code Flow\n1. **Entry Point**: The plugin likely registers the AJAX action in the `init` or `admin_init` hook (not visible in snippet but required for AJAX).\n   - Hook: `add_action( 'wp_ajax_osm_save_geotag', 'saveGeotagAndPic' );`\n2. **Execution**: The `saveGeotagAndPic` function in `osm.php` is called.\n3. **Nonce Verification**: The function checks `wp_verify_nonce( $_POST['geotag_nonce'], 'osm_geotag_nonce' )`.\n4. **Processing**: It sanitizes input using `sanitize_text_field` and `wp_unslash`.\n5. **Vulnerable Sink**: The function (based on its purpose) calls `update_post_meta` or a similar database update function using the provided `$post_id` without verifying if the current user has permission to edit that specific post.\n   - *Note*: A Contributor can only edit their own posts. By providing an Admin's `post_id`, the Contributor performs an unauthorized modification.\n\n## 4. Nonce Acquisition Strategy\nThe nonce `osm_geotag_nonce` is typically generated for the post editor meta box.\n1. **Identify Script Localization**: Look for `wp_localize_script` in the full plugin source that includes `osm_geotag_nonce`.\n2. **Access Editor**: Log in as a Contributor and navigate to the \"Add New Post\" page (`\u002Fwp-admin\u002Fpost-new.php`).\n3. **Extract Nonce**:\n   - Use `browser_eval` to extract the nonce from the global JavaScript object where the plugin stores its settings.\n   - **Likely Variable**: `window.OSM_Data?.geotag_nonce` or similar (based on `osm_geotag_nonce` action).\n   - **Manual Check**: Inspect the page source for `osm_geotag_nonce`.\n\n## 5. Exploitation Strategy\n1. **Prerequisite**: Create a \"Protected Post\" as an Admin (e.g., Post ID 123).\n2. **Authentication**: Authenticate as a Contributor user.\n3. **Nonce Extraction**: \n   - Navigate to `\u002Fwp-admin\u002Fpost-new.php` as the Contributor.\n   - Extract the `geotag_nonce` from the page source or JS context.\n4. **Forge Request**: Use the `http_request` tool to send an AJAX POST request to modify the Admin's post.\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=osm_save_geotag&lat=99.99&lon=99.99&icon=malicious.png&post_id=123&geotag_nonce=[EXTRACTED_NONCE]\n     ```\n5. **Verify Success**: Check if the response contains \"Location (geotag) saved successfully\".\n\n## 6. Test Data Setup\n1. **Admin User**: Created by default.\n2. **Admin Post**: Create a published post.\n   - `wp post create --post_title=\"Admin Secret Post\" --post_status=publish --post_author=1`\n   - Capture the returned **Post ID**.\n3. **Contributor User**: Create a user with the contributor role.\n   - `wp user create attacker attacker@example.com --role=contributor --user_pass=password`\n\n## 7. Expected Results\n- The AJAX request should return a `200 OK` status.\n- The response body should include the string: `Location (geotag) saved successfully`.\n- The metadata for the Admin's post (ID 123) should be updated with the malicious latitude and longitude.\n\n## 8. Verification Steps\nAfter performing the exploit, verify the database state using WP-CLI:\n1. **Check Post Meta**:\n   - `wp post meta list [ADMIN_POST_ID]`\n2. **Look for Keys**:\n   - Check for meta keys like `osm_geo_data` or `osm_lat_lon` (the exact key names depend on the truncated part of `saveGeotagAndPic`).\n   - If the latitude `99.99` is found in the metadata of the Admin's post, the exploit is successful.\n\n## 9. Alternative Approaches\nIf `osm_save_geotag` is not the correct action name:\n1. Search the plugin folder for all `add_action( 'wp_ajax_` registrations:\n   - `grep -r \"wp_ajax_\" .`\n2. Search for where `osm_geotag_nonce` is localized to find the associated JS logic and action name:\n   - `grep -r \"osm_geotag_nonce\" .`\n3. If the Contributor cannot access the nonce on `post-new.php`, check if the OSM widget or shortcode generator on the frontend exposes it.","The OSM – OpenStreetMap plugin for WordPress is vulnerable to unauthorized modification of post metadata due to missing capability checks in its AJAX handlers. Authenticated attackers with Contributor-level access or higher can exploit this to change geographical tags (geotags) and map markers for any post or page, including those they do not own.","\u002F\u002F File: osm.php, around line 170\nfunction saveGeotagAndPic() {\n    if ( isset( $_POST['lat'], $_POST['lon'], $_POST['icon'], $_POST['post_id'], $_POST['geotag_nonce'] ) ) {\n        $latlon  = sanitize_text_field( wp_unslash( $_POST['lat'] ) ) . ',' . sanitize_text_field( wp_unslash( $_POST['lon'] ) );\n        $icon    = sanitize_text_field( wp_unslash( $_POST['icon'] ) );\n        $post_id = sanitize_text_field( wp_unslash( $_POST['post_id'] ) );\n        $nonce   = sanitize_text_field( wp_unslash( $_POST['geotag_nonce'] ) );\n\n        if ( ! wp_verify_nonce( $nonce, 'osm_geotag_nonce' ) ) {\n            echo \"Error: Bad ajax request\";\n        } else {\n            \u002F\u002F ... execution continues to update_post_meta using $post_id without current_user_can check\n\n---\n\n\u002F\u002F File: osm.php, around line 215\nfunction savePostMarker() {\n    if ( isset( $_POST['MarkerId'], $_POST['MarkerLat'], $_POST['MarkerLon'], $_POST['MarkerIcon'], $_POST['MarkerName'], $_POST['post_id'], $_POST['marker_nonce'], $_POST['MarkerText'] ) ) {\n\n        $MarkerId      = sanitize_text_field( wp_unslash( $_POST['MarkerId'] ) );\n        $MarkerLatLon  = sanitize_text_field( wp_unslash( $_POST['MarkerLat'] ) ) . ',' . sanitize_text_field( wp_unslash( $_POST['MarkerLon'] ) );\n        $MarkerIcon    = sanitize_text_field( wp_unslash( $_POST['MarkerIcon'] ) );\n        $MarkerName    = sanitize_text_field( wp_unslash( $_POST['MarkerName'] ) );\n        $post_id       = sanitize_text_field( wp_unslash( $_POST['post_id'] ) );\n        $nonce         = sanitize_text_field( wp_unslash( $_POST['marker_nonce'] ) );\n        \n        \u002F\u002F ... \n\n        \u002F\u002F Nonce check only, no capability check\n        if ( ! wp_verify_nonce( $nonce, 'osm_marker_nonce' ) ) {\n            echo \"Error: Bad ajax request\";\n        } else {\n            \u002F\u002F ... execution continues to update_post_meta using $post_id\n        }","diff -ru \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Fosm\u002F6.1.12\u002Fosm.php \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Fosm\u002F6.1.13\u002Fosm.php\n--- \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Fosm\u002F6.1.12\u002Fosm.php\t2026-01-25 15:47:46.000000000 +0000\n+++ \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Fosm\u002F6.1.13\u002Fosm.php\t2026-01-25 18:49:30.000000000 +0000\n@@ -169,9 +169,17 @@\n \n function saveGeotagAndPic() {\n     if ( isset( $_POST['lat'], $_POST['lon'], $_POST['icon'], $_POST['post_id'], $_POST['geotag_nonce'] ) ) {\n+\n+        $post_id = absint( wp_unslash( $_POST['post_id'] ) );\n+\n+        \u002F\u002F SECURITY-FIX: Berechtigungsprüfung\n+        if ( ! $post_id || ! current_user_can( 'edit_post', $post_id ) ) {\n+            echo \"Error: Unauthorized access.\";\n+            wp_die();\n+        }\n+\n         $latlon  = sanitize_text_field( wp_unslash( $_POST['lat'] ) ) . ',' . sanitize_text_field( wp_unslash( $_POST['lon'] ) );\n         $icon    = sanitize_text_field( wp_unslash( $_POST['icon'] ) );\n-        $post_id = sanitize_text_field( wp_unslash( $_POST['post_id'] ) );\n         $nonce   = sanitize_text_field( wp_unslash( $_POST['geotag_nonce'] ) );\n \n         if ( ! wp_verify_nonce( $nonce, 'osm_geotag_nonce' ) ) {\n@@ -215,37 +222,49 @@\n function savePostMarker() {\n     if ( isset( $_POST['MarkerId'], $_POST['MarkerLat'], $_POST['MarkerLon'], $_POST['MarkerIcon'], $_POST['MarkerName'], $_POST['post_id'], $_POST['marker_nonce'], $_POST['MarkerText'] ) ) {\n \n-        $MarkerId      = sanitize_text_field( wp_unslash( $_POST['MarkerId'] ) );\n-        $MarkerLatLon  = sanitize_text_field( wp_unslash( $_POST['MarkerLat'] ) ) . ',' . sanitize_text_field( wp_unslash( $_POST['MarkerLon'] ) );\n-        $MarkerIcon    = sanitize_text_field( wp_unslash( $_POST['MarkerIcon'] ) );\n-        $MarkerName    = sanitize_text_field( wp_unslash( $_POST['MarkerName'] ) );\n-        $post_id       = sanitize_text_field( wp_unslash( $_POST['post_id'] ) );\n-        $nonce         = sanitize_text_field( wp_unslash( $_POST['marker_nonce'] ) );\n-        \n-        $allowed_html  = array( \n+        \u002F\u002F post_id korrekt behandeln\n+        $post_id = absint( wp_unslash( $_POST['post_id'] ) );\n+\n+        \u002F\u002F SECURITY-FIX: Berechtigungsprüfung\n+        if ( ! $post_id || ! current_user_can( 'edit_post', $post_id ) ) {\n+            echo \"Error: Unauthorized access.\";\n+            wp_die();\n+        }\n+\n+        \u002F\u002F restliche Felder wie gehabt\n+        $MarkerId     = absint( wp_unslash( $_POST['MarkerId'] ) );\n+        $MarkerLatLon = sanitize_text_field( wp_unslash( $_POST['MarkerLat'] ) ) . ',' .\n+                        sanitize_text_field( wp_unslash( $_POST['MarkerLon'] ) );\n+        $MarkerIcon   = sanitize_file_name( wp_unslash( $_POST['MarkerIcon'] ) );\n+        $MarkerName   = sanitize_text_field( wp_unslash( $_POST['MarkerName'] ) );\n+        $nonce        = sanitize_text_field( wp_unslash( $_POST['marker_nonce'] ) );","To exploit this vulnerability, an attacker must have Contributor-level access to the WordPress dashboard. 1. Access the post editor (e.g., \u002Fwp-admin\u002Fpost-new.php) to extract the localized AJAX nonces 'osm_geotag_nonce' or 'osm_marker_nonce'. 2. Identify a target post ID that the attacker does not have permission to edit (e.g., a published post by an administrator). 3. Send a POST request to \u002Fwp-admin\u002Fadmin-ajax.php using the action 'osm_save_geotag' or 'osm_save_post_marker'. 4. Include the extracted nonce, the target post_id, and the desired latitude\u002Flongitude\u002Ficon metadata in the request body. Because the plugin only verifies the nonce and not the user's permission to edit the specific post_id, the metadata for the target post will be updated.","gemini-3-flash-preview","2026-05-04 21:11:41","2026-05-04 21:12:02",{"type":36,"vulnerable_version":37,"fixed_version":11,"vulnerable_browse":38,"vulnerable_zip":39,"fixed_browse":40,"fixed_zip":41,"all_tags":42},"plugin","6.1.12","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Fosm\u002Ftags\u002F6.1.12","https:\u002F\u002Fdownloads.wordpress.org\u002Fplugin\u002Fosm.6.1.12.zip","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Fosm\u002Ftags\u002F6.1.13","https:\u002F\u002Fdownloads.wordpress.org\u002Fplugin\u002Fosm.6.1.13.zip","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Fosm\u002Ftags"]