在WEB系统中,上传文件时都需要做文件的类型校验,大致有如下几种方法:
1. 通过后缀名,如exe,jpg,bmp,rar,zip等等。
2. 通过读取文件,获取文件的Content-type来判断。
3. 通过读取文件流,根据文件流中特定的一些字节标识来区分不同类型的文件。
4. 若是图片,则通过缩放来判断,可以缩放的为图片,不可以的则不是。
然而,在安全性较高的业务场景中,1,2两种方法的校验会被轻易绕过。
1. 伪造后缀名,如图片的,非常容易修改。
2. 伪造文件的Content-type,这个稍微复杂点,为了直观,截图如下:
3.较安全,但是要读取文件,并有16进制转换等操作,性能稍差,但能满足一定条件下对安全的要求,所以建议使用。
但是文件头的信息也可以伪造,截图如下,对于图片可以采用图片缩放或者获取图片宽高的方法避免伪造头信息漏洞。
被伪装成gif的恶意图片文件
对应的Java代码如下:
- package apistudy;
-
-
import java.awt.image.BufferedImage;
-
import java.io.File;
-
import java.io.FileInputStream;
-
import java.io.FileNotFoundException;
-
import java.io.IOException;
-
import java.io.InputStream;
-
import java.util.HashMap;
-
import java.util.Iterator;
-
import java.util.Map;
-
import java.util.Map.Entry;
-
import javax.imageio.ImageIO;
-
import javax.imageio.ImageReader;
-
import javax.imageio.stream.ImageInputStream;
-
-
public class FileTypeTest
- {
-
public final static Map<String, String> FILE_TYPE_MAP = new HashMap<String, String>();
-
-
private FileTypeTest(){}
-
static{
-
getAllFileType();
- }
-
-
-
-
-
-
-
private static void getAllFileType()
- {
-
FILE_TYPE_MAP.put("jpg", "FFD8FF");
-
FILE_TYPE_MAP.put("png", "89504E47");
-
FILE_TYPE_MAP.put("gif", "47494638");
-
FILE_TYPE_MAP.put("tif", "49492A00");
-
FILE_TYPE_MAP.put("bmp", "424D");
-
FILE_TYPE_MAP.put("dwg", "41433130");
-
FILE_TYPE_MAP.put("html", "68746D6C3E");
-
FILE_TYPE_MAP.put("rtf", "7B5C727466");
-
FILE_TYPE_MAP.put("xml", "3C3F786D6C");
-
FILE_TYPE_MAP.put("zip", "504B0304");
-
FILE_TYPE_MAP.put("rar", "52617221");
-
FILE_TYPE_MAP.put("psd", "38425053");
-
FILE_TYPE_MAP.put("eml", "44656C69766572792D646174653A");
-
FILE_TYPE_MAP.put("dbx", "CFAD12FEC5FD746F");
-
FILE_TYPE_MAP.put("pst", "2142444E");
-
FILE_TYPE_MAP.put("xls", "D0CF11E0");
-
FILE_TYPE_MAP.put("doc", "D0CF11E0");
-
FILE_TYPE_MAP.put("mdb", "5374616E64617264204A");
-
FILE_TYPE_MAP.put("wpd", "FF575043");
-
FILE_TYPE_MAP.put("eps", "252150532D41646F6265");
-
FILE_TYPE_MAP.put("ps", "252150532D41646F6265");
-
FILE_TYPE_MAP.put("pdf", "255044462D312E");
-
FILE_TYPE_MAP.put("qdf", "AC9EBD8F");
-
FILE_TYPE_MAP.put("pwl", "E3828596");
-
FILE_TYPE_MAP.put("wav", "57415645");
-
FILE_TYPE_MAP.put("avi", "41564920");
-
FILE_TYPE_MAP.put("ram", "2E7261FD");
-
FILE_TYPE_MAP.put("rm", "2E524D46");
-
FILE_TYPE_MAP.put("mpg", "000001BA");
-
FILE_TYPE_MAP.put("mov", "6D6F6F76");
-
FILE_TYPE_MAP.put("asf", "3026B2758E66CF11");
-
FILE_TYPE_MAP.put("mid", "4D546864");
- }
-
-
public static void main(String[] args) throws Exception
- {
-
File f = new File("c://aaa.gif");
-
if (f.exists())
- {
- String filetype1 = getImageFileType(f);
- System.out.println(filetype1);
- String filetype2 = getFileByFile(f);
- System.out.println(filetype2);
- }
- }
-
-
-
-
-
-
-
-
-
public final static String getImageFileType(File f)
- {
-
if (isImage(f))
- {
-
try
- {
- ImageInputStream iis = ImageIO.createImageInputStream(f);
- Iterator<ImageReader> iter = ImageIO.getImageReaders(iis);
-
if (!iter.hasNext())
- {
-
return null;
- }
- ImageReader reader = iter.next();
- iis.close();
-
return reader.getFormatName();
- }
-
catch (IOException e)
- {
-
return null;
- }
-
catch (Exception e)
- {
-
return null;
- }
- }
-
return null;
- }
-
-
-
-
-
-
-
-
-
public final static String getFileByFile(File file)
- {
-
String filetype = null;
-
byte[] b = new byte[50];
-
try
- {
-
InputStream is = new FileInputStream(file);
- is.read(b);
- filetype = getFileTypeByStream(b);
- is.close();
- }
-
catch (FileNotFoundException e)
- {
- e.printStackTrace();
- }
-
catch (IOException e)
- {
- e.printStackTrace();
- }
-
return filetype;
- }
-
-
-
-
-
-
-
-
-
public final static String getFileTypeByStream(byte[] b)
- {
- String filetypeHex = String.valueOf(getFileHexString(b));
- Iterator<Entry<String, String>> entryiterator = FILE_TYPE_MAP.entrySet().iterator();
-
while (entryiterator.hasNext()) {
- Entry<String,String> entry = entryiterator.next();
- String fileTypeHexValue = entry.getValue();
-
if (filetypeHex.toUpperCase().startsWith(fileTypeHexValue)) {
-
return entry.getKey();
- }
- }
-
return null;
- }
-
-
-
-
-
-
-
-
-
public static final boolean isImage(File file){
-
boolean flag = false;
-
try
- {
- BufferedImage bufreader = ImageIO.read(file);
-
int width = bufreader.getWidth();
-
int height = bufreader.getHeight();
-
if(width==0 || height==0){
-
flag = false;
-
}else {
-
flag = true;
- }
- }
-
catch (IOException e)
- {
-
flag = false;
-
}catch (Exception e) {
-
flag = false;
- }
-
return flag;
- }
-
-
-
-
-
-
-
-
-
public final static String getFileHexString(byte[] b)
- {
-
StringBuilder stringBuilder = new StringBuilder();
-
if (b == null || b.length <= 0)
- {
-
return null;
- }
-
for (int i = 0; i < b.length; i++)
- {
-
int v = b[i] & 0xFF;
- String hv = Integer.toHexString(v);
-
if (hv.length() < 2)
- {
-
stringBuilder.append(0);
- }
- stringBuilder.append(hv);
- }
-
return stringBuilder.toString();
- }
- }
这样,不管是传入的文件有后缀名,还是无后缀名,或者修改了后缀名,真正获取到的才是该文件的实际类型,这样避免了一些想通过修改后缀名或者Content-type信息来攻击的因素。但是性能与安全永远是无法同时完美的,安全的同时付出了读取文件的代价。本人建议可采用后缀名与读取文件的方式结合校验,毕竟攻击是少数,后缀名的校验能排除大多数用户,在后缀名获取不到时再通过获取文件真实类型校验,这样来适当提高性能。
分享到:
相关推荐
Jmagick是一款将ImageMagick图像处理库与Java平台相结合的扩展库,它允许Java开发者利用强大的ImageMagick功能来处理图像。在Java应用程序中,Jmagick通过Jmagick.dll动态链接库和Jmagick.jar文件提供对底层C++接口...
本文将深入探讨“Jmagick缩图”这一主题,它是一种基于Java的图片处理工具,用于快速有效地生成图片的缩略图。 JMagick是ImageMagick的一个Java接口,ImageMagick是一个强大的跨平台图像处理库。它允许Java开发者...
**JMagick图片处理**是图像操作的重要工具,它是一个Java接口,用于ImageMagick库,使得在Java环境中可以方便地进行图像处理。这个技术涵盖了多个关键知识点,包括创建缩略图、添加水印、切图以及压缩图片,这些都是...
本文将详细介绍如何在Java环境中安装和配置JMagick,以及如何使用提供的示例进行测试。 ### 1. 获取必备组件 首先,你需要下载以下两个关键组件: - **jmagick.dll**: 这是JMagick的核心动态链接库,它提供了Java...
- 安全监控:在安防系统中,可以利用JMagick进行视频帧的截取和分析,辅助识别异常行为。 总的来说,JMagick-win-6.3.9是Java开发者在处理图像任务时的一款强大工具,它结合了Java的便捷性和ImageMagick的强大功能...
jmagick.jar java图像应用
通过 JMagick,Java 开发者可以利用 C++ 编写的 ImageMagick 库的强大功能,无需直接编写原生代码或使用 JNI(Java Native Interface)。 **JMagick 的安装与配置** 在使用 JMagick 之前,需要先确保已经正确安装...
在Java中,垃圾回收机制通常能自动回收不再使用的对象,但在处理图像时,由于大型图像数据可能导致内存占用较高,需要特别注意内存的释放。 防止内存泄露的关键在于及时释放不再需要的资源。在JMagick中,这通常...
### Java高清处理图片:利用ImageMagick提升图片质量和效率 #### 背景与需求 在实际项目开发中,图片处理是一项常见的需求,包括但不限于图片的压缩、尺寸调整以及添加水印等操作。传统的Java库虽然能够实现这些...
里面包括jmagick 所需所有文件,jmagick.dll,jmagick.jar 还有安装文件, 以及linux安装说明! jmagick jmagick.jar jmagick资料 jmagick缩略图 jmagick jmagick.jar jmagick资料 jmagick缩略图
《JMagick与ImageMagick在Java环境中的应用》 JMagick与ImageMagick是两个在图像处理领域中广泛使用的开源库,尤其在Java环境中,它们为开发者提供了强大的图像处理功能。本文将深入探讨这两个工具的核心概念、功能...
"jmagick.jar"则是Java中的类库,提供了Java到C++接口的封装,使得开发者可以在Java代码中直接调用ImageMagick的API。这个文件需要添加到项目的类路径(classpath)中,以便Java编译器和运行时能够识别和使用。 ...
jmagick处理图片,图片高质量压缩,图片加水印。
本文将深入探讨JMagick及其在Java中的应用。 JMagick是ImageMagick的一个Java接口,ImageMagick是一款开源的跨平台图像处理工具,支持超过100种不同的图像文件格式。通过JMagick,Java开发者可以利用ImageMagick的...
jmagick.jar,Java项目中使用
JMagick将这种能力无缝地集成到Java应用程序中,使得开发者可以在Java环境中执行复杂的图像操作,而无需依赖外部进程或插件。 **核心特性** 1. **广泛的图像格式支持**:JMagick继承了ImageMagick的强大功能,能够...
在Java中,可以通过JavaMagick这个Java绑定库来调用ImageMagick的功能,如缩放、裁剪、转换格式等。`jmagick.dll`是JavaMagick在Windows环境下的动态链接库,用于支持Java与ImageMagick的交互。 6. **JavaMagick**...
描述和标签中的信息与标题相同,暗示这个压缩包可能包含了完整的JMagick源码或者二进制库,以及可能的构建或配置文件,以便用户在自己的Java项目中集成和使用JMagick。 压缩包内的文件名称列表包括: 1. README.TXT...
要实现在Java中添加水印,我们可以利用开源的图像处理库,如Apache Commons Imaging(原名:Sanselan)、ImageMagick的Java绑定(JMagick)或Java Advanced Imaging (JAI)。这里以Apache Commons Imaging为例,因为...
JMagick则将其功能融入到Java环境中,使得Java开发者可以利用C++编写的ImageMagick库进行图像操作,而无需关心底层实现的复杂性。 在JMagick-5.5.6-0版本中,包含了完整的源代码,这对于开发者来说是极具价值的。源...