梦想之家

PHPCMS uploadfile被上传php文件或其他执行文件解决方案

在使用phpcms的时候,发现 /uploadfile/ 目录下总是会生成一些php后缀的文件,这是攻击者利用PHPCMS会员注册的漏洞进行的文件注入,具体的会员注册文件流程这里就不做多介绍了;网上有很多相关的注入的文件流程,这里我直接说一下自己使用中是如何解决的。

文件注入的核心文件就是这个:/phpcms/libs/classes/attachment.class.php 文件里的download函数

/**
 * 附件下载
 * Enter description here ...
 * @param $field 预留字段
 * @param $value 传入下载内容
 * @param $watermark 是否加入水印
 * @param $ext 下载扩展名
 * @param $absurl 绝对路径
 * @param $basehref 
 */
function download($field, $value,$watermark = '0',$ext = 'gif|jpg|jpeg|bmp|png', $absurl = '', $basehref = '')
{
   global $image_d;
   $this->att_db = pc_base::load_model('attachment_model');
   $upload_url = pc_base::load_config('system','upload_url');
   $this->field = $field;
   $dir = date('Y/md/');
   $uploadpath = $upload_url.$dir;
   $uploaddir = $this->upload_root.$dir;
   $string = new_stripslashes($value);
   $ext = strval( $ext ); 
   if(!preg_match_all("/(href|src)=([\"|']?)([^ \"'>]+\.($ext))\\2/i", $string, $matches)) return $value;
   if( strpos($string,'#') !== false) return $value; //防止 member['info'] 提交带 xxx.php#.jpg 的文件注入
   $remotefileurls = array();
   foreach($matches[3] as $matche)
   {
      if(strpos($matche, '://') === false) continue;
      dir_create($uploaddir);
      $remotefileurls[$matche] = $this->fillurl($matche, $absurl, $basehref);
   }
   unset($matches, $string);
   $remotefileurls = array_unique($remotefileurls);
   $oldpath = $newpath = array();
   foreach($remotefileurls as $k=>$file) {
      if(strpos($file, '://') === false || strpos($file, $upload_url) !== false) continue;
      $filename = fileext($file);
      $file_name = basename($file);
      $filename = $this->getname($filename);

      $newfile = $uploaddir.$filename;
      $upload_func = $this->upload_func;
      if($upload_func($file, $newfile)) {
         $oldpath[] = $k;
         $GLOBALS['downloadfiles'][] = $newpath[] = $uploadpath.$filename;
         @chmod($newfile, 0777);
         $fileext = fileext($filename);
         if($watermark){
            watermark($newfile, $newfile,$this->siteid);
         }
         $filepath = $dir.$filename;
         $downloadedfile = array('filename'=>$filename, 'filepath'=>$filepath, 'filesize'=>filesize($newfile), 'fileext'=>$fileext);
         $aid = $this->add($downloadedfile);
         $this->downloadedfiles[$aid] = $filepath;
      }
   }
   return str_replace($oldpath, $newpath, $value);
}


注意在:

if(!preg_match_all("/(href|src)=([\"|']?)([^ \"'>]+\.($ext))\\2/i", $string, $matches)) return $value;

这行代码下面多加了一行:

if( strpos($string,'#') !== false) return $value; //防止 member['info'] 提交带 xxx.php#.jpg 的文件注入

这里代表匹配了文件名里有 # 字符串的,即返回不再下载文件了。这个符号在php中可以代表注释,后面的不执行,攻击者就是利用这个漏洞才进行的文件注入的。
网上还说还有一个方法就是,把  /uploadfile/  这个目录设为 禁止执行。

相关推荐

您此刻的心情: