ช่องโหว่ที่ร้ายแรงแก้ไขในปลั๊กอิน SEO ทั้งหมดในเวอร์ชันเดียว 4.1.5.3

เผยแพร่แล้ว: 2021-12-15

ในระหว่างการตรวจสอบภายในของปลั๊กอิน All In One SEO เราพบช่องโหว่ของ SQL Injection และจุดบกพร่องในการยกระดับสิทธิ์

หากถูกโจมตี ช่องโหว่ SQL Injection อาจทำให้ผู้โจมตีสามารถเข้าถึงข้อมูลพิเศษจากฐานข้อมูลของไซต์ที่ได้รับผลกระทบ (เช่น ชื่อผู้ใช้และรหัสผ่านที่แฮช)

บั๊กการยกระดับสิทธิ์ที่เราค้นพบอาจทำให้ผู้ไม่ประสงค์ดีเข้าถึงปลายทาง 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-ID: 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 API ที่ได้รับการร้องขอเพื่อให้ทราบว่าสิทธิ์ใดที่จะตรวจสอบเพื่อบังคับใช้ในคำขอที่กำหนด เนื่องจากไม่ได้คำนึงถึงความจริงที่ว่า WordPress ถือว่าเส้นทาง REST API เป็นสตริงที่ไม่คำนึงถึงขนาดตัวพิมพ์ การเปลี่ยนอักขระตัวเดียวเป็นตัวพิมพ์ใหญ่จะเป็นการข้ามขั้นตอนการตรวจสอบสิทธิ์โดยสมบูรณ์

สิ่งนี้น่ากังวลเป็นพิเศษเพราะจุดปลายของปลั๊กอินบางตัวค่อนข้างอ่อนไหว ตัวอย่างเช่น จุด aioseo/v1/htaccess สามารถเขียน .htaccess ของไซต์ใหม่ด้วยเนื้อหาที่กำหนดเองได้ ผู้โจมตีสามารถใช้คุณลักษณะนี้ในทางที่ผิดเพื่อซ่อน .htaccess backdoors และรันโค้ดที่เป็นอันตรายบนเซิร์ฟเวอร์

การฉีด SQL ที่รับรองความถูกต้อง

เวอร์ชันที่ได้ รับผลกระทบ: ทุกเวอร์ชันระหว่าง 4.1.3.1 ถึง 4.1.5.2 โดยรวม
CVE-ID: 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() ซึ่งสามารถเข้าถึงได้ผ่านเส้นทาง /wp-json/aioseo/v1/objects REST API เลี่ยงการป้อนข้อมูลของผู้ใช้โดย ใช้ 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 ที่ยอดเยี่ยมเพื่อให้แน่ใจว่าไซต์และผู้เยี่ยมชมของคุณปลอดภัย

เครดิต

นักวิจัยต้นฉบับ: Marc Montpas

ขอขอบคุณทีมงาน Jetpack Scan ที่เหลือสำหรับความคิดเห็น ความช่วยเหลือ และการแก้ไข