multiple improvements

This commit is contained in:
bjiang
2016-03-28 14:06:30 -04:00
parent a22fc550b3
commit ab48d2c2ff
6 changed files with 133 additions and 35 deletions

View File

@@ -97,16 +97,16 @@ public class FileNameAnalyzer extends AbstractAnalyzer implements Analyzer {
}
//add as vendor and product evidence
if (fileName.contains("-")) {
dependency.getProductEvidence().addEvidence("file", "name",
fileName, Confidence.HIGHEST);
dependency.getVendorEvidence().addEvidence("file", "name",
fileName, Confidence.HIGHEST);
} else {
// if (fileName.contains("-")) {
// dependency.getProductEvidence().addEvidence("file", "name",
// fileName, Confidence.HIGHEST);
// dependency.getVendorEvidence().addEvidence("file", "name",
// fileName, Confidence.HIGHEST);
// } else {
dependency.getProductEvidence().addEvidence("file", "name",
fileName, Confidence.HIGH);
dependency.getVendorEvidence().addEvidence("file", "name",
fileName, Confidence.HIGH);
}
// }
}
}

View File

@@ -181,21 +181,21 @@ public class RubyBundleAuditAnalyzer extends AbstractFileTypeAnalyzer {
@Override
protected void analyzeFileType(Dependency dependency, Engine engine)
throws AnalysisException {
if (needToDisableGemspecAnalyzer) {
boolean failed = true;
final String className = RubyGemspecAnalyzer.class.getName();
for (FileTypeAnalyzer analyzer : engine.getFileTypeAnalyzers()) {
if (analyzer instanceof RubyGemspecAnalyzer) {
((RubyGemspecAnalyzer) analyzer).setEnabled(false);
LOGGER.info("Disabled " + className + " to avoid noisy duplicate results.");
failed = false;
}
}
if (failed) {
LOGGER.warn("Did not find" + className + '.');
}
needToDisableGemspecAnalyzer = false;
}
// if (needToDisableGemspecAnalyzer) {
// boolean failed = true;
// final String className = RubyGemspecAnalyzer.class.getName();
// for (FileTypeAnalyzer analyzer : engine.getFileTypeAnalyzers()) {
// if (analyzer instanceof RubyGemspecAnalyzer) {
// ((RubyGemspecAnalyzer) analyzer).setEnabled(false);
// LOGGER.info("Disabled " + className + " to avoid noisy duplicate results.");
// failed = false;
// }
// }
// if (failed) {
// LOGGER.warn("Did not find" + className + '.');
// }
// needToDisableGemspecAnalyzer = false;
// }
final File parentFile = dependency.getActualFile().getParentFile();
final Process process = launchBundleAudit(parentFile);
try {
@@ -229,6 +229,7 @@ public class RubyBundleAuditAnalyzer extends AbstractFileTypeAnalyzer {
private void processBundlerAuditOutput(Dependency original, Engine engine, BufferedReader rdr) throws IOException {
final String parentName = original.getActualFile().getParentFile().getName();
final String fileName = original.getFileName();
final String filePath = original.getFilePath();
Dependency dependency = null;
Vulnerability vulnerability = null;
String gem = null;
@@ -242,7 +243,7 @@ public class RubyBundleAuditAnalyzer extends AbstractFileTypeAnalyzer {
appendToDescription = false;
gem = nextLine.substring(NAME.length());
if (!map.containsKey(gem)) {
map.put(gem, createDependencyForGem(engine, parentName, fileName, gem));
map.put(gem, createDependencyForGem(engine, parentName, fileName, filePath, gem));
}
dependency = map.get(gem);
LOGGER.debug(String.format("bundle-audit (%s): %s", parentName, nextLine));
@@ -329,13 +330,16 @@ public class RubyBundleAuditAnalyzer extends AbstractFileTypeAnalyzer {
return vulnerability;
}
private Dependency createDependencyForGem(Engine engine, String parentName, String fileName, String gem) throws IOException {
final File tempFile = File.createTempFile("Gemfile-" + gem, ".lock", Settings.getTempDirectory());
private Dependency createDependencyForGem(Engine engine, String parentName, String fileName, String filePath, String gem) throws IOException {
final File gemFile = new File(Settings.getTempDirectory(), gem + "_Gemfile.lock");
gemFile.createNewFile();
final String displayFileName = String.format("%s%c%s:%s", parentName, File.separatorChar, fileName, gem);
FileUtils.write(tempFile, displayFileName); // unique contents to avoid dependency bundling
final Dependency dependency = new Dependency(tempFile);
FileUtils.write(gemFile, displayFileName); // unique contents to avoid dependency bundling
final Dependency dependency = new Dependency(gemFile);
dependency.getProductEvidence().addEvidence("bundler-audit", "Name", gem, Confidence.HIGHEST);
dependency.setDisplayFileName(displayFileName);
dependency.setFileName(fileName);
dependency.setFilePath(filePath);
engine.getDependencies().add(dependency);
return dependency;
}

View File

@@ -26,8 +26,14 @@ import org.owasp.dependencycheck.dependency.EvidenceCollection;
import org.owasp.dependencycheck.utils.FileFilterBuilder;
import org.owasp.dependencycheck.utils.Settings;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileFilter;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FilenameFilter;
import java.io.IOException;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@@ -52,10 +58,12 @@ public class RubyGemspecAnalyzer extends AbstractFileTypeAnalyzer {
private static final String GEMSPEC = "gemspec";
private static final FileFilter FILTER
= FileFilterBuilder.newInstance().addExtensions(GEMSPEC).addFilenames("Rakefile").build();
= FileFilterBuilder.newInstance().addExtensions(GEMSPEC).build();
private static final String EMAIL = "email";
private static final String VERSION_FILE_NAME = "VERSION";
/**
* @return a filter that accepts files named Rakefile or matching the glob pattern, *.gemspec
*/
@@ -133,7 +141,9 @@ public class RubyGemspecAnalyzer extends AbstractFileTypeAnalyzer {
vendor.addEvidence(GEMSPEC, "name_project", name + "_project", Confidence.LOW);
}
addStringEvidence(product, contents, blockVariable, "summary", Confidence.LOW);
addStringEvidence(dependency.getVersionEvidence(), contents, blockVariable, "version", Confidence.HIGHEST);
String value = addStringEvidence(dependency.getVersionEvidence(), contents, blockVariable, "version", Confidence.HIGHEST);
if(value.length() < 1)
addEvidenceFromVersionFile(dependency.getActualFile(), dependency.getVersionEvidence());
}
}
@@ -158,4 +168,31 @@ public class RubyGemspecAnalyzer extends AbstractFileTypeAnalyzer {
}
return value;
}
private String addEvidenceFromVersionFile(File dependencyFile, EvidenceCollection versionEvidences) {
String value = null;
File parentDir = dependencyFile.getParentFile();
if(parentDir != null) {
File[] matchingFiles = parentDir.listFiles(new FilenameFilter() {
public boolean accept(File dir, String name) {
return name.contains(VERSION_FILE_NAME);
}
});
for(int i = 0; i < matchingFiles.length; i++) {
try {
List<String> lines = FileUtils.readLines(matchingFiles[i]);
if(lines.size() == 1) { //TODO other checking?
value = lines.get(0).trim();
versionEvidences.addEvidence(GEMSPEC, "version", value, Confidence.HIGH);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
return value;
}
}

View File

@@ -22,6 +22,9 @@ import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
import java.io.File;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import org.junit.After;
import org.junit.Assume;
@@ -32,6 +35,8 @@ import org.owasp.dependencycheck.Engine;
import org.owasp.dependencycheck.analyzer.exception.AnalysisException;
import org.owasp.dependencycheck.data.nvdcve.DatabaseException;
import org.owasp.dependencycheck.dependency.Dependency;
import org.owasp.dependencycheck.dependency.Evidence;
import org.owasp.dependencycheck.dependency.Identifier;
import org.owasp.dependencycheck.utils.Settings;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -99,17 +104,18 @@ public class RubyBundleAuditAnalyzerTest extends BaseTest {
public void testAnalysis() throws AnalysisException, DatabaseException {
try {
analyzer.initialize();
final Dependency result = new Dependency(BaseTest.getResourceAsFile(this,
"ruby/vulnerable/gems/rails-4.1.15/Gemfile.lock"));
final String resource = "ruby/vulnerable/gems/rails-4.1.15/Gemfile.lock";
final Dependency result = new Dependency(BaseTest.getResourceAsFile(this, resource));
final Engine engine = new Engine();
analyzer.analyze(result, engine);
int size = engine.getDependencies().size();
assertThat(size, is(1));
assertTrue(size >= 1);
Dependency dependency = engine.getDependencies().get(0);
assertTrue(dependency.getProductEvidence().toString().toLowerCase().contains("redcarpet"));
assertTrue(dependency.getVersionEvidence().toString().toLowerCase().contains("2.2.2"));
assertTrue(dependency.getFilePath().endsWith(resource));
assertTrue(dependency.getFileName().equals("Gemfile.lock"));
} catch (Exception e) {
LOGGER.warn("Exception setting up RubyBundleAuditAnalyzer. Make sure Ruby gem bundle-audit is installed. You may also need to set property \"analyzer.bundle.audit.path\".", e);
@@ -137,4 +143,55 @@ public class RubyBundleAuditAnalyzerTest extends BaseTest {
LOGGER.info("phantom-bundle-audit is not available. Ruby Bundle Audit Analyzer is disabled as expected.");
}
}
/**
* Test Ruby dependencies and their paths.
*
* @throws AnalysisException is thrown when an exception occurs.
*/
@Test
public void testDependenciesPath() throws AnalysisException, DatabaseException {
final Engine engine = new Engine();
engine.scan(BaseTest.getResourceAsFile(this,
// "ruby/vulnerable/gems/chef-12.8.4/"));
"ruby/vulnerable/gems/rails-4.1.15/"));
// "java"));
engine.analyzeDependencies();
List<Dependency> dependencies = engine.getDependencies();
LOGGER.info(dependencies.size() + " dependencies found.");
Iterator<Dependency> dIterator = dependencies.iterator();
while(dIterator.hasNext()) {
Dependency dept = dIterator.next();
LOGGER.info("dept path: " + dept.getActualFilePath());
Set<Identifier> identifiers = dept.getIdentifiers();
Iterator<Identifier> idIterator = identifiers.iterator();
while(idIterator.hasNext()) {
Identifier id = idIterator.next();
LOGGER.info(" Identifier: " + id.getValue() + ", type=" + id.getType() + ", url=" + id.getUrl() + ", conf="+ id.getConfidence());
}
Set<Evidence> prodEv = dept.getProductEvidence().getEvidence();
Iterator<Evidence> it = prodEv.iterator();
while(it.hasNext()) {
Evidence e = it.next();
LOGGER.info(" prod: name=" + e.getName() + ", value=" + e.getValue() + ", source=" + e.getSource() + ", confidence=" + e.getConfidence());
}
Set<Evidence> versionEv = dept.getVersionEvidence().getEvidence();
Iterator<Evidence> vIt = versionEv.iterator();
while(vIt.hasNext()) {
Evidence e = vIt.next();
LOGGER.info(" version: name=" + e.getName() + ", value=" + e.getValue() + ", source=" + e.getSource() + ", confidence=" + e.getConfidence());
}
Set<Evidence> vendorEv = dept.getVendorEvidence().getEvidence();
Iterator<Evidence> vendorIt = vendorEv.iterator();
while(vendorIt.hasNext()) {
Evidence e = vendorIt.next();
LOGGER.info(" vendor: name=" + e.getName() + ", value=" + e.getValue() + ", source=" + e.getSource() + ", confidence=" + e.getConfidence());
}
}
}
}

View File

@@ -79,7 +79,7 @@ public class RubyGemspecAnalyzerTest extends BaseTest {
@Test
public void testSupportsFiles() {
assertThat(analyzer.accept(new File("test.gemspec")), is(true));
assertThat(analyzer.accept(new File("Rakefile")), is(true));
// assertThat(analyzer.accept(new File("Rakefile")), is(true));
}
/**

View File

@@ -101,4 +101,4 @@ analyzer.nexus.enabled=false
analyzer.nexus.proxy=true
#Use your own bundle-audit install directory.
#analyzer.bundle.audit.path=/usr/local/bin/bundle-audit
analyzer.bundle.audit.path=/usr/local/bin/bundle-audit