晚餐吃撑了,瞄下代码消化消化。最近Php0day群里的兄弟都在讨论dede洞多,赶紧下了套,用editplus搜索了几个关键字,果然发现些问题。(话说平时写代码也喜欢用editplus,小巧方便多年习惯)
{6 v8 S9 I r' S; T) k3 ~1 U; u0 ^% G
出现漏洞的两个文件为:* U! p o0 n, S: z
Include/payment/alipay.php5 y3 c, L; A7 R9 H
Include/payment/yeepay.php
8 |2 T# p; @0 p$ v( f漏洞均出现在respond方法里,估计这两个文件是临时工写的。
. A4 B7 n# j- l+ {, b! J" G4 r: g* q7 V2 j
Include/payment/alipay.php; ^% s- r) B$ k2 X) A$ x
7 j* s8 B' Y) h, [0 N5 Q+ L1 v. K....../ o" J9 m3 d: _! p: p( F
function respond()
" a+ {: \3 S; W9 f, w4 c {7 N; f- W- s: I% M0 q$ ^
if (!empty($_POST))5 n3 x1 K! I- v$ b. o
{
3 t# _( e6 H9 N" \3 ? foreach($_POST as $key => $data)
) n) D5 j% `+ g8 {- X {! m0 K- T2 w$ j- W2 _2 ]! F
$_GET[$key] = $data;
9 [# z2 r; n) g }
3 w7 ?3 Z5 o H6 o/ l; W# ?' } }
! ]. U# ^" i" ~- \ /* 引入配置文件 */2 j; T- t( `/ q- {
require_once DEDEDATA.'/payment/'.$_GET['code'].'.php';
6 A" S/ g) n4 G% }. R8 K7 M/ Y& v......
- X& U. v3 Y: Q5 K0 K O0 i `3 V( E0 \) V+ V& E
' r# J5 @5 P0 Z: U大概在133行左右,$_GET[‘code’]没有经过任何判断和过滤。6 {! r& b* I6 P9 Y9 j
- L- H& _' S1 I4 |1 Z5 W+ ?
Include/payment/yeepay.php
9 `1 I. ^1 D( v% G2 y' A/ f) A$ k
4 Q: O9 k' Y* t ~0 z9 Y! s8 R$ H
8 ? Z! N& A9 m2 X9 L# f
......4 X9 Q3 \) \& T5 [' J' a; a
function respond()
+ W, ]- |4 u T3 [! n8 ~& \ {* P. M7 c% |" k) ]) A0 X
A. x s/ w6 ]( S9 i$ _$ ]: g3 \
/* 引入配置文件 */
) r7 T# E3 s" [& @ require_once DEDEDATA.'/payment/'.$_REQUEST['code'].'.php';
3 w/ ^& w& \ j( R! ~" K ! _/ p4 R5 A( ^" m9 z" J
$p1_MerId = trim($payment['yp_account']);
$ R1 o' p8 @! w, a1 Z" j: [2 M+ | $merchantKey = trim($payment['yp_key']);
~* g1 B7 M" |7 B0 T: b...... # j7 f4 N6 `! l/ a# S) o; h( a, T
6 U q# ^, C5 t) A* t1 P X! Z" O; \) G
0 a7 R9 t/ {3 v' ^
( O4 K) \1 f8 q* I+ {+ _0 _9 ]
大概在145行左右,$_REQUEST['code']没有经过任何判断和过滤。
: e4 `/ e$ n" v; j. C
1 P; k( @ Z' n) T) s& M0 O) |7 f这两个方法在plus/carbuyaction.php文件调用。
+ I8 @' x0 @# H3 F0 @
: M B# M4 q. v: u5 _4 O! [! gplus/carbuyaction.php% L0 C _3 U" w, {- s
: U. k6 u2 F. ~
......$ X% H) `3 n3 b) x2 M
} else if ($dopost == 'return') {, ^1 v v: _3 p$ H2 S7 R% T+ R
$write_list = array('alipay', 'bank', 'cod', 'yeepay');
9 j1 P8 G) R$ c if (in_array($code, $write_list))0 I z8 n: X4 _6 a
{
/ q) O; r6 N) C; [& |5 K, [ require_once DEDEINC.'/payment/'.$code.'.php';
& `5 |' R: f4 B! w: E% F $pay = new $code;# |5 v9 @8 v4 z. k
$msg=$pay->respond();, j3 v) b4 N, }$ c4 _" X1 N+ l4 `
ShowMsg($msg, "javascript:;", 0, 3000);
- G: u% X1 s- D( t0 Z exit();
) P Z( K/ n* E& Z+ f6 Y* J# K } else {
$ q6 o' @ z3 q2 U& j exit('Error:File Type Can\'t Recognized!');3 m% X# q" N% v" H$ {8 {
}
2 H! ~( p6 o2 q& M}7 }$ e5 y3 |; {) p3 n
......
- \* _, m$ L J1 x
, p0 j) l! Z7 |- G. S3 T( a4 ^1 a* o' N4 |
( r/ I4 K, K. n; f2 d* ], Y( D
3 b* M5 E' Z3 Z
! g) N4 O4 A4 T! C! I& d. x2 \
S9 ]! v6 Z- }4 ^4 z
大概在334行,当$dopost等于return的时候就开始进入过程了。熟悉dedecms朋友都知道在include/common.inc.php使用了一种类似register_globals的机制。
' u4 s6 P" d5 c) }. ^0 T3 A; a3 D所以$_GET['code']或$_REQUEST['code']会变成$code,而$code是经过判断的,值必须在$write_list数组以内这样才能继续后面的流程调用respond方法触发漏洞。这样的话貌似就无法控制$_GET['code']为任意值了。% z. N- S; c, ], z
4 k8 A/ P V/ d9 M% U8 Y
回到include/common.inc.php来看看他的机制。% J F; Y) F: x( i3 k
& k( d+ L! f& O5 g, z$ Z
% r5 n7 W* Z2 w% ^" R0 O+ M
+ t& n) j' X* U+ m; X. _" ~
......
Q, R; R) O5 F: ~& Yforeach(Array('_GET','_POST','_COOKIE') as $_request)
/ o% I" [6 M, W9 A# c6 `' [{8 K; T. S; w3 `9 V& |
foreach($$_request as $_k => $_v)
$ m, L5 g1 x8 z; b4 V; Y {* `0 j) ?7 J& ?0 |% C! P) @
if($_k == 'nvarname') ${$_k} = $_v;
2 ?0 n) X; j) W; G0 v else ${$_k} = _RunMagicQuotes($_v);
6 T2 F/ ?0 G5 R2 t, S: d }0 V: x0 Y- P4 X# s: C
}
7 C+ U$ B+ u$ J3 _: N/ S6 t& j...... 1 i" C( v* U. [9 B# 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。暴路径:8 c4 h! V' K% y( \' l$ T
由于bank和cod这两个文件并没有respond方法,所以如果code等于bank或者cod时将会暴错泄露路径。注:请勿非法测试,产生后果与本人无关。 |