晚餐吃撑了,瞄下代码消化消化。最近Php0day群里的兄弟都在讨论dede洞多,赶紧下了套,用editplus搜索了几个关键字,果然发现些问题。(话说平时写代码也喜欢用editplus,小巧方便多年习惯)$ \: l1 [% a/ O( b
\* d& D- b/ _2 q! W/ W( T
出现漏洞的两个文件为:
' u. C2 K, p$ c7 G. m5 H3 EInclude/payment/alipay.php
1 ]6 @7 n) C6 Y1 A0 }Include/payment/yeepay.php; c( A O8 w# D0 l1 L# c" {' p' D
漏洞均出现在respond方法里,估计这两个文件是临时工写的。2 j) e u6 O% s0 ?/ C7 c
* ?, O9 h$ s8 m. `% Z
Include/payment/alipay.php
6 t: F/ ^+ Q# G' U& C) Y. {% N
, \' ^5 a: I/ N6 K2 i- P......
% i' ?, J/ s, K) H! F6 z* T+ _1 |, p4 ^ function respond()
, p3 Y* `2 P+ W$ a {
$ D) J0 n! O! i3 @$ E- w( g6 | if (!empty($_POST)) \# G" ]- P2 d
{9 i2 L9 I# ^ `5 T4 e7 X; e
foreach($_POST as $key => $data)
7 o0 ] Z9 _7 {1 p+ s% c( x8 u {1 Z" s3 ?+ f, {2 ], @
$_GET[$key] = $data;( e7 C F! p) q4 c" j
}% I9 H- u( L; y% g" F# A: }
}# R s' l6 d1 ^: C
/* 引入配置文件 */. R, a. F% u3 E& b' w$ `
require_once DEDEDATA.'/payment/'.$_GET['code'].'.php';5 U6 l( Z+ m+ o& H9 g
...... $ `4 P7 }. d- ^2 X: W3 U
7 ]. P" a) [8 f% \
$ P9 M9 S, @/ x/ u9 q% M* F5 X" ]
大概在133行左右,$_GET[‘code’]没有经过任何判断和过滤。 `3 A. @' K8 S
" y6 C. |/ ?4 V; r V1 OInclude/payment/yeepay.php; G4 x/ f( W/ ^: e6 ]
. U/ @* p2 i1 O. Y( A
( Q6 Z) \- d. n: g! W% l/ o( W* D. U5 s B( f: ?
......
( s) L1 D' e. s( `, s function respond()
1 Z- l0 c! E1 n {
( |' Q, ^* \' q+ I K 0 R0 N( a9 ]! t- L# n. i8 J
/* 引入配置文件 */
' w9 x j' C( D require_once DEDEDATA.'/payment/'.$_REQUEST['code'].'.php';3 j9 N4 F7 p% _' i, L# m! G" r
/ d8 }/ z7 D2 K) B
$p1_MerId = trim($payment['yp_account']);
# ~. f4 M& C' A- R! M2 U6 p% c $merchantKey = trim($payment['yp_key']);# u* u( L# g4 c
......
2 [# H" O; T8 l4 s3 G( i# ^- k
8 I3 M/ h/ k V3 K
1 E- ~2 ] i; _2 O3 t# {6 Z ' G& A+ Q2 c q6 S1 \) _
$ M0 T& q2 R0 b8 d0 |! S5 h大概在145行左右,$_REQUEST['code']没有经过任何判断和过滤。8 |; x) s' W u+ `$ P
6 o% f& ~/ w) C, R1 B( t这两个方法在plus/carbuyaction.php文件调用。
; J3 P9 g( s2 i4 j# P- {4 E
; [1 z: T4 l0 p8 c% q, cplus/carbuyaction.php
) f6 L* ^ L, q/ N2 n- ]. z
2 m; k6 G5 B! f2 A......
# h" Q2 G- S7 Q* t} else if ($dopost == 'return') {+ X; F+ b( I- }4 e" F
$write_list = array('alipay', 'bank', 'cod', 'yeepay');
) g- K5 Z. Q' g% ~: g& h: g if (in_array($code, $write_list))! T# V d l0 k% @
{2 o# \/ e9 |+ z0 T: ?9 M0 n
require_once DEDEINC.'/payment/'.$code.'.php';1 [+ L) s5 t, X: z4 N! N
$pay = new $code;
: r0 b( }2 g/ {+ H @2 y- Z $msg=$pay->respond();
5 f$ i1 V3 Y, z8 |0 k0 k" \! q3 l ShowMsg($msg, "javascript:;", 0, 3000);
9 s: E$ Z# o1 ^! o( i exit(); 2 A4 l0 l: a! L, B2 @6 h
} else {
" y$ |1 [& D* l exit('Error:File Type Can\'t Recognized!');
1 o8 U3 J) B$ S0 x- \, e( z5 m }
F2 r. |1 z: A0 G( [}& s5 a. ]+ _. _$ V' d5 W& v
...... , F+ y# e D! a, K e. y
# z# t5 a% G$ P/ k4 l
4 r7 m2 P3 u6 n& N- z* @3 k 6 e9 o3 Y/ N% |2 o4 o, N0 E
7 S9 ~# M2 D% D, [ 4 v4 C- a8 E' U! B) x: e
) B( I8 Y1 Q! k9 K; R$ Q& a" g
大概在334行,当$dopost等于return的时候就开始进入过程了。熟悉dedecms朋友都知道在include/common.inc.php使用了一种类似register_globals的机制。" }1 D' z" a3 }5 [% L% v4 D
所以$_GET['code']或$_REQUEST['code']会变成$code,而$code是经过判断的,值必须在$write_list数组以内这样才能继续后面的流程调用respond方法触发漏洞。这样的话貌似就无法控制$_GET['code']为任意值了。
" F* o) | y5 q1 x& Z+ x
7 o. Y# i4 j5 S/ C p$ d回到include/common.inc.php来看看他的机制。% I7 ^9 A i. P) K, h
$ o ]/ @; u: t5 j7 d+ X
Q" L V0 B' e0 y0 m: L
) |0 l( D- B% A. h: o% @7 ~
......8 E) v& E+ i, d8 \# ~
foreach(Array('_GET','_POST','_COOKIE') as $_request)* O# R: x; ]/ G7 [
{9 w1 R, K/ e7 Q; i4 |- y# ^$ J
foreach($$_request as $_k => $_v) 6 U3 w3 E$ M7 g$ _9 g: a
{& i Y/ [8 O: @
if($_k == 'nvarname') ${$_k} = $_v;
" v" i7 |9 H; @+ V else ${$_k} = _RunMagicQuotes($_v);9 f3 r& u% B a, `2 d5 {( p
}( ~% p4 C: d# B$ ^8 F
}
8 C5 l/ {/ y/ s......
. j( k" m3 Z4 [' Z" J! }1 B大概在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。暴路径:: o7 {7 [, N0 m* W; H: d( n( m
由于bank和cod这两个文件并没有respond方法,所以如果code等于bank或者cod时将会暴错泄露路径。注:请勿非法测试,产生后果与本人无关。 |