导语:研究人员发现WordPress创建博客的方式存在逻辑漏洞,攻击者利用该漏洞可以访问只有管理员才可以访问的特征。这会导致WordPress内核产生存储型XSS和对象注入等漏洞。

研究人员发现WordPress创建博客的方式存在逻辑漏洞,攻击者利用该漏洞可以访问只有管理员才可以访问的特征。这会导致WordPress内核产生存储型XSS和对象注入等漏洞。

影响

WordPress是博客软件的核心,允许用户创建和发布博客。随着时间的推移,产生了不同的post类型,比如页面和图像、视频等。插件可以注册新的post类型,比如产品和联系人表单。根据插件注册的post type的类型,可以提供不同的特征。比如通讯录form插件可能允许用户用文件上传域来常见一个联系人form。创建联系人form的用户可以定义允许上传的文件类型。恶意用户可以允许上传php文件,然后在站点上执行任意代码。但这并不是一个问题,因为插件可以限制对post类型的访问。下面要讲的权限提升就允许低权限用户绕过wordpress应用的安全检查,并创建任意类型的post,误用定制的post类型的特征。最终导致WordPress core产生存储型XSS和对象注入漏洞。根据安装的插件,还有更严重的漏洞可以利用。

技术背景

为注册新的post类型,插件必须要用新的post类型和一些meta信息来调用register_post_type()。

image.png

为什么定制的post类型是安全的?

每个post类型都有自己的编辑页面,比如 example.com/wordpress/wp-admin/?page=example_post_type_editor

image.png

图1: post type为联系人表单,只有管理员可以访问该页面

如果插件开发者决定只有管理员可以使用插件的post类型,那么就可以检查如果用户是不是管理员,然后执行。

image.png

WordPress post提交

虽然所有注册的post类型都有自己的编辑页,但是都可以用WordPress post提交API,用WordPress函数wp_write_post()插入和更新post。该函数的输入类型为$_POST[‘post_type’], $_POST[‘post_title’], $_POST[‘post_content’],因此知道如何处理post。
在WordPress post提交过程中,WordPress必须首先了解用户想要编辑已有的post还是创建一个新的post。因此WordPress要检查用户是否发送过该post的ID。WordPress允许$_GET[‘post’]或$_POST[‘post_ID’]。如果ID存在,用户就可以用已有的ID去编辑post;如果ID不存在,就是要创建新的post。

image.png

然后WordPress要确定用户在创建那种post类型。如果post ID已经发送了,WordPress就会从wp_posts table中的数据库中取出post_type列。如果用户想要创建新的post,目标post类型应该是 $_POST[‘post_type’]。

image.png

WordPress在知道了用户要创建或编辑的post的post类型后,会检查用户是否有权限使用该post类型。这一过程是通过一个只能从编辑页获得的随机数来确认的。用随机数来确认的代码如下:

image.png

如果$post_type 是post,$nonce_name就是add-post。如果$post_type是example_post_type, $nonce_name就是add-example_post_type。随机数只能由可以创建这些post类型的用户获取,因为只有这些用户可以访问该post类型的编辑页,这也是唯一严重获得随机数的方法。

WordPress的失败

虽然低权限的攻击者不能访问该页面和示例post类型的随机数,但攻击者仍然可以获取正常post的随机数。也就是说攻击者可以讲post ID设置为有post type post的post,这样就可以绕过随机数验证。

image.png

但是该方法只能更新已有的post,无法覆写新的post的post_type。如果post ID已经存在了,WordPress就会在更新post之前从参数中移除post_type。
但WordPress只会移除设置了$_POST[‘post_ID’]的$post_type参数。攻击者就可以通过 $_POST[‘post_ID’]或$_GET[‘post’]发送一个post ID。如果攻击者通过$_GET[‘post’]发送了post ID:
1、WordPress就会看到一个设置了的post ID,然后从数据库中拿出其post type。
2、WordPress会检查攻击者是否为该post type发送了有效的随机数。
3、通过随机数检查后,WordPress会决定应该调用wp_update_post()还是wp_insert_post()。这一过程是通过设置$_POST[‘post_ID’]实现的。如果设置了,就调用wp_update_post并移除$post_type参数,这样攻击者就不能覆写post type了。如果没有设置,WordPress就调用wp_insert_post(),并用$_POST[‘post_type’]作为新post的post type。

因为WordPress没有检查第3步的$_GET[‘post’],攻击者可以绕过随机数验证,并且创建一个任意post type的新post。

image.png

image.png

利用:通过Contact Forms 7读取wp-config.php

因此,低权限的用户也可以滥用该bug来创建任意类型的post,对网站的影响依赖于安装的插件以及安装的插件提供的post type的特征。
比如,攻击者可以以contributor的角色滥用WordPress主流插件Contact Form 7的特征来读取目标网站wp-config.php文件的内容。该文件中含有数据库凭证和加密密钥。
在Contact Forms 7 v5.0.3以上版本中,可以设置本地文件附件。管理员创建了联系人表单。并讲用户输入的所有数据都发送给管理员。
也就是说攻击者简单创建一个新的联系人表单,设置本地文件附件到../wp-config.php,设置邮箱到数据要发送的邮箱,提交表单、然后读取重要WordPress文件的内容。

补丁

image.png

XMLRPC和REST API

因此可以通过WordPress的XMLRPC和REST API创建post,这并不会执行特定post type的随机数验证。但是通过这些API创建post,但是不能设置任意的post meta field。插件中的大多数漏洞都是可以通过设置post meta域进行利用的。

总结

攻击者可以以低权限的用户角色来创建本来没有权限访问的post type的post。攻击者因此可以访问本来只有管理员才可以访问的特征。研究人员在WordPress最流行的5个插件中供发现了2个漏洞。研究人员估计有上千个插件存在漏洞。而且WordPress的内部post type还被发现有存储型XSS和对象注入漏洞,存储型XSS可以通过点击劫持攻击触发,一旦JS执行后,整个网站都会被接管。

源链接

Hacking more

...