تم إصلاح نقاط الضعف الشديدة في إصدار البرنامج المساعد لتحسين محركات البحث الكل في واحد 4.1.5.3
نشرت: 2021-12-15أثناء التدقيق الداخلي للمكوِّن الإضافي All In One SEO ، اكتشفنا ثغرة أمنية في حقن SQL وخطأ تصعيد الامتياز.
إذا تم استغلالها ، فقد تمنح ثغرة حقن SQL للمهاجمين حق الوصول إلى المعلومات المميزة من قاعدة بيانات الموقع المتأثر (على سبيل المثال ، أسماء المستخدمين وكلمات المرور المجزأة).
قد يمنح خطأ تصعيد الامتياز الذي اكتشفناه الممثلين السيئين الوصول إلى نقاط نهاية REST API المحمية التي لا ينبغي لهم الوصول إليها. قد يؤدي ذلك في النهاية إلى تمكين المستخدمين الذين لديهم حسابات ذات امتيازات منخفضة ، مثل المشتركين ، من تنفيذ التعليمات البرمجية عن بُعد على المواقع المتأثرة.
لقد أبلغنا مؤلف المكون الإضافي عن الثغرات الأمنية عبر البريد الإلكتروني ، وأصدروا مؤخرًا الإصدار 4.1.5.3 لمعالجتها. نوصي بشدة أن تقوم بالتحديث إلى أحدث إصدار من البرنامج المساعد وأن يكون لديك حل أمان ثابت على موقعك ، مثل Jetpack Security.
تفاصيل
اسم البرنامج المساعد: All In One SEO
عنوان URI للمكون الإضافي: https://wordpress.org/plugins/all-in-one-seo-pack/
المؤلف: https://aioseo.com/
نقاط الضعف
تصعيد امتياز موثق
الإصدارات المتأثرة: كل إصدار بين 4.0.0 و 4.1.5.2 شاملاً.
معرف CVE: CVE-2021-25036
CVSSv3.1: 9.9
CWSS: 92.1
/**
* Validates access from the routes array.
*
* @since 4.0.0
*
* @param \WP_REST_Request $request The REST Request.
* @return bool True if validated, false if not.
*/
public function validateAccess( $request ) {
$route = str_replace( '/' . $this->namespace . '/', '', $request->get_route() );
$routeData = isset( $this->getRoutes()[ $request->get_method() ][ $route ] ) ? $this->getRoutes()[ $request->get_method() ][ $route ] : [];
// No direct route name, let's try the regexes.
if ( empty( $routeData ) ) {
foreach ( $this->getRoutes()[ $request->get_method() ] as $routeRegex => $routeInfo ) {
$routeRegex = str_replace( '@', '\@', $routeRegex );
if ( preg_match( "@{$routeRegex}@", $route ) ) {
$routeData = $routeInfo;
break;
}
}
}
if ( empty( $routeData['access'] ) ) {
return true;
}
// We validate with any of the access options.
if ( ! is_array( $routeData['access'] ) ) {
$routeData['access'] = [ $routeData['access'] ];
}
foreach ( $routeData['access'] as $access ) {
if ( current_user_can( $access ) ) {
return true;
}
}
if ( current_user_can( apply_filters( 'aioseo_manage_seo', 'aioseo_manage_seo' ) ) ) {
return true;
}
return false;
}
اشتملت عمليات التحقق من الامتياز التي يطبقها All In One SEO لتأمين نقاط نهاية REST API على خطأ دقيق للغاية كان من الممكن أن يمنح المستخدمين ذوي الحسابات منخفضة الامتياز (مثل المشتركين) الوصول إلى كل نقطة نهاية يسجلها المكون الإضافي.
تعتمد طريقة Api :: validateAccess () على مسار واجهة برمجة تطبيقات REST المطلوب لمعرفة فحوصات الامتياز التي يجب فرضها على طلب معين. نظرًا لأنه لا يأخذ في الحسبان حقيقة أن WordPress يتعامل مع مسارات واجهة برمجة تطبيقات REST على أنها سلاسل غير حساسة لحالة الأحرف ، فإن تغيير حرف واحد إلى أحرف كبيرة سيتجاوز روتين اختبارات الامتياز تمامًا.
هذا مقلق بشكل خاص لأن بعض نقاط نهاية المكون الإضافي حساسة جدًا. على سبيل المثال ، يمكن لنقطة نهاية aioseo/v1/htaccess
إعادة كتابة .htaccess لموقع ما بمحتوى عشوائي. قد يسيء المهاجم استخدام هذه الميزة لإخفاء .htaccess backdoors وتنفيذ تعليمات برمجية ضارة على الخادم.
حقن SQL مصدق
الإصدارات المتأثرة: كل إصدار بين 4.1.3.1 و 4.1.5.2 شاملاً.
معرف CVE: CVE-2021-25037
CVSSv3.1: 7.7
CWSS: 80.4

