任意文件上传漏洞,添加白名单校验

为解决任意文件上传漏洞,添加白名单校验文件后缀名 1)添加配置信息

file_strict_name=true
file_special_characters=
file_allow_types=jpg,png,tif,gif,dwg,pdf,zip,docx,doc,xls,xlsx
file_allows=true

2)添加白名单校验方法

@Service
public class ObsService {
          
   
	
	/**
	 * 是否要判断文件名含有非法字符
	 */
	@Value("${file_strict_name}")
    private String fileStrictName;
	/**
	 * 文件名含有的特殊字符
	 */
    @Value("${file_special_characters}")
    private String fileSpecialCharacters;
    
    /**
	 * 允许上传的文件类型
	 */
    @Value("${file_allow_types}")
    private String[] fileAllowTypes;
    /**
	 * 是否开启文件类型白名单
	 */
	@Value("${file_allows}")
    private String fileAllows;
	
	
	/**
	 * 判断文件名中是否含有非法字符
	 * @param fileName
	 */
	public void illegalCharacters(String fileName) throws Exception{
          
   
		if(StringUtils.isNotBlank(fileStrictName) && Boolean.valueOf(fileStrictName)) {
          
   
			//要判断文件名中是否包含非法字符
			if(StringUtils.isNotBlank(fileName)) {
          
   
				//默认允许包含中文、英文、数字包括下划线
				String n = "[\u4E00-\u9FA5A-Za-z0-9_]+";
				//不为空则拼接上
				if (null != fileSpecialCharacters && !"".equals(fileSpecialCharacters)) {
          
   
					n = "[\u4E00-\u9FA5A-Za-z0-9_" + fileSpecialCharacters+"]+"; 
				}
				Pattern pattern = Pattern.compile(n); 
				String nn = fileName;
				int last = nn.lastIndexOf(".");
				if (last != -1) {
          
   
					//截取掉扩展名好判断一些
					nn = nn.substring(0,last);
					
				}
				Matcher mat = pattern.matcher(nn); 
				if(!mat.matches()){
          
   
					throw new RuntimeException("文件名包含非法的字符,文件名允许输入【汉字,汉字标点符号,字母,数字,下划线,空格】");
				}
			}
		}
	}
	
	/**
	 * 上传文件类型是否在白名单中
	 * @param fileName
	 */
	public void whiteListVerify(String fileName) throws Exception{
          
   
		if(StringUtils.isNotBlank(fileAllows) && Boolean.valueOf(fileAllows)) {
          
   
			if(StringUtils.isNotBlank(fileName)) {
          
   
				String nn = fileName;
				int last = nn.lastIndexOf(".");
				if (last != -1) {
          
   
					//截取掉扩展名好判断一些
					nn = nn.substring(last+1, nn.length());
				}
				if(fileAllowTypes != null) {
          
   
					List<String> fileAllowsList = Arrays.asList(fileAllowTypes);
					if(!fileAllowsList.contains(nn.toLowerCase())) {
          
   
						throw new RuntimeException("文件【"+fileName+"】格式不正确,请上传["+StringUtils.join(fileAllowTypes, ",")+"]格式的文件");
					}
				}
			}
		}
	}
	
}

3)在文件上传接口中,调用白名单校验接口

@PostMapping("putFile")
	@Transactional
	public void putObject(HttpServletRequest request) throws Exception {
          
   
		List<MultipartFile> files = ((MultipartHttpServletRequest)request).getFiles("name");
		String businessType = request.getParameter("businessType");
		String businessMid = request.getParameter("businessKey");
		Attachments attachments = null;
		for(MultipartFile file: files) {
          
   
			try {
          
   
				//设置文件业务信息
				String fileName = file.getOriginalFilename();
				
				try {
          
   
					//判断文件名中是否含有非法字符
					obsService.illegalCharacters(fileName);
					//文件类型是否包含在白名单中
					obsService.whiteListVerify(fileName);
				}catch (Exception e1) {
          
   
					// TODO: handle exception
					throw e1;
				}
				
				......
			} catch (Exception e) {
          
   
				log.error("文件上传失败", e);
				throw e;
			}
		}
	}
经验分享 程序员 微信小程序 职场和发展