WordPress 5.8.3 SQL 注入漏洞 (CVE-2022–21661)
作者:Sec-Labs | 发布时间: | 更新时间:
介绍
wordpress,它是世界上 最常用的开源CMS之一。在允许开发者自己构建插件和主题来管理网站的时候,由于它的便利性而被大量使用,wordpress的核心会提供插件/主题的功能来调用和使用wordpress提供的数据格式、查询数据库等功能, ... 在wordpress提供的类中,我们发现WP提供的查询DB的类中有SQL Injection错误:WP_Query。
错误分析
在 5.8.3 版本中,wordpress 已经修复了这个错误,比较提交更改可以在处理变量之前clean_query添加检查的函数中看到。$query['field']$query['terms']

函数clean_query从 调用get_sql_for_clause。阅读该函数的代码会发现该函数的工作是为 SQL 查询中的条件创建子句,具体而言,它的工作是处理接收到的数据,将这些数据组合成 SQL 查询中的条件。将其返回给父函数。所以我们可以控制这个函数的返回数据,也就是说我们可以控制SQL查询和执行SQL注入。

回到函数clean_query,当没有做这个改变时,默认情况下$query['terms']只会删除in 的值,然后调用 to $this->transform_query( $query, 'term_taxonomy_id' );。
为避免下降if,它$query['taxonomy']需要为空或is_taxonomy_hierarchical返回 false的值。

该函数transform_query将检查$query['field'] == $resulting_field,如果为真,则返回并且不做进一步处理,所以如果变量$query['field']是term_taxonomy_id,我们可以在不改变变量值的情况下退出函数$query['terms']。
(这里的比较是使用==了Loose comparisons的漏洞,在某些情况下这个错误可以用来随意创建一个条件句)。

退出函数后,码流回到原位会调用clean_query函数get_sql_for_clause,变量的值$query['terms']会直接作为SQL查询条件,导致SQL注入。

所以总而言之,要发生 SQL 注入,必须满足两个条件:
$query['field']成为term_taxonomy_id$query['taxonomy']空的或is_taxonomy_hierarchical($query['taxonomy']) === false
流导致以下错误:

开发
虽然这是wordpress核心的错误,但是wordpress核心使用的方式并没有触发错误,所以我转而寻找插件和主题的错误。WP_Query当您要查询数据库时,插件/主题将调用该类,从源代码中了解错误的方法是在您使用它时,WP_Query($data)并且 $data 是您可以控制的。
例如new WP_Query(json_decode($_POST['query_vars'])),有效负载将具有以下形式:
query_vars={"tax_query":{"0":{"field":"term_taxonomy_id","terms":["<inject>"]}}} 或者query_vars={"tax_query":{"0":{"taxonomy":"nav_menu","field":true,"terms":["<inject>"]}}}
在构建错误测试环境时,启用 DEBUG 功能将可以通过基于错误的方式检测 SQL 注入:

得出结论
在 wordpress 的补丁中$query['field']首先添加了检查,否则它将转换$query['terms']为整数,因此 SQLI 不会发生。
由于wordpress插件和主题众多,我们团队只专注于寻找下载量> 100k(免费版)的,除了付费插件/主题或下载量< 100k,我们没有时间继续。
结果,发现相当多的插件和主题受到该漏洞的影响(authen 和 unauthen)。
我的团队在 9 月底向 ZDI 报告了此漏洞,3 个月后,Wordpress 在其核心中修复了该漏洞。具体来说,时间线如下:

感谢阅读^^。