晚餐吃撑了,瞄下代码消化消化。最近Php0day群里的兄弟都在讨论dede洞多,赶紧下了套,用editplus搜索了几个关键字,果然发现些问题。(话说平时写代码也喜欢用editplus,小巧方便多年习惯)* `& V% l6 t' V6 X5 A: _
- _7 e! ^6 r0 r
出现漏洞的两个文件为:/ `- y$ J& d' \( }/ b
Include/payment/alipay.php
' ^1 M7 @) N" z* |1 ?3 v- C) JInclude/payment/yeepay.php: M% v* k; |/ V! U& |
漏洞均出现在respond方法里,估计这两个文件是临时工写的。
3 S! s+ P0 e9 F: Z) ?* L. G+ i0 I* s" U4 ~$ n; h
Include/payment/alipay.php
% Q8 M+ |& r" K: |9 O
+ ?% h: C8 o0 q# c+ z; r2 P......
" r, P9 w0 e [% I5 j function respond()
/ u/ h( o* R7 E {. R* Y1 f/ B/ G
if (!empty($_POST))# h$ P6 K( q; S& Q* t' |
{) ?, o' q- K, R7 Y$ A! H
foreach($_POST as $key => $data)
: u- N- ^. [4 y# V {
& b7 K" S" t) ^; }* g! S1 v $_GET[$key] = $data;
9 J T" O! G3 V b6 ]' p# u' _2 n }, \: x# f+ ?4 |% d1 X9 e- X
}
* {8 D1 _& E7 X+ v( i3 a /* 引入配置文件 */, d! G- y& L$ X# b% m; i2 B. }
require_once DEDEDATA.'/payment/'.$_GET['code'].'.php'; _/ B2 D0 b; }. _ o
......
6 Y4 P7 \, p& U- Y4 |6 l2 g
8 O4 b4 y' Q3 G( J' E8 [3 i" |- z, g* O. {" X% r1 X
大概在133行左右,$_GET[‘code’]没有经过任何判断和过滤。
: }& b8 l& `1 v! I6 T
" b u# _+ S! XInclude/payment/yeepay.php
9 ]; c8 @: k0 E/ [9 _3 N8 h' \
& L+ S1 N3 `" X2 _& v" N 3 C5 J# I a9 E& O2 v2 a
) @( v+ q# {; _8 u
......! `$ w0 d9 O1 O& o% ?8 \9 c
function respond()
# l/ K. Q* i% v7 W* a {7 g9 H+ C: i# x# k& ^) c0 m. q" V
n( S( |% l" ^1 _
/* 引入配置文件 *// m) t0 K' W V) C
require_once DEDEDATA.'/payment/'.$_REQUEST['code'].'.php';" D5 L2 C* ]# x0 D" h
' k3 t9 d& H; H3 M7 l# }
$p1_MerId = trim($payment['yp_account']);
$ Z. `' p1 u7 A# Z $merchantKey = trim($payment['yp_key']);
' F f2 |4 P! I+ D0 n7 b...... # [9 E. w5 K6 @7 y" y
; h: ^, T" t! m5 H
5 ^1 i# x2 {5 [6 I0 ` / U, N# v' ~. {3 l6 B
* N$ G8 W" W8 M+ M' q9 x; `大概在145行左右,$_REQUEST['code']没有经过任何判断和过滤。8 ]4 D4 C9 S8 B' P3 z6 T
( _' v. H. f+ l3 z; }) P2 |- [
这两个方法在plus/carbuyaction.php文件调用。# q1 s3 J$ L: N
$ h4 F( R% C. O& H( L! [plus/carbuyaction.php
( a7 L0 x. B1 p& W' R5 f
9 s) K3 y3 H' M( d3 S7 H5 G- Q1 j......- P. p" G# l! Z1 e# ]0 Q
} else if ($dopost == 'return') {1 R$ Q# D9 s) z7 g+ K4 n0 H# P
$write_list = array('alipay', 'bank', 'cod', 'yeepay');% _' m: `& i J
if (in_array($code, $write_list))
T. u5 Z0 |' {) ^9 o9 k {
$ J t9 I/ n0 c5 f' M; L' X require_once DEDEINC.'/payment/'.$code.'.php';
6 U+ g2 z3 n/ t; z! A $pay = new $code;( ~ _: o- Y, b: o' _: n9 J
$msg=$pay->respond();. H5 R; B$ Q/ `& L
ShowMsg($msg, "javascript:;", 0, 3000);
$ {# i! p5 \" c$ z1 G6 z exit();
$ r- r: @- @& K$ }5 n3 ]: f, a } else {
( \& `9 A3 ]1 ] exit('Error:File Type Can\'t Recognized!');8 M! P8 k6 L1 X% L
}
: u* ^# L5 f2 S1 Y3 {, ]}
# \2 M; X- t, i- P6 W......
8 ]: |2 W6 S) I% Y0 q 5 D; Y' A* V' v( L$ A
; z- E b& W1 q) y. T. d( Q) a
. a3 _! y4 D. R7 J* J- q
9 B8 I) h8 P! F, J& |* ] Z
+ Y" Z1 U a; y) g1 c7 [2 P8 ^4 i4 c- A) A
大概在334行,当$dopost等于return的时候就开始进入过程了。熟悉dedecms朋友都知道在include/common.inc.php使用了一种类似register_globals的机制。
" H. ]' g ?% V+ w [所以$_GET['code']或$_REQUEST['code']会变成$code,而$code是经过判断的,值必须在$write_list数组以内这样才能继续后面的流程调用respond方法触发漏洞。这样的话貌似就无法控制$_GET['code']为任意值了。
1 ?- m1 h3 U/ B" g
+ \9 h0 r+ [* f- X, D( _$ u回到include/common.inc.php来看看他的机制。5 l& K: C4 ?2 D& I0 f7 ^
1 a: d9 x; S8 \( p; B5 ] . D& j# g) @+ T( k
) p2 V9 L$ Y. [5 V# C8 w......
3 D7 D5 {) T" M. u" I3 ~. |+ tforeach(Array('_GET','_POST','_COOKIE') as $_request)
; [4 t1 l. z2 G, d: v' E{
' A3 C/ V) |8 i$ J) T( e3 ^ foreach($$_request as $_k => $_v) : Z. J, y! [5 I) D# V# O
{
6 b' ]5 Z3 L& S8 n if($_k == 'nvarname') ${$_k} = $_v;
$ ?- _9 a0 V( ^1 K! w! C else ${$_k} = _RunMagicQuotes($_v);
! ^; L8 m; F$ F/ C! ^4 q }
2 g4 q! S8 o% j' J! b}0 n/ m7 R0 j& F# J# s9 ~
......
* D+ Z7 L, R# E& E& G* J$ g: d大概在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。暴路径:
. ^6 w2 ?. `) \! \; i由于bank和cod这两个文件并没有respond方法,所以如果code等于bank或者cod时将会暴错泄露路径。注:请勿非法测试,产生后果与本人无关。 |