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

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

缺陷编号:wooyun-2014-074521

漏洞标题:74CMS 最新版二次SQL注入多出可越权操作

相关厂商:74c,s.com

漏洞作者: xfkxfk

提交时间:2014-09-01 12:14

修复时间:2014-11-30 12:16

公开时间:2014-11-30 12:16

漏洞类型:SQL注射漏洞

危害等级:高

自评Rank:20

漏洞状态:厂商已经确认

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

Tags标签:

4人收藏 收藏
分享漏洞:


漏洞详情

披露状态:

2014-09-01: 细节已通知厂商并且等待厂商处理中
2014-09-02: 厂商已经确认,细节仅向厂商公开
2014-09-05: 细节向第三方安全合作伙伴开放
2014-10-27: 细节向核心白帽子及相关领域专家公开
2014-11-06: 细节向普通白帽子公开
2014-11-16: 细节向实习白帽子公开
2014-11-30: 细节向公众公开

简要描述:

74CMS 最新版二次SQL注入多出可越权操作

详细说明:

74CMS最新版:74cms_v3.4.20140820 官方8.20号更新
文件:/user/personal/personal_resume.php

//保存-求职意向
elseif ($act=='make2_save')
{

$resumeuid=intval($_SESSION['uid']);
$resumepid=intval($_REQUEST['pid']);
if ($resumeuid==0 || $resumepid==0 ) showmsg('参数错误!',1);
$resumearr['recentjobs']=trim($_POST['recentjobs']);
$resumearr['nature']=intval($_POST['nature'])?intval($_POST['nature']):showmsg('请选择期望岗位性质!',1);
$resumearr['nature_cn']=trim($_POST['nature_cn']);
$resumearr['district']=trim($_POST['district'])?intval($_POST['district']):showmsg('请选择期望工作地!',1);
$resumearr['sdistrict']=intval($_POST['sdistrict']);
$resumearr['district_cn']=trim($_POST['district_cn']);
$resumearr['wage']=intval($_POST['wage'])?intval($_POST['wage']):showmsg('请选择期望月薪!',1);
$resumearr['wage_cn']=trim($_POST['wage_cn']);
$resumearr['trade']=$_POST['trade']?trim($_POST['trade']):showmsg('请选择期望从事的行业!',1);
$resumearr['trade_cn']=trim($_POST['trade_cn']);
$resumearr['intention_jobs']=trim($_POST['intention_jobs']);
if ($_CFG['audit_edit_resume']!="-1")
{
$resumearr['audit']=$_CFG['audit_edit_resume'];
}
add_resume_jobs($resumepid,$_SESSION['uid'],$_POST['intention_jobs_id'])?"":showmsg('更新失败!',0);
updatetable(table('resume'),$resumearr," id='{$resumepid}' AND uid='{$resumeuid}'");
updatetable(table('resume_tmp'),$resumearr," id='{$resumepid}' AND uid='{$resumeuid}'");
check_resume($_SESSION['uid'],intval($_REQUEST['pid']));
if ($_POST['go_resume_show'])
{
header("Location: ?act=resume_show&pid={$resumepid}");
}
else
{
header("Location: ?act=make3&pid=".intval($_POST['pid']));
}
}


这里插入了求职意向,主要这里的职位信息:recentjobs

//创建简历-技能特行
elseif ($act=='make3_save')
{

if (intval($_POST['pid'])==0 ) showmsg('参数错误!',1);
$setsqlarrspecialty['specialty']=!empty($_POST['specialty'])?$_POST['specialty']:showmsg('请填写您的技能特长!',1);
$_CFG['audit_edit_resume']!="-1"?$setsqlarrspecialty['audit']=intval($_CFG['audit_edit_resume']):"";
updatetable(table('resume'),$setsqlarrspecialty," id='".intval($_POST['pid'])."' AND uid='".intval($_SESSION['uid'])."'");
updatetable(table('resume_tmp'),$setsqlarrspecialty," id='".intval($_POST['pid'])."' AND uid='".intval($_SESSION['uid'])."'");
check_resume($_SESSION['uid'],intval($_REQUEST['pid']));
if ($_POST['go_resume_show'])
{
header("Location: ?act=resume_show&pid={$_POST['pid']}");
}
else
{
header("Location: ?act=make4&pid=".intval($_POST['pid']));
}
}


