Media: Prevent CSRF setting attachment thumbnails.

Props martinkrcho, paulkevan, peterwilsoncc, xknown, peterwilsoncc.



git-svn-id: https://develop.svn.wordpress.org/trunk@55764 602fd350-edb4-49c9-b593-d223f7449a82
This commit is contained in:
Jb Audras 2023-05-16 14:26:01 +00:00
parent a6f0f3ea29
commit 35c0ab3c74
4 changed files with 98 additions and 1 deletions

View File

@ -106,6 +106,7 @@ VideoDetails = MediaDetails.extend(/** @lends wp.media.view.MediaFrame.VideoDeta
wp.ajax.send( 'set-attachment-thumbnail', {
data : {
_ajax_nonce: wp.media.view.settings.nonce.setAttachmentThumbnail,
urls: urls,
thumbnail_id: attachment.get( 'id' )
}

View File

@ -2771,6 +2771,10 @@ function wp_ajax_set_attachment_thumbnail() {
wp_send_json_error();
}
if ( false === check_ajax_referer( 'set-attachment-thumbnail', '_ajax_nonce', false ) ) {
wp_send_json_error();
}
$post_ids = array();
// For each URL, try to find its corresponding post ID.
foreach ( $_POST['urls'] as $url ) {

View File

@ -4528,7 +4528,8 @@ function wp_enqueue_media( $args = array() ) {
/** This filter is documented in wp-admin/includes/media.php */
'captions' => ! apply_filters( 'disable_captions', '' ),
'nonce' => array(
'sendToEditor' => wp_create_nonce( 'media-send-to-editor' ),
'sendToEditor' => wp_create_nonce( 'media-send-to-editor' ),
'setAttachmentThumbnail' => wp_create_nonce( 'set-attachment-thumbnail' ),
),
'post' => array(
'id' => 0,

View File

@ -101,4 +101,95 @@ class Tests_Ajax_wpAjaxSendAttachmentToEditor extends WP_Ajax_UnitTestCase {
$this->assertTrue( $response['success'] );
$this->assertSame( $expected, $response['data'] );
}
public function test_wp_ajax_set_attachment_thumbnail_success() {
// Become an administrator.
$post = $_POST;
$user_id = self::factory()->user->create(
array(
'role' => 'administrator',
'user_login' => 'user_36578_administrator',
'user_email' => 'user_36578_administrator@example.com',
)
);
wp_set_current_user( $user_id );
$_POST = array_merge( $_POST, $post );
// Upload the attachment itself.
$filename = DIR_TESTDATA . '/uploads/small-audio.mp3';
$contents = file_get_contents( $filename );
$upload = wp_upload_bits( wp_basename( $filename ), null, $contents );
$attachment = $this->_make_attachment( $upload );
// Upload the thumbnail.
$filename = DIR_TESTDATA . '/images/waffles.jpg';
$contents = file_get_contents( $filename );
$upload = wp_upload_bits( wp_basename( $filename ), null, $contents );
$thumbnail = $this->_make_attachment( $upload );
// Set up a default request.
$_POST['_ajax_nonce'] = wp_create_nonce( 'set-attachment-thumbnail' );
$_POST['thumbnail_id'] = $thumbnail;
$_POST['urls'] = array( wp_get_attachment_url( $attachment ) );
// Make the request.
try {
$this->_handleAjax( 'set-attachment-thumbnail' );
} catch ( WPAjaxDieContinueException $e ) {
unset( $e );
}
// Get the response.
$response = json_decode( $this->_last_response, true );
// Ensure everything is correct.
$this->assertTrue( $response['success'] );
}
public function test_wp_ajax_set_attachment_thumbnail_missing_nonce() {
// Become an administrator.
$post = $_POST;
$user_id = self::factory()->user->create(
array(
'role' => 'administrator',
'user_login' => 'user_36578_administrator',
'user_email' => 'user_36578_administrator@example.com',
)
);
wp_set_current_user( $user_id );
$_POST = array_merge( $_POST, $post );
// Upload the attachment itself.
$filename = DIR_TESTDATA . '/uploads/small-audio.mp3';
$contents = file_get_contents( $filename );
$upload = wp_upload_bits( wp_basename( $filename ), null, $contents );
$attachment = $this->_make_attachment( $upload );
// Upload the thumbnail.
$filename = DIR_TESTDATA . '/images/waffles.jpg';
$contents = file_get_contents( $filename );
$upload = wp_upload_bits( wp_basename( $filename ), null, $contents );
$thumbnail = $this->_make_attachment( $upload );
// Set up a default request.
$_POST['thumbnail_id'] = $thumbnail;
$_POST['urls'] = array( wp_get_attachment_url( $attachment ) );
// Make the request.
try {
$this->_handleAjax( 'set-attachment-thumbnail' );
} catch ( WPAjaxDieContinueException $e ) {
unset( $e );
}
// Get the response.
$response = json_decode( $this->_last_response, true );
// Check that success is false without sending nonce.
$this->assertFalse( $response['success'] );
}
}