/**
* Searches for posts or terms by ID/name.
*
* @since 4.0.0
*
* @param \WP_REST_Request $request The REST Request
* @return \WP_REST_Response The response.
*/
public static function searchForObjects( $request ) {
$body = $request->get_json_params();
if ( empty( $body['query'] ) ) {
return new \WP_REST_Response( [
'success' => false,
'message' => 'No search term was provided.'
], 400 );
}
if ( empty( $body['type'] ) ) {
return new \WP_REST_Response( [
'success' => false,
'message' => 'No type was provided.'
], 400 );
}
$searchQuery = aioseo()->db->db->esc_like( $body['query'] );
$objects = [];
$dynamicOptions = aioseo()->dynamicOptions->noConflict();
if ( 'posts' === $body['type'] ) {
$postTypes = aioseo()->helpers->getPublicPostTypes( true );
foreach ( $postTypes as $postType ) {
// Check if post type isn't noindexed.
if ( $dynamicOptions->searchAppearance->postTypes->has( $postType ) && ! $dynamicOptions->searchAppearance->postTypes->$postType->show ) {
$postTypes = aioseo()->helpers->unsetValue( $postTypes, $postType );
}
}
$objects = aioseo()->db
->start( 'posts' )
->select( 'ID, post_type, post_title, post_name' )
->whereRaw( "( post_title LIKE '%{$searchQuery}%' OR post_name LIKE '%{$searchQuery}%' OR )" )
->whereIn( 'post_type', $postTypes )
->whereIn( 'post_status', [ 'publish', 'draft', 'future', 'pending' ] )
->orderBy( 'post_title' )
->limit( 10 )
->run()
->result();
طريقة PostsTerms :: searchForObjects () ، والتي يمكن الوصول إليها عبر مسار واجهة برمجة تطبيقات REST /wp-json/aioseo/v1/objects
فقط هربت من إدخال المستخدم باستخدام wpdb :: esc_like () قبل إلحاق الإدخال المذكور باستعلام SQL. نظرًا لأن هذه الطريقة ليست مصممة للتخلص من علامات الاقتباس ، فلا يزال بإمكان المهاجم إدخالها وإجبار الاستعلام على تسريب معلومات حساسة من قاعدة البيانات ، مثل بيانات اعتماد المستخدم.
على الرغم من أن نقطة النهاية هذه لم يكن من المفترض أن تكون في متناول المستخدمين ذوي الحسابات منخفضة الامتياز ، إلا أن متجه هجوم تصعيد الامتياز المذكور أعلاه جعل من الممكن لهم إساءة استخدام هذه الثغرة الأمنية.
الجدول الزمني
2021-12-01 - الاتصال الأولي بـ All In One SEO
2021-12-02 - نرسل لهم تفاصيل حول هذه الثغرات الأمنية
2021-12-08 - تم إصدار All In One SEO 4.1.5.3
خاتمة
نوصيك بالتحقق من إصدار المكون الإضافي All In One SEO الذي يستخدمه موقعك ، وإذا كان ضمن النطاق المتأثر ، فقم بتحديثه في أقرب وقت ممكن!
في Jetpack ، نعمل بجد للتأكد من حماية مواقع الويب الخاصة بك من هذه الأنواع من الثغرات الأمنية. نوصي بأن يكون لديك خطة أمان لموقعك تتضمن فحص الملفات الضارة والنسخ الاحتياطي. Jetpack Security هو أحد خيارات الأمان الرائعة في WordPress لضمان أمان موقعك وزوارك.
الاعتمادات
الباحث الأصلي: مارك مونباس
شكرًا لبقية فريق Jetpack Scan على التعليقات والمساعدة والتصحيحات.