晚餐吃撑了,瞄下代码消化消化。最近Php0day群里的兄弟都在讨论dede洞多,赶紧下了套,用editplus搜索了几个关键字,果然发现些问题。(话说平时写代码也喜欢用editplus,小巧方便多年习惯)
* {6 N: r2 {; ]; V: _8 k/ @; Z; R& Y _( {
出现漏洞的两个文件为:
- f1 D: w/ P, N$ T( J0 x$ pInclude/payment/alipay.php
1 L6 Q/ h; u: @Include/payment/yeepay.php
- n$ h; ?6 E2 I1 [4 i2 `漏洞均出现在respond方法里,估计这两个文件是临时工写的。
1 I3 W) A, k4 p$ I
' w3 L* p# `8 D. aInclude/payment/alipay.php# Q& Y+ c- v5 a" E/ {2 s$ V" f/ |
' r# v1 G! @: {" H3 g
...... E% W0 R4 l( f! M
function respond()# c/ v4 o# p8 ]% M* E4 i5 ~* k5 t
{5 u& y1 B1 h* D/ Y3 ]. H
if (!empty($_POST))
+ P e$ `4 W! o' A$ _ {
3 s0 m( H3 d" T/ ~( R foreach($_POST as $key => $data)
2 b% p6 m6 ^0 ~9 x) G: L7 _! S {
* B5 T2 U; H) ^4 q" t $_GET[$key] = $data;
: s: N9 A3 P7 U6 n }, s0 ~; j2 l1 r1 G
}
4 |2 p. ]- h* ^$ ]. I0 O /* 引入配置文件 */, d9 c( X: R# @0 P! M; t/ X
require_once DEDEDATA.'/payment/'.$_GET['code'].'.php';
$ F( A8 S( e) S2 R! \...... 7 S2 z( ~/ E% J9 R
0 o3 Y4 T+ K" a4 V- P! e; R* D/ ^/ w( D/ |7 P+ Z6 b
大概在133行左右,$_GET[‘code’]没有经过任何判断和过滤。6 ] }) o9 x V; r7 _7 k
/ n3 I0 j$ ]+ q. {
Include/payment/yeepay.php
# [+ q( X3 M; x" n" ?
1 V J8 n. [3 T2 W
& j( H& N: ]- ^& G
3 C6 g1 y S2 U......
3 A# l; O$ E7 }2 O" y: B+ a function respond()
, i* m. Q/ u/ T1 T; o {
3 Q1 K3 _1 [8 v- q$ p: ~5 f \5 W5 r7 k8 w
/* 引入配置文件 */
. ]( U1 x6 M" K require_once DEDEDATA.'/payment/'.$_REQUEST['code'].'.php';! ~) N3 O2 Y* B" y# j
/ q2 i* j8 x3 i7 S' O& L
$p1_MerId = trim($payment['yp_account']);6 q9 _8 o. N6 o4 B3 o
$merchantKey = trim($payment['yp_key']);, v0 j* C$ c% ?) S8 S. _# h/ A3 v
......
( m/ c4 |- n6 v/ B7 B' P8 M
1 @5 O! x% A+ b2 f, s; j
$ A$ G4 L3 z. J. P3 W `$ m / q5 _: h1 v) H/ @. O
% T$ A$ S; T7 N大概在145行左右,$_REQUEST['code']没有经过任何判断和过滤。
6 E5 K6 x1 v; @2 T8 |! V: e4 R* a c! V2 X' m
这两个方法在plus/carbuyaction.php文件调用。8 L7 r& B, f. u
" f* S0 B1 x; `% b! ~8 a8 cplus/carbuyaction.php
+ V0 `6 N( V! \! @. l
7 C% v. I0 h" O. w0 l......& F, A0 v% G8 v% f! r# Z
} else if ($dopost == 'return') {
/ E$ ~) `4 _9 N3 W* y L/ Q/ l $write_list = array('alipay', 'bank', 'cod', 'yeepay');
' g1 Z0 M8 l: y+ E if (in_array($code, $write_list))2 h; E& x1 u' u- c
{
/ r" Q# j( g7 h, v require_once DEDEINC.'/payment/'.$code.'.php';( i& c" y- r Y8 U
$pay = new $code;
# `. c, U5 `8 M $msg=$pay->respond();
1 F- I5 C8 _3 @" N/ `; M* ^ ShowMsg($msg, "javascript:;", 0, 3000);
: u* I- Q, ]3 D: K6 Z exit(); ( d8 z" K5 x6 w! u: l. k+ q
} else {' o, B4 u: u% v) }0 c5 { J
exit('Error:File Type Can\'t Recognized!');/ M9 }: g7 d" f- h) i& ]
}
! P8 D4 |% A% L3 u5 L6 L}
1 J9 i. G+ R/ f) g! [9 O Y5 x......
- K& R% ]. E* r) k* M: N5 g
4 H8 U% e" u3 r# }* |. A( h- q V6 a
1 L4 u6 u" c. x2 }2 y/ g
( h7 ^3 w- }" B$ |' Q$ F 3 U% K5 X9 G4 X, A& U) _
, d x! A3 C: |* d
大概在334行,当$dopost等于return的时候就开始进入过程了。熟悉dedecms朋友都知道在include/common.inc.php使用了一种类似register_globals的机制。
3 s4 R( | L" s0 @1 H5 |所以$_GET['code']或$_REQUEST['code']会变成$code,而$code是经过判断的,值必须在$write_list数组以内这样才能继续后面的流程调用respond方法触发漏洞。这样的话貌似就无法控制$_GET['code']为任意值了。, Q. h+ ^3 m G0 M, s% L1 Y3 w# @0 V
6 L7 P6 E" x2 y
回到include/common.inc.php来看看他的机制。/ B% c! t: d6 |4 W: _# d
7 W- {& L+ K2 R! g
/ W: a; j; I3 S( b& y
- m3 w5 M) _! D% a
......
% J6 _5 R4 f4 w" {- E Iforeach(Array('_GET','_POST','_COOKIE') as $_request)
% f! U% k; m# }% d+ l# t{
4 a; c# T* h9 E! ` foreach($$_request as $_k => $_v) 3 t4 n8 R) a# K9 l, O9 g0 k: W A
{
! g% d! l/ y3 h T# R if($_k == 'nvarname') ${$_k} = $_v;" T( Q9 S- C, Y* S" X
else ${$_k} = _RunMagicQuotes($_v);# b" A9 l' z& l9 k/ i
}$ Q$ e# O' ]2 a8 i1 l
}
7 A% B$ w8 L, d( N......
0 P4 W* N: y( w1 m w大概在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。暴路径:7 s) P' Q+ b0 ^8 p* C9 _' [
由于bank和cod这两个文件并没有respond方法,所以如果code等于bank或者cod时将会暴错泄露路径。注:请勿非法测试,产生后果与本人无关。 |