web安全——判断文件流的文件上传解决上传漏洞

分手后的思念是犯贱 2021-11-22 13:46 445阅读 0赞

web安全——判断文件流的文件上传解决上传漏洞

主要实现的功能:

  • 读取文件流来识别文件格式,判断上传的文件是否是jsp、js、exe等可执行文件。
  • 根据日期分文件存放
  • 防止文件名冲突

    package cn.jiangdoc.utils.file;

    import cn.jiangdoc.entity.Result;
    import cn.jiangdoc.utils.FileType;
    import cn.jiangdoc.utils.FileUtil;

    import org.springframework.web.bind.annotation.*;
    import org.springframework.web.multipart.MultipartFile;

    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import java.io.*;
    import java.text.SimpleDateFormat;
    import java.util.Calendar;
    import java.util.Date;

    @RestController
    public class FileController {

    1. /** * 单文件上传 * * @param file * @param request * @return */
    2. @RequestMapping(value = "/uploadFile", method = RequestMethod.POST)
    3. public Result uploadFile(@RequestParam("file") MultipartFile file, HttpServletRequest request) {
    4. // ------------------判断文件流类型的代码---------------
    5. FileType fileType = null;
    6. try {
    7. fileType = FileUtil.getFileType(file.getInputStream());
    8. } catch (IOException e1) {
    9. // TODO Auto-generated catch block
    10. e1.printStackTrace();
    11. }
    12. if (fileType == null) {
    13. // 非图片格式
    14. return new Result(false, "非法文件!");
    15. }
    16. // -----------------end------------------------------
    17. //文件的扩展名
    18. String originalFilename = file.getOriginalFilename();
    19. String extName = originalFilename.substring(originalFilename.lastIndexOf(".") + 1);
    20. SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmssSS");
    21. String res = sdf.format(new Date());
    22. // 新文件名
    23. String newFileName = "sliver" + res +"."+ extName;
    24. // upload文件夹位置,webapp下
    25. String rootPath = request.getSession().getServletContext().getRealPath("upload/");
    26. //获取协议名+域名+端口号+项目名 = http+"://"+localhost+":"+8080+/booksystem
    27. String url = request.getScheme() + "://" + request.getServerName() + ":" + request.getServerPort() + request.getContextPath();
    28. try {
    29. // 创建年月文件夹
    30. Calendar date = Calendar.getInstance();
    31. File dateDirs = new File(date.get(Calendar.YEAR) + File.separator + (date.get(Calendar.MONTH) + 1));
    32. // 新文件
    33. File newFile = new File(rootPath + File.separator + dateDirs + File.separator + newFileName);
    34. // 判断目标文件所在目录是否存在
    35. if (!newFile.getParentFile().exists()) {
    36. // 如果目标文件所在的目录不存在,则创建父目录
    37. newFile.getParentFile().mkdirs();
    38. }
    39. // 将内存中的数据写入磁盘
    40. file.transferTo(newFile);
    41. // 完整的url
    42. String fileUrl = url + "/upload/" + date.get(Calendar.YEAR) + "/" + (date.get(Calendar.MONTH) + 1) + "/" + newFileName;
    43. return new Result(true, fileUrl);
    44. } catch (Exception e) {
    45. e.printStackTrace();
    46. return new Result(false, "上传失败");
    47. }
    48. }
    49. /** * 多文件上传 * * @param files * @param request * @return */
    50. @RequestMapping(value = "/uploadFiles", method = RequestMethod.POST)
    51. public Result uploadFiles(@RequestParam("files") MultipartFile[] files, HttpServletRequest request) {
    52. //判断file数组不能为空并且长度大于0
    53. if (files != null && files.length > 0) {
    54. try {
    55. //循环获取file数组中得文件
    56. String str = "[";
    57. for (int i = 0; i < files.length; i++) {
    58. Result result = uploadFile(files[i], request);
    59. if (result.isFlag()) {
    60. str += "{\"id\":" + i + ",\"url\":\"" + result.getMsg() + "\"},";
    61. }
    62. }
    63. str = str.substring(0, str.lastIndexOf(","));
    64. str += "]";
    65. return new Result(true, str);
    66. } catch (Exception e) {
    67. e.printStackTrace();
    68. return new Result(false, "[]");
    69. }
    70. } else
    71. return null;
    72. }

    }

