CVE-2017-5487分析

针对Content Injection Vulnerability in WordPress进行复现并分析。
success.png

漏洞简述

由于WordPress4.7.0-4.7.1REST API接口权限判断不合理导致命令注入。

漏洞分析

复现过程

下载POC脚本,运行即可。

原理分析

查看/wp-includes/rest-api/endpoints/class-wp-rest-posts-controller.php的第90行,发现参数ID的值会被过滤成数字。发现REST API在管理访问时,其会在正则表达式之前优先考虑$_GET和$_POST的值。例如: /wp-json/wp/v2/posts/1234?id=12345helloworld,REST API会将其ID参数设置成12345helloworld。
在99行使用了update_item和update_item_permissions_check。
1.png
查看593行的update_item_permissions_check函数,其将ID值传递给get_post()函数。这个函数功能用来检查帖子是否存在、是否有权限。如果发送的ID没有对应的post,就可以绕过权限检查,并允许继续执行update_item方法。
2.png
由于使用get_instance()静态方法来获取post,造成get_post()在特定情况下无法找到对应的ID。
查看/wordpress/wp-includes/class-wp-post.php第210行,发现需全部使用数字,例如123ABC将会导致获取post失败。有一个细节,其会将ID参数在传递给get_post之前会将其转换成整数。
3.png
PHP语言中做类型的比较和转换时,其会返回整数。例如
4.png
例如提交一个请求为/wp-json/wp/v2/posts/123?id=456ABC,PHP会将其ID返回456。由于456ABC并不是纯数字会导致/wordpress/wp-includes/class-wp-post.php获取post_id失败。在流程进入权限检查时update_item_permissions_check判断其没有对应的post绕过权限判断,进行更新操作update_item。最终导致ID为456被修改。
在受影响的WordPress版本中REST API接口是默认开放的。任何用户都可以利用该漏洞修改任意文章,只需要指定修改文章的ID即可。
修改前:
5.png
修改后:
6.png

复现注意事项

在复现时如果遇到id is not of type integer报错信息,有可能是因为版本不对。最新版本的4.7.2已经对该漏洞进行修复。
11.png
12.png

修复建议

升级WordPress至4.7.2及以上。