phpcmsV9某sql注射漏洞及修复

phpcmsV9某sql注射漏洞及修复
2014-05-24       0  个评论      
收藏    我要投稿

别人说最危险的地方最安全,我说最安全的地方最危险。。。
相信你们也没有想到这个最常见,常常会在各种教程出现的地方会存在SQL注射。。。
需 GPC OFF

首先,我们看登陆的地方。。最常见了吧。。。

http://127.0.0.1/index.php?m=member&c=index&a=login

 

默认安装情况下,会使有 V9自带的用户中心。

 

phpcms\modules\member\index.php

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
public function 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

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
$ return = $ this ->_ps_send( 'login' , array( 'username' =>$username, 'password' =>$password));
 
  
 
private function _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));
 
  }
 
  
 
 
public function 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_stripslashes
 
private function _ps_stripslashes($string) {
 
   !defined( 'MAGIC_QUOTES_GPC' ) && define( 'MAGIC_QUOTES_GPC' , get_magic_quotes_gpc());
 
   if (MAGIC_QUOTES_GPC) {
 
    return stripslashes($string);
 
   } else {
 
    return $string;
 
   }
 
  }


 


还原了 GPC,传参数给 API。

我们再看看 API 方的处理方式

 

phpsso_server\phpcms\modules\phpsso\classes\phpsso.class.php

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
if (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

 

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
public function 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 .php
 
final public function 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 连接串。
 
   */
 
  final public function 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中没有对数据进行过滤

 

可以做什么?盲注,任意用户登陆。。。其实还有很多利用的地方。。

测试如下:





修复方案:
过滤

转载于:https://www.cnblogs.com/lry0916/p/4635708.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值