校验文件的合法性

今天客户提出需要检验系统的安全性并且提出几点需要处理:

1、任意下载文件问题

可以任意下载文件,在使用burp抓包后,发送请求可以随便下载文件,解决方法对传入的路径过滤".","\","、"字符串。

2、发射型xss

可以通过XSS过滤检测或者对数据进行转义。

3、使用备份获取shell

限定文件后缀名,文件路径。

4、任意上传文件

检查文件的合法性和后缀名。

package com.hundsun.fund.common;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

public class FileFormatVerify {
    private static Map<String,String> FileTypes = null;
    
    public FileFormatVerify(){
        FileTypes = new HashMap<String,String>();
        
        // images          
        FileTypes.put("FFD8FFE0", ".jpg");
        FileTypes.put("89504E47", ".png");
        FileTypes.put("47494638", ".gif");
        FileTypes.put("49492A00", ".tif");
        FileTypes.put("424D", ".bmp");
         
        //PS和CAD
        FileTypes.put("38425053", ".psd");
        FileTypes.put("41433130", ".dwg"); // CAD
        FileTypes.put("252150532D41646F6265",".ps");
         
        //办公文档类
        FileTypes.put("D0CF11E0", ".doc"); //ppt、doc、xls
        FileTypes.put("504B0304", ".docx");//pptx、docx、xlsx   
         
        /**注意由于文本文档录入内容过多,则读取文件头时较为多变-START**/
        FileTypes.put("0D0A0D0A", ".txt");//txt
        FileTypes.put("0D0A2D2D", ".txt");//txt
        FileTypes.put("0D0AB4B4", ".txt");//txt       
        FileTypes.put("B4B4BDA8", ".txt");//文件头部为汉字
        FileTypes.put("73646673", ".txt");//txt,文件头部为英文字母
        FileTypes.put("32323232", ".txt");//txt,文件头部内容为数字
        FileTypes.put("0D0A09B4", ".txt");//txt,文件头部内容为数字
        FileTypes.put("3132330D", ".txt");//txt,文件头部内容为数字     
        /**注意由于文本文档录入内容过多,则读取文件头时较为多变-END**/
 
         
        FileTypes.put("7B5C727466", ".rtf"); // 日记本
         
        FileTypes.put("255044462D312E", ".pdf");
         
        //视频或音频类
        FileTypes.put("3026B275",".wma");
        FileTypes.put("57415645", ".wav");
        FileTypes.put("41564920", ".avi");
        FileTypes.put("4D546864", ".mid");
        FileTypes.put("2E524D46", ".rm");
        FileTypes.put("000001BA", ".mpg");
        FileTypes.put("000001B3", ".mpg");
        FileTypes.put("6D6F6F76", ".mov");
        FileTypes.put("3026B2758E66CF11", ".asf");
         
        //压缩包
        FileTypes.put("52617221", ".rar");    
        FileTypes.put("1F8B08", ".gz");
         
        //程序文件
        FileTypes.put("3C3F786D6C", ".xml");
        FileTypes.put("68746D6C3E", ".html");
        FileTypes.put("7061636B", ".java");
        FileTypes.put("3C254020", ".jsp");
        FileTypes.put("4D5A9000", ".exe");        
         
         
        FileTypes.put("44656C69766572792D646174653A", ".eml"); // 邮件
        FileTypes.put("5374616E64617264204A", ".mdb");//Access数据库文件
         
        FileTypes.put("46726F6D", ".mht");
        FileTypes.put("4D494D45", ".mhtml");
    }
    
    /**
     * @Description 根据传入的文件获得后缀,获得指定文件格式byte[]数组中的前8位字符
     *              将传入文件转化为byte[]数组,取前8位.判断传入文件的前8位和我们指定好的文件byte[]的前8位是否相同,
     *              如果相同则文件格式没有被篡改,反之,文件后缀格式被篡改
     * @Param [file]
     * @return boolean 返回true 表示文件格式验证通过, 返回false 文件格式验证失败
     **/
    public boolean suffixVerify(File file){
        String fileType = "";
        boolean isgood = false;
        String name = file.getName();
        int i = name.lastIndexOf(".");
        // 获取文件的后缀
        if(i > 0){
             fileType = name.substring(i + 1);
        }
        //根据文件的后缀获取,获取文件的byte[]的前8位
        if(FileTypes.containsValue(fileType.toLowerCase())){
            
            for(Map.Entry<String, String> filetype:FileTypes.entrySet()){
                if(filetype.getValue().equals(fileType)){
                    String fileByte8 = String.valueOf(filetype.getKey());
                    //获取传入文件的byte[]的前8位
                    byte[] bytes = inputStream2ByteArray(file);
                    String compareByte = bytesToHexString(bytes);
                    //如果传入文件的byte[]的前8位和我们定义好的byte[]的前8位相同,验证通过.
                    if (compareByte.startsWith(fileByte8)){
                        //如果格式校验成功
                        isgood = true;
                    }
                }
            }
        }else{
            return isgood;
        }
        return isgood;
    }
    
    /**
     * @Description  将file文件转化为byte[]
     * @Param [file]
     * @return byte[]
     **/   
    public  byte[] inputStream2ByteArray(File file){
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        FileInputStream fis = null;
        byte[] buffer = null;

        try {
            fis = new FileInputStream(file);
            //不用读取全部文件,只读文件前面的部分
            byte[] b = new byte[1024];
            fis.read(b);
            bos.write(b, 0, 1024);
            buffer = bos.toByteArray();
        }catch (FileNotFoundException e){
            e.printStackTrace();
        }catch (IOException e1){
            e1.printStackTrace();
        }finally {
            try {
                if(fis !=null){
                    fis.close();
                }
            }catch (Exception e){
                e.printStackTrace();
            }
            try {
                if(bos !=null){
                    bos.close();
                }
            }catch (Exception e){
                e.printStackTrace();
            }
        }
        return buffer;
    }
    
    /**
     * @Description  取byte[]前8位的为字符串
     * @Param [src]
     * @return java.lang.String
     **/
    public  String bytesToHexString(byte[] src) {
        StringBuilder stringBuilder = new StringBuilder();
        if (src == null || src.length <= 0) {
            return null;
        }
        for (int i = 0; i < src.length; i++) {
            int v = src[i] & 0xFF;
            String hv = Integer.toHexString(v);
            if (hv.length() < 2) {
                stringBuilder.append(0);
            }
            stringBuilder.append(hv);
        }
        //return stringBuilder.toString().substring(0, 8);
        return stringBuilder.toString();
    }
}

 

  

posted on 2021-05-28 17:04  幻灵祭祀  阅读(451)  评论(0编辑  收藏  举报

导航