深度刨析 Wordpress 的 SQL 注入 (CVE-2022–21661)
遵纪守法
任何个人和组织使用网络应当遵守宪法法律,遵守公共秩序,尊重社会公德,不得危害网络安全,不得利用网络从事危害国家安全、荣誉和利益
漏洞描述
Wordpress,它是世界上使用最多的开源 CMS 之一。在允许开发者自己构建插件和主题来管理网站时,使用我们的许多便捷功能,wordpress的核心会提供插件/主题调用和使用wordpress函数的功能,如数据格式、查询数据库等许多选项在提供的众多wordpress ma类中,我们在提供查询DB的WP服务器类中发现SQL Injection错误:WP_Query。
风险等级
高危
影响版本
wordpress < 5.8.3
漏洞分析
在 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的值,然后再调用到$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比较的漏洞,在某些情况下这个错误可以用来随意创建条件句)。
函数逃逸后,返回原位的代码流会调用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核心的bug,但是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注入:
修复方案
目前厂商已发布升级补丁以修复漏洞,补丁获取链接:
https://github.com/WordPress/wordpress-develop/security/advisories/GHSA-6676-cqfm-gw84