1. 首页
  2. 代码审计

BBPress未经身份验证的提权漏洞分析

【推荐学习】暗月渗透测试培训 十多年渗透经验,体系化培训渗透测试 、高效学习渗透测试,欢迎添加微信好友aptimeok 咨询。

前言

BBPress是一款强大的WordPress论坛插件,目前BBPress被安装在超过30万个WordPress站点上。最近BBPress<=2.6.4的版本中被曝出了一个未经身份验证的权限提升漏洞,CVSS评分为9.8。通过利用该漏洞,可以将新用户注册为BBPress论坛的管理员,从而能够进行创建/删除论坛活动、导入/导出论坛用户以及创建版主等操作。本文对该漏洞进行了详细分析。

实验环境 

1.测试工具:BurpSuite v2.1
2.目标主机:Debian9.6 x64
3.软件版本:WordPress 5.2.2
4.插件版本:BBPress2.6.4

漏洞分析

1.在分析了源码之后,发现在用户注册时调用了过滤器钩子函数add_filter,其中挂载回调函数的过滤器名称为signup_user_meta,过滤器应用时调用的回调函数为bbp_user_add_role_to_signup_meta,详细代码如下:

add_filter( 'signup_user_meta', 'bbp_user_add_role_to_signup_meta', 10 );

2.分析步骤1在add_filter中被调用的函数bbp_user_add_role_to_signup_meta,该函数的详细代码如下:

function bbp_user_add_role_to_signup_meta( $meta = array() ) {

	$forum_role = isset( $_POST['bbp-forums-role'] )
		? sanitize_key( $_POST['bbp-forums-role'] )
		: bbp_get_default_role();

	$roles = array_keys( bbp_get_dynamic_roles() );

	if ( empty( $forum_role ) || ! in_array( $forum_role, $roles, true ) ) {
		return $meta;
	}

	$meta['bbp_new_role'] = $forum_role;

	return $meta;
}

2.1函数bbp_user_add_role_to_signup_meta使用POST方式获取参数bbp-forums-role的值,若用户通过POST方式传入了bbp-forums-role值,那么将其赋值给变量$forum_role;若未有bbp-forums-role值传入,那么将BBPress默认的用户角色赋值给$forum_role;

2.2该函数调用bbp_get_dynamic_roles()函数,获取BBPress预定义角色的数组;

2.3接着检测$forum_role是否为空,并且检测其是否在BBPress预定义角色的数组中;

2.4由此可以推测,要破坏程序的正常逻辑,只要将有效的用户角色赋值给bbp-forums-role,然后通过POST方式传递给WordPress站点即可。

3.函数bbp_get_dynamic_roles() 迭代BBPress角色,然后将其创建为标准化数组,再通过apply_filters创建一个名为bbp_get_dynamic_roles的过滤器,详细代码如下:

function bbp_get_dynamic_roles() {

	$to_array = array();
	$roles    = bbpress()->roles;

	foreach ( $roles as $role_id => $wp_role ) {
		$to_array[ $role_id ] = (array) $wp_role;
	}

	return (array) apply_filters( 'bbp_get_dynamic_roles', $to_array, $roles );
}

4.函数bbp_get_keymaster_role()将bbp_get_keymaster_role角色设置为bbp_keymaster,这表明我们只有在post请求的末尾添加bbp_keymaster,才能将定制的用户成功注册为bbp_keymaster用户,最终获取BBPress的最高等级权限,该函数的详细代码如下:

function bbp_get_keymaster_role() {

	return apply_filters( 'bbp_get_keymaster_role', 'bbp_keymaster' );
}

漏洞修复

1.此漏洞在2.6.5版本中得到修复,修复后代码的不同之处主要在于函数bbp_user_add_role_to_signup_meta,其中新增调用了函数bbp_validate_registration_role( $to_validate ),对POST传入的bbp-forums-role参数值进行了过滤,详细代码如下:

function bbp_user_add_role_to_signup_meta( $meta = array() ) {

	if ( ! empty( $meta['bbp_new_role'] ) ) {
		return $meta;
	}

	$to_validate = ! empty( $_POST['bbp-forums-role'] ) && is_string( $_POST['bbp-forums-role'] )
		? sanitize_key( $_POST['bbp-forums-role'] )
		: '';

	$valid_role = bbp_validate_registration_role( $to_validate );

	if ( bbp_has_errors() ) {
		return $meta;
	}

	$meta['bbp_new_role'] = $valid_role;

	return $meta;
}

2.函数bbp_validate_registration_role检测当前是否处于WordPress后台控制面板中,并且当前用户是否具有创建用户的权限,若这两个条件同时为True,那么可以创建任意角色的用户;否则只能创建默认角色的用户(默认角色为bbp_participant)。详细代码如下所示:

function bbp_validate_registration_role( $to_validate = '' ) {

	$retval = bbp_get_default_role();

	if ( is_admin() && current_user_can( 'create_users' ) ) { 
		$retval = $to_validate;   
	}

	return bbp_validate_signup_role( $retval );  
}

3.通过函数bbp_get_default_role可以获取默认的用户角色,详细代码如下所示:

function bbp_get_default_role( $default = 'bbp_participant' ) {

	return apply_filters( 'bbp_get_default_role', get_option( '_bbp_default_role', $default ) );
}

4.函数bbp_validate_registration_role在末尾调用了bbp_validate_signup_role( $retval )函数,函数bbp_validate_signup_role( $retval )主要是通过调用bbp_is_valid_role函数来验证用户角色是否合法,详细代码如下:

function bbp_validate_signup_role( $to_validate = '' ) {

	$retval = '';

	if ( empty( $to_validate ) ) {
		bbp_add_error( 'bbp_signup_role_empty', __( 'ERROR: Empty role.', 'bbpress' ) );
	}

	if ( ! bbp_is_valid_role( $to_validate ) ) {
		bbp_add_error( 'bbp_signup_role_invalid', __( 'ERROR: Invalid role.', 'bbpress' ) );
	}

	if ( ! bbp_has_errors() ) {
		$retval = $to_validate;
	}

	return (string) apply_filters( 'bbp_validate_signup_role', $retval, $to_validate );
}

5.函数bbp_is_valid_role的详细代码如下:

function bbp_is_valid_role( $role = '' ) {

	$retval = false;

	if ( ! empty( $role ) && is_string( $role ) ) {

		$roles = array_keys( bbp_get_dynamic_roles() );

		if ( ! empty( $roles ) ) {

			$retval = in_array( $role, $roles, true );
		}
	}

	return (bool) apply_filters( 'bbp_is_valid_role', $retval, $role );
}

总结

关于BBPress<=2.6.4版本中的未经身份验证的权限提升漏洞的分析与修复就到这里,建议及时将BBPress升级到最新版本2.6.5。

本文来自本文作者:Neroqi, 转载自FreeBuf.COM,经授权后发布,本文观点不代表立场,转载请联系原作者。

联系我们

400-800-8888

在线咨询:点击这里给我发消息

邮件:admin@example.com

工作时间:周一至周五,9:30-18:30,节假日休息