常用文件类型判断(防止文件后缀被篡改)

该博客介绍了如何通过文件的字节码前几位来校验文件的真实类型,即使文件后缀被修改。提供了一个工具类用于读取文件字节并转换为十六进制,以及一个文件类型校验工具类,包含了常见文件类型的字节码头部信息。当文件后缀篡改时,能识别出原始文件类型。
摘要由CSDN通过智能技术生成

判断原理:定义好常用格式的文件后缀,以及对应文件的字节码前N位,作为判断的一句。

一般而言,如果手工修改文件的后缀,其内部文件字节码是不会发生变化的,以此来作为判断的标准。

因此,工作中,定义一个简要的工具来对常用的文件格式进行校验也是必要的。

以下是定义好的常用几种文件格式的校验,若有需要,可以自行增加。

特殊情况:目前,对于文本文件(*.txt)的文件无法校验,其读取的文件字节码几乎都不一样。当然还可能存在其他的。

字节转换为十六进制工具类:

import java.io.InputStream;

public final class BytesUtil {

    public static String readBytesToHex(InputStream in, byte[] buff) {
        readBuff(in, buff);
        return bytesToHex(buff);
    }

    public static boolean readBuff(InputStream in, byte[] buff) {
        try {
            return in.read(buff, 0, buff.length) != -1;
        } catch (Exception e) {
            throw new RuntimeException(e.getMessage());
        }
    }

    public static String bytesToHex(byte[] buff) {
        if (buff == null || buff.length == 0) {
            return null;
        }
        StringBuilder s = new StringBuilder();
        for (byte b : buff) {
            String hv = Integer.toHexString(b & 0xFF);
            if (hv.length() < 2) {
                s.append("0");
            }
            s.append(hv);
        }
        return s.toString().toUpperCase();
    }
}

文件类型校验工具类:

import lombok.Getter;
import lombok.extern.slf4j.Slf4j;

import java.io.*;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Optional;

/**
 * 文件类型校验工具
 */
@Slf4j
public final class FileTypeCheckUtil {

    public static boolean checkType(File file) {
        try (FileInputStream in = new FileInputStream(file)) {
            return checkType(in, file.getName());
        } catch (IOException e) {
            throw new RuntimeException(e.getMessage());
        }
    }

    public static boolean checkType(InputStream in, String fileName) {
        return doCheckRowType(in, fileName, Type.values());
    }

    public static boolean checkRawType(File file, Type targetType) {
        if (file == null) {
            throw new RuntimeException("校验的文件为空");
        }
        try (FileInputStream in = new FileInputStream(file)) {
            return checkRowType(in, file.getName(), targetType);
        } catch (IOException e) {
            throw new RuntimeException(e.getMessage());
        }
    }

    public static boolean checkRowType(InputStream in, String fileName, Type targetType) {
        return doCheckRowType(in, fileName, targetType);
    }

    private static boolean doCheckRowType(InputStream in, String fileName, Type... targetTypes) {
        if (in == null) {
            throw new RuntimeException("校验的文件流为空");
        }
        if (fileName == null) {
            throw new RuntimeException("校验的文件名为空");
        }
        String[] arr = fileName.split("\\.");
        if (arr.length < 2) {
            throw new RuntimeException("校验的文件不是特定格式的文件");
        }
        String fileSuffix = arr[arr.length - 1];
        Optional<Type> op = Arrays.stream(targetTypes).filter(f -> Arrays.stream(f.suffix).anyMatch(s -> s.equalsIgnoreCase(fileSuffix))).findAny();
        if (!op.isPresent()) {
            throw new RuntimeException("无法校验当前文件格式:" + fileSuffix);
        }
        Type type = op.get();
        byte[] buff = new byte[type.hexCode.length() / 2];
        String hex = BytesUtil.readBytesToHex(in, buff);
        boolean matched = type.getHexCode().equals(hex);
        if (!matched) {
            Optional<Type> optional = Arrays.stream(Type.values()).filter(c -> c.getHexCode().equals(hex)).findAny();
            optional.ifPresent(t -> log.error("“{}”文件后缀被篡改, 原文件类型:{}", fileName, t.getSuffix()));
        }
        return matched;
    }


    //文件的字节码头
    @Getter
    public enum Type {
        XLS_DOC_PPT("D0CF11E0A1B11AE1", "xls", "doc", "ppt"),
        XLSX_DOCX_PPTX("504B0304", "xlsx", "docx", "pptx"),
        PDF("255044462D312E", "pdf"),
        LIBRE_OFFICE("504B030414", "odg", "odp", "ods", "odt"),

        ZIP("504B03040A", "zip"),
        RAR("52617221", "rar"),
        GZ("1F8B08", "gz"),

        JPEG("FFD8FF", "jpeg"),
        JPG("FFD8FFE0", "jpg"),
        PNG("89504E47", "png"),
        GIF("47494638", "gif"),
        WEBP("52494646", "webp"),
        BMP("424D", "bmp"),
        BPMN("3C3F786D6C", "bpmn");

