术语

WordPress

WordPress是一个以PHP和MySQL为平台的自由开源的博客软件和内容管理系统。WordPress具有插件架构和模板系统。截至2018年4月,排名前1000万的网站中超过30.6%使 用WordPress。WordPress是最受欢迎的网站内容管理系统。全球有大约30%的网站都是使用WordPress架设网站的。

Rest-API

REST API 也称为 RESTful API,是遵循 REST 架构规范的应用编程接口。REST 是表述性状态传递的英文缩写。

SQL注入

 布尔(Boolean)型是计算机里的一种数据类型,只有True(真)和False(假)两个值。一般也称为逻辑型。页面在执行sql语句后,只显示两种结果,这时可通过构造逻辑表达式的sql语句来判断数据的具体内容。。

WooCommerce

WooCommerce 一款基于 WordPress 的开源电子商务插件。时至今日已变成全球最流行的电商系统,而 WooCommerce 中文站是 薇晓朵 建立的一个中文本地化项目。它是为使用WordPress的小型或大型在线商人而设计的。该插件于2011年9月27日发布,以其易于安装和定制以及免费的基础产品而迅速流行。WooCommerce在WordPress拥有5百万+的用户量。

利用条件

该漏洞的利用条件需要满足以下两个需求其中之一即可:

  • WooCommerce(3.3-5.5.0)
  • WooCommerce Blocks(2.5-5.5.0)

    POC

    Payload(布尔注入)

漏洞分析

根据官方发布的安全更新通告来看,该漏洞影响了大概90多个版本的插件,然后去官方源码库查看代码提交记录,发现在"woocommerce/tags/5.3.1/packages/woocommerce-blocks/src/StoreApi/Utilities/ProductQueryFilters.php"存在sql注入点,在修复后,会调用 wc_sanitize_taxonomy_name 以及 esc_sql 来防止注入。

-w1836

根据该文件的路径去反向推一下访问地址,首先全局搜索该逻辑所在的函数名get_attribute_counts在哪里进行了调用。

-w1466

然后打开该文件(wp-content/plugins/woocommerce/packages/woocommerce-blocks/src/StoreApi/Routes/ProductCollectionData.php),发现当前文件中有get_path()方法,其所对应的就是接口的访问路径,然后拼接到url中即可,最终该文件的访问地址为:
http://wp.local:8888/wp-json/wc/store/products/collection-data,接着继续找漏洞调用点get_attribute_counts在哪里进行了调用,发现在get_route_response中对该漏洞函数进行了调用。
-w885

根据阅读代码发现,需要给定相对应的请求参数calculate_attribute_counts才会进入该判断,根据在 get_collection_params中对 calculate_attribute_counts 参数的定义,可以直接反推出来访问的地址:

-w1066

可以看到其接收的参数类型为数组类型,直接在上面反推出来的当前文件访问地址后面加数组访问参数即可给 $request['calculate_attribute_counts'] 赋值.

接下来就是构造poc了,在对官方修复的文件 wp-content/plugins/woocommerce/packages/woocommerce-blocks/src/StoreApi/Utilities/ProductQueryFilters.php 中86行进行深入分析,对其调用的wc_sanitize_taxonomy_name函数进行查找,全局搜索发现存在的位置为: wp-content/plugins/woocommerce/includes/wc-formatting-functions.php,其内容为:

/**
 * Sanitize taxonomy names. Slug format (no spaces, lowercase).
 * Urldecode is used to reverse munging of UTF8 characters.
 *
 * @param string $taxonomy Taxonomy name.
 * @return string
 */
function wc_sanitize_taxonomy_name( $taxonomy ) {
    return apply_filters( 'sanitize_taxonomy_name', urldecode( sanitize_title( urldecode( $taxonomy ) ) ), $taxonomy );
}

可以看到其返回的结果的核心是调用sanitize_title方法,该方法在官方解释如下,

-w780

在返回结果后,并未对结果进行二次处理,在下面直接调用sql语句拼接了进去,

-w1542

发现其最终导致的问题点,其根本原因是自行封装的函数只调用了 sanitize_title 函数,该函数虽然能过滤一些字符,但是对于最终查询sql语句之前却未调用 esc_sql 函数,从而导致SQL注入。

-w1857

最后修改:2021 年 11 月 22 日
如果觉得我的文章对你有用,请随意赞赏