晚餐吃撑了,瞄下代码消化消化。最近Php0day群里的兄弟都在讨论dede洞多,赶紧下了套,用editplus搜索了几个关键字,果然发现些问题。(话说平时写代码也喜欢用editplus,小巧方便多年习惯)
( G0 v& d1 j/ {2 s3 l* r4 a% q: Z q3 S! h2 Q, Q
出现漏洞的两个文件为:9 f& h9 |) t" `
Include/payment/alipay.php
: {2 X8 Y. T$ S$ T5 [2 \8 c$ |Include/payment/yeepay.php
) H; q* C0 s: M7 |3 s漏洞均出现在respond方法里,估计这两个文件是临时工写的。. v9 X+ i3 D) Z+ Y
0 U4 s4 n6 {2 a/ ^
Include/payment/alipay.php6 Y, l; R# G7 B% p$ D: E+ W* |
6 i/ B, v" y: ^& n0 D1 F7 c+ Q) }
......" I/ k2 p. Z. L- e
function respond()$ }/ \6 t- L, A
{- s" G7 n; z! t/ q$ V# P- A5 |
if (!empty($_POST))! [' s, z2 J1 f' n# Y7 f6 G' B
{
/ R: o& m! ~2 x. m4 ^! I foreach($_POST as $key => $data)
0 g x' y3 {" F {1 k9 F; k* b( \8 j ?( T N
$_GET[$key] = $data;
3 W& @, ?8 c1 q; {1 d& ^( f }
9 X9 s4 o+ W4 S. k: ^4 b" ` }
^3 B* {* T- q! u, U- z) A( A$ { /* 引入配置文件 */5 c; i4 Z# q' M/ Y2 ]4 J2 y2 \
require_once DEDEDATA.'/payment/'.$_GET['code'].'.php';
7 \7 X" [: I* \! @' B......
7 A( P4 f7 p, W: h: [ , v* @5 G# G6 ~( {" K; W
\0 X9 S i2 E7 E2 p+ \, {: M5 K大概在133行左右,$_GET[‘code’]没有经过任何判断和过滤。 }! F l; H, L3 d' n, a1 X
* C$ G* C5 W% x3 A9 Z$ l a
Include/payment/yeepay.php/ i% O# I2 `! F, B, [. A" c
" g% @+ r F5 w* l" q' a0 j
2 N& _" Q! H1 t/ v! @9 @, l& a% e1 a' Q0 V
......
/ _: F, _( S9 W! ]) D: D9 s7 ?" l function respond()
: J0 d9 m. o8 c% V2 I {
% L. v( [8 l' G( G! P+ }9 x7 ^
) J$ t$ V( u8 V, D /* 引入配置文件 */
d. W7 M* Q. N9 K3 { require_once DEDEDATA.'/payment/'.$_REQUEST['code'].'.php';
2 h, c2 b% Q* O+ G 7 l, n4 }4 V J& v& d9 N+ q5 k
$p1_MerId = trim($payment['yp_account']);
4 F R+ D! X. g; b3 O $merchantKey = trim($payment['yp_key']);
, a, f" y7 V/ X6 k' Z: Y......
6 O1 i1 [6 Q8 ~. _ + Z$ r3 ?; x3 V- n! R
; ]4 {% R8 V8 B6 h2 F) ~% ?; z0 l, j
4 R: w9 c0 L( I& x! ^9 S! U; T' P5 N' V
大概在145行左右,$_REQUEST['code']没有经过任何判断和过滤。( B2 S* f! ]7 H6 X4 T/ a$ s' p
/ e7 @% e& I* K2 O这两个方法在plus/carbuyaction.php文件调用。( U' p# l& _( J. P- T3 B* W( q9 y
& |0 i4 [9 }1 R
plus/carbuyaction.php, S' a B+ L. S$ m# x7 k( ?& ]
* d$ B) O$ R" I: _
......) i8 \7 _6 l1 y
} else if ($dopost == 'return') {
1 d( P5 w; e$ f1 F $write_list = array('alipay', 'bank', 'cod', 'yeepay');- A' l, `6 _; h
if (in_array($code, $write_list))! Q- R- g, S2 z
{
7 _' k! w' q) k# W& w' f* k require_once DEDEINC.'/payment/'.$code.'.php';8 t1 q& W# l/ N. F" h
$pay = new $code;& a' {. A1 M% P! w5 G/ @! A- g
$msg=$pay->respond();: h' e& |3 g& J; }% o+ F
ShowMsg($msg, "javascript:;", 0, 3000);# @$ f8 v9 Y* H
exit();
9 n' i3 i+ G: W2 |) F2 F } else {
) ^8 m2 g3 ?& T4 Z5 k exit('Error:File Type Can\'t Recognized!');
x7 I( ^& Q7 \5 o9 ?. M! N }2 D0 D% {* x' _- e8 H( V9 |. W: `
} `4 H4 p5 l2 {7 e9 A) d
...... ' q; N# V7 m! w0 m. q2 f
6 ^' @- G8 G2 A! `
7 b0 W Y# T/ H, X
0 M% g+ z1 T( ?& [/ D$ W
* W _1 o5 F8 v: ]/ z
" z6 Y; x% j& m( }5 P- N" `' E2 i2 u# }/ b3 ]3 b
大概在334行,当$dopost等于return的时候就开始进入过程了。熟悉dedecms朋友都知道在include/common.inc.php使用了一种类似register_globals的机制。
8 {$ S7 H _# q; L* Z所以$_GET['code']或$_REQUEST['code']会变成$code,而$code是经过判断的,值必须在$write_list数组以内这样才能继续后面的流程调用respond方法触发漏洞。这样的话貌似就无法控制$_GET['code']为任意值了。
( W- h; _( _4 G. h
* Q" {8 p ~+ B7 ^8 l回到include/common.inc.php来看看他的机制。
. J( W' u, o7 I4 f
' l: K1 O; N4 K8 E. F 4 u; z0 S7 C. H+ y: m! `/ m
( ~; r3 v' S9 E" M6 w& E( x% ?6 ?$ c......
' p2 ?. }6 ?) Y2 ~! Oforeach(Array('_GET','_POST','_COOKIE') as $_request)8 @0 n* r0 [" n6 C# C1 G4 D1 X& f# e
{# Q# g: F6 B, e* `7 G! e
foreach($$_request as $_k => $_v) " W2 k& ~) `9 ?+ X
{
, B. U; U( ^8 e if($_k == 'nvarname') ${$_k} = $_v;
0 i* l" U* I; |! J) G% ~ else ${$_k} = _RunMagicQuotes($_v);5 {& W( n) V+ q6 m4 I
}
. S2 G5 e4 L) P7 A$ O4 L m}
2 @; u0 A. v; e% `9 J& P: b......
+ I; z1 Q5 z* ~& F8 D$ w; g) t$ i大概在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。暴路径:
+ Y. k: w N' V$ k* @# I+ U由于bank和cod这两个文件并没有respond方法,所以如果code等于bank或者cod时将会暴错泄露路径。注:请勿非法测试,产生后果与本人无关。 |