文件工具类

  1. package cn.jiangdoc.utils.file;
  2. import java.io.IOException;
  3. import java.io.InputStream;
  4. public class FileUtil {
  5. /** * 判断文件是图片格式 * * @param is * @return * @throws IOException */
  6. public static FileType getFileType(InputStream is) throws IOException {
  7. byte[] src = new byte[28];
  8. is.read(src, 0, 28);
  9. StringBuilder stringBuilder = new StringBuilder("");
  10. if (src == null || src.length <= 0) {
  11. return null;
  12. }
  13. for (int i = 0; i < src.length; i++) {
  14. int v = src[i] & 0xFF;
  15. String hv = Integer.toHexString(v).toUpperCase();
  16. if (hv.length() < 2) {
  17. stringBuilder.append(0);
  18. }
  19. stringBuilder.append(hv);
  20. }
  21. FileType[] fileTypes = FileType.values();
  22. for (FileType fileType : fileTypes) {
  23. if (stringBuilder.toString().startsWith(fileType.getValue())) {
  24. return fileType;
  25. }
  26. }
  27. return null;
  28. }
  29. }

受信任的文件类型

  1. package cn.jiangdoc.utils;
  2. public enum FileType {
  3. /** * JPEG */
  4. JPEG("FFD8FF", "jpg"),
  5. /** * PNG */
  6. PNG("89504E47", "png"),
  7. /** * GIF */
  8. GIF("47494638", "gif"),
  9. /** * TIFF */
  10. TIFF("49492A00"),
  11. /** * Windows bitmap */
  12. BMP("424D"),
  13. /** * CAD */
  14. DWG("41433130"),
  15. /** * Adobe photoshop */
  16. PSD("38425053"),
  17. /** * Rich Text Format */
  18. RTF("7B5C727466"),
  19. /** * XML */
  20. XML("3C3F786D6C"),
  21. /** * HTML */
  22. HTML("68746D6C3E"),
  23. /** * Outlook Express */
  24. DBX("CFAD12FEC5FD746F "),
  25. /** * Outlook */
  26. PST("2142444E"),
  27. /** * doc;xls;dot;ppt;xla;ppa;pps;pot;msi;sdw;db */
  28. OLE2("0xD0CF11E0A1B11AE1"),
  29. /** * Microsoft Word/Excel */
  30. XLS_DOC("D0CF11E0"),
  31. /** * Microsoft Access */
  32. MDB("5374616E64617264204A"),
  33. /** * Word Perfect */
  34. WPB("FF575043"),
  35. /** * Postscript */
  36. EPS_PS("252150532D41646F6265"),
  37. /** * Adobe Acrobat */
  38. PDF("255044462D312E"),
  39. /** * Windows Password */
  40. PWL("E3828596"),
  41. /** * ZIP Archive */
  42. ZIP("504B0304"),
  43. /** * ARAR Archive */
  44. RAR("52617221"),
  45. /** * WAVE */
  46. WAV("57415645"),
  47. /** * AVI */
  48. AVI("41564920"),
  49. /** * Real Audio */
  50. RAM("2E7261FD"),
  51. /** * Real Media */
  52. RM("2E524D46"),
  53. /** * Quicktime */
  54. MOV("6D6F6F76"),
  55. /** * Windows Media */
  56. ASF("3026B2758E66CF11"),
  57. /** * MIDI */
  58. MID("4D546864");
  59. private String value = "";
  60. private String ext = "";
  61. FileType(String value) {
  62. this.value = value;
  63. }
  64. FileType(String value, String ext) {
  65. this(value);
  66. this.ext = ext;
  67. }
  68. public String getExt() {
  69. return ext;
  70. }
  71. public String getValue() {
  72. return value;
  73. }
  74. }

解决。

发表评论

表情:
评论列表 (有 0 条评论,445人围观)

还没有评论,来说两句吧...

相关阅读

    相关 文件漏洞详解

    0x01 上传漏洞定义 文件上传漏洞是指用户上传了一个可执行的脚本文件,并通过此脚本文件获得了执行服务器端命令的能力。这种攻击方式是最为直接和有效的,“文件上传”本身没有

    相关 文件漏洞概述

    文件上传漏洞是指用户上传了一个可执行的脚本文件,并通过此脚本文件获得了执行服务器端命令的能力,这种攻击方式是最为直接和有效的,有时候几乎没有什么技术门槛。 文件上传后导致的常

    相关 预防文件漏洞

    预防文件上传漏洞 1.为了防范用户上传恶意的可执行文件和脚本,以及将文件上传服务器当做免费的文件存储服务器使用,需要对上传的文件类型进行白名单(非黑名单,这点非常重要)校