Skip to content

Commit

Permalink
Merge pull request #3226 from mbologna/feat/analyze_rpm
Browse files Browse the repository at this point in the history
Feat: analyze RPM dependencies
  • Loading branch information
jeremylong authored May 9, 2021
2 parents f9aedd2 + a5b9857 commit 5d2c571
Show file tree
Hide file tree
Showing 11 changed files with 72 additions and 7 deletions.
5 changes: 5 additions & 0 deletions core/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -456,6 +456,11 @@ Copyright (c) 2012 Jeremy Long. All Rights Reserved.
<groupId>commons-beanutils</groupId>
<artifactId>commons-beanutils</artifactId>
</dependency>
<dependency>
<groupId>org.eclipse.packager</groupId>
<artifactId>packager-rpm</artifactId>
<version>0.17.0</version>
</dependency>
</dependencies>
<profiles>
<profile>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@

import org.apache.commons.compress.archivers.ArchiveEntry;
import org.apache.commons.compress.archivers.ArchiveInputStream;
import org.apache.commons.compress.archivers.cpio.CpioArchiveInputStream;
import org.apache.commons.compress.archivers.tar.TarArchiveInputStream;
import org.apache.commons.compress.archivers.zip.ZipArchiveEntry;
import org.apache.commons.compress.archivers.zip.ZipArchiveInputStream;
Expand All @@ -45,7 +46,8 @@
import org.apache.commons.compress.compressors.gzip.GzipCompressorInputStream;
import org.apache.commons.compress.compressors.gzip.GzipUtils;
import org.apache.commons.compress.utils.IOUtils;

