mysql 帐户枚举漏洞_Wordpress < 4.7.1用户名枚举漏洞分析(CVE-2017-5487) | 绿盟科技技术博客...

本文介绍了WordPress 4.7.0版本中的REST API越权漏洞,允许攻击者绕过权限检查获取用户信息。该漏洞可通过调用REST API接口进行利用,影响WordPress 4.7.0版本。文章详细分析了漏洞的成因、利用过程,并提供了修复建议。
摘要由CSDN通过智能技术生成

阅读:

4,380

WordPress是一种使用PHP语言开发的博客平台,用户可以在支持PHP和MySQL数据库的服务器上架设属于自己的网站。也可以把 WordPress当作一个内容管理系统来使用。

WordPress 在4.7.0版本之后将REST API插件集成到默认功能之中。REST API为WordPress的使用者提供了一个方便快捷的管理接口。在WordPress 4.7.0版本中,存在着一个越权漏洞,成功的利用这个漏洞,可以绕过管理员权限查看wordpress上所有发布过文章的用户信息列表。

影响版本

WordPress 4.7.0

漏洞分析

在正式的漏洞分析开始前,先来简单介绍下REST API的使用。官网给出的介绍如下:

8e3b2fb07a33dc8ff2c63ddb38ba65b5.png

具体使用详情请参照REST API Handbook

漏洞利用

先从exploitdb上面提供的poc入手

https://www.exploit-db.com/exploits/41497/

9dd6fc316167c1bad9a78baa511fffee.png

POC看起来比较简单,就是调用了wordpress的rest api接口进行users查询,但是在笔者的环境中,需要对这个poc进行一点小改动,如下图,需要加上一个index.php,否则找不到目录。

87ccb60010c3935ccde415492e23b69b.png

接下来看一下代码, 请求首先进入get_items_permissions_check模块进行权限检查/**

* Permissions check for getting all users.

*

* @since 4.7.0

* @access public

*

* @param WP_REST_Request $request Full details about the request.

* @return true|WP_Error True if the request has read access, otherwise WP_Error object.

*/

public function get_items_permissions_check( $request ) {

// Check if roles is specified in GET request and if user can list users.

if ( ! empty( $request['roles'] ) && ! current_user_can( 'list_users' ) ) {

return new WP_Error( 'rest_user_cannot_view', __( 'Sorry, you are not allowed to filter users by role.' ), array( 'status' => rest_authorization_required_code() ) );

}

if ( 'edit' === $request['context'] && ! current_user_can( 'list_users' ) ) {

return new WP_Error( 'rest_forbidden_context', __( 'Sorry, you are not allowed to list users.' ), array( 'status' => rest_authorization_required_code() ) );

}

if ( in_array( $request['orderby'], array( 'email', 'registered_date' ), true ) && ! current_user_can( 'list_users' ) ) {

return new WP_Error( 'rest_forbidden_orderby', __( 'Sorry, you are not allowed to order users by this parameter.' ), array( 'status' => rest_authorization_required_code() ) );

}

return true;

}

看上面的注释可以大概了解这个函数的功能:当请求users参数时,用来检查请求是否有读的权限,否则爆出WP_Error错误。

这个函数一共有三个if判断,这三个if判断都是由两部分组成的,每一个后半部分都是不可控的current_user_can( ‘list_users’ ),经测试,它的值还为false,所以只能使三个if得可控的前半部分不为真,才能最终绕过判定。

我们var_dump下这三个$request值

fcfa4fe1ee43aaa9e40a43ed0589f5f6.png

有意思的事情发生了,我们什么事情也没做,竟然完美的避开了权限检查的三个判定,接下来进入下个环节get_items函数,检索所有的用户。/**

* Retrieves all users.

*

* @since 4.7.0

* @access public

*

* @param WP_REST_Request $request Full details about the request.

* @return WP_REST_Response|WP_Error Response object on success, or WP_Error object on failure.

*/

