Home  >  Article  >  Backend Development  >  php检测下传excel文件类型

php检测下传excel文件类型

WBOY
WBOYOriginal
2016-06-13 13:00:06995browse

php检测上传excel文件类型

前言

介绍一种比较高端检测上传文件类型的方法,可以防止后缀名修改等低端的检测错误,有耐心的同学可以参考一下,我会封装成类供调用


MIME类型

在把输出结果传送到浏览器上的时候,浏览器必须启动适当的应用程序来处理这个输出文档。这可以通过多种类型MIME(multipurpose internet mail extensions)来完成。在http中,MIME类型被定义在content-type header中。

例如,如果客户端上传一个excel文件到服务器上,那么这是的mime类型就是“application/vnd.ms-excel”。在php中,可以通过$_FILE["type"]获得上传文件类型。

最早的HTTP协议中,并没有附加的数据类型信息,所有传送的数据都被客户端解释为HTML文档,而为了支持多媒体数据类型,HTTP协议中就使用了附加在文档之前的MIME数据类型信息来标识数据类型。

每个MIME类型由两部分组成,前面是数据的大类别,后面定义具体的种类。(具体可以查询mime类型表)


文件检测弊端

  • 文件扩展名检测漏洞(ps:文件扩展名可以被任意伪造)
  • 文件MIME类型判断不能使用$_FILES['userfile']['type'](ps:根据PHP官方的文档说明,该值完全可以被伪造!黑客只需修改浏览器的post请求头即可绕过这段代码检查,进而上传任意类型的文件!)

检测方法(针对excel)

  • 通过文件扩展名判断是03的excel文件还是07的excel文件
  • 根据不同的文件,获取不同文件的二进制数据,和file_signature进行对比,我截了03和07的excel的二进制数据图,大家可以参考一下,工具是madedit
  • 03的excel

  • 07的excel(07可以参考zip检测)


检测程序

	/**
	 * Detect upload file type
	 * 
	 * @param array $file        	
	 * @return bool $flag
	 */
	private function detectUploadFileMIME($file) {
		// 1.through the file extension judgement 03 or 07
		$flag = 0;
		$file_array = explode ( ".", $file ["name"] );
		$file_extension = strtolower ( array_pop ( $file_array ) );
		
		// 2.through the binary content to detect the file
		switch ($file_extension) {
			case "xls" :
				// 2003 excel
				$fh = fopen ( $file ["tmp_name"], "rb" );
				$bin = fread ( $fh, 8 );
				fclose ( $fh );
				$strinfo = @unpack ( "C8chars", $bin );
				$typecode = "";
				foreach ( $strinfo as $num ) {
					$typecode .= dechex ( $num );
				}
				if ($typecode == "d0cf11e0a1b11ae1") {
					$flag = 1;
				}
				break;
			case "xlsx" :
				// 2007 excel
				$fh = fopen ( $file ["tmp_name"], "rb" );
				$bin = fread ( $fh, 4 );
				fclose ( $fh );
				$strinfo = @unpack ( "C4chars", $bin );
				$typecode = "";
				foreach ( $strinfo as $num ) {
					$typecode .= dechex ( $num );
				}
				echo $typecode;
				if ($typecode == "504b34") {
					$flag = 1;
				}
				break;
		}
		
		// 3.return the flag
		return $flag;
	}

参考链接

文件类型对照表


Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn