晚餐吃撑了,瞄下代码消化消化。最近Php0day群里的兄弟都在讨论dede洞多,赶紧下了套,用editplus搜索了几个关键字,果然发现些问题。(话说平时写代码也喜欢用editplus,小巧方便多年习惯)
" i/ R. i/ C* O6 f- |8 ~0 i& X/ k
出现漏洞的两个文件为:
( |, O3 J5 C4 j3 T/ ^% q, b# N9 X- EInclude/payment/alipay.php, F* v" G! ]1 ^+ `6 ~
Include/payment/yeepay.php* P1 x0 G2 v! }& d* @
漏洞均出现在respond方法里,估计这两个文件是临时工写的。
9 a% E$ h+ }# f+ R2 P* X* G9 K
/ \8 j: _; N* l, m+ g! HInclude/payment/alipay.php: l9 E8 E" _$ `6 D! W
( ?' D( X8 g% y0 v& r2 B......* T2 h3 f, m3 Q. i. w0 K
function respond()8 T% @2 J: W. l9 Y9 N N3 E% K" y
{7 T) }0 J) U$ U% r3 v6 V
if (!empty($_POST))
& G1 {2 B- `0 Q2 o- ? {
( a7 D( u+ H3 l* _ foreach($_POST as $key => $data), z1 b0 M, Y; l) B: N, C
{4 a; m: r+ A/ R. i
$_GET[$key] = $data;8 ]1 t9 X T0 D0 T# _
}7 r4 ^* V4 F& O! y3 i/ v
}
5 m+ }/ @$ b) u4 K5 f4 N/ n /* 引入配置文件 */6 c( J: k5 n }0 D, {! c
require_once DEDEDATA.'/payment/'.$_GET['code'].'.php';% c% j$ s/ A: v/ O
...... / D, o% t# W/ U4 o
/ w- p- F( F. h& R5 h i
3 P' d4 `4 M' @3 ?" N* i9 q
大概在133行左右,$_GET[‘code’]没有经过任何判断和过滤。
F& P2 x# Y0 k. e0 K4 ?& M/ V9 Q% g8 F1 w- k
Include/payment/yeepay.php# D4 h, ] y5 w- d/ F/ M
2 S) h' ?- m/ ^. P- e8 E3 W
6 ~0 b; Z6 t6 q2 e, Q+ A
5 e; {8 [* t4 n( Q5 d+ X......9 b3 D1 N0 L3 `3 D; ?2 y; J8 s& }8 n- j
function respond()7 P+ x3 Z m) M9 u7 j# l8 U1 ?* W
{1 o8 P/ r9 a- r, R2 W" u X- [" E
! ~5 U1 U2 e6 d# u- ~0 p' K/ B
/* 引入配置文件 */8 j0 f% n7 _6 d) L1 m8 A
require_once DEDEDATA.'/payment/'.$_REQUEST['code'].'.php';2 K M( S" M2 i! ?) ^
3 A1 J0 ]) z9 P9 s* }& E
$p1_MerId = trim($payment['yp_account']);
2 V; s0 z s. ^: Z! [4 r; | $merchantKey = trim($payment['yp_key']);$ q" l" q0 }. H1 a
...... * }- i7 w! U, j- I" N
. s" ~ q- s7 s5 V) J+ d% j
3 c p( a S4 z( a& r/ }* R
; P( { g: Y. @) {
6 v6 [+ d1 a8 M. ~大概在145行左右,$_REQUEST['code']没有经过任何判断和过滤。
' s, e7 x) Q3 v+ j$ [3 F( w6 Q! g( @6 F6 Z
这两个方法在plus/carbuyaction.php文件调用。7 h/ u8 |0 B4 E
) D0 j4 O% h3 rplus/carbuyaction.php
: U( N( b( q# H" o6 V/ i% b( ^0 P1 R7 c9 d; [; _- H: D/ ^
......9 X7 M9 L7 e, z
} else if ($dopost == 'return') {8 P2 I# v5 S' l3 V
$write_list = array('alipay', 'bank', 'cod', 'yeepay');! d4 `5 B- q; l A, H U9 a
if (in_array($code, $write_list)): b, F- s- d8 ^) h
{3 k. B- y- i2 e9 H1 G( v3 w- A
require_once DEDEINC.'/payment/'.$code.'.php';- m2 A. h# @9 I2 Q" \3 N# s
$pay = new $code;
9 t- I$ _! b; l& l5 p' a $msg=$pay->respond();) K4 n( Y3 p7 E2 X/ D* q: ~7 b
ShowMsg($msg, "javascript:;", 0, 3000);" {8 \* n5 q) T7 P2 F* n4 C
exit(); * Y |1 U3 U% V1 m0 y9 Y
} else {% f/ ~& F: }- r5 y$ T9 R, Z" ^
exit('Error:File Type Can\'t Recognized!');" f) N7 I* x# v- q
}# B6 b9 L- d4 a
}3 I2 J' q r7 G5 P; r; w9 e
......
! _- z8 L/ Q- V3 S" {4 }8 e " G+ l# C7 N) V, I- O
0 x0 K ?! e) y, X7 _8 s0 U8 R
: O& a# [% H1 ~) L
5 _2 R# v. b1 u( c
, r7 M1 n' U3 {' {
9 q* d" y) Z* E' f7 S/ m% T' R x* y大概在334行,当$dopost等于return的时候就开始进入过程了。熟悉dedecms朋友都知道在include/common.inc.php使用了一种类似register_globals的机制。
6 q! @6 J. N( E所以$_GET['code']或$_REQUEST['code']会变成$code,而$code是经过判断的,值必须在$write_list数组以内这样才能继续后面的流程调用respond方法触发漏洞。这样的话貌似就无法控制$_GET['code']为任意值了。: @; ~2 C$ _ `& W" x
- Y& n4 T5 W9 a, ~% v, N. X回到include/common.inc.php来看看他的机制。
/ J5 `" l) K" z; j# ^4 @/ q6 [: g/ J5 {: k3 I* \
, \" z3 Q# ~+ J! i& T& l
3 \# B- f0 i! E; b......* }# a& e7 @ H$ Q$ Q# I
foreach(Array('_GET','_POST','_COOKIE') as $_request)
* s* J' r1 R& e. h: C, L5 D* g% I% y{
4 G t# h8 G5 n$ B! p% V foreach($$_request as $_k => $_v)
+ Z3 G0 B+ b" ?. `9 y/ c {
# P- U2 D# W+ ?5 l if($_k == 'nvarname') ${$_k} = $_v;. ]0 b5 a) `, i, ~
else ${$_k} = _RunMagicQuotes($_v);
8 v" a. k' M! X) T! b o7 K; A }- y! z: U, z2 c1 S6 S; y& T' t+ s3 }
}: a# b) B! _+ R# C8 O, U5 r+ A- @
...... ; {: H) O: x8 \) e" ]% q
大概在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。暴路径:0 R6 l$ t) V1 x" e
由于bank和cod这两个文件并没有respond方法,所以如果code等于bank或者cod时将会暴错泄露路径。注:请勿非法测试,产生后果与本人无关。 |