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

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

缺陷编号:wooyun-2014-079425

漏洞标题:大米CMS一处sql注入

相关厂商:damicms.com

漏洞作者: SLAckEr

提交时间:2014-10-19 23:23

修复时间:2015-01-17 23:24

公开时间:2015-01-17 23:24

漏洞类型:SQL注射漏洞

危害等级:中

自评Rank:10

漏洞状态:厂商已经确认

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

Tags标签:

4人收藏 收藏
分享漏洞:


漏洞详情

披露状态:

2014-10-19: 细节已通知厂商并且等待厂商处理中
2014-10-19: 厂商已经确认,细节仅向厂商公开
2014-10-22: 细节向第三方安全合作伙伴开放
2014-12-13: 细节向核心白帽子及相关领域专家公开
2014-12-23: 细节向普通白帽子公开
2015-01-02: 细节向实习白帽子公开
2015-01-17: 细节向公众公开

简要描述:

Rt

详细说明:

上次提交了一次,原因没说明白,,看了半天搞清楚了
\Web\Lib\Action\MemberAction.class.php文件中 147-163行

function modpage(){
self::is_login();
$aid = intval($_REQUEST['aid']);
if($_POST){
$_POST['status'] =0;
$_POST['title'] = htmlspecialchars($_POST['title']);
M('article')->where('dami_uid='.$_SESSION['dami_uid'].' and aid='.$aid)->save($_POST);
$this->assign('jumpUrl',U('Member/tougaolist'));
$this->success('修改成功~,请等待审核!');
}else{
$info = M('article')->where('dami_uid='.$_SESSION['dami_uid'].' and aid='.$aid)->find();
if(!$info){$this->error('记录不存在');exit();}
self::pub_class($info['typeid']);
$this->assign('info',$info);
}
$this->display();
}


可以看到aid这个参数aid被intval了
可是在我测试的时候,却发现aid这个参数是可以注入的。
再往上看。
开头

