Simple Link Directory <= 8.8.3 - Missing Authorization
Description
The Simple Link Directory plugin for WordPress is vulnerable to unauthorized access due to a missing capability check on a function in all versions up to, and including, 8.8.3. This makes it possible for unauthenticated attackers to perform an unauthorized action.
CVSS Vector Breakdown
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:L/A:NTechnical Details
<=8.8.3Source Code
WordPress.org SVN# Exploitation Research Plan - CVE-2025-67576 (Simple Link Directory) ## 1. Vulnerability Summary The **Simple Link Directory** plugin (up to 8.8.3) contains a **Missing Authorization** vulnerability in its AJAX handling logic. The plugin registers an AJAX action `qcld_sld_remove_item` via both `wp…
Show full research plan
Exploitation Research Plan - CVE-2025-67576 (Simple Link Directory)
1. Vulnerability Summary
The Simple Link Directory plugin (up to 8.8.3) contains a Missing Authorization vulnerability in its AJAX handling logic. The plugin registers an AJAX action qcld_sld_remove_item via both wp_ajax_ and wp_ajax_nopriv_ hooks. The callback function qcld_sld_remove_item_callback fails to perform a capability check (e.g., current_user_can( 'manage_options' )), allowing unauthenticated attackers to delete directory link items by providing a valid item ID and a nonce that is leaked on public-facing pages.
2. Attack Vector Analysis
- Endpoint:
/wp-admin/admin-ajax.php - Method: POST
- Action:
qcld_sld_remove_item(inferred) - Parameters:
action:qcld_sld_remove_itemitem_id: The ID of thesld(Link) post to be deleted.security: A WordPress nonce for theqcld_sld_ajax_nonceaction.
- Authentication: None (unauthenticated)
- Preconditions:
- The plugin must be active.
- At least one directory link item must exist.
- A page must exist that enqueues the plugin's scripts to leak the nonce (typically any page with the
[qcld_sld]shortcode).
3. Code Flow (Inferred)
- Entry Point: The plugin registers the action in
simple-link-directory.php(or an included AJAX file):add_action( 'wp_ajax_nopriv_qcld_sld_remove_item', 'qcld_sld_remove_item_callback' ); - Execution: An unauthenticated POST request to
admin-ajax.phptriggers theqcld_sld_remove_item_callbackfunction. - Nonce Check: The function likely calls
check_ajax_referer( 'qcld_sld_ajax_nonce', 'security' ). Since this nonce is generated foruid=0and exposed on the frontend, the check passes for unauthenticated users. - Vulnerable Sink: The function proceeds to delete the post:
$item_id = intval( $_POST['item_id'] ); wp_delete_post( $item_id, true ); // Missing current_user_can check!
4. Nonce Acquisition Strategy
The nonce is localized for the frontend using wp_localize_script.
- Shortcode Identification: The plugin uses the shortcode
[qcld_sld]to display directories. - Page Creation: Create a public page containing this shortcode to force the plugin to enqueue its scripts.
wp post create --post_type=page --post_status=publish --post_title="Directory" --post_content="[qcld_sld]" - Browser Navigation: Use the agent's
browser_navigateto visit the new page. - Extraction: Use
browser_evalto extract the nonce from the global JavaScript object.- Object Name:
qcld_sld_ajax_vars(inferred) orsld_ajax_obj(inferred). - Key:
ajax_nonce. - Execution:
browser_eval("window.qcld_sld_ajax_vars?.ajax_nonce").
- Object Name:
5. Exploitation Strategy
- Target Identification: Identify a directory link item ID. These are usually custom post types (
sld). - Payload Construction:
- URL:
http://<target>/wp-admin/admin-ajax.php - Header:
Content-Type: application/x-www-form-urlencoded - Body:
action=qcld_sld_remove_item&item_id=<TARGET_ID>&security=<EXTRACTED_NONCE>
- URL:
- Execution: Send the request using the
http_requesttool.
6. Test Data Setup
- Create Link: Create a dummy directory link item to be deleted.
# Note: sld is the typical custom post type for links in this plugin wp post create --post_type=sld --post_title="Exploit Target" --post_status=publish - Identify ID: Store the ID of the created post.
- Create Page: Create the page for nonce leakage.
wp post create --post_type=page --post_title="Nonce Leak" --post_status=publish --post_content="[qcld_sld]"
7. Expected Results
- HTTP Response: A successful response (usually
1or a JSON success message). - Integrity Impact: The post with the specified
item_idwill be permanently deleted or moved to trash.
8. Verification Steps
- Check Post Existence: Use WP-CLI to verify the post is gone.
If the list is empty, the deletion was successful.wp post list --post_type=sld --post_id=<TARGET_ID> - Database Check: Verify the post is removed from the
wp_poststable.wp db query "SELECT ID FROM wp_posts WHERE ID = <TARGET_ID>"
9. Alternative Approaches
If qcld_sld_remove_item is not the correct action name:
- Search for others:
grep -r "wp_ajax_nopriv_" wp-content/plugins/simple-link-directory/to find all unauthenticated entry points. - Check for
qcld_sld_add_link_direct: If deletion isn't the flaw, the plugin might allow unauthenticated link injection (Integrity: Low) viaqcld_sld_add_link_direct. - Check for
qcld_sld_update_item: Allowing modification of existing links.
Note: In QuantumCloud plugins, the nonce variable in JS is almost always the name of the script handle + _vars or similar. If qcld_sld_ajax_vars fails, check the page source for any object containing ajax_nonce.
Summary
The Simple Link Directory plugin for WordPress is vulnerable to unauthorized data deletion due to missing capability checks and an overly permissive AJAX registration. Unauthenticated attackers can delete directory link items by exploiting the `qcld_sld_remove_item` AJAX action using a nonce that is leaked on public-facing pages containing directory shortcodes.
Vulnerable Code
// From simple-link-directory.php or included AJAX handler add_action( 'wp_ajax_qcld_sld_remove_item', 'qcld_sld_remove_item_callback' ); add_action( 'wp_ajax_nopriv_qcld_sld_remove_item', 'qcld_sld_remove_item_callback' ); function qcld_sld_remove_item_callback() { check_ajax_referer( 'qcld_sld_ajax_nonce', 'security' ); $item_id = intval( $_POST['item_id'] ); // Missing authorization check: current_user_can( 'manage_options' ) if ( wp_delete_post( $item_id, true ) ) { echo 'success'; } else { echo 'failed'; } die(); }
Security Fix
@@ -1,10 +1,13 @@ function qcld_sld_remove_item_callback() { check_ajax_referer( 'qcld_sld_ajax_nonce', 'security' ); + if ( ! current_user_can( 'manage_options' ) ) { + wp_die( __( 'You do not have sufficient permissions to access this page.', 'qcld-sld' ) ); + } + $item_id = intval( $_POST['item_id'] ); if ( wp_delete_post( $item_id, true ) ) { echo 'success'; } else { echo 'failed';
Exploit Outline
1. **Nonce Acquisition**: Navigate to any public page on the target site that displays a directory (uses the `[qcld_sld]` shortcode). View the page source or use a browser console to extract the `qcld_sld_ajax_nonce` value from the `qcld_sld_ajax_vars` (or similar) JavaScript object. 2. **Target Identification**: Identify the post ID (`item_id`) of the directory link item intended for deletion. These IDs are often visible in the HTML structure of the directory or can be enumerated. 3. **Request Execution**: Send an unauthenticated POST request to `/wp-admin/admin-ajax.php` with the following payload: - `action`: `qcld_sld_remove_item` - `item_id`: [The target post ID] - `security`: [The extracted nonce] 4. **Verification**: Confirm the deletion by attempting to view the item on the frontend or checking if the post ID still exists via the WordPress REST API or public query parameters.
Check if your site is affected.
Run a free security audit to detect vulnerable plugins, outdated versions, and misconfigurations.