晚餐吃撑了,瞄下代码消化消化。最近Php0day群里的兄弟都在讨论dede洞多,赶紧下了套,用editplus搜索了几个关键字,果然发现些问题。(话说平时写代码也喜欢用editplus,小巧方便多年习惯)
) Z/ l. M& W$ K7 z" ?" N& [9 T9 U. A% e6 {$ ]0 ~
出现漏洞的两个文件为:) M* T! f+ T+ Q! O: E
Include/payment/alipay.php
- k% j( p# A Z7 c! h* o' C* A) XInclude/payment/yeepay.php. W8 r9 |2 k6 B" h" `9 k
漏洞均出现在respond方法里,估计这两个文件是临时工写的。
( |6 g& ?6 G# q$ V+ V9 S' h5 @$ J" S5 y. m& C$ A
Include/payment/alipay.php
% Z4 k* I' `: g) M/ J b5 a; |. D: q' ~- m
......
; @ W6 l7 n+ n% q( v) Z. h function respond()
! K% r0 Q$ W4 m/ {" t) E {! E2 R: g; J1 d1 H) e
if (!empty($_POST))) y) ^) J7 F: J& U4 q: x" Z
{- t3 \; ]$ @- Q F2 D1 ~% |/ m
foreach($_POST as $key => $data), {% W, J0 m2 W5 x( L+ P) A+ g) X; [2 |
{
* F- y) R2 E0 V- h5 ^6 x# P W $_GET[$key] = $data;, z: E6 |! T8 R
}
% S. E M Y% d8 w, j9 i$ D }6 I5 o: H, ?. v
/* 引入配置文件 */1 l. ~" a( H( Z$ f
require_once DEDEDATA.'/payment/'.$_GET['code'].'.php';
: z5 Q) k. c }( ?# u2 E...... 2 m; s7 f" C$ {$ Z" k1 H2 S+ ]6 a
7 \$ I, M* k8 _. j
0 r1 k* w1 A! o大概在133行左右,$_GET[‘code’]没有经过任何判断和过滤。
9 \. L3 e( ]; {+ o- U) [2 J6 w: C$ d" [$ @) x7 `- ~
Include/payment/yeepay.php
( C- p( H2 y7 q3 ^; E/ ~) q( P9 w# G: e8 C! k' X0 V, V5 [
1 g/ e9 R4 i9 \4 L
0 s; ~$ ?" A6 k1 b3 [8 R......4 K6 U& f; ?1 e+ Y- A2 J. Y
function respond()
3 r& y& a% T) I' n {
0 }! {2 J }9 O7 r6 n 9 ^) E; R0 ]1 f: q6 [
/* 引入配置文件 */4 [* R! I8 W$ t
require_once DEDEDATA.'/payment/'.$_REQUEST['code'].'.php';5 I2 A) j( D% E" P1 k
! I; H+ q; Y" z8 x$ k/ I) k! O/ d $p1_MerId = trim($payment['yp_account']);5 w: P' ?* e6 w ~
$merchantKey = trim($payment['yp_key']);" B! {( q* a! F
...... $ y+ h8 D5 d: Y$ ?4 n
& |3 D$ `/ R# N7 r
8 p& z/ V! m% K: B2 P+ N' W3 n + g1 s' p& L& }1 a
% X0 r7 H; G! _大概在145行左右,$_REQUEST['code']没有经过任何判断和过滤。) Q. m$ k( C$ Y' m9 p
& l+ f2 p% I& J! K w4 ^这两个方法在plus/carbuyaction.php文件调用。* Y" X* A; y! `# d
, x* B& i+ l+ U' P4 C. }' M; s8 h
plus/carbuyaction.php4 h2 B6 x9 u2 j9 n
9 m1 k7 G. @2 H" A; Q
......
0 s/ x: n) l8 Y: y# o} else if ($dopost == 'return') {) U; I1 |& J9 z/ L; f
$write_list = array('alipay', 'bank', 'cod', 'yeepay'); o1 Q- P: \; c3 n& y
if (in_array($code, $write_list))
1 L" ]0 W4 M3 S: B {0 d' d* s: V4 b# j8 R
require_once DEDEINC.'/payment/'.$code.'.php';
% H [) x5 Q7 p% X" c $pay = new $code;
) d; N# W$ E( d8 E: z6 }5 \ $msg=$pay->respond();% m/ |8 X6 _5 A0 ^3 A
ShowMsg($msg, "javascript:;", 0, 3000);5 m9 l9 Q% R, F8 L' A
exit(); + h# K( x1 n5 A
} else {. s6 y; p: H& z3 L8 M/ b
exit('Error:File Type Can\'t Recognized!');0 B, _9 q; |8 M
}
. V' b1 |4 _( n}9 |3 y" o/ p4 {+ S
...... 7 t k$ |, T7 B/ }$ I. E! l1 B
$ X$ h0 W4 l" d8 H
; k* B- f2 A" T% Y& s 6 C) V, O6 |- v7 Y3 f. o
: Q" E& U& P( @/ B% O; h - R# i A" i& C: ]$ o% b
: h! H4 t0 G, s5 w, l大概在334行,当$dopost等于return的时候就开始进入过程了。熟悉dedecms朋友都知道在include/common.inc.php使用了一种类似register_globals的机制。
. \, _8 G8 L% Y. z1 _1 S& q所以$_GET['code']或$_REQUEST['code']会变成$code,而$code是经过判断的,值必须在$write_list数组以内这样才能继续后面的流程调用respond方法触发漏洞。这样的话貌似就无法控制$_GET['code']为任意值了。
! g: x) v5 d4 @+ ?% r9 ^% o* |% U+ H0 C) |
回到include/common.inc.php来看看他的机制。
H2 E0 p" K9 X! ~% R; [& E8 b( {, b6 M9 O: b
# A6 R8 `2 X* ^& I2 B) x' f1 J0 p& e2 B
......
( T: r: K" b9 Oforeach(Array('_GET','_POST','_COOKIE') as $_request)9 Z0 ]: y' a. F* s& G: ?4 ^
{
3 D7 c0 e) s7 V foreach($$_request as $_k => $_v)
! u I: p2 m w$ E# J8 J, n8 ~ {
% e8 v) K$ M, s, S* D6 o if($_k == 'nvarname') ${$_k} = $_v;
; k9 ?0 }3 [, ?- F else ${$_k} = _RunMagicQuotes($_v);
! b M6 X3 J8 N1 E- U) L# H }: C6 V1 M. y, k% s4 U0 O6 B
}) U7 z- @8 s( B9 g. x6 R# ~
......
# `0 K0 {. b+ x大概在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。暴路径: _4 W8 e$ [* H! @) F) m& K
由于bank和cod这两个文件并没有respond方法,所以如果code等于bank或者cod时将会暴错泄露路径。注:请勿非法测试,产生后果与本人无关。 |