        Type(String hexCode, String... suffix) {
            this.hexCode = hexCode;
            this.suffix = suffix;
        }

        private final String hexCode;
        private final String[] suffix;

        public static List<String> allSuffix() {
            List<String> r = new ArrayList<>();
            for (Type type : Type.values()) {
                r.addAll(Arrays.asList(type.getSuffix()));
            }
            return r;
        }

    }
}

### 回答1: 文件上传漏洞是Web应用程序中常见的安全漏洞之一,攻击者可以通过上传恶意文件来执行代码、获取敏感信息、攻击其他用户等。为了防止文件上传漏洞,可以采用以下防御机制: 1. 文件类型检查:在上传文件之前,应该对文件类型进行严格的检查,只允许上传指定的文件类型,例如图片、文本、PDF等。可以使用文件扩展名、MIME类型等方式来检查文件类型。 2. 文件大小限制:限制上传文件的大小,避免上传过大的文件导致服务器资源耗尽或拒绝服务攻击。 3. 文件名过滤:过滤掉恶意文件名,例如包含特殊字符、脚本代码等的文件名。 4. 文件内容检查:对上传的文件内容进行检查,避免上传包含恶意代码的文件。 5. 文件路径限制:限制上传文件的存储路径,避免上传恶意文件到系统目录或其他敏感目录。 6. 权限控制:对上传文件进行权限控制,例如只允许特定用户上传文件,或限制上传文件的访问权限。 7. 文件重命名:在上传文件时,将文件重命名为随机字符串,避免上传文件名相同的文件覆盖原有文件。 综上所述,通过以上防御机制可以有效地防止文件上传漏洞的发生,提高Web应用程序的安全性。 ### 回答2: WEB安全文件上传防御机制是指在网络应用中,为防止恶意用户上传危险文件并对系统造成安全威胁,采取的一系列防御措施。 首先,一种常见的防御机制是对文件类型进行限制。通过白名单或黑名单的方式,设置允许或禁止上传的文件类型,可以阻止用户上传可能存在风险的文件,如执行文件、脚本文件等。这种限制可以在前端或后台进行,前端可通过验证文件后缀判断,后台可通过文件头信息或内容进行判断。 其次,还可以对文件进行内容检测。这种机制可以通过对上传文件进行解析,检查其中的内容是否符合安全要求。例如,可以检查上传的图片是否包含恶意代码、上传的文档是否存在潜在的漏洞等。这需要在服务器端进行深入解析和检测,以确保上传文件的安全性。 此外,还可以对上传的文件进行重命名和存储路径随机化。通过对文件名进行加密或随机命名,可以避免恶意用户利用已知的文件名进行攻击,同时还可以将上传的文件存储到不可访问的路径中,提高上传文件的安全性。 最后,日志记录和监控也是重要的防御机制。通过记录每次文件上传的相关信息,包括上传者、上传时间、上传文件的属性等,可以方便后续对上传行为进行监控和追溯,及时发现并处理潜在的安全威胁。 综上所述,WEB安全文件上传防御机制涵盖了文件类型限制、内容检测、重命名与路径随机化、日志记录与监控等多种措施,通过这些手段可以提高网络应用的安全性,预防恶意文件上传对系统造成的安全威胁。 ### 回答3: WEB安全文件上传防御机制是为了防止恶意用户上传含有安全漏洞的文件或恶意文件,对WEB应用进行保护的一种机制。 首先,常用的WEB安全文件上传防御机制是通过对文件的类型和扩展名进行检查。通过验证文件的MIME类型和扩展名,可以辨别出危险的文件类型,例如可执行文件或脚本文件。如果检测到这些危险的文件类型,就应该及时拒绝上传,并给出合理的提示。 其次,WEB安全文件上传防御机制还可以通过对文件内容进行检查来确保文件的真实性和完整性。可以使用文件的特征码或哈希值进行校验,以确保文件内容没有被篡改。同时,还可以检测文件中是否含有恶意代码、文件头是否正确等,以确保上传的文件安全可靠。 此外,应该对上传文件的大小进行限制,防止恶意用户上传过大的文件导致服务器压力过大或占用过多的存储空间。可以设置合理的文件大小阈值,超过阈值的文件应及时拒绝上传,并给出相应的警示和提示。 最后,对于敏感文件的上传,应该进行额外的权限设置和访问控制。例如,将敏感文件存放在非web可访问的目录下,通过程序进行读取操作,从而避免用户直接访问敏感文件。 综上所述,WEB安全文件上传防御机制是通过对文件类型、扩展名、内容的检查和限制,确保上传文件的安全性和完整性,同时阻止恶意用户利用文件上传功能进行攻击。这些机制可以有效地保护WEB应用的安全。
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

流沙QS

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值