Spring Mvc中CommonsMultipartFile的特性实例详解

 更新时间:2023年11月20日 15:30:59   作者:zpchcbd  
这篇文章主要给大家介绍了关于Spring Mvc中CommonsMultipartFile特性的相关资料,SpringMVC拥有强大的灵活性,非侵入性和可配置性,文中通过代码介绍的非常详细,需要的朋友可以参考下

前言:

简单的记录下Spring <= 4.1.8的CommonsMultipartFile的特性,遇到一个springmvc的一套系统通过该方法进行绕过上传解决,不过只限于windows的情况下,这篇笔记先介绍下关于CommonsMultipartFile,然后给出实例利用的情况

参考文章:https://forum.butian.net/share/815

MultipartFile是什么

在springmvc中进行文件上传的时候,springmvc提供了两个封装好的上传组件来进行使用,如下图所示,分别是CommonsMultipartFile和StandardMultipartFile

StandardMultipartFile

pom.xml

    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-webmvc</artifactId>
      <version>4.1.8.RELEASE</version>
    </dependency>

如果要使用StandardServletMultipartResolver进行文件上传,需要进行如下两个步骤

先在springmvc-servlet.xml中配置如下multipartResolver为StandardServletMultipartResolver

<bean id="multipartResolver" class="org.springframework.web.multipart.support.StandardServletMultipartResolver" />

然后在web.xml中还需要进行如下配置multipart-config,配置在DispatcherServlet的servlet标签中

        <multipart-config>
            <!--上传的文件的最大限制,单位byte-->
            <max-file-size>4194304</max-file-size>
            <!--multipart/form-data请求的最大限制,单位byte-->
            <max-request-size>10485760</max-request-size>
            <!--将存储上载文件的目录位置-->
            <!--<location></location>-->
        </multipart-config>

对于StandardMultipartFile类中有一个问题就是在获取文件名的时候实现的getOriginalFilename方法是直接获取文件名,没有进行过滤一些特殊字符的情况,这样的情况就会产生安全问题比如路径跳跃

UploadController.java

@Controller
public class UploadController {
    @RequestMapping(value = "/fileupload")
    @ResponseBody
    public String test(HttpServletRequest request) throws Exception {
        MultipartHttpServletRequest req = (MultipartHttpServletRequest)request;
        MultipartFile file = req.getFile("uploadFile");
        String realFileName = file.getOriginalFilename();
        String ctxPath = req.getSession().getServletContext().getRealPath("/tmp/");
        File dirPath = new File(ctxPath);
        if (!dirPath.exists()) {
            dirPath.mkdir();
        }
        String serverPath = ctxPath + File.separator + realFileName;
        try {
            File uploadFile = new File(serverPath);
            FileCopyUtils.copy(file.getBytes(), uploadFile);
            return serverPath;
        } catch (Exception var9) {
            var9.printStackTrace();
            return "upload fail";
        }
    }
}

上面代码的情况下,我们直接上传文件的话会存在目录跳跃的问题,结果如下所示,可以看到readme.jsp可以直接跳出tmp目录

这里主要问题出在getOriginalFilename方法,这里可以观察下StandardMultipartFile的getOriginalFilename,下面的图中可以看到没有对../这些符号做相关的限制

CommonsMultipartFile

pom.xml

    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-webmvc</artifactId>
      <version>4.1.8.RELEASE</version>
    </dependency>

这里可以将代码改为CommonsMultipartFile来进行测试

将springmvc-servlet.xml中配置如下multipartResolver为CommonsMultipartResolver

<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver" />

重新进行发包可以发现就不会出现目录跳跃的问题了

这里同样可以看下org.springframework.web.multipart.commons.CommonsMultipartFile#getOriginalFilename,可以看到首先就会匹配/符号,然后取/之后的内容

这里主要利用了org.springframework.web.multipart.commons.CommonsMultipartFile#getOriginalFilename,而这里有个逻辑问题就是如果在windows下的话\\同样可以作为分隔符来进行识别,所以如果对于/..\..\readme.jsp这种payload的话,那么在windows的情况下同样可以进行利用

这边拿windows的环境来进行测试,结果如下所示

调试过程可以看到org.springframework.web.multipart.commons.CommonsMultipartFile#getOriginalFilename最终取到的就是/之后的内容

漏洞修复

这边将pom.xml中的springmvc修改为4.1.9.RELEASE

    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-webmvc</artifactId>
      <version>4.1.9.RELEASE</version>
    </dependency>

重新测试的情况下,就无法进行绕过了

