记录黑客技术中优秀的内容, 传播黑客文化,分享黑客技术精华

新年礼包第三弹(74cms注入)

2017-01-20 04:15

新年礼包三、提前祝大家17年0day多多。

 

漏洞文件:/Application/Common/Model/CompanyProfileModel.class.php

public function add_company_profile($data,$user)
	{
		$this->_user = $user;
		// 替换原名称
		$company = =$this->field('id,companyname')->where(array('uid'=>$user['uid']))->find();
		if($company){
			$data['companyname'] = $company['companyname'];
		}
		if(false === $this->create($data))
		{
			return array('state'=>0,'error'=>$this->getError());
		}
		else
		{
			if($company['id'])
			{
				if(false === $num = $this->save()){
					return array('state'=>0,'error'=>'数据添加失败!');
				}
				if(!$user['mobile_audit']){
	                $setsqlarr['telephone'] = $data['telephone'];
	            }
	            if(!$user['email_audit']){
	                $setsqlarr['email'] = $data['email'];
	            }
				$setsqlarr && D('Members')->update_user_info($setsqlarr,$user);
			}

首先从数据库中根据当前用户的uid查询出companyname内容然后一个判断是否为真,当真的情况下则把数据库中的内容提出来并进行一个赋值(这里就想到了查询出的内容可控话且下面没有安全防护的情况下,那就存在二次注入)

if($company['id'])
			{
				if(false === $num = $this->save()){
					return array('state'=>0,'error'=>'数据添加失败!');
				}
				if(!$user['mobile_audit']){
	                $setsqlarr['telephone'] = $data['telephone'];
	            }
	            if(!$user['email_audit']){
	                $setsqlarr['email'] = $data['email'];
	            }
				$setsqlarr && D('Members')->update_user_info($setsqlarr,$user);
			}

$company[‘id’]TRUE时进入操作SAVE的数据库执行操作,后面内容太多我就不细说了,就是没有二次转义之类的

关联文件:/Application/Home/Controller/CompanyController.class.php

$setsqlarr['companyname']=I('post.companyname','','trim,badword'); 
			$setsqlarr['registered']=I('post.registered','','trim,badword'); 
			$setsqlarr['currency']=I('post.currency','','trim,badword'); 
			$setsqlarr['address']=I('post.address','','trim,badword'); 
			$setsqlarr['contact']=I('post.contact','','trim,badword');
            $setsqlarr['telephone'] = C('visitor.mobile_audit') ? C('visitor.mobile') : I('post.telephone','','trim,badword');
            $setsqlarr['email'] = C('visitor.email_audit') ? C('visitor.email') : I('post.email','','trim,badword');
            $setsqlarr['website']=I('post.website','','trim,badword');
			$setsqlarr['contents']=I('post.contents','','trim,badword');
			$setsqlarr['contact_show']=I('post.contact_show',1,'intval');
			$setsqlarr['telephone_show']=I('post.telephone_show',1,'intval');
			$setsqlarr['landline_tel_show']=I('post.landline_tel_show',1,'intval');
			$setsqlarr['email_show']=I('post.email_show',1,'intval');
            $setsqlarr['qq']=I('post.qq',0,'intval');
			$setsqlarr['map_x']=I('post.map_x',0,'trim,badword');
			!$setsqlarr['map_x'] && $setsqlarr['map_x'] = 0;
			$setsqlarr['map_y']=I('post.map_y',0,'trim,badword');
			!$setsqlarr['map_y'] && $setsqlarr['map_y'] = 0;
			$setsqlarr['map_zoom']=I('post.map_zoom',0,'intval');
			
			//座机
			$landline_tel_first=I('post.landline_tel_first',0,'trim,badword');
			$landline_tel_next=I('post.landline_tel_next',0,'trim,badword');
			$landline_tel_last=I('post.landline_tel_last',0,'trim,badword');
			$setsqlarr['landline_tel']=$landline_tel_first.'-'.$landline_tel_next.($landline_tel_last?('-'.$landline_tel_last):'');
			$posttag = I('post.tag','','trim,badword');

			if($posttag){
				$tagArr = explode(",",$posttag);
				$r_arr = array();
				foreach ($tagArr as $key => $value) {
					$r_arr[] = $value.'|'.$category['QS_jobtag'][$value];
				}
				if(!empty($r_arr)){
					$setsqlarr['tag'] = implode(",",$r_arr);
				}else{
					$setsqlarr['tag'] = '';
				}
			}

			if($company_profile['contents']) 
			{
				$setsqlarr['id']=$company_profile['id'];
				C('qscms_audit_edit_com')<>"-1"?$setsqlarr['audit']=C('qscms_audit_edit_com'):$setsqlarr['audit']=$company_profile['audit'];
			}
			else
			{
				$setsqlarr['audit']=0;
			}
			$setsqlarr['sync'] = I('post.sync',0,'intval');
			// 插入数据
            // // 
			$rst = D('CompanyProfile')->add_company_profile($setsqlarr,C('visitor'));

进入add中的setsqlarr数组内容均是由post传递,这里也能看见companame这个参数可控,但后面因为又从数据库查询出来进行赋值导致二次注入,现在要找到第一次写入的位置

 

关联文件:/Application/Home/Controller/MembersController.class.php

if(IS_POST && IS_AJAX){
            $data['reg_type'] = I('post.reg_type',0,'intval');//注册方式(1:手机,2:邮箱,3:微信)
            $array = array(1 => 'mobile',2 => 'email');
            if(!$reg = $array[$data['reg_type']]) $this->ajaxReturn(0,'正确选择注册方式!');
            $data['utype'] = I('post.utype',0,'intval');
            if($data['utype'] != 1 && $data['utype'] != 2) $this->ajaxReturn(0,'请正确选择会员类型!');
            if($data['reg_type'] == 1){
                $data['mobile'] = I('post.mobile',0,'trim');
                $smsVerify = session('reg_smsVerify');
                if(!$smsVerify) $this->ajaxReturn(0,'验证码错误!');
                if($data['mobile'] != $smsVerify['mobile']) $this->ajaxReturn(0,'手机号不一致!',$smsVerify);//手机号不一致
                if(time()>$smsVerify['time']+600) $this->ajaxReturn(0,'验证码过期!');//验证码过期
                $vcode_sms = I('post.mobile_vcode',0,'intval');
                $mobile_rand=substr(md5($vcode_sms), 8,16);
                if($mobile_rand!=$smsVerify['rand']) $this->ajaxReturn(0,'验证码错误!');//验证码错误!
                $data['password'] = I('post.password','','trim');
                $passwordVerify = I('post.passwordVerify','','trim');
            }else{
                if($data['utype'] == 1){
                    $data['password'] = I('post.cpassword','','trim');
                    $passwordVerify = I('post.cpasswordVerify','','trim');
                }else{
                    $data['password'] = I('post.emailpassword','','trim');
                    $passwordVerify = I('post.emailpasswordVerify','','trim');
                }
                $data['username'] = I('post.username','','trim,badword');
                $data['email'] = I('post.email','','trim,badword');
                $data['utype']==1 && $data['mobile'] = I('post.telephone','','trim,badword');
                C('qscms_check_reg_email') && $data['status'] = 0;
            }
            !$data['password'] && $this->ajaxReturn(0,'请输入密码!');
            $data['password'] != $passwordVerify && $this->ajaxReturn(0,'两次密码输入不一致!');
            if($data['utype']==1){
                $com_setarr['audit'] = 0;
                $com_setarr['email']=$data['email'];
                   $com_setarr['companyname']=I('post.companyname','','trim,badword');
                $com_setarr['contact']=I('post.contact','','trim,badword');
                $com_setarr['telephone']=I('post.telephone','','trim,badword');
                $com_setarr['landline_tel']=I('post.landline_tel','','trim,badword');
                $company_mod = D('CompanyProfile');
                if(false === $company_mod->create($com_setarr)) $this->ajaxReturn(0,$company_mod->getError());
            }
            $passport = $this->_user_server();
            if(false === $data = $passport->register($data)){

通过一串的代码发现

$com_setarr['companyname']=I('post.companyname','','trim,badword');

写入进去companyname是可控的,然后跟入最后的insert发现期间并没有二次转义

 

本地复现:

Companyname填入sql语句


在保存时请求发现直接爆出管理表中的username信息

 

官网演示:

这里有必要提出的一点是:

数据库中是对该字段进行了长度限制的,也就是sql语句最长只能为60长度,这里首先要感谢@phithon为我提出一个60长度的雏形:

‘–~(select*from((select password from as_admin limit 1))f)#

但在注入时提示这个导致没法注入

于是开启自我琢磨模式,因为我在测试时发现updaexml可注入,但这里就占了8个字节加上闭合的以及注释的总共就占去了12个字节,剩下的只有49个字节。最终得到

虽然只能注一条管理数据,但总得在一些情况下也是一个突破的机会。希望有对sql更厉害的大神搞出更短的语句便于学习

知识来源: www.91ri.org/16713.html

阅读:130502 | 评论:0 | 标签:代码审计 漏洞研究 注入 cms

想收藏或者和大家分享这篇好文章→复制链接地址

“新年礼包第三弹(74cms注入)”共有0条留言

发表评论

姓名:

邮箱:

网址:

验证码:

公告

关注公众号hackdig,学习最新黑客技术

推广

工具

标签云