晚餐吃撑了,瞄下代码消化消化。最近Php0day群里的兄弟都在讨论dede洞多,赶紧下了套,用editplus搜索了几个关键字,果然发现些问题。(话说平时写代码也喜欢用editplus,小巧方便多年习惯)
; B0 M4 t( @ d* L3 D
4 ~$ M3 H" D n! U+ e出现漏洞的两个文件为:9 x5 ~- O# U* W+ P7 [
Include/payment/alipay.php1 k9 L: u4 I2 `7 B0 ^4 C/ K9 I g
Include/payment/yeepay.php, _8 l% R& F: U9 L, B+ R
漏洞均出现在respond方法里,估计这两个文件是临时工写的。8 ]6 M E; A( d
6 W6 u6 @5 P+ yInclude/payment/alipay.php) _; @0 @7 Y ]. q
2 y/ {- s( b/ t......% r: |3 O2 O7 j7 I5 A. e/ L
function respond()
9 q1 c5 V$ h) h" e8 `. S9 L2 _ {
* I4 s/ f8 ^9 ?7 q if (!empty($_POST))4 f$ H# I, A( d* m( c' \) J0 V
{0 O6 ?) X( B s3 v
foreach($_POST as $key => $data)
5 B8 O# w9 g9 z1 ]0 A2 \$ c. | {4 v! f' I$ K$ s* }
$_GET[$key] = $data;+ k6 I3 \, s" \
}* ]1 T9 T4 ]. v* V' U
}# X+ y5 n- b- _
/* 引入配置文件 */! s$ j% p' h& U2 t2 R
require_once DEDEDATA.'/payment/'.$_GET['code'].'.php';
. H* b4 _! D/ k' r: A ?......
# b3 e0 [4 G8 r
: @3 ^9 e3 @) H' d3 w5 L' W+ y4 j0 S% a
大概在133行左右,$_GET[‘code’]没有经过任何判断和过滤。
! p; M6 g% y* L2 d0 g( J5 ~" S. O& I3 K2 i$ I/ l3 _
Include/payment/yeepay.php
- C/ f( C0 {5 t
: y( m$ \0 r8 S6 s1 m
3 g7 L; \) H6 R+ Q6 E+ r& r9 B& g8 y M; R6 K+ `; `
......" N( ?5 s. G8 k; m
function respond()
3 ]$ a! A& M/ L, q& K6 S {2 ^2 e, S# E; M% _! F
) E1 @% V" V" _; ]& N: z3 _ /* 引入配置文件 */8 _$ W. ]- f4 h: A
require_once DEDEDATA.'/payment/'.$_REQUEST['code'].'.php';% u+ \ U$ w' [ b* V( |
* V% o, l2 j# b
$p1_MerId = trim($payment['yp_account']);
. n3 w: \4 p1 p& V $merchantKey = trim($payment['yp_key']);
* I) U, j5 F; p! S...... 9 @- }( u6 t. |7 U& q0 N
3 H9 Q1 Z/ |% d' X6 n. F% j5 |; ~1 d4 k' T8 Y; E- b; f
2 \4 [- b" K3 ?7 B* Q+ S) M* Q7 b
大概在145行左右,$_REQUEST['code']没有经过任何判断和过滤。
- i* h6 c/ P. p' J( R' p8 h9 F$ r$ f6 L8 H% \3 p
这两个方法在plus/carbuyaction.php文件调用。/ O; F* V$ V2 {
6 Q2 M1 {8 ]$ a% j9 [4 E, m$ B1 dplus/carbuyaction.php
- ?# A& I1 Z, l) `( g- i
7 _" C' b( w7 d2 z' v......+ S9 ?! i- Y/ ?
} else if ($dopost == 'return') {
. N3 L- u5 h# u% r8 U $write_list = array('alipay', 'bank', 'cod', 'yeepay');6 x7 ^0 ~# O/ C7 |, O7 S, ]8 C
if (in_array($code, $write_list))
7 C' j: s6 H: z! F4 q' M9 B' R L {5 X4 [$ w) a8 P- \. b$ P3 A
require_once DEDEINC.'/payment/'.$code.'.php';) Z6 L2 N; l0 G3 J4 E
$pay = new $code;) l: G. J: @, P
$msg=$pay->respond();9 |/ U* a, q" M k) h
ShowMsg($msg, "javascript:;", 0, 3000);9 t( L1 N3 Q9 N
exit();
) h" S3 V) E. m1 h4 O } else {' g* j. Q6 U; X' n
exit('Error:File Type Can\'t Recognized!');0 `- D7 i* D9 `5 m, ^) E) h
}
. n N) m# S: l# T}
: ?& ^1 _/ [& v% p0 n3 _...... 2 W- A. |" e6 ~7 v9 D
7 V" z- P: T6 s
1 q; G8 h1 Q% R, x. Y3 m% ? + ^ |& U9 c, K h
, z# \4 X0 v2 ]6 B9 n9 t0 U; O 3 o' ^, g3 v7 O b
# D, l3 G/ ^+ K5 |6 W( t
大概在334行,当$dopost等于return的时候就开始进入过程了。熟悉dedecms朋友都知道在include/common.inc.php使用了一种类似register_globals的机制。
$ |; P7 ?$ I) R8 C+ G所以$_GET['code']或$_REQUEST['code']会变成$code,而$code是经过判断的,值必须在$write_list数组以内这样才能继续后面的流程调用respond方法触发漏洞。这样的话貌似就无法控制$_GET['code']为任意值了。0 k$ {$ n! N( o' x, a
) D% Q8 h: C- ]+ r
回到include/common.inc.php来看看他的机制。* T8 g5 B7 v, n8 L4 R6 }5 ^
1 X! d9 c) o' _& U( H1 u
( _6 V/ J r7 O9 o8 E9 t' N+ x* j3 Z" s# k3 U
......% R9 C: m" ~: ?) X1 q
foreach(Array('_GET','_POST','_COOKIE') as $_request)
6 H# V, Z! T( t2 X{ K8 E+ Q0 j: X2 a
foreach($$_request as $_k => $_v)
; }1 l: ]: p2 `3 O* H; b8 j, ^ {/ f9 s$ M3 c0 D! ]( C" ^0 S; @9 `
if($_k == 'nvarname') ${$_k} = $_v; }4 w& w, m) e( o5 g
else ${$_k} = _RunMagicQuotes($_v);
6 h: N& y0 i5 [6 h% E2 Z/ h }- Z1 S1 u* w6 ~& M) J, q7 x
}3 f7 d( q. j1 l, ]7 @: u" H7 T
...... $ S% g( e" A8 V3 @) a
大概在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。暴路径:8 k4 {+ _% ?# ?' v, V, {4 q" f5 P
由于bank和cod这两个文件并没有respond方法,所以如果code等于bank或者cod时将会暴错泄露路径。注:请勿非法测试,产生后果与本人无关。 |