在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 java 图像处理jmagick java 图像处理jmagick java 图像处理jmagick java 图像处理jmagick java 图像处理
jmagick.jar java图像应用
里面包括jmagick 所需所有文件,jmagick.dll,jmagick.jar 还有安装文件, 以及linux安装说明! jmagick jmagick.jar jmagick资料 jmagick缩略图 jmagick jmagick.jar jmagick资料 jmagick缩略图
JMagick图片处理 缩略图 水印 切图 压缩图片
jmagick处理图片,图片高质量压缩,图片加水印。
使用两中方法进行压缩,可以只改变图片大小,如,原图片100kb,压缩后变成40kb。并且不改变宽高。 一.使用ImageMagick进行压缩类-Aa.java ...使用java自带的awt进行压缩,无需加入第三方jar,在ImageSizer.java中。
Jmagick32位的和Jmagick64位的Jmagick.dll,Jmagick.jar 图片处理必备工具
压缩包在java下使用jmagick的所有必需工具和安装包,还有使用实例。
开发图片搜索系统时用到的图片缩图解决方案,里面带了例子
JMagick是一个开源API,利用JNI(Java Native Interface)技术实现了对 ImageMagick API的Java访问接口,因此也将比纯Java实现的图片操作函数在速度上要快。
jmagick-win-6.3.9 java 图片裁剪工具
强大的图片处理工具,imagemagick的java接口
文件包含:ImageMagick-6.4.5-3-Q16-windows-dll.exe,jmagick.dll,jmagick.jar,压缩包中的版本统一,安装ImageMagick,复制ImageMagick安装目录的所有.dll文件和Jmagick.dll到,系统的system32下 即可使用,System.set...
jmagick.zip
jmagick.jar 及用法。。。。。。。。。。
java 图片放缩结束...防止内存泄露
jmagick image generate or operator library
压缩包在java下使用jmagick的所有必需工具和安装包,还有使用实例。
JMagick-6.0.4-0.tar 下载
jmagick-6.2.4-1-IM-6.2.5.zip