提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
前言
因系统扫描出现如下代码,故后台添加上传白名单,通过文件后缀来对比文件byte前8位判断文件是否可以上传。
扫描漏洞:文件上传绕过测试 ;
风险描述:文件上传漏洞通常由于网页代码中的文件上传路径变量过滤不严或webserver相关解析漏洞未修复而造成的,如文件上传功能实现代码没有严格限制用户上传的文件后缀以及文件类型。
修复建议:服务端白名单校验可上传的文件类型。
提示:以下是本篇文章正文内容,下面案例可供参考
代码如下(示例):
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
public class FileTypeVerifyUtils {
private static Map<String, String> fileFormat = new HashMap<String, String>();
static {
fileFormat.put("jpg","ffd8ffe0");
fileFormat.put("png","89504e47");
fileFormat.put("tif","49492a00");
fileFormat.put("gif","47494638");
fileFormat.put("dwg","41433130");
fileFormat.put("pdf","255044462");
fileFormat.put("zip","504b0304");
fileFormat.put("docx","504b0304");
fileFormat.put("doc","d0cf11e0");
fileFormat.put("xls","d0cf11e0");
fileFormat.put("xlsx","504b0304");
}
/**
* @Description 根据传入的文件获得后缀,获得指定文件格式byte[]数组中的前8位字符
* 将传入文件转化为byte[]数组,取前8位.判断传入文件的前8位和我们指定好的文件byte[]的前8位是否相同,
* 如果相同则文件格式没有被篡改,反之,文件后缀格式被篡改
* @Param [file]
* @return boolean 返回true 表示文件格式验证通过, 返回false 文件格式验证失败
**/
public static boolean suffixVerify(File file){
String fileType = "";
String name = file.getName();
int i = name.lastIndexOf(".");
// 获取文件的后缀
if(i > 0){
fileType = name.substring(i + 1);
}
//根据文件的后缀获取,获取文件的byte[]的前8位
if(fileFormat.containsKey(fileType.toLowerCase())){
String fileByte8 = String.valueOf(fileFormat.get(fileType.toLowerCase()));
//获取传入文件的byte[]的前8位
byte[] bytes = inputStream2ByteArray(file);
String compareByte = bytesToHexString(bytes);
//如果传入文件的byte[]的前8位和我们定义好的byte[]的前8位相同,验证通过.
if (compareByte.startsWith(fileByte8)){
//如果格式校验成功
return true;
}else{
return false;
}
}else{
return false;
}
}
/**
* @Description 将file文件转化为byte[]
* @Param [file]
* @return byte[]
**/
private static byte[] inputStream2ByteArray(File file){
ByteArrayOutputStream bos = new ByteArrayOutputStream();
FileInputStream fis = null;
byte[] buffer = null;
try {
fis = new FileInputStream(file);
//不用读取全部文件,只读文件前面的部分
byte[] b = new byte[1024];
fis.read(b);
bos.write(b, 0, 1024);
buffer = bos.toByteArray();
}catch (FileNotFoundException e){
e.printStackTrace();
}catch (IOException e1){
e1.printStackTrace();
}finally {
try {
fis.close();
} catch (IOException e1) {
e1.printStackTrace();
}
try {
if(bos !=null){
bos.close();
}
}catch (Exception e){
e.printStackTrace();
}
}
return buffer;
}
/**
* @Description 取byte[]前8位的为字符串
* @Param [src]
* @return java.lang.String
**/
private static String bytesToHexString(byte[] src) {
StringBuilder stringBuilder = new StringBuilder();
if (src == null || src.length <= 0) {
return null;
}
for (int i = 0; i < src.length; i++) {
int v = src[i] & 0xFF;
String hv = Integer.toHexString(v);
if (hv.length() < 2) {
stringBuilder.append(0);
}
stringBuilder.append(hv);
}
return stringBuilder.toString().toLowerCase();
}
//直接main方法测试测试
public static void main(String[] args) {
String[] files = {"D:\\测试文件\\501.doc","D:\\测试文件\\601.xlsx","D:\\测试文件\\111.html",
"D:\\测试文件\\3f809f80a7e545e6a4431648277aa3e1.tif", "D:\\测试文件\\0e7755fbc4dd44dd8614ecd4d7814e97.pdf",
"D:\\测试文件\\03dad112881e4a0a80a08605e36ee44a.jpg"};
for (int i = 0; i < files.length; i++) {
boolean aaa = suffixVerify(new File(files[i]));
System.out.println("验证结果:" + aaa);
}
}
总结
本文根据原文链接:https://blog.csdn.net/qq_35976271/article/details/90025788 博主的内容进行的添加,因已2次碰到该漏洞检测问题,故主要对该问题处理进行一个保存供以后使用。