这里更新了技能特长:specialty
最后在文件:/include/fun_personal.php

//检查简历的完成程度
function check_resume($uid,$pid)
{
global $db,$timestamp,$_CFG;
$uid=intval($uid);
$pid=intval($pid);
$percent=0;
......省略
if ($percent>=60)
{
$j=get_resume_basic($uid,$pid);
$searchtab['sex']=$j['sex'];
$searchtab['nature']=$j['nature'];
$searchtab['marriage']=$j['marriage'];
$searchtab['experience']=$j['experience'];
$searchtab['district']=$j['district'];
$searchtab['sdistrict']=$j['sdistrict'];
$searchtab['wage']=$j['wage'];
$searchtab['education']=$j['education'];
$searchtab['photo']=$j['photo'];
$searchtab['refreshtime']=$j['refreshtime'];
$searchtab['talent']=$j['talent'];
updatetable(table('resume_search_rtime'),$searchtab,"uid='{$uid}' AND id='{$pid}'");
$searchtab['key']=$j['key'];
$searchtab['likekey']=$j['intention_jobs'].','.$j['recentjobs'].','.$j['specialty'].','.$j['fullname'];
updatetable(table('resume_search_key'),$searchtab,"uid='{$uid}' AND id='{$pid}'");
unset($searchtab);


这里从简历信息里取出来了信息
注意这里:

$searchtab['likekey']=$j['intention_jobs'].','.$j['recentjobs'].','.$j['specialty'].','.$j['fullname'];


这里的recentjobs,specialty,就是上面插入简历信息里面的recentjobs,specialty,这里取出来后,有进入了updatetable:

updatetable(table('resume_search_key'),$searchtab,"uid='{$uid}' AND id='{$pid}'");


这里是更新搜索关键字的
最后来看看updatetable函数:

function updatetable($tablename, $setsqlarr, $wheresqlarr, $silent=0) {
global $db;
$setsql = $comma = '';
foreach ($setsqlarr as $set_key => $set_value) {
if(is_array($set_value)) {
$setsql .= $comma.'`'.$set_key.'`'.'='.$set_value[0];
} else {
$setsql .= $comma.'`'.$set_key.'`'.'=\''.$set_value.'\'';
}
$comma = ', ';
}
$where = $comma = '';
if(empty($wheresqlarr)) {
$where = '1';
} elseif(is_array($wheresqlarr)) {
foreach ($wheresqlarr as $key => $value) {
$where .= $comma.'`'.$key.'`'.'=\''.$value.'\'';
$comma = ' AND ';
}
} else {
$where = $wheresqlarr;
}
//echo "UPDATE ".($tablename)." SET ".$setsql." WHERE ".$where, $silent?"SILENT":"";
return $db->query("UPDATE ".($tablename)." SET ".$setsql." WHERE ".$where, $silent?"SILENT":"");
}


将参数直接进入SQL语句,没有经过过滤。
总结:
1、求职职位和技能特长进入数据库,可带入恶意sql语句
2、从简历信息里取出来职位及特长
3、再次进入数据库,没有过滤,恶意SQL语句进入数据库
4、导致二次sql注入
这里的求职职位,技能特长,姓名三处都存在二次注入
这里通过截断即可更新任意用户的信息了

漏洞证明:

1、在求职职位中输入

444.png


2、在技能特长处输入

555.png


3、最后看看是否执行成功:

666.png


数据库中likekey成功被修改,恶意sql语句成功执行

修复方案:

进入数据库时再次过滤

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


漏洞回应

厂商回应:

危害等级:高

漏洞Rank:20

确认时间:2014-09-02 09:46

厂商回复:

感谢反馈

最新状态:

暂无


漏洞评价:

评论

  1. 2014-09-01 22:17 | 树上草 ( 路人 | Rank:20 漏洞数:8 | <img height="12" width="12" style="verti...)

    我擦,牛逼

  2. 2014-09-02 10:14 | 尼玛椰子树 ( 路人 | Rank:0 漏洞数:1 | 简单,守护心中那份沉静。疯狂,爆破黎明的...)

    哥哥 你累不累呀!~