精华内容
下载资源
问答
  • 2021-09-03 20:06:44

    Java文件上传实例并解决跨域问题

    目录

    了解MultipartFile接口

    文件上传业务代码

    Controller类

    Service类:写了具体的业务逻辑

    修改nginx配置,将文件存储到文件服务器中

    每次上传文件都会经过网关,必然会给网关带来很大的压力,那我们如何绕过网关呢?

    1.在网关中配置白名单 ,这样也会走网关,只是压力少了一点点

    2.在nginx做转发,当请求文件上传时,直接转到相应的服务

    解决上传文件出现跨域问题

    写配置类CorsFilter

    在nginx配置中配置请求实体大小


    在Web应用系统开发中,文件上传和下载功能是非常常用的功能,今天来讲一下JavaWeb中的文件上传功能的实现。

    了解MultipartFile接口

    我们实现文件的上传用到了Spring-web框架中的 MultipartFile接口,MultipartFile接口的源码注释中说“MultipartFile接口是  在大部分请求中接收的上载文件的表示形式。”

    A representation of an uploaded file received in a multipart request.
    The file contents are either stored in memory or temporarily on disk. In either case, the user is responsible for copying file contents to a session-level or persistent store as and if desired. The temporary storage will be cleared at the end of request processing.

    常用方法如下表

    Method Summary
     byte[]获取文件的字节数组getBytes()
              Return the contents of the file as an array of bytes.
     String获取文件的类型getContentType()
              Return the content type of the file.
     InputStream获取文件的输入流getInputStream()
              Return an InputStream to read the contents of the file from.
     String获取文件名getName()
              Return the name of the parameter in the multipart form.
     String获取原始文件名(防止篡改文件类型)getOriginalFilename()
              Return the original filename in the client's filesystem.
     long获取文件的大小,以字节的形式)getSize()
              Return the size of the file in bytes.
     boolean判断文件是否为空isEmpty()
              Return whether the uploaded file is empty, that is, either no file has been chosen in the multipart form or the chosen file has no content.
     void将接收到的文件传输到给定的目标文件。transferTo(File dest)
              Transfer the received file to the given destination file.

    文件上传业务代码

    Controller类

    /**
     * @Author: 小小张自由
     * @Date: 2021/7/6 - 20:56
     * @Description: 文件上传
     * @version: 1.0
     */
    @Controller
    @RequestMapping("upload")
    public class UploadController {
    
        @Autowired
        private UploadService uploadService;
    
        @PostMapping("image")
        public ResponseEntity<String> uploadImage(@RequestParam("file") MultipartFile file){
           String url= this.uploadService.uploadImage(file);
           if (StringUtils.isBlank(url)){
               return ResponseEntity.badRequest().build();
           }
            return ResponseEntity.status(HttpStatus.CREATED).body(url);
        }
    }
    

    Service类:写了具体的业务逻辑

    /**
     * @Author: 小小张自由
     * @Date: 2021/7/6 - 21:01
     * @Description: 文件上传
     * @version: 1.0
     */
    @Service
    public class UploadService {
    
        //用于判断文件的类型,暂时只判断了“image/gif","image/jpeg”
        private static final List<String> CONTENT_TYPES= Arrays.asList("image/gif","image/jpeg");
    
        private static final Logger LOGGER= LoggerFactory.getLogger(UploadService.class);
    
        /**
         * 业务逻辑代码
         * @param file 文件的存储的url
         * @return
         */
        public String uploadImage(MultipartFile file) {
    
            String originalFilename = file.getOriginalFilename();
            //校验文件类型
            //方法一:截取字符串
            String afterLast = StringUtils.substringAfterLast(".", originalFilename);
            //方法二:使用getContentType方法
            String contentType = file.getContentType();
            if (!CONTENT_TYPES.contains(contentType)){
                LOGGER.info("文件类型不合法:"+originalFilename);
                return null;
            }
            //校验文件内容
            try {
                //获取文件流
                BufferedImage bufferedImage = ImageIO.read(file.getInputStream());
                if (bufferedImage==null){
                    LOGGER.info("文件内容不合法:{}",originalFilename);
                    return null;
                }
                //保存到服务器   E:\Leyou\image
                //将接收到的文件传输到给定的目标文件。
                file.transferTo(new File("E:\\Leyou\\Image\\"+originalFilename));
                
                //返回URL,进行回显
                //可以使用Nginx-图片服务器
                return "http://image.leyou.com/"+originalFilename;
            } catch (Exception e) {
                LOGGER.info("服务器内部错误:"+originalFilename);
                e.printStackTrace();
            }
            return null;
        }
    }

    修改nginx配置,将文件存储到文件服务器中

    修改Nginx的配置文件nginx.conf,监听80端口,设置root的值为:E盘

    - 图片不能保存在服务器内部,这样会对服务器产生额外的加载负担
    - 一般静态资源都应该使用独立域名,这样访问静态资源时不会携带一些不必要的cookie,减小请求的数据量

    server {
            listen       80;
            server_name  image.leyou.com;
    
            proxy_set_header X-Forwarded-Host $host;
    		proxy_set_header X-Forwarded-Server $host;
    		proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    		
    		location / {
    			root E:\\Leyou\\image;
    		}
        }

    每次上传文件都会经过网关,必然会给网关带来很大的压力,那我们如何绕过网关呢?

    1.在网关中配置白名单 ,这样也会走网关,只是压力少了一点点

    @Slf4j
    public class AuthorizeFilter implements GlobalFilter, Ordered {
    
        //白名单:存放放行的URL
        private List<String> allowPaths;
    
    
        @Override
        public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
           
            //获取请求的url路径
            String path = request.getURI().getPath();
            boolean flag=isAllowPath(path);
            if (flag) {
                log.info("请求在白名单中,leyou.filter: {}",path);
                //放行
                return chain.filter(exchange);
            } else {
              //写其他的业务逻辑
                ~~~~
                
            }
        }
    
        private boolean isAllowPath(String path) {
         
              //判断是否允许放行
             if (allowPaths.contains(path)){
                 return true;
             }
             return  false;
    
      }

    2.在nginx做转发,当请求文件上传时,直接转到相应的服务

    本实例使用了方法二、需要增加配置

    	server {
            listen       80;
            server_name  api.leyou.com;
    
            proxy_set_header X-Forwarded-Host $host;
    		proxy_set_header X-Forwarded-Server $host;
    		proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    		# 新增加的配置,用于文件上传
    		location /api/upload {
    			proxy_pass http://127.0.0.1:8082;
    			proxy_connect_timeout 600;
    			proxy_read_timeout 600;
    			
    			rewrite "^/api/(.*)$" /$1 break;
    		}
    		# 网关的配置
    		location / {
    			proxy_pass http://127.0.0.1:10010;
    			proxy_connect_timeout 600;
    			proxy_read_timeout 600;
    		}
        }

    当这样配置之后,文件上传就不会过网关,减少了网关的压力。但是有引来了一个新问题那就是跨域。

    解决上传文件出现跨域问题

    由于Nginx将文件上传的请求直接转发到了具体服务中,不再走gateway,所以gateway中的跨域配置,不再生效了。 需要在文件上传这个服务中单独配置跨域。

    写配置类CorsFilter

    /**
     * @Author: 小小张自由
     * @Date: 2021/6/15 - 11:12
     * @Description: 解决 跨域问题
     * @version: 1.0
     */
    @Configuration
    public class LeyouCorsConfiguration {
    
        @Bean
        public CorsFilter corsFilter(){
            //初始化配置对象
            CorsConfiguration configuration = new CorsConfiguration();
            //允许跨域访问的域名
            configuration.addAllowedOrigin("*");
           // configuration.setAllowCredentials(true);  //运行携带cookie
            configuration.addAllowedMethod("*"); //代表所有请求方法
            configuration.addAllowedHeader("*"); //允许携带任何头信息
    
            //初始化cors配置源对象
            UrlBasedCorsConfigurationSource configurationSource=new UrlBasedCorsConfigurationSource();
            configurationSource.registerCorsConfiguration("/**",configuration);
    
            //返回CorSfilter实例,参数
            return new CorsFilter(configurationSource);
        }
    
    }

    到此应该就可以上传了,但是还是报跨域,我已经配置好了啊,为什么还是报跨域呢?

    在nginx配置中配置请求实体大小

    我就想是不是Nginx的问题,然后我就一行一行的读配置,最后发现

    nginx配置中没有配置请求实体大小

    image.png

    加上这行配置就好了

    client_max_body_size 1024m;

    如果本篇博客对您有一定的帮助,大家记得留言+点赞+收藏哦。 

    更多相关内容
  • SpringMVC文件上传,多文件上传实例

    千次下载 热门讨论 2014-03-01 20:28:21
    在上一篇SpringMVC基础教程的源码基础上增加了文件上传,多文件上传
  • 文件上传漏洞

    千次阅读 2022-02-22 20:48:29
    文件上传 文件上传是现代互联网常见的功能,允许用户上传图片、视频、及其他类型文件,向用户提供的功能越多,Web受攻击的风险就越大。 文件上传漏洞 上传文件时,如果未对上传的文件进行严格的验证和过滤,就...

    文件上传

    文件上传是现代互联网常见的功能,允许用户上传图片、视频、及其他类型文件,向用户提供的功能越多,Web受攻击的风险就越大。

    文件上传漏洞

    • 上传文件时,如果未对上传的文件进行严格的验证和过滤,就容易造成文件上传漏洞,上传脚本文件(包括asp、aspx、php、jsp等)
    • 恶意上传行为可能导致网站甚至整个服务器被控制。恶意的脚本文件又被称为WebShell,WebShell具有强大的功能,如查看服务器目录、服务器中文件、执行系统命令等。

    文件上传漏洞成因

    文件上传漏洞的成因(复杂),一方面,Web 应用开放了文件上传功能,并且对上传的文件没有进行足够的限制;另一方面,程序开发部署时候,没有考虑到系统特性和过滤不严格;再者就是,攻击者通过Web服务器解析漏洞绕过限制,导致可以上传任意文件。

    文件上传漏洞危害

    • 文件上传漏洞最直接的威胁就是上传任意文件,包括恶意脚本、可执行程序等。
    • 如果Web 服务器所保存上传文件的可写目录具有执行权限,那么就可以直接上传后门文件,导致网站沦陷。
    • 如果攻击者通过其他漏洞进行提权操纵,拿到系统管理权限,那么直接导致服务器沦陷。
    • 同服务器下的其他网站无一幸免,均会被攻击者控制。

    文件上传利用

    • Web 服务器要开启文件上传功能,并且上传api(接口)对外“开放”(Web用户可以访问);
    • Web 用户对目标目录具有可写权限,甚至具有执行权限,一般情况下,Web 目录都有执行权限。
    • 要想完美利用文件上传漏洞,就是上传的文件可以执行,也就是Web 容器可以解析我们上传的脚本,无论脚本以什么样的形式存在。

     小马

    • 小马通常指一句话木马,因为其代码量较小,就是一句简单的代码。
    • 一句话木马短小精悍,功能强大,是为了绕过waf的检测,虽然出现了无数的变形,但本质是不变的:木马的函数执行了我们发送的命令。
    • 通过GET、POST、COOKIE三种方式提交数据
    • 用$_GET[' ']、$_POST[' ']、$_COOKIE[' ']接收传递的数据,并把接收的数据传递给一句话木马中执行命令的函数,进而执行命令。
    PHP:<?php @eval($_REQUST['cmd']);?>
    ASP:<%eval request("cmd")%>
    ASPX:<%@ Page Language="Jscript"%>
          <%eval(Request.Item["cmd"],"unsafe";)%>

    经典的一句话木马大多都只有两个部分,一个是可以执行代码的函数部分,个是接收数据的部分。

    例如 <?php @eval($_POST['cmd']);?>

    eval就是执行命令的函数,$_POST[ ‘cmd’]就是接收的数据。eval函数把接收的数据当作PHP代码来执行。这样我们就能够让插入了一句话木马的网站执行我们传递过去的任意PHP语句。

    大马 

    之所以叫大马,是因为与小马(一句话木马)区分开,并且代码比较大,但是功能比较丰富。同样,大马有很多种脚本格式,其功能基本相同。每个团队都有自己的定制大马。

    文件上传检测与绕过

    客户端检测与绕过

    检测原理

    • 客户端(Client):或称为用户端(前端),与服务器相对应。由于客户端对于文件上传漏洞的防御是通过JS代码实现的,所以客户端检测与绕过也称为JS检测与绕过。
    • 调用JS的selectFlle()函数,先将文件名转换为小写,然后通过substr获取文件名最后一个点号后面的后缀(包括点号)进行判断。

    绕过方法 

    由于后端PHP代码没有对文件做任何检测,所以只要绕过前端JS的校验就可以上传WebShell。

    • 删除浏览器事件

    • 利用BurpSuite抓包修改文件后缀名

    • 构造上传表单

    <form enctype="multipart/form-data" action="http://168.2.5.100/UpFileImage" method="post">  
    
    Upload a new file:<br>  
    
    <input type="file" name="file" size="50"><br>  
    
    <input type="submit" value="Upload">  
    
    </form>

    服务器检测与绕过

    对于文件上传,只从Web 前端进行检测显然防护不足,那么服务器端就特别重要了。一般服务端检测包括以下几个方面:

    • 后缀名检测与绕过
    • MIME类型检测与绕过
    • 文件内容检测与绕过
    • 00截断检测与绕过
    • 条件竞争检测与绕过

    后缀名检测与绕过 

    检测原理

    通过函数pathinfo()获取文件后缀,将后缀转为小写后判断是不是php。

     绕过方法1:黑名单--大小写绕过

      绕过方法1:黑名单--名单列表绕过(黑名单之外的后缀名)

    有些中间件允许解析其他文件后缀名,如asa、cer之类的或在httpd.conf配置文件中,配置如下代码,则能解析php、php3、phtml文件。所以上传一个后缀名为php3、phtml的文件即可。

     

       绕过方法1:黑名单--Windows特性

    一些特殊的文件名命名方式在Windows下是不被允许的,利用BurpSuite抓包修改后缀名,绕过验证后上传文件,windows会自动去掉后面添加的,但要注意Unix/Linux系统没有这个特性。比如:

    • 末尾的点(.)        【1.php.】
    • 空格( )        【1.php 】
    • ::$DATA        【1.php::$DATA】

     绕过方法2:白名单

    白名单绕过需要配合文件包含漏洞或解析漏洞

    绕过方法3 :.htaccess文件攻击

    • .htaccess文件是Apache服务器中的分布式配置文件(IIS中不存在该文件)该配置文件会覆盖Apache 服务器的全局配置,作用于当前目录及其子目录。
    • 如果一个Web 应用允许上传.htaccess 文件,那就意味着攻击者可以更改Apache的配置,这是十分危险。
    • 在httpd.conf配置文件中,AllowOverride参数就是指明Apache服务器是否去找.htacess文件作为配置文件,如果设置为none,那么服务器将忽略.htacess文件;如果设置为AⅡ,那么所有在.htaccess文件里有的指令都将被重写,即允许.htaccess文件覆盖掉Apache的配置。

    •  将内容符合php语法规则的文件当作PHP文件解析

    •  匹配文件名中的关键字

    比如:当文件名[info.php.png] 中包含关键字[.php],并且.htaccess 文件内容如下,info.php.png 中的代码会被执行。

    • 匹配文件名 
    <FilesMatch "sxf">
        setHandler application/x-httpd-php
    </FilesMatch>

     上传一个htaccess文件 可以让服务器将符合PHP语法规则的文件当作php解析

    绕过方法4

    结合Apache文件解析机制,从右向左开始解析文件后缀,若后缀名不可识别则继续判断直到遇到可解析的后缀为止。

    MIME类型检测与绕过 

    MIME(Multipurpose Internet Mail Extensions)是描述消息内容类型的因特网标准。MIME消息能包含文本、图像、音频、视频以及其他应用程序专用的数据。常见的MIME 类型如下:

    文件扩展名Mime-Type
    .js  application/x-javascript
    .html text/html
    .jpgimage/jpeg
    .pngimage/png
    .pdf application/pdf

    检测原理

    判断$_FILES["file"]["type"]是不是图片格式(image/gif、image/jpeg、image/pjpeg),不是则不允许上传。在HTTP 协议中,使用Content-Type 字段表示文件的MIME 类型。 $_FILES["file"]["type"]的值是从请求数据包中Content-Type中获取。

     绕过方法

    通过抓取数据请求包,上传php文件时,Content--Type值是applcation/octer-stream,上传jpg格式的文件时Content-Type值是imaag/jpeg。可修改文件类型进行绕过。

     文件内容检测与绕过

    检测原理

    利用getimagesize()函数获取图片的宽高等信息,如果上传的不是图片,那么则获取不到信息。

    文件相关信息检测

    检测图像文件相关信息

     文件幻数检测

    • JPG :FF D8 FF E0 00 10 4A 46 49 46
    • GIF :47 49 46 38 39 61(GIF89a)
    • PNG:89 50 4E 47

     

    绕过方法

    在脚本文件开头补充图片对应头部值,或在图片后写入脚本代码

    制作图片马

    • 在图片后写入脚本代码
    • copy 1.jpg/b+1.php/a 2.jpg

    参数/b指定以二进制格式复制、合并文件,用于图像类/声音类文件
    参数/a指定以ASCⅡ格式复制、合并文件,用于txt等文档类文件

     图片马上传的漏洞无法解析,需要配合文件解析或者文件包含漏洞

     00截断检测与绕过

    检测原理

    截断漏洞出现的核心就是chr(0),这个字符不为空(NuⅡ),也不是空字符(" "),更不是空格。当程序在输出含有 chr(0)变量时,chr(0)后面的数据会被停止,换句话说,就是误把它当成结束符,后面的数据直接忽略,这就导致了漏洞产生。由于00代表结束符,PHP会把00后面的所有字符删除。
    截断条件:PHP版本小于5.3.4、magic_quotes_gpc 为OFF状态

    GET方式

    POST方式

     条件竞争检测与绕过

    检测原理

    些网站文件检测逻辑是先允许上传任意文件,然后检查文件内容是否包含可执行脚本,如果包含则删除。这里使用sleep()函数来模拟判断是否含有脚本所需要的时间。

    绕过方法

    利用成功上传到删除文件的时间差,上传一个.php文件,在未删除之前立即访问,则会自动生成一个新php文件,新文件不会被删除。

    <?php 
    fputs(fopen('../shell.php','w'),'<?php phpinfo();?>');
    ?>

    防御方法

    文件上传的目录设置为不可执行

           判断文件类型

           使用随机数改写文件名和文件路径

           单独设置文件服务器的域名

           使用安全设备

    展开全文
  • SpringMVC单文件上传、多文件上传、文件列表显示、文件下载,具体效果和过程看博文http://blog.csdn.net/evankaka/article/details/45826697
  • springmvc实现文件上传jar包

    千次下载 热门讨论 2015-04-03 00:41:42
    springmvc中实现文件上传所要用到的jar包
  • 文件上传漏洞总结

    千次阅读 2022-03-17 16:40:59
    1、文件上传漏洞原理 2、常见的文件上传类型 3、文件上传注入点 4、web中常见的上传验证 黑名单常见自定义过滤规则 白名单常见的过滤规则 5、逻辑数组绕过 5.1、图片一句话木马的制作与利用 5.2、文件头检查...

    目录

    1、文件上传漏洞原理

    2、常见的文件上传类型

    3、文件上传注入点

    4、web中常见的上传验证

    黑名单常见自定义过滤规则

    白名单常见的过滤规则

    5、逻辑数组绕过

    5.1、图片一句话木马的制作与利用

    5.2、文件头检查

    5.3、getimagesize()图像信息判断

    5.4、竞争条件攻击

    5.5、突破exif_imagetype()

    5.6、脚本解析漏洞

    6、WAF绕过

    7、文件上传安全修复方案



    1、文件上传漏洞原理

    网站Web应用都有一些文件上传功能,比如文档、图片、头像、视频上传,当上传功能的实现代码没有严格校验上传文件的后缀和文件类型,此时攻击者就可以上传一个webshell到一个Web可访问的目录上,并将恶意文件传递给如PHP解释器去执行,之后就可以在服务器上执行恶意代码,进行数据库执行、服务器文件管理,服务器命令执行等恶意操作。还有一部分是攻击者通过Web服务器的解析漏洞来突破Web应用程序的防护。

    2、常见的文件上传类型

    常规类:扫描获取上传,会员中心上传,后台系统上传,各种途径上传

    CMS类:已知CMS源码,搜索已知cms漏洞(wordpress等)

    编辑器类:ckeditor,fckeditor,kindeditor,xxxeditor,也是搜索相关编辑器漏洞

    中间件类:可以通过中间件解析漏洞,上传包含后门代码的图片

    3、文件上传注入点

    1. 常规文件上传地址的获取说明

    使用谷歌语法搜索inurl:upload.php

    2. 寻找特定网站的文件上传:

    site:xx.xx upload

    3. 通过后台目录扫描工具扫描

    4、web中常见的上传验证

    后缀名:黑名单、白名单

    文件类型:MIME信息(数据包里Content-Type:image/gif)

    文件头:内容头信息

    Gif图片(GIF89a)

    jsp脚本(JFIF)

    黑名单常见自定义过滤规则

    replace('php','')

    $deny_ext = array('.asp','.aspx','.php','.jsp');//黑名单数组
    $file_name = trim($_FILES['upload_file']['name']);//去掉文件名两侧的空白字符
    $file_name = deldot($file_name);//删除文件名末尾的点
    $file_ext = strrchr($file_name, '.');//截取最后.之后的内容
    $file_ext = strtolower($file_ext); //转换为小写
    $file_ext = str_ireplace('::$DATA', '', $file_ext);//去除字符串::$DATA
    $file_ext = trim($file_ext); //收尾去空

     绕过方式(黑盒测试):

    1、a.php::$DATA,Windows系统下PHP服务器会将后缀名带::$DATA的文件当作文件流处理,过滤不起作用,上传到服务器之后,截取::之前的格式作为文件后缀,也就是a.php

    2、大小写绕过

    3、.htaccess文件(配置文件,将文件名为shana的文件当作php文件执行)

    <FilesMatch "shana">
    SetHandler application/x-httpd-php
    </FilesMatch>

    4、针对黑名单规则只过滤一次,双写脚本后缀        一次过滤: a.php->a. a.pphphp->a.php

    5、点绕过。

    $file_name = deldot($file_name);//删除文件名末尾的点

    可以更改上传文件的后缀名a.php改为a.php. .

    经过代码过滤之后文件后缀名变为a.php. 。从而绕过黑名单提交到服务器,Windows服务器不允许后缀名最后带.,因此将文件后缀名还原为a.php

    6、空格绕过。"a.php "不会匹配黑名单的.php从而绕过。且上传后会被Windows服务器自动去掉空格。

    7、中间件解析漏洞。

    白名单常见的过滤规则

    对于网站而言,白名单验证比名单拦截更要安全

    if(isset($_POST['submit'])){
        $ext_arr = array('jpg','png','gif');
        $file_ext = substr($_FILES['upload_file']['name'],strrpos($_FILES['upload_file']['name'],".")+1); //截取后缀名
        if(in_array($file_ext,$ext_arr)){
            $temp_file = $_FILES['upload_file']['tmp_name'];
            $img_path = $_GET['save_path']."/".rand(10, 99).date("YmdHis").".".$file_ext;

    绕过白名单验证方式:

    1、%00和0x00截断。%00是被服务器解码为0x00发挥了截断作用

    0x00是十六进制表示方法,是ascii码为0的字符,在有些函数处理时,会把这个字符当做结束符。

    %00和0x00是有区别的:%00是URL中的,0x00是文件命名

    %00需要PHP版本小于5.3.4,且打开php的配置文件php-ini,将magic_quotes_gpc(魔术引号)设置为Off

    get会自动解码 %00

    post不会解码 %00 -> url编码

    2、0x0a截断:原理同上

    3、MIME绕过。burp抓包,修改Content-type值为合法的image/jpeg,image/gif等即可绕过

    5、逻辑数组绕过

    5.1、图片一句话木马的制作与利用

    cmd命令行,将图片与马合成图片🐎

    copy 1.png /b + shell.php /a webshell.jpg

     利用文件包含漏洞,include函数解析图片马

    5.2、文件头检查

    主要是检测文件内容开始处的文件幻数,比如图片类型的文件幻数如下,要绕过jpg文件幻数检测就要在文件开头写上下图的值:

    在这里插入图片描述
    Value = FF D8 FF E0 00 10 4A 46 49 46

    要绕过gif文件幻数检测就要在文件开头写上下图的值

    在这里插入图片描述
    Value = 47 49 46 38 39 61

    要绕过png文件幻数检测就要在文件开头写上下面的值

    在这里插入图片描述
    Value = 89 50 4E 47

    然后在文件幻数后面加上自己的一句话木马代码就行了

    5.3、getimagesize()图像信息判断

     如果上传的不是图片文件,那么getimagesize()就获取不到信息,则不允许上传。

    通过Linux合成图片马,此时使用getimagesize()既可以获取图片信息,文件后缀php也能被解析为脚本文件,从而绕过getimagesize()的限制。

    cat image.jpg webshell.php > image.php

    5.4、竞争条件攻击

    一些网站上传文件的逻辑是先允许上传任意文件,然后检查上传的文件是否包含Webshell脚本,如果包含则删除文件。这里存在一个问题是文件上传成功后和删除文件之间存在一个短的时间差(因为要执行文件上传和删除文件的操作),攻击者就可以利用这个时间差完成竞争条件的上传漏洞攻击。

      利用:可以先上传一个webshell脚本10.php,10.php的内容是生成一个新的webshell脚本shell.php。10.php的代码如下

    <?
    fputs(fopen('../shell.php','w'),'<?php @eval($_POST['x']) ?>');
    ?>

            当10.php上传成功后,客户端检查脚本文件后会自动生成shell.php。

    5.5、突破exif_imagetype()

    exif_imagetype() 读取一个图像的第一个字节并检查其签名。如果发现了恰当的签名则返回一个对应的常量,否则返回 FALSE。返回值跟getimagesize() 返回的数组中的索引 2 的值是一样的,但exif_imagetype函数快得多。PHP需要开启php_exif模块

    返回值与图像类型对应表如下

    绕过方法:

    给上传脚本加上相应的幻数头字节就可以,php引擎会将 <?之前的内容当作html文本,不解释而跳过之,后面的代码仍然能够得到执行比如下面:

    (一般不限制图片文件格式的时候使用GIF的头比较方便,因为全都是文本可打印字符。)

    GIF89a
    
    <?
    
    php echo shell_exec($_GET['cmd']);
    
    ?>

    图片文件通常有称作幻数的头字节,我们来看一下几种图片文件的幻数:

    (注意!下面是二进制而不是文本格式的数据)

    JPG

    FF D8 FF E0 00 10 4A 46 49 46

    GIF(相当于文本的GIF89a)

    47 49 46 38 39 61

    PNG

    89 50 4E 47

    通过检查头几位字节,可以分辨是否是图片文件

    5.6、脚本解析漏洞

     参考链接:https://blog.csdn.net/weixin_43965597/article/details/107665597

    参考链接:https://blog.csdn.net/weixin_34088838/article/details/94607178

    6、WAF绕过

    常见的绕过方法:

    1、数据溢出-防匹配(xxx...)
    2、符号变异-防匹配(' " ;)
    3、数据截断-防匹配(%00 ; 换行)
    4、重复数据-防匹配(参数多次)

    1、数据溢出绕过WAF需要大量的模糊测试,当垃圾参数过多时,WAF的检测就可能会失效

     

    2、符号变异就是猜测WAF检测的依据,例如filename="a.php"

    网站安全狗WAF软件现在的机制就是匹配单/双引号里面的内容

    pyload

    "xx'.php
    "xx;.php
    'xx;.php
    ";xx.php
    ';xx.php
    " xx.php
    ' xx.php
    "x x.php
    'x x.php

     

      

    3、数据截断-防匹配(%00 ; 换行)

    通过用; 或者 %00 或者 换行 来截断文件名,使得WAF错误识别或不能识别文件类型从而达到绕过WAF

    • 文件名中加入图片后缀提前用分号截断(可行)

    原因是防护软件只检测分号(;)前面的部分,一旦正确就放行,不再检测后面的,然而apache服务器会取最后的文件类型来命名

    payload

    "ab.jpg;.php"
    
    "abc.php%00.jpg"                             #注意%00需要经过url编码
    
    "x.p
    h
    p"
    
    x.ph
    p
    
    x.
    p
    h
    p

    4、重复数据-防匹配(参数多次)

    payload

    filename="Content-Disposition: form-data; name="upload_file";x.php"
    filename="xx.jpg";filename="xx.jpg";filename="xx.jpg";filename="xx.jpg";...........filename="xx.php";
    • 重复filename 

    前面的filename为可接受的文件格式,最后一个为php文件格式,前面的重复多次,可绕过。

    ●filename中配合其他参数

    配合Content-Disposition

     配合Content-Type

    5、配合目录命名绕过

    "/"与";"配合绕过

      payload:

    filename="/jpeg;x.php"
    filename="/jpeg;/x.php"

      

    6、配合FUZZ字典测试绕过

    手工测试的话有点麻烦,可以借助写好的字典配合BP进行批量测试,先在本地测试,然后在真实环境进行测试,以防封IP。

    https://github.com/TheKingOfDuck/fuzzDictsicon-default.png?t=M276https://github.com/TheKingOfDuck/fuzzDicts
    GitHub - fuzzdb-project/fuzzdb: Dictionary of attack patterns and primitives for black-box application fault injection and resource discovery.icon-default.png?t=M276https://github.com/fuzzdb-project/fuzzdb

    7、文件上传安全修复方案

    后端验证:采用服务端验证模式

    后缀检测:基于黑名单,白名单过滤

    MIME 检测:基于上传自带类型检测

    内容检测:文件头,完整性检测

    自带函数过滤:参考 uploadlabs 函数

    自定义函数过滤:function check_file(){}

    WAF 防护产品:宝塔,云盾,安全公司产品等

    展开全文
  • js实现文件上传

    热门讨论 2013-04-09 14:06:14
    很棒的js文件上传源代码,上传稳定还有进度提示,需要使用commons-fileupload和commons-io.可以直接嵌入项目里面使用。
  • easyUI文件上传

    千次下载 热门讨论 2013-07-10 20:30:44
    基于easyui上传 支持大型文件 多文件上传 希望用到的朋友 不要忘记评价
  • 文件上传下载需要的jar包 java文件上传下载 源码 http://blog.csdn.net/da_zhuang/article/details/8737618
  • Java 文件上传与下载

    千次阅读 2021-06-06 19:29:35
    MultipartFile 这个类一般是用来接受前台传过来的文件 Part能获取所有的请求参数的参数名,而Parameter只能获取非文件类型的...Part能获得上传文件文件大小、文件类型 HttpServletRequest request @RequestPart ...

    Ⅰ、文件上传

    一、form-data 类型

    form-data 类型即常用的表单提交

    两种处理参数的方式

    • MultipartFile 类接受前台传过来的文件
    • part 接收字节流

    @RequestPart 作用类似 @RequestParam

    1、postMan 请求

    在这里插入图片描述

    2、文件上传接口

    直接上代码

    @RestController
    public class TestFile {
        private BufferedOutputStream bufferedOutputStream = null;
    
        @RequestMapping(value = "/upload", method = RequestMethod.POST)
        @ResponseBody
        public String readFile(HttpServletRequest request, @RequestParam("name") String name, @RequestPart("file1") MultipartFile file3,@RequestPart("photo") MultipartFile photo) throws IOException, ServletException {
           
            String path= "I:\\spring\\spring-mybatis-plus\\src\\main\\resources\\public\\static\\";
    
            System.out.println(name);
            /*
            第一种 : 使用 MultipartFile 封装好的 transferTo() 方法保存文件
            photo.transferTo(new File(path+photo.getOriginalFilename()));
    
            第二种 :  使用 MultipartFile 字节流保存文件
             fileUtil(file3, String.valueOf(path));
    
    		第三种 :  使用 Part 接收文件字节流
            Part file2 = request.getPart("file2");
            file2.write(path + file2.getSubmittedFileName());
            */
    		// request.getParts() 获取的是全部参数(name,age,file1,file2),包括文件参数和非文件参数
            for (Part part : request.getParts()) {
                // 获取文件类型
               part.getContentType();
                // 获取文件大小
               part.getSize();
                // 获取文件名
               part.getSubmittedFileName();
               // 获取参数名 (name,age,file1,file2)
               part.getName()
                if(part.getContentType()!=null){
                    part.write(path + part.getSubmittedFileName());
                }else{
    				 // 可以获取文本参数值
              		 request.getParameter(part.getName())
    			}
            }
            return "success";
        }
    
        public String fileUtil(MultipartFile file, String path) {
    
            if (!file.isEmpty()) {
                try {
                    byte[] bytes = file.getBytes();
                    bufferedOutputStream = new BufferedOutputStream(new FileOutputStream(
                            new File(path + file.getOriginalFilename())));
                    bufferedOutputStream.write(bytes);
                    bufferedOutputStream.close();
                    return file.getOriginalFilename() + "success upload";
                } catch (Exception e) {
                    return file.getOriginalFilename() + "failed to upload ---> " + e;
                }
            } else {
                return file.getOriginalFilename() + "You failed to upload file was empty.";
            }
        }
    }
    
    

    实际开发中,上面有很多需要优化的地方,比如写出文件工具类,获取项目路径(注意测试和打包上线路径),三种方法使用一种即可,流参数输出之后,就获取不到,不像其他参数可以在该请求的任意位置获取

    如果一个输入框多个文件,可以使用

    List<MultipartFile> files = ((MultipartHttpServletRequest) request).getFiles("");
    // 也可以使用 part.getName() 获取参数名做判断
    part.getName()
    

    或者 MultipartFile[] file3

        public String readFile(HttpServletRequest request, @RequestParam("name") String name, @RequestPart("file1") MultipartFile[] file3) 
    
    3、 测试

    在这里插入图片描述

    二、binary 类型

    binary 这一类型,指的就是一些二进制文件类型,如application/pdf,指定了特定二进制文件的MIME类型。就像对于text文件类型若没有特定的子类型(subtype),就使用 text/plain。类似的,二进制文件没有特定或已知的 subtype,即使用 application/octet-stream,这是应用程序文件的默认值。

    对于application/octet-stream,只能提交二进制,而且只能提交一个二进制,如果提交文件的话,只能提交一个文件,后台接收参数只能有一个,而且只能是流(或者字节数组)。

    1、postMan 请求

    在这里插入图片描述

    2、文件上传接口

    就是简单的文件读写,其中细节可以根据需求自行添加

    @RequestMapping(value = "/upload2",method = RequestMethod.POST)
        public String upload2(HttpServletRequest request) throws IOException {
            ServletInputStream inputStream = null;
            FileOutputStream fileOutputStream = null;
            try {
                inputStream = request.getInputStream();
    
                fileOutputStream = new FileOutputStream(new File("I:\\spring\\spring-mybatis-plus\\src\\main\\resources\\public\\static\\微信图片_20210729130156.jpg"));
    
                int len;
                byte[] bytes = new byte[1024];
                while((len = inputStream.read(bytes))!=-1){
                    fileOutputStream.write(bytes,0,len);
                }
            } catch (IOException e) {
                e.printStackTrace();
                return "上传失败";
            }
            finally {
                if(fileOutputStream!=null){
                    fileOutputStream.close();
                }
                if(inputStream!=null){
                    inputStream.close();
                }
            }
            return "上传成功";
        }
    
    3、测试

    上传成功
    在这里插入图片描述

    三、springboot 配置

    入股不配置,可能上传文件过大会保错,默认上传文件小于 1MB

    如果是 springboot 项目,可以通过配置文件限制文件上传大小

    文件上传配置类 MultipartAutoConfiguration
    在这里插入图片描述
    MultipartProperties 默认参数,可以看到默认开启,单个文件最大 1MB,单个请求最大 10MB
    在这里插入图片描述
    application.yml 上传文件配置

    spring:
      servlet:
        multipart:
          max-file-size: 10MB # 单个文件最大 10MB
          maxRequestSize: 100MB # 单个请求最大 100 MB
    
    四、总结

    part 使用起来比较方便,接受的就是字节流,读取文件类型,文件名,文件大小也比较方便,不清楚 getParameter() 和 getPart() 区别 的可以看我另一篇博客
    https://blog.csdn.net/qq_41538097/article/details/117637372

    Ⅱ、文件下载

    一、下载本地资源

    Content-Disposition 详细说明:参考https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Headers/Content-Disposition
    Content-disposition 是 MIME 协议的扩展,MIME 协议指示 MIME 用户代理如何显示附加的文件。
    response.setHeader("Content-Disposition", "attachment;fileName=test.txt" ;
    意味着消息体应该被下载到本地;大多数浏览器会呈现一个“保存为”的对话框,将 filename 的值预填为下载后的文件名,假如它存在的话(fileName 或者 filename 都可以使用)
    response.setHeader(“Content-Disposition”, “inline; filename=test.jpg” );设置为在线打开

    public class FileDownload {
        @RequestMapping("/download")
        public void download(String fileName, HttpServletResponse response,boolean isOnLine) throws IOException {
        // 路径可以指定当前项目相对路径
            File file = new File("C:\\Users\\Administrator\\Pictures\\小程序\\" + fileName);
            if (file.exists()) {
                FileInputStream fileInputStream = new FileInputStream(file);
                ServletOutputStream outputStream = response.getOutputStream();
                if(!isOnLine){
                    response.setContentType("application/octet-stream");
                    // 如果文件名为中文需要设置编码
                    response.setHeader("Content-Disposition", "attachment;fileName=" + URLEncoder.encode("test.jpg", "utf8"));
                }
                byte[] bytes = new byte[1024];
                int len;
                while ((len = fileInputStream.read(bytes)) != -1) {
                    outputStream.write(bytes, 0, len);
                }
            }
        }
    }
    

    测试下载:
    接口:http://localhost:8081/download?fileName=test.jpg

    不同的浏览器弹出的操作可能不同

    chrome浏览器
    在这里插入图片描述
    IE浏览器
    在这里插入图片描述
    都可以下载成功
    在这里插入图片描述
    测试在线打开
    http://localhost:8081/download?fileName=test.jpg&isOnLine=false
    在这里插入图片描述
    如果不指定下载,则默认是在线打开(谷歌浏览器)或者使用 response.setHeader(“Content-Disposition”, “inline; filename=test.jpg” );设置为在线打开

    二、下载网络资源

    到网易云音乐找个歌曲
    在这里插入图片描述

        @RequestMapping("/downLoadMusic")
        public void downloadNetworkFile(HttpServletResponse response) throws IOException {
            URL url = new URL("https://m701.music.126.net/20210808175335/c2ed0b504dd7bf3f86ac67a40fd092d2/jdyyaac/565b/065f/0358/a1cd0e25a815dffcc0c1422398efde9e.m4a");
            URLConnection urlConnection = url.openConnection();
            InputStream inputStream = urlConnection.getInputStream();
            ServletOutputStream outputStream = response.getOutputStream();
            response.setContentType("application/octet-stream");
            response.setHeader("Content-Disposition", "attachment;fileName=" + URLEncoder.encode("起风了.m4a", "utf8"));
            byte[] bytes = new byte[1024];
            int len;
            while ((len = inputStream.read(bytes)) != -1) {
                outputStream.write(bytes, 0, len);
            }
            outputStream.close();
            inputStream.close();
        }
    

    chrome测试
    在这里插入图片描述
    IE测试
    在这里插入图片描述

    下载成功
    在这里插入图片描述
    注意:下面的情况针对静态资源在 resources 目录下,运行找不到资源的原因以及解决办法
    首先,开发环境使用绝对路径肯定是不会错的,但部署运行环境就需要考虑路径问题,下面解决这个问题
    对于 springboot 项目打成 jar 包,在 window/linux 系统使用 java -jar 运行时,需要考虑路径问题,因为是运行未解压 jar 包,如果直接指定 resources 目录下文件也运行是找不到的,此时必须使用输入流才可以 InputStream resourceAsStream = FileDownload.class.getClassLoader().getResourceAsStream("static/0.jpg"); 亲测对于 window/Linux 都有效
    更多文件下载可参考 https://www.jb51.net/article/203861.htm

    展开全文
  • 开发项目的时候,用到文件上传的功能很常见,包括单文件上传和多文件上传,上传各种类型的文件。在vue里面要实现多文件上传功能,还是很方便的。 本文就一起来学习一下,如何把多文件上传功能封装成一个组件,后面...
  • 俺亲手写的: 1.支持多文件上传 2.带进度条 3.可以显示文件名称 4.可以实时显示已上传的大小 5.可以从队列中删除 6.各元素的样式都可以自己控制
  • 文章目录前言一、环境准备及依赖库二、项目结构三、 功能实现1、axios二次封装2、 单文件上传FROM-DATA,先选文件再上传3、 单文件上传BASE64,只能上传小于100K的png或jpg图片文件4、多文件上传FORM-DATA5、多文件...
  • 1.添加权限(访问网络权限和读写权限) 2.获取上传文件路径并判断是否为空 3.若不为空,创建异步请求对象 4.创建上传文件路径 5.执行post请求(指定url路径,封装上传参数,新建AsyncHttpResponseHandler方法)
  • 文件上传漏洞2

    千次阅读 2022-03-22 16:32:24
    有些系统只是在客户端使用js对上传文件的后缀进行检查,服务端没有进行检查。由于客户端的js用户可以禁用,修改等等,导 致可以绕过客户端的检测,上传不合法文件。漏洞利用 1.将js禁用 2.修改客户端的js 3.上传合法...
  • Selenium系列教程 - 文件上传

    千次阅读 2022-01-25 14:11:10
    主要内容一、通过send_keys方法(该方法只适用于input标签)二、通过AutoIt来处理上传文件(适用所有)三、多文件上传 在Web UI自动化测试中可能会遇到文件上传的场景,针对该场景我们要区分上传按钮的种类,大体上...
  • ① 定义允许上传的附件类型: attachment: file: maxSize: 10 types: jpeg: FFD8FF jpg: FFD8FF bmp: 424D png: 89504E47 rtf: 7B5C727466 txt: 75736167 pdf: 255044462D312E doc: D0CF11E0 docx: 504B...
  • DVWA靶场-文件上传漏洞

    千次阅读 2022-03-08 14:37:58
    第五关:File upload(文件上传)       文件上传漏洞,通常是由于对上传文件的类型、内容没有进行严格的过滤、检查,使得攻击者可以通过上传木马获取服务器的webshell权限,因此文件...
  • android批量文件上传(附服务端Demo)

    热门讨论 2015-08-04 17:38:22
    android——SpringMVC实现批量文件上传 HTTP协议和HttpClient2种方式实现批量上传
  • 本文详细讲解了如何实现文件上传功能。掌握全套的文件上传方法。
  • SpringBoot文件上传和下载

    千次阅读 2021-11-26 12:07:40
    SpringBoot文件上传和下载 一、SpringBoot文件上传 1、SpringMVC文件上传 1、Client处理 选择文件 (1)form表单 选择文件 method="post" (2)enctype="multipart/form-data" (3) 准备文件框<input type=...
  • ASP.NET Web API 接收文件上传

    热门讨论 2015-05-24 10:07:42
    ASP.NET Web API File Upload and Multipart MIME
  • 文件上传漏洞绕过手法

    千次阅读 2021-11-29 09:58:18
    1.文件上传原理 有一些网站提供上传服务,比如头像的设置就是上传图片,或者上传文档,上传压缩包等等。一般网站是希望上传图片格式或者文本格式的,当如果检测手段不全面,就会导致攻击者直接上传了恶意的脚本代码...
  • tomcat文件上传功能

    千次阅读 2020-06-16 10:37:12
    文件上传下载功能实现零、流程一、准备工作1、创建空项目2、导包3、配置Tomcat二、文件上传的注意事项(调优)三、需要用到的类详解FileItem类ServletFileUpload类四、代码编写 零、流程 一、准备工作 1、创建空...
  • 1. 了解文件上传漏洞的原理。 2. 掌握文件上传漏洞的防御手段。
  • 通用文件上传设计

    千次阅读 2018-12-21 15:47:36
    前端采用XMLHttpRequest进行文件上传。后端(springboot2.x)接口支持多文件同时上传,接口可根据数据库动态配置验证(文件大小、文件类型)合法性,该接口可满足上传文件大小500mb的需求(大于50...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 1,520,786
精华内容 608,314
关键字:

文件上传