校验文件的合法性
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
校验⽂件的合法性
今天客户提出需要检验系统的安全性并且提出⼏点需要处理:
1、任意下载⽂件问题
可以任意下载⽂件,在使⽤burp抓包后,发送请求可以随便下载⽂件,解决⽅法对传⼊的路径过滤".","\","、"字符串。
2、发射型xss
可以通过XSS过滤检测或者对数据进⾏转义。
3、使⽤备份获取shell
限定⽂件后缀名,⽂件路径。
4、任意上传⽂件
检查⽂件的合法性和后缀名。
package mon;
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 FileFormatVerify {
private static Map<String,String> FileTypes = null;
public FileFormatVerify(){
FileTypes = new HashMap<String,String>();
// images
FileTypes.put("FFD8FFE0", ".jpg");
FileTypes.put("89504E47", ".png");
FileTypes.put("47494638", ".gif");
FileTypes.put("49492A00", ".tif");
FileTypes.put("424D", ".bmp");
//PS和CAD
FileTypes.put("38425053", ".psd");
FileTypes.put("41433130", ".dwg"); // CAD
FileTypes.put("252150532D41646F6265",".ps");
//办公⽂档类
FileTypes.put("D0CF11E0", ".doc"); //ppt、doc、xls
FileTypes.put("504B0304", ".docx");//pptx、docx、xlsx
/**注意由于⽂本⽂档录⼊内容过多,则读取⽂件头时较为多变-START**/
FileTypes.put("0D0A0D0A", ".txt");//txt
FileTypes.put("0D0A2D2D", ".txt");//txt
FileTypes.put("0D0AB4B4", ".txt");//txt
FileTypes.put("B4B4BDA8", ".txt");//⽂件头部为汉字
FileTypes.put("73646673", ".txt");//txt,⽂件头部为英⽂字母
FileTypes.put("32323232", ".txt");//txt,⽂件头部内容为数字
FileTypes.put("0D0A09B4", ".txt");//txt,⽂件头部内容为数字
FileTypes.put("3132330D", ".txt");//txt,⽂件头部内容为数字
/**注意由于⽂本⽂档录⼊内容过多,则读取⽂件头时较为多变-END**/
FileTypes.put("7B5C727466", ".rtf"); // ⽇记本
FileTypes.put("255044462D312E", ".pdf");
//视频或⾳频类
FileTypes.put("3026B275",".wma");
FileTypes.put("57415645", ".wav");
FileTypes.put("41564920", ".avi");
FileTypes.put("4D546864", ".mid");
FileTypes.put("2E524D46", ".rm");
FileTypes.put("000001BA", ".mpg");
FileTypes.put("000001B3", ".mpg");
FileTypes.put("6D6F6F76", ".mov");
FileTypes.put("3026B2758E66CF11", ".asf");
//压缩包
FileTypes.put("52617221", ".rar");
FileTypes.put("1F8B08", ".gz");
//程序⽂件
FileTypes.put("3C3F786D6C", ".xml");
FileTypes.put("68746D6C3E", ".html");
FileTypes.put("7061636B", ".java");
FileTypes.put("3C254020", ".jsp");
FileTypes.put("4D5A9000", ".exe");
FileTypes.put("44656C69766572792D646174653A", ".eml"); // 邮件
FileTypes.put("5374616E64617264204A", ".mdb");//Access数据库⽂件
FileTypes.put("46726F6D", ".mht");
FileTypes.put("4D494D45", ".mhtml");
}
/**
* @Description 根据传⼊的⽂件获得后缀,获得指定⽂件格式byte[]数组中的前8位字符
* 将传⼊⽂件转化为byte[]数组,取前8位.判断传⼊⽂件的前8位和我们指定好的⽂件byte[]的前8位是否相同, * 如果相同则⽂件格式没有被篡改,反之,⽂件后缀格式被篡改
* @Param [file]
* @return boolean 返回true 表⽰⽂件格式验证通过, 返回false ⽂件格式验证失败
**/
public boolean suffixVerify(File file){
String fileType = "";
boolean isgood = false;
String name = file.getName();
int i = stIndexOf(".");
// 获取⽂件的后缀
if(i > 0){
fileType = name.substring(i + 1);
}
//根据⽂件的后缀获取,获取⽂件的byte[]的前8位
if(FileTypes.containsValue(fileType.toLowerCase())){
for(Map.Entry<String, String> filetype:FileTypes.entrySet()){
if(filetype.getValue().equals(fileType)){
String fileByte8 = String.valueOf(filetype.getKey());
//获取传⼊⽂件的byte[]的前8位
byte[] bytes = inputStream2ByteArray(file);
String compareByte = bytesToHexString(bytes);
//如果传⼊⽂件的byte[]的前8位和我们定义好的byte[]的前8位相同,验证通过.
if (compareByte.startsWith(fileByte8)){
//如果格式校验成功
isgood = true;
}
}
}
}else{
return isgood;
}
return isgood;
}
/**
* @Description 将file⽂件转化为byte[]
* @Param [file]
* @return byte[]
**/
public 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 {
if(fis !=null){
fis.close();
}
}catch (Exception e){
e.printStackTrace();
}
try {
if(bos !=null){
bos.close();
}
}catch (Exception e){
e.printStackTrace();
}
}
return buffer;
}
/**
* @Description 取byte[]前8位的为字符串
* @Param [src]
* @return ng.String
**/
public 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().substring(0, 8);
return stringBuilder.toString();
}
}。