山东大学软件学院项目实训-创新实训-SDUMeeting(七)

山东大学软件学院项目实训-创新实训-SDUMeeting(七)

web安全(二)

山大会议的客户端加入了对用户自定义头像的支持,需要用户自行上传头像图片,这个过程存在文件注入漏洞,这篇文章记录解决文件注入漏洞的过程。

package com.meeting.file.util;

import com.meeting.common.exception.BaseException;
import com.meeting.common.exception.FileFormatException;
import com.meeting.common.util.UUIDUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;

import java.io.*;

@Component
public class PictureUtil {

    @Value("${file.path}")
    public String path;

    @Value("${picture.reg}")
    private String reg;

    /**
     * 文件后缀名,.jpg
     */
    @Autowired
    private UUIDUtil uuidUtil;

    /**
     * 文件地址 /file/pic/{图片类型}/{uid}.jpg
     * 处理图片
     * @param type 类型
     * @param file 图片
     * @param fileType 图片格式
     */
    public void handlePicture(String type, MultipartFile file, long uid, String fileType)
            throws IOException{
        String originalName = file.getOriginalFilename();
        String fileType_in = file.getContentType();

1.文件名检查
要求文件名不能为空,文件头格式为"image/jpeg",文件后缀为"jpeg"和"png",限制了上传的文件只能为图片格式

        if (originalName == null) {
            throw new BaseException("文件名不能为空");
        }
        if (!("image/jpeg").equals(fileType_in)
                && !("image/png").equals(fileType_in)) {
            throw new FileFormatException("不支持的文件格式,文件头表示的格式不支持");
        }
        if (!"jpeg".equals(fileType) && !"png".equals(fileType)) {
            throw new FileFormatException("不支持的文件格式,fileType参数");
        }
        if (!originalName.matches(reg)) {
            throw new FileFormatException("不支持的文件格式,img参数");
        }

2.文件重命名
将文件名重命名为用户的uid
防范00截断
00截断原理,为什么能做到00截断? 答:0x00是字符串的结束标识符,攻击者通过手动添加字符串标识符的方式,将00后面内容截断。 但是00后面的东西又能帮助我们绕过文件检测。

        // 新的文件名
        String fileName = "" + uid + "." + fileType;
        // 文件目的地址
        File dest = new File(path + '/' + type + '/' + fileName);
        if(!dest.getParentFile().exists()){
            dest.getParentFile().mkdir();
        }
        file.transferTo(dest);
    }

    public byte[] openPicture(String filename, String type)
            throws FileNotFoundException {
        File source = new File(path + '/' + type + '/' + filename);
        if (source.exists() && source.isFile()) {
            InputStream inputStream = null;
            ByteArrayOutputStream outputStream = null;
            try {
                inputStream = new FileInputStream(source);
                outputStream = new ByteArrayOutputStream();
                byte[] buff = new byte[1024];
                int read = -1;
                while ((read = inputStream.read(buff)) != -1) {
                    outputStream.write(buff, 0, read);
                }
                if (outputStream.size() == 0) {
                    throw new FileNotFoundException("空文件");
                }
                return outputStream.toByteArray();
            } catch (IOException exception) {
                return null;
            } finally {
                handleClose(inputStream, outputStream);
            }
        } else {
            throw new FileNotFoundException("文件不存在");
        }
    }

    private void handleClose(InputStream inputStream, OutputStream outputStream) {
        try {
            if (inputStream != null) {
                inputStream.close();
            }
            if (outputStream != null) {
                outputStream.close();
            }
        } catch (IOException exception) {
            exception.printStackTrace();
        }
    }

}

3.限制上传的文件大小,限制文件最大为5Mb

package com.meeting.file;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.servlet.MultipartConfigFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.util.unit.DataSize;

import javax.servlet.MultipartConfigElement;

@SpringBootApplication
public class FileApplication {

    @Bean
    public MultipartConfigElement multipartConfigElement() {
        MultipartConfigFactory factory = new MultipartConfigFactory();
        // 单个文件最大
        factory.setMaxFileSize(DataSize.parse("5MB"));
        // 文件上传总大小
        factory.setMaxRequestSize(DataSize.parse("5MB"));
        return factory.createMultipartConfig();
    }

    public static void main(String[] args) {
        SpringApplication.run(FileApplication.class, args);
    }

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值