Skip to content

Commit c620b3a

Browse files
committed
Grouped backports to the 4.1 branch.
- Comments: Prevent users who can not see a post from seeing comments on it. - Shortcodes: Restrict ajax handler for media shortcode. - Prevent unintended behavior when certain objects are unserialized. Merges [56835], [56836], and [56838] to the 4.1 branch. Props xknown, jorbin, joehoyle, peterwilsoncc, ehtis, tykoted, antpb. git-svn-id: https://develop.svn.wordpress.org/branches/4.1@56850 602fd350-edb4-49c9-b593-d223f7449a82
1 parent b152eda commit c620b3a

File tree

7 files changed

+166
-7
lines changed

7 files changed

+166
-7
lines changed

src/wp-admin/includes/ajax-actions.php

Lines changed: 32 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -828,7 +828,7 @@ function wp_ajax_get_tagcloud() {
828828
if ( ! $tax ) {
829829
wp_die( 0 );
830830
}
831-
831+
832832
if ( ! current_user_can( $tax->cap->assign_terms ) ) {
833833
wp_die( -1 );
834834
}
@@ -2767,8 +2767,36 @@ function wp_ajax_parse_media_shortcode() {
27672767
wp_send_json_error();
27682768
}
27692769

2770-
setup_postdata( $post );
2771-
$shortcode = do_shortcode( wp_unslash( $_POST['shortcode'] ) );
2770+
$shortcode = wp_unslash( $_POST['shortcode'] );
2771+
2772+
// Only process previews for media related shortcodes:
2773+
$found_shortcodes = get_shortcode_tags_in_content( $shortcode );
2774+
$media_shortcodes = array(
2775+
'audio',
2776+
'embed',
2777+
'playlist',
2778+
'video',
2779+
'gallery',
2780+
);
2781+
2782+
$other_shortcodes = array_diff( $found_shortcodes, $media_shortcodes );
2783+
2784+
if ( ! empty( $other_shortcodes ) ) {
2785+
wp_send_json_error();
2786+
}
2787+
2788+
if ( ! empty( $_POST['post_ID'] ) ) {
2789+
$post = get_post( (int) $_POST['post_ID'] );
2790+
}
2791+
2792+
// the embed shortcode requires a post
2793+
if ( ! $post || ! current_user_can( 'edit_post', $post->ID ) ) {
2794+
if ( in_array( 'embed', $found_shortcodes, true ) ) {
2795+
wp_send_json_error();
2796+
}
2797+
} else {
2798+
setup_postdata( $post );
2799+
}
27722800

27732801
if ( empty( $shortcode ) ) {
27742802
wp_send_json_error( array(
@@ -2835,7 +2863,7 @@ function wp_ajax_destroy_sessions() {
28352863
$message = __( 'You are now logged out everywhere else.' );
28362864
} else {
28372865
$sessions->destroy_all();
2838-
/* translators: 1: User's display name. */
2866+
/* translators: 1: User's display name. */
28392867
$message = sprintf( __( '%s has been logged out.' ), $user->display_name );
28402868
}
28412869

src/wp-admin/includes/class-wp-comments-list-table.php

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -362,6 +362,19 @@ public function single_row( $a_comment ) {
362362

363363
$this->user_can = current_user_can( 'edit_comment', $comment->comment_ID );
364364

365+
$edit_post_cap = $post ? 'edit_post' : 'edit_posts';
366+
if (
367+
current_user_can( $edit_post_cap, $comment->comment_post_ID ) ||
368+
(
369+
empty( $post->post_password ) &&
370+
current_user_can( 'read_post', $comment->comment_post_ID )
371+
)
372+
) {
373+
// The user has access to the post
374+
} else {
375+
return false;
376+
}
377+
365378
echo "<tr id='comment-$comment->comment_ID' class='$the_comment_class'>";
366379
$this->single_row_columns( $comment );
367380
echo "</tr>\n";

src/wp-admin/includes/class-wp-list-table.php

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -573,6 +573,20 @@ protected function view_switcher( $current_mode ) {
573573
protected function comments_bubble( $post_id, $pending_comments ) {
574574
$pending_phrase = sprintf( __( '%s pending' ), number_format( $pending_comments ) );
575575

576+
$post_object = get_post( $post_id );
577+
$edit_post_cap = $post_object ? 'edit_post' : 'edit_posts';
578+
if (
579+
current_user_can( $edit_post_cap, $post_id ) ||
580+
(
581+
empty( $post_object->post_password ) &&
582+
current_user_can( 'read_post', $post_id )
583+
)
584+
) {
585+
// The user has access to the post and thus can see comments
586+
} else {
587+
return false;
588+
}
589+
576590
if ( $pending_comments )
577591
echo '<strong>';
578592

src/wp-admin/includes/dashboard.php

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -778,8 +778,18 @@ function wp_dashboard_recent_comments( $total_items = 5 ) {
778778
echo '<h4>' . __( 'Comments' ) . '</h4>';
779779

780780
echo '<div id="the-comment-list" data-wp-lists="list:comment">';
781-
foreach ( $comments as $comment )
782-
_wp_dashboard_recent_comments_row( $comment );
781+
foreach ( $comments as $comment ) {
782+
$comment_post = get_post( $comment->comment_post_ID );
783+
if (
784+
current_user_can( 'edit_post', $comment->comment_post_ID ) ||
785+
(
786+
empty( $comment_post->post_password ) &&
787+
current_user_can( 'read_post', $comment->comment_post_ID )
788+
)
789+
) {
790+
_wp_dashboard_recent_comments_row( $comment );
791+
}
792+
}
783793
echo '</div>';
784794

785795
if ( current_user_can('edit_posts') )

src/wp-includes/class-wp-theme.php

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -476,6 +476,28 @@ public function parent() {
476476
return isset( $this->parent ) ? $this->parent : false;
477477
}
478478

479+
/**
480+
* Perform reinitialization tasks.
481+
*
482+
* Prevents a callback from being injected during unserialization of an object.
483+
*
484+
* @return void
485+
*/
486+
public function __wakeup() {
487+
if ( $this->parent && ! $this->parent instanceof self ) {
488+
throw new UnexpectedValueException();
489+
}
490+
if ( $this->headers && ! is_array( $this->headers ) ) {
491+
throw new UnexpectedValueException();
492+
}
493+
foreach ( $this->headers as $value ) {
494+
if ( ! is_string( $value ) ) {
495+
throw new UnexpectedValueException();
496+
}
497+
}
498+
$this->headers_sanitized = array();
499+
}
500+
479501
/**
480502
* Adds theme data to cache.
481503
*
@@ -1232,4 +1254,16 @@ private static function _name_sort_i18n( $a, $b ) {
12321254
// Don't mark up; Do translate.
12331255
return strnatcasecmp( $a->display( 'Name', false, true ), $b->display( 'Name', false, true ) );
12341256
}
1257+
1258+
private static function _check_headers_property_has_correct_type( $headers ) {
1259+
if ( ! is_array( $headers ) ) {
1260+
return false;
1261+
}
1262+
foreach ( $headers as $key => $value ) {
1263+
if ( ! is_string( $key ) || ! is_string( $value ) ) {
1264+
return false;
1265+
}
1266+
}
1267+
return true;
1268+
}
12351269
}

src/wp-includes/media.php

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -974,11 +974,24 @@ function gallery_shortcode( $attr ) {
974974
$attachments[$val->ID] = $_attachments[$key];
975975
}
976976
} elseif ( ! empty( $atts['exclude'] ) ) {
977+
$post_parent_id = $id;
977978
$attachments = get_children( array( 'post_parent' => $id, 'exclude' => $atts['exclude'], 'post_status' => 'inherit', 'post_type' => 'attachment', 'post_mime_type' => 'image', 'order' => $atts['order'], 'orderby' => $atts['orderby'] ) );
978979
} else {
980+
$post_parent_id = $id;
979981
$attachments = get_children( array( 'post_parent' => $id, 'post_status' => 'inherit', 'post_type' => 'attachment', 'post_mime_type' => 'image', 'order' => $atts['order'], 'orderby' => $atts['orderby'] ) );
980982
}
981983

984+
if ( ! empty( $post_parent_id ) ) {
985+
$post_parent = get_post( $post_parent_id );
986+
987+
// terminate the shortcode execution if user cannot read the post or password-protected
988+
if (
989+
( ! is_post_publicly_viewable( $post_parent->ID ) && ! current_user_can( 'read_post', $post_parent->ID ) )
990+
|| post_password_required( $post_parent ) ) {
991+
return '';
992+
}
993+
}
994+
982995
if ( empty( $attachments ) ) {
983996
return '';
984997
}
@@ -1268,6 +1281,15 @@ function wp_playlist_shortcode( $attr ) {
12681281
$attachments = get_children( $args );
12691282
}
12701283

1284+
if ( ! empty( $args['post_parent'] ) ) {
1285+
$post_parent = get_post( $id );
1286+
1287+
// terminate the shortcode execution if user cannot read the post or password-protected
1288+
if ( ! current_user_can( 'read_post', $post_parent->ID ) || post_password_required( $post_parent ) ) {
1289+
return '';
1290+
}
1291+
}
1292+
12711293
if ( empty( $attachments ) ) {
12721294
return '';
12731295
}

src/wp-includes/shortcodes.php

Lines changed: 39 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -170,7 +170,45 @@ function has_shortcode( $content, $tag ) {
170170
}
171171

172172
/**
173-
* Search content for shortcodes and filter shortcodes through their hooks.
173+
* Returns a list of registered shortcode names found in the given content.
174+
*
175+
* Example usage:
176+
*
177+
* get_shortcode_tags_in_content( '[audio src="file.mp3"][/audio] [foo] [gallery ids="1,2,3"]' );
178+
* // array( 'audio', 'gallery' )
179+
*
180+
* @since 6.3.2
181+
*
182+
* @param string $content The content to check.
183+
* @return string[] An array of registered shortcode names found in the content.
184+
*/
185+
function get_shortcode_tags_in_content( $content ) {
186+
if ( false === strpos( $content, '[' ) ) {
187+
return array();
188+
}
189+
190+
preg_match_all( '/' . get_shortcode_regex() . '/', $content, $matches, PREG_SET_ORDER );
191+
if ( empty( $matches ) ) {
192+
return array();
193+
}
194+
195+
$tags = array();
196+
foreach ( $matches as $shortcode ) {
197+
$tags[] = $shortcode[2];
198+
199+
if ( ! empty( $shortcode[5] ) ) {
200+
$deep_tags = get_shortcode_tags_in_content( $shortcode[5] );
201+
if ( ! empty( $deep_tags ) ) {
202+
$tags = array_merge( $tags, $deep_tags );
203+
}
204+
}
205+
}
206+
207+
return $tags;
208+
}
209+
210+
/**
211+
* Searches content for shortcodes and filter shortcodes through their hooks.
174212
*
175213
* If there are no shortcode tags defined, then the content will be returned
176214
* without any filtering. This might cause issues when plugins are disabled but

0 commit comments

Comments
 (0)