import org.eclipse.packager.rpm.RpmTag;
import org.eclipse.packager.rpm.parse.RpmInputStream;
import org.owasp.dependencycheck.Engine;
import static org.owasp.dependencycheck.analyzer.AbstractNpmAnalyzer.shouldProcess;
import org.owasp.dependencycheck.analyzer.exception.AnalysisException;
Expand Down Expand Up @@ -107,14 +109,14 @@ public class ArchiveAnalyzer extends AbstractFileTypeAnalyzer {
* in {@link #extractFiles(File, File, Engine)}.
*/
private static final Set<String> EXTENSIONS = Collections.unmodifiableSet(
newHashSet("tar", "gz", "tgz", "bz2", "tbz2"));
newHashSet("tar", "gz", "tgz", "bz2", "tbz2", "rpm"));

/**
* Detects files with extensions to remove from the engine's collection of
* dependencies.
*/
private static final FileFilter REMOVE_FROM_ANALYSIS = FileFilterBuilder.newInstance()
.addExtensions("zip", "tar", "gz", "tgz", "bz2", "tbz2", "nupkg").build();
.addExtensions("zip", "tar", "gz", "tgz", "bz2", "tbz2", "nupkg", "rpm").build();
/**
* Detects files with .zip extension.
*/
Expand Down Expand Up @@ -434,6 +436,8 @@ private void extractFiles(File archive, File destination, Engine engine) throws
TarArchiveInputStream tin = null;
GzipCompressorInputStream gin = null;
BZip2CompressorInputStream bzin = null;
RpmInputStream rin = null;
CpioArchiveInputStream cain = null;
try {
if (KNOWN_ZIP_EXT.contains(archiveExt) || ADDITIONAL_ZIP_EXT.contains(archiveExt)) {
in = new BufferedInputStream(fis);
Expand Down Expand Up @@ -475,6 +479,12 @@ private void extractFiles(File archive, File destination, Engine engine) throws
decompressFile(bzin, f);
}
}
else if ("rpm".equals(archiveExt)) {
rin = new RpmInputStream(fis);
String rpmName = (String) rin.getPayloadHeader().getTag(RpmTag.NAME);
cain = new CpioArchiveInputStream(rin);
extractArchive(cain, destination, engine);
}
} catch (ArchiveExtractionException ex) {
LOGGER.warn("Exception extracting archive '{}'.", archive.getName());
LOGGER.debug("", ex);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -391,7 +391,7 @@ protected boolean isCore(Dependency left, Dependency right) {
returnVal = true;
} else if (!left.isVirtual() && right.isVirtual()) {
returnVal = false;
} else if ((!rightName.matches(".*\\.(tar|tgz|gz|zip|ear|war).+") && leftName.matches(".*\\.(tar|tgz|gz|zip|ear|war).+"))
} else if ((!rightName.matches(".*\\.(tar|tgz|gz|zip|ear|war|rpm).+") && leftName.matches(".*\\.(tar|tgz|gz|zip|ear|war|rpm).+"))
|| (rightName.contains("core") && !leftName.contains("core"))
|| (rightName.contains("kernel") && !leftName.contains("kernel"))
|| (rightName.contains("server") && !leftName.contains("server"))
Expand All @@ -400,7 +400,7 @@ protected boolean isCore(Dependency left, Dependency right) {
|| (rightName.contains("akka-stream") && !leftName.contains("akka-stream"))
|| (rightName.contains("netty-transport") && !leftName.contains("netty-transport"))) {
returnVal = false;
} else if ((rightName.matches(".*\\.(tar|tgz|gz|zip|ear|war).+") && !leftName.matches(".*\\.(tar|tgz|gz|zip|ear|war).+"))
} else if ((rightName.matches(".*\\.(tar|tgz|gz|zip|ear|war|rpm).+") && !leftName.matches(".*\\.(tar|tgz|gz|zip|ear|war|rpm).+"))
|| (!rightName.contains("core") && leftName.contains("core"))
|| (!rightName.contains("kernel") && leftName.contains("kernel"))
|| (!rightName.contains("server") && leftName.contains("server"))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -302,6 +302,7 @@ protected void removeBadMatches(Dependency dependency) {
|| dependency.getFileName().toLowerCase().endsWith(".tar")
|| dependency.getFileName().toLowerCase().endsWith(".gz")
|| dependency.getFileName().toLowerCase().endsWith(".tgz")
|| dependency.getFileName().toLowerCase().endsWith(".rpm")
|| dependency.getFileName().toLowerCase().endsWith(".ear")
|| dependency.getFileName().toLowerCase().endsWith(".war"))) {
dependency.removeVulnerableSoftwareIdentifier(i);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ public void testSupportsExtensions() {
expResult.add("tgz");
expResult.add("bz2");
expResult.add("tbz2");
expResult.add("rpm");
for (String ext : expResult) {
assertTrue(ext, instance.accept(new File("test." + ext)));
}
Expand Down Expand Up @@ -362,6 +363,36 @@ public void testAnalyzeTbz2() throws Exception {
}
}

/**
* Test of analyze method, of class ArchiveAnalyzer.
*/
@Test
public void testAnalyzeRpm() throws Exception {
Settings settings = getSettings();
settings.setBoolean(Settings.KEYS.AUTO_UPDATE, false);
settings.setBoolean(Settings.KEYS.ANALYZER_NEXUS_ENABLED, false);
settings.setBoolean(Settings.KEYS.ANALYZER_CENTRAL_ENABLED, false);
settings.setBoolean(Settings.KEYS.ANALYZER_OSSINDEX_ENABLED, false);

ArchiveAnalyzer instance = new ArchiveAnalyzer();
instance.initialize(settings);
//trick the analyzer into thinking it is active so that it will prepare
instance.accept(new File("struts-1.2.9-162.35.1.uyuni.noarch.rpm"));
try (Engine engine = new Engine(settings)) {
instance.prepare(null);

File file = BaseTest.getResourceAsFile(this, "xmlsec-2.0.7-3.7.uyuni.noarch.rpm");
Dependency dependency = new Dependency(file);

int initial_size = engine.getDependencies().length;
instance.analyze(dependency, engine);
int ending_size = engine.getDependencies().length;
assertTrue(initial_size < ending_size);
} finally {
instance.close();
}
}

/**
* Test of analyze method, of class ArchiveAnalyzer.
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,17 @@ public void testZippableExtensions() throws Exception {
assertFalse(instance.getFileFilter().accept(new File("c:/test.z4")));
}

/**
* Test of analyzeDependency method, of class ArchiveAnalyzer.
*/
@Test
public void testRpmExtension() throws Exception {
assumeFalse(isPreviouslyLoaded("org.owasp.dependencycheck.analyzer.ArchiveAnalyzer"));
ArchiveAnalyzer instance = new ArchiveAnalyzer();
instance.initialize(getSettings());
assertTrue(instance.getFileFilter().accept(new File("/srv/struts-1.2.9-162.35.1.uyuni.noarch.rpm")));
}

private boolean isPreviouslyLoaded(String className) {
try {
Method m = ClassLoader.class.getDeclaredMethod("findLoadedClass", String.class);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,13 @@ public void testIsCore() {
expResult = true;
result = instance.isCore(left, right);
assertEquals(expResult, result);

left.setFileName("struts-1.2.7.jar");
right.setFileName("struts-1.2.9-162.35.1.uyuni.noarch.rpm");

expResult = true;
result = instance.isCore(left, right);
assertEquals(expResult, result);
}

@Test
Expand Down
Binary file not shown.
Binary file not shown.
2 changes: 1 addition & 1 deletion src/site/markdown/analyzers/archive-analyzer.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ OWASP dependency-check includes an analyzer an archive analyzer that will attemp
to extract files from the archive that are supported by the other file type
analyzers.

Files Types Scanned: ZIP, EAR, WAR, JAR, SAR, APK, NUPKG, TAR, GZ, TGZ
Files Types Scanned: ZIP, EAR, WAR, JAR, SAR, APK, NUPKG, TAR, GZ, TGZ, RPM

Additional file extensions for ZIP archives can be added, see the configuration
section in the Maven, Ant, or CLI interfaces for more information on configuration.
Expand Down
2 changes: 1 addition & 1 deletion src/site/markdown/analyzers/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ to extract identification information from the files analyzed.

| Analyzer | File Types Scanned | Analysis Method |
| -------- | ------------------ | --------------- |
| [Archive](./archive-analyzer.html) | Zip archive format (\*.zip, \*.ear, \*.war, \*.jar, \*.sar, \*.apk, \*.nupkg); Tape Archive Format (\*.tar); Gzip format (\*.gz, \*.tgz); Bzip2 format (\*.bz2, \*.tbz2) | Extracts archive contents, then scans contents with all available analyzers. |
| [Archive](./archive-analyzer.html) | Zip archive format (\*.zip, \*.ear, \*.war, \*.jar, \*.sar, \*.apk, \*.nupkg); Tape Archive Format (\*.tar); Gzip format (\*.gz, \*.tgz); Bzip2 format (\*.bz2, \*.tbz2); RPM format (\*.rpm) | Extracts archive contents, then scans contents with all available analyzers. |
| [Assembly](./assembly-analyzer.html) | .NET Assemblies (\*.exe, \*.dll) | Uses [GrokAssembly.exe](https://github.com/colezlaw/GrokAssembly), which requires .NET Framework or Mono runtime to be installed. |
| [Jar](./jar-analyzer.html) | Java archive files (\*.jar); Web application archive (\*.war) | Examines archive manifest metadata, and Maven Project Object Model files (pom.xml). |
| [RetireJS](./retirejs-analyzer.html) | JavaScript files | Analyzes JavaScript files using the [RetireJS](https://github.com/RetireJS/retire.js) database. |
Expand Down

0 comments on commit 5d2c571

Please sign in to comment.