实战遇到的代码

这边拿前面篇头说的实际审计的情况,这个环境下是在/tmp/目录下禁止访问,所以如果要利用的话那么就需要上传的文件不在该目录下,那么这边的话就可以用getOriginalFilename跨越目录,用/..\..\readme.jsp来利用即可

    public static String upLoadFile(HttpServletRequest request) {
        MultipartHttpServletRequest req = (MultipartHttpServletRequest)request;
        MultipartFile file = req.getFile("uploadFile");
        String realFileName = file.getOriginalFilename();
        String ctxPath = request.getContextPath();
        ctxPath = req.getSession().getServletContext().getRealPath("/tmp/");
        File dirPath = new File(ctxPath);
        if (!dirPath.exists()) {
            dirPath.mkdir();
        }

        SimpleDateFormat format = new SimpleDateFormat("yyyyMMddHHmmss");
        String serverPath = ctxPath + File.separator + format.format(new Date()) + realFileName;

        try {
            File uploadFile = new File(serverPath);
            FileCopyUtils.copy(file.getBytes(), uploadFile);
            return serverPath;
        } catch (Exception var9) {
            var9.printStackTrace();
            return null;
        }
    }

总结

到此这篇关于Spring Mvc中CommonsMultipartFile特性的文章就介绍到这了,更多相关Spring Mvc CommonsMultipartFile特性内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • spring boot中interceptor拦截器未生效的解决

    spring boot中interceptor拦截器未生效的解决

    这篇文章主要介绍了spring boot中interceptor拦截器未生效的解决,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-09-09
  • SpringBoot整合Minio实现文件上传和读取功能

    SpringBoot整合Minio实现文件上传和读取功能

    最近有一个需求是关于视频上传播放的,需要设计一个方案,中间谈到了Minio这个技术,于是来学习一下,所以本文给大家介绍了SpringBoot整合Minio实现文件上传和读取功能,文中有详细的代码示例供大家参考,需要的朋友可以参考下
    2024-07-07
  • java中File类应用遍历文件夹下所有文件

    java中File类应用遍历文件夹下所有文件

    这篇文章主要为大家详细介绍了java中File类应用遍历文件夹下所有文件,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2019-08-08
  • Springmvc如何实现向前台传递数据

    Springmvc如何实现向前台传递数据

    这篇文章主要介绍了Springmvc如何实现向前台传递数据,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-07-07
  • SWT(JFace)体验之RowLayout布局

    SWT(JFace)体验之RowLayout布局

    相对于FillLayout来说,RowLayout比较灵活,功能也比较强。用户可以设置布局中子元素的大小、边距、换行及间距等属性。
    2009-06-06
  • Java防止短信盗刷和轰炸的解决方案

    Java防止短信盗刷和轰炸的解决方案

    短信盗刷和短信轰炸是项目开发中必须要解决的问题之一,它的优先级不亚于 SQL 注入的问题,今天我们就来看下,如何防止这个问题,需要的朋友可以参考下
    2024-02-02
  • Java事务管理学习之Spring和Hibernate详解

    Java事务管理学习之Spring和Hibernate详解

    这篇文章主要给大家介绍了Java事务管理学习之Spring和Hibernate的相关资料,文中通过示例代码介绍的非常详细,需要的朋友们可以参考借鉴,下面来一起看看吧。
    2017-03-03
  • 浅谈Java读写注册表的方式Preferences与jRegistry

    浅谈Java读写注册表的方式Preferences与jRegistry

    这篇文章主要介绍了浅谈Java读写注册表的方式Preferences与jRegistry,分享了相关代码示例,小编觉得还是挺不错的,具有一定借鉴价值,需要的朋友可以参考下
    2018-02-02
  • Java基础之java泛型通配符详解

    Java基础之java泛型通配符详解

    Java 泛型(generics)是 JDK 5 中引入的一个新特性, 泛型提供了编译时类型安全检测机制,该机制允许开发者在编译时检测到非法的类型,今天通过本文给大家介绍java泛型通配符的相关知识,感兴趣的朋友一起看看吧
    2021-07-07
  • 详解Mybatis Generator的具体使用教程

    详解Mybatis Generator的具体使用教程

    Mybatis Generator可以帮助我们自动生成很多结构化的代码,比如每张表对应的Entity、Mapper接口和Xml文件,可以省去很多繁琐的工作,今天通过本文给大家介绍Mybatis Generator的具体使用教程,感兴趣的朋友一起看看吧
    2022-02-02

最新评论