ورود

توجه ! این یک نسخه آرشیو شده میباشد و در این حالت شما عکسی را مشاهده نمیکنید برای مشاهده کامل متن و عکسها بر روی لینک مقابل کلیک کنید : بررسی باگ [Content Injection] در وردپرس 4.7.0 / 4.7.1



T.Toosi
February 8th, 2017, 21:39
باسلام، همانطور که اطلاع دارید هفته گذشته وردپرس بدون اطلاع رسانی در آپدیت جدید خود یک آسیب پذیری DREAD Score 9 را برطرف کرد، این باگ مربوط به قسمت REST API Endpoint در نسخه 4.7.0/1 هست که قادر خواهید بود محتوا پست ها و پیج ها را ادیت یا محتوا تزریق کنید، باهم بررسی میکنیم این اتفاق چگونه رخ میده.

مشکل از جایی شروع میشود که در فایل زیر مسیر دهی ای برای request ها تعریف شده است که مقدار پارامتر پست آیدی را از کاربر دریافت کند :


./wp-includes/rest-api/endpoints/class-wp-rest-posts-controller.php

مقدار پست آیدی به 2 صورت زیر قایل دریافت است :


/wp-json/wp/v2/posts/1452?id=1452


/wp-json/wp/v2/posts/1452

در حالت اول هکر به صورت زیر پارامتر پست آیدی را مقدار دهی میکند :


wp-json/wp/v2/posts/1452?id=14521َََََAA

سپس برای بررسی که کاربر اجازه دارد پست را آپدیت یا ادیت و .. بکند تابع update_item_permissions_check از کلاس WP_REST_Posts_Controller فراخوانی و اجرا خواهد شد :


public function update_item_permissions_check( $request ) {

$post = $this->get_post( $request['id'] );
$post_type = get_post_type_object( $this->post_type );

if ( $post && ! $this->check_update_permission( $post ) ) {
return new WP_Error( 'rest_cannot_edit', __( 'Sorry, you are not allowed to edit this post.' ), array( 'status' => rest_authorization_required_code() ) );
}

if ( ! empty( $request['author'] ) && get_current_user_id() !== $request['author'] && ! current_user_can( $post_type->cap->edit_others_posts ) ) {
return new WP_Error( 'rest_cannot_edit_others', __( 'Sorry, you are not allowed to update posts as this user.' ), array( 'status' => rest_authorization_required_code() ) );
}

if ( ! empty( $request['sticky'] ) && ! current_user_can( $post_type->cap->edit_others_posts ) ) {
return new WP_Error( 'rest_cannot_assign_sticky', __( 'Sorry, you are not allowed to make posts sticky.' ), array( 'status' => rest_authorization_required_code() ) );
}

if ( ! $this->check_assign_terms_permission( $request ) ) {
return new WP_Error( 'rest_cannot_assign_term', __( 'Sorry, you are not allowed to assign the provided terms.' ), array( 'status' => rest_authorization_required_code() ) );
}

return true;
}

کافیست ما شرط اول را bypass کنیم، در شرط اول مقدار پست آیدی فرستاده شده بررسی میشود تا همچین پستی وجود داشته باشد سپس در مرجله دوم دسترسی کاربر بررسی میشود، کافیست پست آیدی ما وجود نداشته باشد تا به مرحله دوم شرط نرسیم :


if ( $post && ! $this->check_update_permission( $post ) )

زمانی که هکر مقدار پست آیدی : 1452AA را ارسال میکند (get_post مقدار false را برگشت میدهد) این شرط در مرحله اول false برگشت میخورد و به مرحله تایید هویت کاربر (check_update_permission در کلاس) نخواهیم رسید، سپس تابع update_item_permissions_check که برای بررسی دسترسی کاربر اجرا شده بود با مقدار true برگشت خواهد خورد، به همین سادگی تایید دسترسی byepass خواهد شد!

شاید حالا براتون سوال بشه پست آیدی 1452AA که وجود ندارد چه پستی را قرار هست آپدیت یا ادیت کنیم ؟! مقدار (1452) یک پست آیدی معتبر که در دیتابیس وجود دارد است سپس چند کارکتر به آن اضافه کردیم برای byepass کردن مرحله تایید دسترسی. حالا که دسترسی داریم تابع update_item اجرا خواهد شد در 2 خط اول این تابع مشاهده خواهید کرد :


public function update_item( $request ) {

$id = (int) $request['id'];
$post = get_post( $id );

در خط اول مقدار پست آیدی ما که (14521َََََAA) بود به (14521) تبدیل خواهد شد، چرا ؟ به دلیل اینکه تایپ int برای پست آیدی مشخص شده است و تمامی کارکتر ها به جز numberic ها از رشته حذف خواهد شد و به این صورت پست ما با آیدی 14521 آپدیت خواهد شد.

kiava
February 8th, 2017, 21:50
تشکر عزیز از پست مفیدتون :x