phpcmsV9某sql注射漏洞及修复
- phpcmsV9某sql注射漏洞及修复
-
别人说最危险的地方最安全,我说最安全的地方最危险。。。
相信你们也没有想到这个最常见,常常会在各种教程出现的地方会存在SQL注射。。。
需 GPC OFF
首先,我们看登陆的地方。。最常见了吧。。。http://127.0.0.1/index.php?m=member&c=index&a=login
默认安装情况下,会使有 V9自带的用户中心。
phpcms\modules\member\index.php
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253publicfunction login() {$this->_session_start();//获取用户siteid$siteid = isset($_REQUEST['siteid']) && trim($_REQUEST['siteid']) ? intval($_REQUEST['siteid']) :1;//定义站点id常量if(!defined('SITEID')) {define('SITEID', $siteid);}if(isset($_POST['dosubmit'])) {if(empty($_SESSION['connectid'])) {//判断验证码$code = isset($_POST['code']) && trim($_POST['code']) ? trim($_POST['code']) : showmessage(L('input_code'), HTTP_REFERER);if($_SESSION['code'] != strtolower($code)) {showmessage(L('code_error'), HTTP_REFERER);}}$username = isset($_POST['username']) && trim($_POST['username']) ? trim($_POST['username']) : showmessage(L('username_empty'), HTTP_REFERER);$password = isset($_POST['password']) && trim($_POST['password']) ? trim($_POST['password']) : showmessage(L('password_empty'), HTTP_REFERER);$cookietime = intval($_POST['cookietime']);$synloginstr ='';//同步登陆js代码if(pc_base::load_config('system','phpsso')) {$this->_init_phpsso();$status = $this->client->ps_member_login($username, $password);$memberinfo = unserialize($status);
可以看到用户名密码交给了1$this->client->ps_member_login($username, $password);我们跟进。
phpcms\modules\member\classes\client.class.php
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071$return= $this->_ps_send('login', array('username'=>$username,'password'=>$password));privatefunction _ps_send($action, $data =null) {return$this->_ps_post($this->ps_api_url."/index.php?m=phpsso&c=index&a=".$action,500000, $this->auth_data($data));}publicfunction auth_data($data) {$s = $sep ='';foreach($data as $k => $v) {if(is_array($v)) {$s2 = $sep2 ='';foreach($v as $k2 => $v2) {$s2 .="$sep2{$k}[$k2]=".$this->_ps_stripslashes($v2);$sep2 ='&';}$s .= $sep.$s2;}else{$s .="$sep$k=".$this->_ps_stripslashes($v);}$sep ='&';}$auth_s ='v='.$this->ps_vsersion.'&appid='.APPID.'&data='.urlencode($this->sys_auth($s));return$auth_s;}_ps_stripslashesprivatefunction _ps_stripslashes($string) {!defined('MAGIC_QUOTES_GPC') && define('MAGIC_QUOTES_GPC', get_magic_quotes_gpc());if(MAGIC_QUOTES_GPC) {returnstripslashes($string);}else{return$string;}}
还原了 GPC,传参数给 API。我们再看看 API 方的处理方式
phpsso_server\phpcms\modules\phpsso\classes\phpsso.class.php
1234567891011121314151617if(isset($_POST['data'])) {parse_str(sys_auth($_POST['data'],'DECODE', $this->applist[$this->appid]['authkey']), $this->data);if(!is_array($this->data)) {exit('0');}}else{exit('0');}
parse_str 函数默认是根据 GPC情况过滤。再到
phpsso_server\phpcms\modules\phpsso\index.php
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263publicfunction login() {$this->password = isset($this->data['password']) ? $this->data['password'] :'';$this->email = isset($this->data['email']) ? $this->data['email'] :'';if($this->email) {$userinfo = $this->db->get_one(array('email'=>$this->email));}else{$userinfo = $this->db->get_one(array('username'=>$this->username));}phpsso_server\phpcms\libs\classes\model.class.phpfinalpublicfunction get_one($where ='', $data ='*', $order ='', $group ='') {if(is_array($where)) $where = $this->sqls($where);return$this->db->get_one($data, $this->table_name, $where, $order, $group);}/*** 将数组转换为SQL语句* @param array $where 要生成的数组* @param string $font 连接串。*/finalpublicfunction sqls($where, $font =' AND ') {if(is_array($where)) {$sql ='';foreach ($where as $key=>$val) {$sql .= $sql ?" $font `$key` = '$val' ":" `$key` = '$val'";}return$sql;}else{return$where;}}
可以看到全程没有对字符串进行过滤。。。因此,在GPC为 OFF 时,存在SQL注入。
可能没说清楚问题在那里
两个:
1、auth_data 参数拼接
2、api中没有对数据进行过滤
可以做什么?盲注,任意用户登陆。。。其实还有很多利用的地方。。
测试如下:
![]()
![]()
![]()
修复方案:
过滤
我要投稿


浙公网安备 33010602011771号