public function get_items( $request ) {

。。。。。。。。。

/**

* Filters WP_User_Query arguments when querying users via the REST API.

*

* @link https://developer.wordpress.org/reference/classes/wp_user_query/

*

* @since 4.7.0

*

* @param array $prepared_args Array of arguments for WP_User_Query.

* @param WP_REST_Request $request The current request.

*/

$prepared_args = apply_filters( 'rest_user_query', $prepared_args, $request );

$query = new WP_User_Query( $prepared_args );

$users = array();

foreach ( $query->results as $user ) {

$data = $this->prepare_item_for_response( $user, $request );

$users[] = $this->prepare_response_for_collection( $data );

}

$response = rest_ensure_response( $users );

。。。。。。。。。。。

上面代码省略了些内容,前半部分省略的是一些相关的参数配置,然后读到注释部分了解到下面参数经过过滤,就要进入WP_User_Query()部分了,我们通过给出的链接看一下查询部分的WP_User_Query()是怎么解释的

e89875fbc3f3b497b7b89bd55062dfff.png

在跟进WP_User_Query中我们可以看到一个构造方法

66723880e00f7ddd08ffe504a1772035.png

在这里可以看到如果$query不为空,则先调用prepare_query(),接着再执行$this->query()

我们看一下prepare_query()是做什么的。

8fac01c20724a607ddcfb5b86f410e65.png

看注释可以了解到,它是准备查询变量的作用,可以看做是对变量的预处理。

接下来往后看$this->query();。跟进query()函数看看它最终执行了什么。/**

* Execute the query, with the current variables.

*

* @since 3.1.0

*

* @global wpdb $wpdb WordPress database abstraction object.

*/

public function query() {

global $wpdb;

$qv =& $this->query_vars;

$this->request = "SELECT $this->query_fields $this->query_from $this->query_where $this->query_orderby $this->query_limit";

if ( is_array( $qv['fields'] ) || 'all' == $qv['fields'] ) {

$this->results = $wpdb->get_results( $this->request );

} else {

$this->results = $wpdb->get_col( $this->request );

}

query()函数使用当前变量来执行查询,下面$this->request构造了一个sql查询语句,我们查看下它的值SELECT SQL_CALC_FOUND_ROWS wp_users.* FROM wp_users WHERE 1=1 AND wp_users.ID IN ( SELECT DISTINCT wp_posts.post_author FROM wp_posts WHERE wp_posts.post_status = 'publish' AND wp_posts.post_type IN ( 'post', 'page', 'attachment' ) ) ORDER BY display_name ASC LIMIT 0, 10

可以看出这里可以查询的wp_users信息是有约束条件的,这里可以查询的用户必须满足发表过‘publish’类型的文章,并且类型还要是‘post’、‘page’、‘attachment’中的一个

我们分别看一下wp_users表和wp_posts表

8b89d5cb82a01f4ac65eef9754f0c574.png

wp_posts表

887f0235fe18f183c75239b12948cef1.png

wp_users表

最终通过api返回的用户信息

0afe67e49b62c8c3ba75e125d8aab47b.png

修补防御

升级wordpress至最新版本。

如果您需要了解更多内容,可以

加入QQ群:570982169

直接询问:010-68438880

这题其实和之前的题目一样,只是文法不同,我们可以按照相同的步骤来构造规范 LR 项集族和 LALR 项集族。 首先,我们需要构造出这个文法的 LR(0) 项集族: | I | CLOSURE(I) | GOTO(I, X) | |---|-----------|------------| | 0 | {S' -> .S} | | | 1 | {S' -> S., S -> .SS+, S -> .SS*, S -> .a} | | | 2 | {S -> SS.+, S -> SS.*} | | | 3 | {S -> a.} | | 接下来,我们使用 LR(0) 项集族中项目集的核心来构造出规范 LR(1) 项集族。对于这个文法来说,LR(0) 项集族中的每个项目集都是 LR(1) 项集族中的核心,所以我们直接把 LR(0) 项集族中的项目集放入规范 LR(1) 项集族中: | I | CLOSURE(I) | GOTO(I, X) | |---|-----------|------------| | 0 | {S' -> .S} | | | 1 | {S' -> S., S -> .SS+, S -> .SS*, S -> .a} | | | 2 | {S -> SS.+, S -> SS.*} | | | 3 | {S -> a.} | | 现在,我们需要合并一些项目集。对于这个文法来说,项目集 2 和项目集 3 可以合并,因为它们的状态集合相同,且它们的向前看符号也相同,都是 $+$ 或 $*$ 或 $a$。所以,我们把它们合并成一个项目集: | I | CLOSURE(I) | GOTO(I, X) | |---|-----------|------------| | 0 | {S' -> .S} | | | 1 | {S' -> S., S -> .SS+, S -> .SS*, S -> .a} | | | 2 | {S -> SS.+ | SS.* | a.} | | 现在,我们需要构造出这个文法的 LALR(1) 项集族。我们需要检查每个项目集的向前看符号,如果两个项目集状态相同,且它们的向前看符号集合也相同,那么我们就可以合并它们。在这个文法中,所有项目集的向前看符号都是一样的,都是 $+$ 或 $*$ 或 $a$,所以我们不需要合并任何项目集。因此,规范 LR(1) 项集族就是上面构造出来的 LALR(1) 项集族: | I | CLOSURE(I) | GOTO(I, X) | |---|-----------|------------| | 0 | {S' -> .S} | | | 1 | {S' -> S., S -> .SS+, S -> .SS*, S -> .a} | | | 2 | {S -> SS.+ | SS.* | a.} | | 这就是这个文法的规范 LR 项集族和 LALR 项集族。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值