class MemberAction extends BaseAction
{
function _initialize() {
R('Public','head');
$member_menu = S('member_menu');
if(!is_array($member_menu)){
$member_menu = M('member_menu')->where('is_show=1')->order('drand')->select();
S('member_menu',$member_menu);
}
$this->assign('member_menu',$member_menu);
}


看下R这个函数
/Core/Common/functions.php

function R($module, $action, $app='@') {
$class = A($module, $app);
if ($class)
return call_user_func(array(&$class, $action));
else
return false;
}


再来看看A
/Core/Common/functions.php

function A($name, $app='@') {
static $_action = array();
if (isset($_action[$app . $name]))
return $_action[$app . $name];
$OriClassName = $name;
if (strpos($name, '.')) {
$array = explode('.', $name);
$name = array_pop($array);
$className = $name . 'Action';
import($app . '.Action.' . implode('.', $array) . '.' . $className);
} else {
$className = $name . 'Action';
import($app . '.Action.' . $className);
}
if (class_exists($className)) {
$action = new $className();
$_action[$app . $OriClassName] = $action;
return $action;
} else {
return false;
}
}


意思就是调用一个远程模块。
而回头看\Web\Lib\Action\MemberAction.class.php
R('Public','head');
结合函数A 和 R也就是调用了PublicAction前台公共action,里面的head函数。
我们再来看下head函数
/Web/Lib/Action/PublicAction.class.php

public function head()
{
//读取数据库和缓存
$type = M('type');
$article = M('article');
$config = F('basic','','./Web/Conf/');

//封装网站配置
$this->assign('config',$config);

//滚动公告
$data['status'] = 1;
$data['typeid'] = $config['noticeid'];
$roll=$article->where($data)->field('aid,title')->order('addtime desc')->limit($config['rollnum'])->select();
//处理标题:防止标题过长撑乱页面
foreach ($roll as $k=>$v)
{
$roll[$k]['title'] = msubstr($v['title'],0,20,'utf-8');
}
$this->assign('roll',$roll);

//网站导航
$menu = $type->where('ismenu=1')->order('drank asc')->select();
foreach( $menu as $k=>$v)
{
$menuson[$k] = $type->where('fid='.$v['typeid'].' AND drank <> 0')->order('drank asc')->select();
$menu[$k]['submenu'] = $menuson[$k];
}
$this->assign('menuson',$menuson);
$this->assign('menu',$menu);

//位置导航
$nav = '<a href="'.$config['siteurl'].'">首页</a>';
if(isset($_GET['aid']))
{
$typeid = $article->where('aid='.$_GET['aid'])->getField('typeid');
}
else
{
$typeid = intval($_GET['typeid']);
}
$typename = $type->where('typeid='.$typeid)->getField('typename');
$path = $type->where('typeid='.$typeid)->getField('path');
$typelist = explode('-',$path);
//拼装导航栏字符串
foreach($typelist as $v)
{
if($v==0) continue;
$s = $type->where('typeid='.$v)->getField('typename');
$nav.="&nbsp;&gt;&nbsp;<a href=\"".U('lists/'.$v)."\">{$s}</a>";
}
$nav.="&nbsp;&gt;&nbsp;<a href=\"".U('lists/'.$typeid)."\">{$typename}</a>";
$this->assign('nav',$nav);
//释放内存
unset($type,$article);
$this->assign('head',TMPL_PATH.cookie('think_template').'/head.html');
$this->assign('footer',TMPL_PATH.cookie('think_template').'/footer.html');
}


看这里

//位置导航
$nav = '<a href="'.$config['siteurl'].'">首页</a>';
if(isset($_GET['aid']))
{
$typeid = $article->where('aid='.$_GET['aid'])->getField('typeid');
}


这个aid没有经过过滤直接就带入到了sql中。
getField函数。
/Core/Lib/Think/Core/Model.class.php

public function getField($field,$condition='',$sepa=' ') {
if(empty($condition) && isset($this->options['where']))
$condition = $this->options['where'];
$options['where'] = $condition;
$options['field'] = $field;
$options = $this->_parseOptions($options);
if(strpos($field,',')) { // 多字段
$resultSet = $this->db->select($options);
if(!empty($resultSet)) {
$field = explode(',',$field);
$key = array_shift($field);
$cols = array();
foreach ($resultSet as $result){
$name = $result[$key];
$cols[$name] = '';
foreach ($field as $val)
$cols[$name] .= $result[$val].$sepa;
$cols[$name] = substr($cols[$name],0,-strlen($sepa));
}
return $cols;
}
}else{ // 查找一条记录
$options['limit'] = 1;
$result = $this->db->select($options);
if(!empty($result)) {
return reset($result[0]);
}
}
return null;
}


获取一条记录的某个字段值
所以,总结一下。
在我们注册一个用户之后
发布一个投稿,
然后修改他

1.png


2.png


这个分类,就是保存在数据库中的,上面说的所有内容,就是通过文章修改这个函数
获得aid参数,然后用aid这个参数从type中查找类型,显示出来。
而查找这个过程的aid却没经过过滤,导致了注入的产生。

3.png


SELECT * FROM `dami_article` WHERE dami_uid=6 and aid=129
日志里,下面的这个,就是在修改文章这个函数中的aid是经过Intval的
而上面的这个
105 Query SELECT `typeid` FROM `dami_article` WHERE aid=129 LIMIT 1
105 Query SELECT `typename` FROM `dami_type` WHERE typeid=14 LIMIT 1
通过get传进来的aid函数,从article表中查找出typeid,然后再从type表中根据typeid来查找类型的名字(typeid)。
http://127.0.0.1/dami/index.php?m=member&a=modpage&aid=129 and 1=2
所以一个完整的sql操作就是这样的
108 Query SELECT `typeid` FROM `dami_article` WHERE aid=129 and 1=2 LIMIT 1
108 Query SELECT `typename` FROM `dami_type` WHERE typeid= LIMIT 1
108 Query SELECT `path` FROM `dami_type` WHERE typeid= LIMIT 1
108 Query SELECT * FROM `dami_article` WHERE dami_uid=6 and aid=129 LIMIT 1
108 Query SELECT typeid,typename,fid,concat(path,'-',typeid) as bpath FROM `dami_type` WHERE islink=0 and isuser=1 ORDER BY bpath
108 Query SELECT * FROM `dami_flash` WHERE status=1 ORDER BY rank asc
108 Query SELECT * FROM `dami_link` WHERE islogo=1 and status=1 ORDER BY rank asc LIMIT 8
108 Quit

4.png

漏洞证明:

见上面

修复方案:

在前台公共类(文件)
/Web/Lib/Action/PublicAction.class.php
把传入的参数intval一下。

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


漏洞回应

厂商回应:

危害等级:低

漏洞Rank:5

确认时间:2014-10-19 23:38

厂商回复:

可能导致数据泄露,但无法直接操作数据,还是很感谢作者的细心发现

最新状态:

暂无