多合一 SEO 插件版本 4.1.5.3 中修復的嚴重漏洞

已發表: 2021-12-15

在對 All In One SEO 插件進行內部審核期間,我們發現了一個 SQL 注入漏洞和一個權限提升漏洞。

如果被利用,SQL 注入漏洞可能允許攻擊者訪問受影響站點數據庫中的特權信息(例如,用戶名和散列密碼)。

我們發現的權限提升錯誤可能會授予不良行為者訪問他們不應該訪問的受保護 REST API 端點的權限。 這最終可以使具有低權限帳戶的用戶(如訂閱者)能夠在受影響的站點上執行遠程代碼執行。

我們通過電子郵件向插件作者報告了這些漏洞,他們最近發布了 4.1.5.3 版本來解決這些問題。 我們強烈建議您更新到最新的插件版本,並在您的站點上安裝成熟的安全解決方案,例如 Jetpack Security。

細節

插件名稱:多合一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 後門並在服務器上執行惡意代碼。

經過身份驗證的 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 路由訪問,在將所述輸入附加到 SQL 查詢之前使用 wpdb::esc_like() 轉義用戶輸入。 由於此方法並非旨在轉義引號,因此攻擊者仍然可以注入它們並強制查詢從數據庫中洩漏敏感信息,例如用戶憑據。

雖然此端點並不意味著具有低權限帳戶的用戶可以訪問,但上述權限提升攻擊向量使他們有可能濫用此漏洞。

時間線

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 團隊的其他成員提供反饋、幫助和更正。