恐龙网站建设,阳江兼职招聘网最新招聘,网络推广项目计划书,动漫在线设计平台java任意文件漏洞修复#xff0c;使用文件魔数解决 背景#xff1a; 客户进行渗透测试#xff0c;验证上传文件的程序没有对上传文件作任何过滤#xff0c;导致可以上传任意文件到服务器#xff0c;甚至是病毒文件和Webshell木马文件。 解决办法#xff1a;对于上传的附件… java任意文件漏洞修复使用文件魔数解决 背景 客户进行渗透测试验证上传文件的程序没有对上传文件作任何过滤导致可以上传任意文件到服务器甚至是病毒文件和Webshell木马文件。 解决办法对于上传的附件验证程序要做严格验证使用服务器端校验而不能仅用前端验证。 代码实例
// 允许上传文件后缀
private static final String[] ALLOWED_FILE_EXTENSIONS {jpg, jpeg, png, gif, doc, docx, xls, xlsx, pdf, ppt, pptx};
// 允许上传文件头魔数十六进制字符串
private static final ListString ALLOWED_MAGIC_NUMBERS Arrays.asList(FFD8FF, 89504E47, 47494638, 25504446, D0CF11E0, 504B0304
); // JPEG (jpg),PNG (png),GIF (gif),pdf,(doc、xls、ppt),(xls、pptx)// 允许上传文件的MIME类型
private static final SetString ALLOWED_MIME_TYPES new HashSet();
static {ALLOWED_MIME_TYPES.add(image/jpeg); // jpg, jpeg ALLOWED_MIME_TYPES.add(image/png); // png ALLOWED_MIME_TYPES.add(image/gif); // gif ALLOWED_MIME_TYPES.add(application/msword); // doc ALLOWED_MIME_TYPES.add(application/vnd.openxmlformats-officedocument.wordprocessingml.document); // docx ALLOWED_MIME_TYPES.add(application/vnd.ms-excel); // xls ALLOWED_MIME_TYPES.add(application/vnd.openxmlformats-officedocument.spreadsheetml.sheet); // xlsx ALLOWED_MIME_TYPES.add(application/pdf); // pdf ALLOWED_MIME_TYPES.add(application/vnd.ms-powerpoint); // pptALLOWED_MIME_TYPES.add(application/vnd.openxmlformats-officedocument.presentationml.presentation); // pptx
} SuppressWarnings(unchecked)
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {request.setCharacterEncoding(UTF-8);String fileType;// 1.创建文件上传工厂类DiskFileItemFactory fac new DiskFileItemFactory();// 2.创建文件上传核心类对象ServletFileUpload upload new ServletFileUpload(fac);// 【一、设置单个文件最大1024M】upload.setFileSizeMax(1024 * 1024 * 1024);// 1024MM// 【二、设置总文件大小2048M】upload.setSizeMax(2048 * 1024 * 1024); // 2048MListString StringArrnew ArrayListString();// 判断当前表单是否为文件上传表单if (upload.isMultipartContent(request)) {try {// 3.把请求数据转换为FileItem对象的集合ListFileItem list upload.parseRequest(request);Calendar calendar Calendar.getInstance();int year calendar.get(Calendar.YEAR);// 遍历得到每一个上传项for (FileItem item : list) {// 判断是普通表单项还是文件上传表单项if (item.isFormField()) {// 普通表单xString fieldName item.getFieldName();// 获取元素名称String value item.getString(UTF-8); // 获取元素值fileTypevalue;System.out.println(fieldName : value);} else {// 文件上传表单//文件保存目录路径String savePath getServletContext().getRealPath(/) uploadFiles/wjgl/fileType/year/;File uploadFile new File(savePath);if (!uploadFile.exists()) {uploadFile.mkdirs();}String oldname item.getName(); // 上传的文件名称String fileExtension item.getName().substring(item.getName().lastIndexOf(.) 1);//获取到文件后缀if (!Arrays.asList(ALLOWED_FILE_EXTENSIONS).contains(fileExtension)) {//验证文件后缀response.setStatus(500);throw new FileUploadException(if1无效的文件扩展名: fileExtension);}String contentType item.getContentType();if(!ALLOWED_MIME_TYPES.contains(contentType)){response.setStatus(500);throw new FileUploadException(if2无效的文件扩展名: fileExtension);}if (!isFileValid(item)) {// 文件有效进行处理response.setStatus(500);throw new FileUploadException(被改了后缀判断文件内容魔术无效的文件扩展名: fileExtension);}//时间戳String timeString.valueOf(new Date().getTime());String name timeoldname;// 【三、上传到指定目录获取上传目录路径】String realPath uploadFiles/wjgl/fileType/year/;// 创建文件对象File file new File(savePath, name);item.write(file);item.delete();response.setContentType(application/json);response.setCharacterEncoding(UTF-8);JSONObject obj new JSONObject();obj.put(fileName, oldname);obj.put(filePath, realPath name);StringArr.add(obj.toString());}}response.getWriter().println(StringArr);} catch (Exception e) {e.printStackTrace();}} else {System.out.println(不处理);}}//校验是否为jpg,jpeg,png,gif,doc,docx,xls,xlsx,pdf,pptx格式
public static boolean isFileValid(FileItem fileItem) throws IOException {String fileName fileItem.getName();try (InputStream inputStream fileItem.getInputStream()) {return isValidFileMagicNumber(inputStream);}
}
//验证文件魔数
public static boolean isValidFileMagicNumber(InputStream inputStream) throws IOException {boolean blfalse;byte[] buffer new byte[8];inputStream.read(buffer, 0, 8);String hexMagicNumber bytesToHex(buffer);for(int i 0; iALLOWED_MAGIC_NUMBERS.size(); i){String msALLOWED_MAGIC_NUMBERS.get(i);if(hexMagicNumber.toUpperCase().startsWith(ms)){bltrue;break;}}return bl;
}
//字节转换16进制
private static String bytesToHex(byte[] bytes) {StringBuilder hexString new StringBuilder();for (byte b : bytes) {hexString.append(String.format(%02X, b));}return hexString.toString();
}