Wordpress它是世界上 最常用的开源CMS之一,在允许开发者自己构建插件和主题来管理网站的时候,由于它的便利性而被大量使用,wordpress的核心会提供插件/主题的功能来调用和使用wordpress提供的数据格式、查询数据库等功能。
WordPress的核心部分发现了一个SQL Injection漏洞,最近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插件和主题数量众多,发现相当多的插件和主题受到该漏洞的影响(authen 和 unauthen)。
相关链接:
https://wordpress.org/news/2022/01/wordpress-5-8-3-security-release/
https://cognn.medium.com/sql-injection-in-wordpress-core-zdi-can-15541-a451c492897
原文始发于微信公众号(Khan安全攻防实验室):WordPress 核心代码 SQL注入 (CVE-2022–21661)