多合一 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 团队的其他成员提供反馈、帮助和更正。