赞
踩
软件保障参考数据集(SARD)包含118种CWE漏洞类型,是专门为评估静态分析工具的能力而开发的。数据集中的每一个样本都以其函数名称为标签,后缀字符串为 “good “或 “bad”,因此我们可以很容易地利用这些后缀信息来生成每个样本的标签。
为了从SARD中构建一个java漏洞数据集,需要对SARD进行一定的预处理。
这里SARD使用Juiletjava。
/** * SARD数据集预处理:去除web.xml、antbuild等无用文件和文件夹 * @param filePath */ public static void getFile(String filePath) { File file = new File(filePath); if(file.isDirectory()){ File[] files = file.listFiles(); for (File file1 : files) { if(file1.isDirectory()){ if("antbuild".equals(file1.getName())){ deleteFileOrDirectory(file1.getAbsolutePath()); } getFile(file1.getAbsolutePath()); }else{ if("ServletMain.java".equals(file1.getName())){ deleteFileOrDirectory(file1.getAbsolutePath()); } } } }else{ if("ServletMain.java".equals(file.getName())){ deleteFileOrDirectory(file.getAbsolutePath()); } } } /** * 删除文件或文件夹 * * @param fileName 文件名 * @return 删除成功返回true,失败返回false */ public static boolean deleteFileOrDirectory(String fileName) { File file = new File(fileName); // fileName是路径或者file.getPath()获取的文件路径 if (file.exists()) { if (file.isFile()) { return deleteFile(fileName); // 是文件,调用删除文件的方法 } else { return deleteDirectory(fileName); // 是文件夹,调用删除文件夹的方法 } } else { System.out.println("文件或文件夹删除失败:" + fileName); return false; } } /** * 删除文件 * * @param fileName 文件名 * @return 删除成功返回true,失败返回false */ public static boolean deleteFile(String fileName) { File file = new File(fileName); if (file.isFile() && file.exists()) { file.delete(); System.out.println("删除文件成功:" + fileName); return true; } else { System.out.println("删除文件失败:" + fileName); return false; } } /** * 删除文件夹 * 删除文件夹需要把包含的文件及文件夹先删除,才能成功 * * @param directory 文件夹名 * @return 删除成功返回true,失败返回false */ public static boolean deleteDirectory(String directory) { // directory不以文件分隔符(/或\)结尾时,自动添加文件分隔符,不同系统下File.separator方法会自动添加相应的分隔符 if (!directory.endsWith(File.separator)) { directory = directory + File.separator; } File directoryFile = new File(directory); // 判断directory对应的文件是否存在,或者是否是一个文件夹 if (!directoryFile.exists() || !directoryFile.isDirectory()) { System.out.println("文件夹删除失败,文件夹不存在" + directory); return false; } boolean flag = true; // 删除文件夹下的所有文件和文件夹 File[] files = directoryFile.listFiles(); for (int i = 0; i < files.length; i++) { // 循环删除所有的子文件及子文件夹 // 删除子文件 if (files[i].isFile()) { flag = deleteFile(files[i].getAbsolutePath()); if (!flag) { break; } } else { // 删除子文件夹 flag = deleteDirectory(files[i].getAbsolutePath()); if (!flag) { break; } } } if (!flag) { System.out.println("删除失败"); return false; } // 最后删除当前文件夹 if (directoryFile.delete()) { System.out.println("删除成功:" + directory); return true; } else { System.out.println("删除失败:" + directory); return false; } }
111
package Main; import com.thoughtworks.qdox.JavaProjectBuilder; import com.thoughtworks.qdox.model.JavaClass; import com.thoughtworks.qdox.model.JavaMethod; import java.io.BufferedReader; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileOutputStream; import java.io.FileReader; import java.io.FileWriter; import java.io.IOException; import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.regex.Matcher; import java.util.regex.Pattern; import org.dom4j.Document; import org.dom4j.DocumentHelper; import org.dom4j.Element; import org.dom4j.io.OutputFormat; import org.dom4j.io.XMLWriter; public class JavaParser { /** * SARD数据集预处理:去除web.xml、antibuild等无用文件和文件夹 * @param filePath */ public static void getFile(String filePath) { File file = new File(filePath); if(file.isDirectory()){ File[] files = file.listFiles(); for (File file1 : files) { if(file1.isDirectory()){ if("antbuild".equals(file1.getName())){ deleteFileOrDirectory(file1.getAbsolutePath()); } getFile(file1.getAbsolutePath()); }else{ if("ServletMain.java".equals(file1.getName())){ deleteFileOrDirectory(file1.getAbsolutePath()); } } } }else{ if("ServletMain.java".equals(file.getName())){ deleteFileOrDirectory(file.getAbsolutePath()); } } } public static void main(String[] args) throws IOException { String filePath = "C:\\Users\\rooooot\\Desktop\\SARD-Java\\generality test\\CWE614_Sensitive_Cookie_Without_Secure"; String targetPath = "C:\\Users\\rooooot\\Desktop\\SARD-Java\\multi-class classification"; HashMap<String, String> cweMap = new HashMap<String, String>(); cweMap.put("CWE643", "xpathi"); cweMap.put("CWE614", "securecookie"); cweMap.put("CWE327", "crypto"); cweMap.put("CWE328", "hash"); cweMap.put("CWE90", "ldapi"); cweMap.put("CWE89", "sqli"); cweMap.put("CWE78", "cmdi"); GenerateClassFile(filePath,targetPath,cweMap); } /** * 根据CWE编号生成类级Java文件以及xml标签 * @param filePath * @throws IOException */ public static void GenerateClassFile(String Path,String targetPath,HashMap<String, String> cweMap) throws IOException { File directory = new File(Path); int i = 0; for(File javaFile:directory.listFiles()) { //无漏洞函数缓存表 ArrayList<String> goodList = new ArrayList<String>(); //有漏洞函数缓存表 ArrayList<String> badList = new ArrayList<String>(); JavaProjectBuilder builder = new JavaProjectBuilder(); //源码目录 builder.addSourceTree(javaFile); //读取CWE编号 String[] filenames = javaFile.getName().split("_"); String cwe = filenames[0]; //读取文件编号 String fileno = filenames[filenames.length-1].split("\\.")[0]; //不包含跨文件代码,直接生成 if(!check(fileno)) { //读取漏洞函数及无漏洞函数 Collection<JavaClass> classes = builder.getClasses(); Iterator<JavaClass> it = classes.iterator(); //逐个类进行读取 while(it.hasNext()) { JavaClass cls = builder.getClassByName(it.next().getCanonicalName()); List<JavaMethod> methods = cls.getMethods(); for(JavaMethod method : methods){ String methodName = method.getName(); //方法名 if(ignoreCaseIndexOf(methodName,"bad")!=-1) { badList.add(method.getSourceCode()); }else if(ignoreCaseIndexOf(methodName,"good")!=-1){ goodList.add(method.getSourceCode()); } } } //生成无漏洞类文件及其xml说明文件 //重建java类文件 File f = new File(targetPath+"\\"+javaFile.getName());//新建一个文件对象,如果不存在则创建一个该文件 FileWriter fw; StringBuffer codeFile = new StringBuffer(readFile(javaFile.getAbsolutePath())); try { fw = new FileWriter(f); for(String text:badList) { int start = ignoreCaseIndexOf(codeFile.toString(), text); if(start!=-1) { codeFile.replace(start, start+text.length(),""); }else { System.out.println("文件解析异常:"+javaFile.getAbsolutePath()); } } fw.write(codeFile.toString());//将字符串写入到指定的路径下的文件中 fw.close(); } catch (IOException e) { e.printStackTrace(); } String[] args = {javaFile.getName().split("\\\\.")[0],cweMap.get(cwe),Integer.toString(i),"false",cwe.replaceAll("CWE", "")}; i++; createXML(targetPath, args); //生成有漏洞类文件及其xml说明文件 //重建java类文件 File fv = new File(targetPath+"\\"+"v_"+javaFile.getName());//新建一个文件对象,如果不存在则创建一个该文件 FileWriter fwv; StringBuffer codeFilev = new StringBuffer(readFile(javaFile.getAbsolutePath())); try { fwv = new FileWriter(fv); for(String text:goodList) { int start = ignoreCaseIndexOf(codeFilev.toString(), text); if(start!=-1) { codeFilev.replace(start, start+text.length(),""); }else { System.out.println("文件解析异常:"+javaFile.getAbsolutePath()); } } fwv.write(codeFilev.toString());//将字符串写入到指定的路径下的文件中 fwv.close(); } catch (IOException e) { e.printStackTrace(); } String[] argsv = {"v_"+javaFile.getName().split("\\\\.")[0],cweMap.get(cwe),Integer.toString(i),"true",cwe.replaceAll("CWE", "")}; i++; createXML(targetPath, argsv); }else { //包含跨文件代码,暂时忽略 } } System.out.println("总文件数:"+i); } /** * 根据CWE编号生成函数片段级Java文件及xml标签 * @param filePath */ public static void GenerateSliceFile(String filePath) { } /** * 删除文件或文件夹 * @param fileName 文件名 * @return 删除成功返回true,失败返回false */ public static boolean deleteFileOrDirectory(String fileName) { File file = new File(fileName); // fileName是路径或者file.getPath()获取的文件路径 if (file.exists()) { if (file.isFile()) { return deleteFile(fileName); // 是文件,调用删除文件的方法 } else { return deleteDirectory(fileName); // 是文件夹,调用删除文件夹的方法 } } else { System.out.println("文件或文件夹删除失败:" + fileName); return false; } } /** * 删除文件 * * @param fileName 文件名 * @return 删除成功返回true,失败返回false */ public static boolean deleteFile(String fileName) { File file = new File(fileName); if (file.isFile() && file.exists()) { file.delete(); System.out.println("删除文件成功:" + fileName); return true; } else { System.out.println("删除文件失败:" + fileName); return false; } } /** * 删除文件夹 * 删除文件夹需要把包含的文件及文件夹先删除,才能成功 * * @param directory 文件夹名 * @return 删除成功返回true,失败返回false */ public static boolean deleteDirectory(String directory) { // directory不以文件分隔符(/或\)结尾时,自动添加文件分隔符,不同系统下File.separator方法会自动添加相应的分隔符 if (!directory.endsWith(File.separator)) { directory = directory + File.separator; } File directoryFile = new File(directory); // 判断directory对应的文件是否存在,或者是否是一个文件夹 if (!directoryFile.exists() || !directoryFile.isDirectory()) { System.out.println("文件夹删除失败,文件夹不存在" + directory); return false; } boolean flag = true; // 删除文件夹下的所有文件和文件夹 File[] files = directoryFile.listFiles(); for (int i = 0; i < files.length; i++) { // 循环删除所有的子文件及子文件夹 // 删除子文件 if (files[i].isFile()) { flag = deleteFile(files[i].getAbsolutePath()); if (!flag) { break; } } else { // 删除子文件夹 flag = deleteDirectory(files[i].getAbsolutePath()); if (!flag) { break; } } } if (!flag) { System.out.println("删除失败"); return false; } // 最后删除当前文件夹 if (directoryFile.delete()) { System.out.println("删除成功:" + directory); return true; } else { System.out.println("删除失败:" + directory); return false; } } /** * 根据传入的参数创建XML标签文件 * @param path:目标文件路径 * @param args {文件名,category的值,test-number的值,vulnerability的值,cwe编号} */ public static void createXML(String path,String[] args) { // 1.声明文件名称 String fileName = args[0]; // 2.创建dom对象 Document document = DocumentHelper.createDocument(); // 3.添加节点,根据需求添加,这里我只是设置了一个head节点,下面有name和age两个子节点 Element test_metadata = document.addElement("test-metadata"); Element wbe_version = test_metadata.addElement("wbe-version"); wbe_version.setText("1.1"); Element category = test_metadata.addElement("category"); category.addText(args[1]); Element test_number = test_metadata.addElement("test-number"); test_number.addText(args[2]); Element vulnerability = test_metadata.addElement("vulnerability"); vulnerability.addText(args[3]); Element cwe = test_metadata.addElement("cwe"); cwe.addText(args[4]); // 4、格式化模板 //OutputFormat format = OutputFormat.createCompactFormat(); OutputFormat format = OutputFormat.createPrettyPrint(); format.setEncoding("UTF-8"); // 5、生成xml文件 ByteArrayOutputStream out = new ByteArrayOutputStream(); try { XMLWriter writer = new XMLWriter(out, format); writer.write(document); writer.close(); } catch (IOException e) { System.out.println("生成xml文件失败。文件名【" + fileName + "】"); } // 6、生成的XML利用文件输出流输出到文件 try (FileOutputStream fos = new FileOutputStream(path+"\\"+fileName + ".xml")) { fos.write(out.toByteArray()); } catch (IOException e) { e.printStackTrace(); } } /** * 判断字符串中是否包含字母 * @param str * @return */ public static boolean check(String str) { String regex=".*[a-zA-Z]+.*"; Matcher m=Pattern.compile(regex).matcher(str); return m.matches(); } /** * 返回指定子字符串在此字符串中第一次出现处的索引,从指定的索引开始,不区分大小。 * * @param subject 被查找字符串。 * @param search 要查找的子字符串。 * @return 指定子字符串在此字符串中第一次出现处的索引,从指定的索引开始。 */ public static int ignoreCaseIndexOf(String subject, String search) { return ignoreCaseIndexOf(subject, search,-1); } /** * 返回指定子字符串在此字符串中第一次出现处的索引,从指定的索引开始,不区分大小。 * * @param subject 被查找字符串。 * @param search 要查找的子字符串。 * @param fromIndex 开始查找的索引位置。其值没有限制,如果它为负,则与它为 0 的效果同样:将查找整个字符串。 * 如果它大于此字符串的长度,则与它等于此字符串长度的效果相同:返回 -1。 * @return 指定子字符串在此字符串中第一次出现处的索引,从指定的索引开始。 */ public static int ignoreCaseIndexOf(String subject, String search, int fromIndex) { //当被查找字符串或查找子字符串为空时,抛出空指针异常。 if (subject == null || search == null) { throw new NullPointerException("输入的参数为空"); } fromIndex = fromIndex < 0 ? 0 : fromIndex; if (search.equals("")) { return fromIndex >= subject.length() ? subject.length() : fromIndex; } int index1 = fromIndex; int index2 = 0; char c1; char c2; loop1: while (true) { if (index1 < subject.length()) { c1 = subject.charAt(index1); c2 = search.charAt(index2); } else { break loop1; } while (true) { if (isEqual(c1, c2)) { if (index1 < subject.length() - 1 && index2 < search.length() - 1) { c1 = subject.charAt(++index1); c2 = search.charAt(++index2); } else if (index2 == search.length() - 1) { return fromIndex; } else { break loop1; } } else { index2 = 0; break; } } //重新查找子字符串的位置 index1 = ++fromIndex; } return -1; } /** * 判断两个字符是否相等。 * @param c1 字符1 * @param c2 字符2 * @return 若是英文字母,不区分大小写,相等true,不等返回false; * 若不是则区分,相等返回true,不等返回false。 */ private static boolean isEqual(char c1,char c2){ // 字母小写 字母大写 if(((97<=c1 && c1<=122) || (65<=c1 && c1<=90)) && ((97<=c2 && c2<=122) || (65<=c2 && c2<=90)) && ((c1-c2==32) || (c2-c1==32))){ return true; } else if(c1==c2){ return true; } return false; } /** * 将java文件读取成字符串返回 * @param file * @return * @throws IOException */ public static String readFile(String file) throws IOException { BufferedReader reader = new BufferedReader(new FileReader (file)); String line = null; StringBuilder stringBuilder = new StringBuilder(); String ls = System.getProperty("line.separator"); try { while((line = reader.readLine()) != null) { stringBuilder.append(line); stringBuilder.append(ls); } return stringBuilder.toString(); } finally { reader.close(); } } }
2024.06.14更新:
我把我处理好的数据集放在下面,需要的自行下载:
链接:https://pan.baidu.com/s/17cUtYQebqfQwELP43DwUhw?pwd=7rc8
提取码:7rc8
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。