任意文件上传示例
  1. public class FileUploadServlet extends HttpServlet {
  2. private static final long serialVersionUID = 1L;
  3. protected void doPost(HttpServletRequest request, HttpServletResponse response)
  4. throws ServletException, IOException {
  5. //判断请求是否为multipart请求
  6. if(!ServletFileUpload.isMultipartContent(request)){
  7. throw new RuntimeException("当前请求不支持文件上传");
  8. }
  9. try {
  10. /*
  11. DiskFileItemFactory可以设置缓存大小以及临时文件保存的位置
  12. 临时文件默认村粗在系统的临时文件目录下
  13. */
  14. DiskFileItemFactory factory = new DiskFileItemFactory();
  15. /*
  16. ServletFileUpload(factory)创建一个上传工具,指定使用缓存区与零食文件存储位置
  17. */
  18. ServletFileUpload servletFileUpload = new ServletFileUpload(factory);
  19. //解析请求,获取到所有的item,每一个item相当于一个上传项
  20. List<FileItem> items = servletFileUpload.parseRequest(request);
  21. //遍历items
  22. for(FileItem item : items){
  23. //isFormField,True表示是普通表单项,false为文件表单项
  24. if(item.isFormField()){ //若item为普通表单项
  25. String fieldName = item.getFieldName(); //获取表单项名称
  26. String fieldValue = item.getString(); //获取表单项的值
  27. System.out.println(fieldName + " = " + fieldValue);
  28. }else{ //若item为文件表单项
  29. //获取上传文件原始名称
  30. String fileName = item.getName();
  31. //获取输入流,其中有上传 文件的内容
  32. InputStream is = item.getInputStream();
  33. //获取文件保存在服务器的路径
  34. String path = this.getServletContext().getRealPath("/images");
  35. //创建目标文件,将用来保存上传文件
  36. File file = new File(path, fileName);
  37. //将输入流中的数据写入到输出流中
  38. OutputStream os = new FileOutputStream(file);
  39. //将输入流中的数据写入输出流中
  40. int len = -1;
  41. byte[] buf = new byte[1024];
  42. while((len = is.read(buf)) != -1){
  43. os.write(buf, 0, len);
  44. }
  45. os.close();
  46. is.close();
  47. }
  48. }
  49. } catch (FileUploadException e) {
  50. e.printStackTrace();
  51. }
  52. }
  53. }

几种修复方式

通过后缀名进行判断
  1. String fileType= "";
  2. int i = fileName.lastIndexOf('.');
  3. if (i > 0) {
  4. fileType= fileName.substring(i+1);
  5. }
  6. //...
  7. if("jpg".equals(fileType) || "png".equals(fileType) ....){
  8. //your code
  9. }

通过文件头校验
  1. // 获得文件头部字符串
  2. public static String bytesToHexString(byte[] src) {
  3. StringBuilder stringBuilder = new StringBuilder();
  4. if (src == null || src.length <= 0) {
  5. return null;
  6. }
  7. for (int i = 0; i < src.length; i++) {
  8. int v = src[i] & 0xFF;
  9. String hv = Integer.toHexString(v);
  10. if (hv.length() < 2) {
  11. stringBuilder.append(0);
  12. }
  13. stringBuilder.append(hv);
  14. }
  15. return stringBuilder.toString();
  16. }
  17. FILE_TYPE_MAP.put("jpg", "FFD8FF"); //JPEG
  18. FILE_TYPE_MAP.put("png", "89504E47"); //PNG
  19. FILE_TYPE_MAP.put("gif", "47494638"); //GIF

通过ImageIO判断
  1. /**
  2. * 通过读取文件并获取其width及height的方式,来判断判断当前文件是否图片,这是一种非常简单的方式。
  3. * @param imageFile
  4. * @return
  5. */
  6. public static boolean isImage(File imageFile) {
  7. if (!imageFile.exists()) {
  8. return false;
  9. }
  10. Image img = null;
  11. try {
  12. img = ImageIO.read(imageFile);
  13. if (img == null || img.getWidth(null) <= 0 || img.getHeight(null) <= 0) {
  14. return false;
  15. }
  16. return true;
  17. } catch (Exception e) {
  18. return false;
  19. } finally {
  20. img = null;
  21. }
  22. }

jspx解析为Jsp

Java任意文件上传漏洞 - 图1