Initial commit

This commit is contained in:
Šesták Vít
2020-01-31 15:00:44 +01:00
commit 05b1e8caa4
43 changed files with 2001 additions and 0 deletions

10
README.md Normal file
View File

@@ -0,0 +1,10 @@
Adds DevAudit scan to OWASP Dependency Check. It is an ODC plugin.
The plugin relies on index provided by nuget-indexer . The index is stored in ODC vulnerability database, so there is no need for extra configuration.
Config properties:
* com.ysoft.dotnetEnhancer.enabled enables/disables the analyzers
* com.ysoft.dotnetEnhancer.vulnerabilityMode CVE_ONLY uses description from NVD and ignores vulnerabilities without CVE; CVE_PREFERRED prefers description from NVD, but allows some best-effort output if CVE is not available; PURE_DA always uses data from DevAudit.
* com.ysoft.dotnetEnhancer.devAuditPath Path to DevAudit folder. On Linux, it is expected that devaudit.exe is executable and binfmt is configured for running .NET binaries.
* com.ysoft.dotnetEnhancer.strictSearch Raises exception instead of warning if a .NET library could not be found in index.

49
pom.xml Normal file
View File

@@ -0,0 +1,49 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.ysoft.security</groupId>
<artifactId>odc-devaudit-dotnet</artifactId>
<version>1.3</version>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>org.owasp</groupId>
<artifactId>dependency-check-core</artifactId>
<version>5.2.4</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>21.0</version>
<scope>test</scope>
</dependency>
</dependencies>
</project>

View File

@@ -0,0 +1,20 @@
package com.ysoft.security.odc.dotnet;
import org.owasp.dependencycheck.analyzer.AbstractFileTypeAnalyzer;
import java.io.FileFilter;
abstract class AbstractDotNetEnhancerAnalyzer extends AbstractFileTypeAnalyzer {
public static final String DOTNET_ENHANCER_ANALYZER_KEY = "com.ysoft.dotnetEnhancer.enabled";
protected FileFilter getFileFilter() {
return f -> f.getName().toLowerCase().endsWith(".dll");
}
@Override
protected String getAnalyzerEnabledSettingKey() {
return DOTNET_ENHANCER_ANALYZER_KEY;
}
}

View File

@@ -0,0 +1,72 @@
package com.ysoft.security.odc.dotnet;
import java.util.Objects;
import java.util.Optional;
public final class DAVulnerability {
private final String title;
private final String identifier;
private final String description;
private final String afectedVersions;
private final String ossIndexId;
private final String providedBy;
private final Optional<String> optionalCve;
public DAVulnerability(String title, String identifier, String description, String afectedVersions, String ossIndexId, String providedBy, Optional<String> optionalCve) {
this.title = title;
this.identifier = identifier;
this.description = description;
this.afectedVersions = afectedVersions;
this.ossIndexId = ossIndexId;
this.providedBy = providedBy;
this.optionalCve = optionalCve;
}
public String getTitle() {
return title;
}
public String getIdentifier() {
return identifier;
}
public String getDescription() {
return description;
}
public String getAfectedVersions() {
return afectedVersions;
}
public String getOssIndexId() {
return ossIndexId;
}
public String getProvidedBy() {
return providedBy;
}
public Optional<String> getOptionalCve() {
return optionalCve;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
DAVulnerability that = (DAVulnerability) o;
return Objects.equals(title, that.title) &&
Objects.equals(identifier, that.identifier) &&
Objects.equals(description, that.description) &&
Objects.equals(afectedVersions, that.afectedVersions) &&
Objects.equals(ossIndexId, that.ossIndexId) &&
Objects.equals(providedBy, that.providedBy) &&
Objects.equals(optionalCve, that.optionalCve);
}
@Override
public int hashCode() {
return Objects.hash(title, identifier, description, afectedVersions, ossIndexId, providedBy, optionalCve);
}
}

View File

@@ -0,0 +1,63 @@
package com.ysoft.security.odc.dotnet;
import java.util.Collections;
import java.util.Map;
public final class DAVulnerableDependency {
private final String name;
private final String version;
private final Map<String, DAVulnerability> vulnerabilities;
public DAVulnerableDependency(String name, String version, Map<String, DAVulnerability> vulnerabilities) {
this.name = name;
this.version = version;
this.vulnerabilities = vulnerabilities;
}
public String getName() {
return name;
}
public Map<String, DAVulnerability> getVulnerabilities() {
return vulnerabilities;
}
public String getVersion() {
return version;
}
public String getKey() {
return getName() + ":" + getVersion();
}
public static DAVulnerableDependency withNoVulnerability(String identifier) {
final String[] parts = identifier.split(":");
if(parts.length != 2){
throw new IllegalArgumentException("Identifier is expected to contain exactly one colon: "+identifier);
}
return new DAVulnerableDependency(parts[0], parts[1], Collections.emptyMap());
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
DAVulnerableDependency that = (DAVulnerableDependency) o;
if (!name.equals(that.name)) return false;
if (!version.equals(that.version)) return false;
return vulnerabilities.equals(that.vulnerabilities);
}
@Override
public int hashCode() {
int result = name.hashCode();
result = 31 * result + version.hashCode();
result = 31 * result + vulnerabilities.hashCode();
return result;
}
}

View File

@@ -0,0 +1,208 @@
package com.ysoft.security.odc.dotnet;
import java.io.IOException;
import java.nio.file.Paths;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.NoSuchElementException;
import java.util.Objects;
import java.util.Optional;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import org.apache.commons.collections.map.ReferenceMap;
import org.owasp.dependencycheck.Engine;
import org.owasp.dependencycheck.analyzer.AnalysisPhase;
import org.owasp.dependencycheck.analyzer.exception.AnalysisException;
import org.owasp.dependencycheck.data.nvdcve.CveDB;
import org.owasp.dependencycheck.data.nvdcve.DatabaseException;
import org.owasp.dependencycheck.dependency.Dependency;
import org.owasp.dependencycheck.dependency.Vulnerability;
import org.owasp.dependencycheck.dependency.naming.Identifier;
import org.owasp.dependencycheck.exception.InitializationException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import static org.apache.commons.collections.map.AbstractReferenceMap.HARD;
import static org.apache.commons.collections.map.AbstractReferenceMap.SOFT;
enum Mode {
// The options can be accessed reflectively, so they might look unused
@SuppressWarnings("unused") CVE_ONLY(true, false),
@SuppressWarnings("unused") CVE_PREFERRED(true, true),
@SuppressWarnings("unused") PURE_DA(false, true);
private final boolean convertCve;
private final boolean useNonCve;
Mode(boolean convertCve, boolean useNonCve) {
this.convertCve = convertCve;
this.useNonCve = useNonCve;
}
public boolean convertCve() {
return convertCve;
}
public boolean useNonCve() {
return useNonCve;
}
}
public class DevAuditDotNetEnhancerAnalyzer extends AbstractDotNetEnhancerAnalyzer {
private static final Logger LOGGER = LoggerFactory.getLogger(DevAuditDotNetEnhancerAnalyzer.class);
static final AnalysisPhase ANALYSIS_PHASE = AnalysisPhase.FINDING_ANALYSIS;
private DevAuditRunner devAuditRunner;
private CveDB cveDB;
/**
* Once analysis fails, it never tries it again in order not to spam the OSS Index API and the log
*/
private boolean failed = false;
@SuppressWarnings("unchecked")
private final Map<Engine, Map<String, DAVulnerableDependency>> results = new ReferenceMap(SOFT, HARD);
/**
* We do most of the work when called for the first dependency (we can't go parallel at this moment) and then just quickly lookup the results for
* other dependencies (when parallelism is almost useless). So, parallelism would require some work for synchronizing the initial lookup with low
* payoff.
*/
@Override
public boolean supportsParallelProcessing() {
return false;
}
private Map<String, DAVulnerableDependency> getOrCreateResultsForEngine(Engine engine) throws IOException {
// Cannot use computeIfAbsent due to checked exceptions… Fsck!
final Map<String, DAVulnerableDependency> resultIfCached = results.get(engine);
if (resultIfCached != null) {
return resultIfCached;
}
if (failed) {
// Don't spam API and log
throw new RuntimeException("The analyzer " + getName() + " is in failed state. Look for the first error message of this analyzer.");
}
try {
final Map<String, DAVulnerableDependency> result = findVulnerableLibrariesForEngine(engine);
results.put(engine, result);
return result;
} catch (Throwable e) {
failed = true;
throw e;
}
}
public Map<String, DAVulnerableDependency> getResultsForEngine(Engine engine) throws IOException {
final Map<String, DAVulnerableDependency> resultIfCached = results.get(engine);
if (resultIfCached != null) {
return resultIfCached;
} else {
throw new NoSuchElementException();
}
}
private Map<String, DAVulnerableDependency> findVulnerableLibrariesForEngine(Engine engine) throws IOException {
final List<String> nugetIdentifiers = Arrays.stream(engine.getDependencies())
.flatMap(dependency -> dependency.getSoftwareIdentifiers().stream()
.filter(identifier -> identifier.getValue().startsWith("pkg:" + DllFindingDotNetEnhancerAnalyzer.DEPENDENCY_TYPE)))
.map(Identifier::getValue)
.collect(Collectors.toList());
final Map<String, DAVulnerableDependency> results = devAuditRunner.run(nugetIdentifiers);
LOGGER.info("scan results: {}", results);
return results;
}
@Override
protected void prepareFileTypeAnalyzer(Engine engine) throws InitializationException {
devAuditRunner = new DevAuditRunner(Paths.get(getSettings().getString("com.ysoft.dotnetEnhancer.devAuditPath")));
try {
cveDB = new CveDB(getSettings());
} catch (DatabaseException e) {
throw new InitializationException(e);
}
}
private Mode getMode() {
return Mode.valueOf(getSettings().getString("com.ysoft.dotnetEnhancer.vulnerabilityMode", "CVE_PREFERRED"));
}
@Override
public String getName() {
return ".NET Analyzer Enhancer DevAudit runner";
}
@Override
public AnalysisPhase getAnalysisPhase() {
return ANALYSIS_PHASE;
}
@Override
protected void analyzeDependency(Dependency dependency, Engine engine) throws AnalysisException {
try {
final Map<String, DAVulnerableDependency> resultsForEngine = getOrCreateResultsForEngine(engine);
LOGGER.info("Scanning Dependency {}", dependency);
final Stream<DAVulnerability> matchedVulnerabilities = findRelevantVulnerabilities(dependency, resultsForEngine);
for (final DAVulnerability daVulnerability : matchedVulnerabilities.collect(Collectors.toSet())) {
convertVulnerability(daVulnerability).ifPresent(dependency::addVulnerability);
}
} catch (IOException e) {
throw new AnalysisException(e);
}
}
Stream<DAVulnerability> findRelevantVulnerabilities(Dependency dependency, Map<String, DAVulnerableDependency> resultsForEngine) {
final Stream<String> identifiers = dependency.getSoftwareIdentifiers().stream()
.map(Identifier::getValue)
.filter(value -> value.startsWith("pkg:" + DllFindingDotNetEnhancerAnalyzer.DEPENDENCY_TYPE))
.peek(value -> LOGGER.info("Identifier: {}", value));
final Stream<DAVulnerableDependency> matchedVulnerableDependencies =
identifiers
.map(resultsForEngine::get)
.filter(Objects::nonNull)
.peek(vulnerableDependency -> LOGGER.info("Vulnerable dependency: {}", vulnerableDependency));
return matchedVulnerableDependencies
.flatMap(x -> x.getVulnerabilities().values().stream())
.peek(vulnerability -> LOGGER.info("Vulnerability: {}", vulnerability));
}
private Optional<Vulnerability> convertVulnerability(DAVulnerability daVulnerability) throws AnalysisException {
final Optional<String> optionalCve = daVulnerability.getOptionalCve();
if (getMode().convertCve() && optionalCve.isPresent()) {
final String cve = optionalCve.get();
try {
final Vulnerability vulnerability = cveDB.getVulnerability(cve);
if (vulnerability != null) {
return Optional.of(vulnerability);
} else {
LOGGER.warn("Cannot load details for vulnerability {} from ODC DB", cve);
// Now, we will continue with other options
}
} catch (DatabaseException e) {
throw new AnalysisException(e);
}
}
// now, we don't have CVE
if (getMode().useNonCve()) {
final Vulnerability vulnerability = new Vulnerability();
vulnerability.setName(daVulnerability.getIdentifier());
vulnerability.setDescription(daVulnerability.getTitle() + "\n\n" + daVulnerability.getDescription());
return Optional.of(vulnerability);
} else {
LOGGER.warn("Ignoring vulnerability {} because it has no CVE. If you would like to include such vulnerabilities, configure com.ysoft.dotnetEnhancer.vulnerabilityMode accordingly.", daVulnerability.getIdentifier());
return Optional.empty();
}
}
@Override
protected void closeAnalyzer() throws Exception {
cveDB.close();
super.closeAnalyzer();
}
}

View File

@@ -0,0 +1,304 @@
package com.ysoft.security.odc.dotnet;
import java.io.BufferedReader;
import java.io.IOException;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import static java.lang.Character.isDigit;
import static java.util.Collections.unmodifiableMap;
/**
* Parsers for DevAudit results. It is expected that -n is passed to DevAudit. If it is not the case, DevAudit might
* provide results that are not parseable by this class.
*/
public class DevAuditResultParser {
private static final Pattern VULNERABLE_PATTERN = Pattern.compile(
"\\[[0-9]+/[0-9]+\\] ([^ ]+) \\[VULNERABLE\\] +[0-9]+ known vulnerabilit.*affecting installed package version\\(s\\): \\[([^, ]+)\\]$"
);
private static final Pattern NON_VULNERABLE_PATTERN = Pattern.compile(
"\\[[0-9]+/[0-9]+\\] ([^ ]+) (no known vulnerabilities\\.|[0-9]+ known vulnerabilit(y|ies), 0 affecting installed package version\\(s\\)\\.)$"
);
// --[1/3] [CVE-2011-4969] Improper Neutralization of Input During Web Page Generation ("Cross-site Scripting")
private static final Pattern CVE_VULNERABILITY_START_PATTERN = Pattern.compile("--\\[[0-9]+/[0-9]+\\] \\[(CVE-[0-9]{4}-[0-9]+)\\] (.*)$");
// --[2/3] Cross Site Scripting (XSS)
private static final Pattern VULNERABILITY_START_PATTERN = Pattern.compile("--\\[[0-9]+/[0-9]+\\] (.*)$");
public static final String BANNER_FIRST_LINE = " _____ _______ __ __ __ ";
public static Map<String, DAVulnerableDependency> parse(BufferedReader in) throws IOException {
//final String version = consumeHeaderWithVersion(in);
consumeLog(in);
expectLine(in, "Package Source Audit Results");
expectLine(in, "============================");
expectLineRegex(in, "^([0-9]+ total vulnerabilities|1 total vulnerability) found in NuGet package source audit. Total time for audit: [0-9]+ ms.");
expectLine(in, "");
final Map<String, DAVulnerableDependency> out = consumeVulnerableDependencies(in);
if(out.isEmpty()){
// When there is no vulnerability, there is also no footer
final String line = in.readLine();
if(line != null){
throw new UnexpectedFormatException("Expected EOF when there is no vulnerability.");
}
}else{
consumeFooter(in);
}
return out;
}
private static void consumeBanner(BufferedReader in) throws IOException {
expectLine(in, BANNER_FIRST_LINE);
consumeRestOfBanner(in);
}
private static void consumeRestOfBanner(BufferedReader in) throws IOException {
expectLine(in, "| \\ .-----..--.--.| _ |.--.--..--| ||__|| |_ ");
expectLine(in, "| -- || -__|| | || || | || _ || || _|");
expectLine(in, "|_____/ |_____| \\___/ |___|___||_____||_____||__||____|");
expectLine(in, " ");
expectLine(in, "");
}
private static Map<String, DAVulnerableDependency> consumeVulnerableDependencies(BufferedReader in) throws IOException {
final Map<String, DAVulnerableDependency> result = new HashMap<>();
Optional<Optional<DAVulnerableDependency>> maybeVulnerableDependency;
while ( (maybeVulnerableDependency = consumeDependencyInfo(in)).isPresent()){
if(maybeVulnerableDependency.get().isPresent()){
final DAVulnerableDependency vulnerableDependency = maybeVulnerableDependency.get().get();
final String key = vulnerableDependency.getKey();
if(result.containsKey(key) && !result.get(key).equals(vulnerableDependency)){
throw new UnexpectedFormatException("Vulnerable dependency with the following key is there twice with a different result: "+key);
}
result.put(key, vulnerableDependency);
}
}
return unmodifiableMap(result);
}
private static Optional<Optional<DAVulnerableDependency>> consumeDependencyInfo(BufferedReader in) throws IOException {
/* Now, I am expecting either line like this:
[11/17] jQuery.Validation [VULNERABLE] 1 known vulnerabilities, 1 affecting installed package version(s): [1.6.0]
or like this:
[12/17] AntiXSS 1 known vulnerability, 0 affecting installed package version(s).
or an empty line (end)
*/
final String headerLine = in.readLine();
if(headerLine.equals("")){
return Optional.empty();
}else{
final Matcher vulnerableMatcher = VULNERABLE_PATTERN.matcher(headerLine);
if(vulnerableMatcher.matches()){
final String name = vulnerableMatcher.group(1);
final String version = vulnerableMatcher.group(2);
final DAVulnerableDependency vd = consumeVulnerableDependencyInfo(in, name, version);
return Optional.of(Optional.of(vd));
} else {
final Matcher nonVulnerableMatcher = NON_VULNERABLE_PATTERN.matcher(headerLine);
if(nonVulnerableMatcher.matches()){
return Optional.of(Optional.empty());
} else {
throw new UnexpectedFormatException("Expected dependency header, found: "+headerLine);
}
}
}
}
private static DAVulnerableDependency consumeVulnerableDependencyInfo(BufferedReader in, String name, String version) throws IOException {
final VulnerabilitiesParser vulnerabilitiesParser = new VulnerabilitiesParser();
String line;
while(!(line = in.readLine()).equals("")){
vulnerabilitiesParser.push(line);
}
return new DAVulnerableDependency(name, version, vulnerabilitiesParser.finish());
}
private static void consumeFooter(BufferedReader in) throws IOException {
expectLine(in, "Vulnerabilities Data Providers");
expectLine(in, "==============================");
expectLine(in, "");
//noinspection StatementWithEmptyBody
while( in.readLine() != null) {
}
}
private static void expectLine(BufferedReader in, String expectedLine) throws IOException {
final String line = in.readLine();
if(line == null){
throw new UnexpectedFormatException("Expected '"+expectedLine+"', got EOF");
}
if(!line.equals(expectedLine)){
throw new UnexpectedFormatException("Expected '"+expectedLine+"', got: "+line);
}
}
private static void expectLineRegex(BufferedReader in, String regex) throws IOException {
final String line = in.readLine();
if(line == null){
throw new UnexpectedFormatException("Expected something that matches '"+regex+"', got EOF");
}
if(!line.matches(regex)){
throw new UnexpectedFormatException("Expected something that matches '"+regex+"', got: "+line);
}
}
private static void consumeLog(BufferedReader in) throws IOException {
String line;
while( (line = in.readLine()) != null){
if(line.equals(" ") || line.equals("")){
return;
}else if(line.equals(BANNER_FIRST_LINE)){
consumeRestOfBanner(in);
}else{
if(line.toLowerCase().contains("[error]")){
if(isInnocentErrorMessage(line)){
System.out.println("Ignoring error message: "+line);
}else{
final StringBuilder messageBuilder = new StringBuilder(line);
while( (line = in.readLine()) != null){
messageBuilder.append(line);
messageBuilder.append('\n');
}
throw new IOException("Error when running DevAudit: "+messageBuilder.toString());
}
}
System.out.println("log: "+line);
}
}
throw new UnexpectedFormatException("Reached EOF before finding end of log");
}
private static boolean isInnocentErrorMessage(String line) {
final int firstSpacePos = line.indexOf(' ');
if(firstSpacePos == -1){
return false;
}
final String bareErrorMessage = line.substring(firstSpacePos + 1);
return bareErrorMessage.equals("[AUDIT] [ERROR] GetOSName() failed.");
}
private static String consumeHeaderWithVersion(BufferedReader in) throws IOException {
String line;
while( (line = in.readLine()) != null){
if(line.startsWith("v")){
return line.substring(1);
}
}
throw new UnexpectedFormatException("Reached EOF before finding DevAudit version");
}
private static class VulnerabilitiesParser {
private final Map<String, DAVulnerability> vulnerabilities = new HashMap<>();
private VulnerabilityParser vulnerabilityParser;
public void push(String line) throws UnexpectedFormatException {
if(line.startsWith("--")){
finishOldVulnerability();
// new vulnerability
final Optional<String> cve;
final String title;
final Matcher cveVulnerabilityMatcher = CVE_VULNERABILITY_START_PATTERN.matcher(line);
if(cveVulnerabilityMatcher.matches()){
cve = Optional.of(cveVulnerabilityMatcher.group(1));
title = cveVulnerabilityMatcher.group(2);
}else{
final Matcher vulnerabilityMatcher = VULNERABILITY_START_PATTERN.matcher(line);
if(vulnerabilityMatcher.matches()){
title = vulnerabilityMatcher.group(1);
cve = Optional.empty();
}else{
throw new UnexpectedFormatException("Unexpected initial vulnerability line: "+line);
}
}
vulnerabilityParser = new VulnerabilityParser(title, cve);
}else{
vulnerabilityParser.push(line);
}
}
private void finishOldVulnerability() throws UnexpectedFormatException {
if(vulnerabilityParser != null) {
final DAVulnerability vulnerability = vulnerabilityParser.build();
final String key = vulnerability.getIdentifier();
if (vulnerabilities.containsKey(key)) {
throw new UnexpectedFormatException("The following vulnerability is there multiple times: " + vulnerability);
} else {
vulnerabilities.put(key, vulnerability);
vulnerabilityParser = null;
}
}
}
public Map<String, DAVulnerability> finish() throws UnexpectedFormatException {
finishOldVulnerability();
return unmodifiableMap(vulnerabilities);
}
}
private static class VulnerabilityParser {
private final String title;
private final Optional<String> cve;
private String lastKey = null;
private final Map<String, String> data = new HashMap<String, String>();
public VulnerabilityParser(String title, Optional<String> cve) {
this.title = title;
this.cve = cve;
}
public DAVulnerability build() {
final String ossIndexId = data.get("Id");
final String identifier = cve.orElseGet(() -> "OSSINDEX-"+ossIndexId);
return new DAVulnerability(
title.trim(),
identifier,
data.get("Description").trim(),
data.get("Affected versions").trim(),
ossIndexId,
data.get("Provided by").trim(),
cve
);
}
private void addAffectedVersion(String affectedVersion) {
if(data.containsKey("Affected versions")){
data.put("Affected versions", data.get("Affected versions")+", "+affectedVersion);
}else{
data.put("Affected versions", affectedVersion);
}
}
public void push(String line) throws UnexpectedFormatException {
if(line.startsWith(" --")){
final String[] parts = line.split(":", 2);
final String key = parts[0].substring(4);
final String value = parts[1].trim();
lastKey = key;
if(data.containsKey(key)){
throw new UnexpectedFormatException("Duplicate key for vulnerability: "+key);
}else{
data.put(key, value);
}
}else if(line.startsWith(" --") /*4 spaces and 2 minuses*/ || line.startsWith(" "/* 6 spaces*/)){
// multiline
data.put(lastKey, data.get(lastKey)+"\n"+line.substring(6));
}else if(data.containsKey("Description") && !line.equals("") && isDigit(line.charAt(0))){
// looks like affected version number
addAffectedVersion(line);
}else{
throw new UnexpectedFormatException("Unexpected line start: "+line);
}
}
}
}

View File

@@ -0,0 +1,162 @@
package com.ysoft.security.odc.dotnet;
import org.apache.commons.collections.map.ReferenceMap;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.SystemUtils;
import org.owasp.dependencycheck.utils.Pair;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.*;
import java.nio.charset.StandardCharsets;
import java.nio.file.FileVisitResult;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.SimpleFileVisitor;
import java.nio.file.attribute.BasicFileAttributes;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import static java.util.Collections.emptyMap;
import static java.util.function.Function.identity;
import static org.apache.commons.collections.map.AbstractReferenceMap.HARD;
import static org.apache.commons.collections.map.AbstractReferenceMap.SOFT;
import static org.apache.commons.lang3.StringEscapeUtils.escapeXml10;
public class DevAuditRunner {
private static final Logger LOGGER = LoggerFactory.getLogger(DevAuditRunner.class);
private final Path devAuditPath;
@SuppressWarnings("unchecked")
private final Map<String, DAVulnerableDependency> cache = new ReferenceMap(HARD, SOFT);
public DevAuditRunner(Path devAuditPath) {
this.devAuditPath = devAuditPath;
}
public Map<String, DAVulnerableDependency> run(Path packagesConfigPath) throws IOException {
final ProcessBuilder processBuilder = new ProcessBuilder(
ArrayUtils.addAll(devAuditExe(), "nuget", "-n", "--file", packagesConfigPath.resolve("packages.config").toString())
);
processBuilder.redirectErrorStream(true);
final Process process = processBuilder.start();
try{
process.getOutputStream().close();
try (BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()))) {
final Map<String, DAVulnerableDependency> res = DevAuditResultParser.parse(reader);
process.waitFor();
final int exitValue = process.exitValue();
if(exitValue != 0){
throw new IOException("Error when running DevAudit: Unexpected exit code: "+exitValue);
}
return res;
}
} catch (InterruptedException e){
throw new IOException(e);
} finally {
process.destroyForcibly();
}
}
private String[] devAuditExe() throws IOException {
final String devAuditNativePath = devAuditPath.resolve("devaudit").toString();
final String devAuditExePath = devAuditPath.resolve("devaudit.exe").toString();
return new File(devAuditNativePath).exists()
? new String[]{devAuditNativePath}
: (SystemUtils.IS_OS_WINDOWS || hasCliBinfmt())
? new String[]{devAuditExePath}
: new String[]{findDotNetRuntime(), devAuditExePath};
}
private String findDotNetRuntime() throws IOException {
final Process process = Runtime.getRuntime().exec("which cli mono");
try {
new Thread(() -> {
try (InputStream errorStream = process.getErrorStream()) {
final byte[] buffer = new byte[1024];
while (errorStream.read(buffer) != -1) {
// ignore
}
} catch (IOException e) {
throw new RuntimeException(e);
}
}).start();
try (BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()))) {
return reader.readLine();
}
} finally {
process.destroy();
}
}
private boolean hasCliBinfmt() {
return new File("/proc/sys/fs/binfmt_misc/cli").exists();
}
public synchronized Map<String, DAVulnerableDependency> run(List<String> identifiers) throws IOException {
if(identifiers.isEmpty()){
return emptyMap();
}
final Map<String, DAVulnerableDependency> cached = loadFromCache(identifiers);
final HashSet<String> missing = new HashSet<>(identifiers);
missing.removeAll(cached.keySet());
LOGGER.info("Cache hits: {}", cached.keySet());
LOGGER.info("Cache misses: {}", missing);
if(missing.isEmpty()){ // fast path
return cached;
}
final Path tempProjectDir = Files.createTempDirectory(null);
try {
final StringBuilder xmlBuilder = new StringBuilder(
"<?xml version=\"1.0\" encoding=\"utf-8\"?>\n" +
"<packages>\n"
);
for (final String identifier: missing) {
final String[] identifierParts = identifier.split(":");
if(identifierParts.length != 2){
throw new UnexpectedFormatException("Unexpected count of colons in identifier: "+identifier);
}
final String name = identifierParts[0];
final String version = identifierParts[1];
xmlBuilder.append(" <package id=\"").append(escapeXml10(name)).append("\" version=\"").append(escapeXml10(version)).append("\" />\n");
}
xmlBuilder.append("</packages>\n");
final String xml = xmlBuilder.toString();
LOGGER.debug("packages.config: {}", xml);
Files.write(tempProjectDir.resolve("packages.config"), xml.getBytes(StandardCharsets.UTF_8));
final Map<String, DAVulnerableDependency> missingResults = new HashMap<>(missing.stream().collect(Collectors.toMap(identity(), DAVulnerableDependency::withNoVulnerability)));
missingResults.putAll(run(tempProjectDir));
cache.putAll(missingResults);
final Map<String, DAVulnerableDependency> result = new HashMap<>(cached);
result.putAll(missingResults);
return result;
} finally {
Files.walkFileTree(tempProjectDir, new SimpleFileVisitor<Path>() {
@Override
public FileVisitResult visitFile(Path path, BasicFileAttributes basicFileAttributes) throws IOException {
Files.delete(path);
return FileVisitResult.CONTINUE;
}
@Override
public FileVisitResult postVisitDirectory(Path path, IOException e) throws IOException {
Files.delete(path);
return FileVisitResult.CONTINUE;
}
});
}
}
private synchronized Map<String, DAVulnerableDependency> loadFromCache(List<String> identifiers) {
return identifiers.stream()
.map(identifier -> new Pair<>(identifier, cache.get(identifier)))
.filter(p -> p.getRight() != null)
.collect(Collectors.toMap(Pair::getLeft, Pair::getRight));
}
}

View File

@@ -0,0 +1,106 @@
package com.ysoft.security.odc.dotnet;
import java.io.*;
import java.nio.charset.StandardCharsets;
public class DllAnalyzer {
public static boolean isDotNet(RandomAccessFile in) throws IOException {
/*
Excerpt from https://www.darwinsys.com/file/ sources at magic/Magdir/msdos:
0 string/b MZ
# If the relocation table is 0x40 or more bytes into the file, it's definitely
# not a DOS EXE.
>0x18 leshort >0x3f
# Maybe it's a PE?
>>(0x3c.l) string PE\0\0 PE
>>>(0x3c.l+24) leshort 0x010b
>>>>(0x3c.l+232) lelong >0 Mono/.Net assembly
explanation: .l little endian unsigned long
For more, see `man magic`.
*/
// Check MZ
{
in.seek(0);
if (!checkString(in, "MZ")) {
return false;
}
}
// Check relocation table size
{
in.seek(0x18);
final int relocationTableSize = readLittleEndianUnsignedShort(in);
if(relocationTableSize < 0x40) {
return false;
}
}
in.seek(0x3c);
final long base = readLittleEndianLong(in);
// Check if it is PE
{
in.seek(base);
if(!checkString(in, "PE\0\0")){
return false;
}
}
// Check .NET
{
in.seek(base+24);
if(readLittleEndianUnsignedShort(in) != 0x010b){
return false;
}
in.seek(base+232);
return readLittleEndianLong(in) > 0;
}
}
private static boolean checkString(RandomAccessFile in, String asciiString) throws IOException {
return checkString(in, asciiString.getBytes(StandardCharsets.US_ASCII));
}
private static boolean checkString(RandomAccessFile in, byte[] bytes) throws IOException {
for (final byte expectedByte : bytes) {
final byte b = in.readByte();
if (b != expectedByte) {
return false;
}
}
return true;
}
private static int readLittleEndianUnsignedShort(RandomAccessFile in) throws IOException {
final byte buffer0 = in.readByte();
final byte buffer1 = in.readByte();
return
(buffer0 & 0xFF) |
(buffer1 & 0xFF) << 8;
}
private static long readLittleEndianLong(DataInput in) throws IOException {
final byte buffer0 = in.readByte();
final byte buffer1 = in.readByte();
final byte buffer2 = in.readByte();
final byte buffer3 = in.readByte();
return
(buffer0 & 0xFF) |
(buffer1 & 0xFF) << 8 |
(buffer2 & 0xFF) << 16 |
(buffer3 & 0xFF) << 24;
}
public static boolean isDotNet(File file) throws IOException {
try (RandomAccessFile raf = new RandomAccessFile(file, "r")) {
return isDotNet(raf);
}
}
}

View File

@@ -0,0 +1,126 @@
package com.ysoft.security.odc.dotnet;
import org.owasp.dependencycheck.Engine;
import org.owasp.dependencycheck.analyzer.AnalysisPhase;
import org.owasp.dependencycheck.analyzer.exception.AnalysisException;
import org.owasp.dependencycheck.dependency.Confidence;
import org.owasp.dependencycheck.dependency.Dependency;
import org.owasp.dependencycheck.dependency.naming.PurlIdentifier;
import org.owasp.dependencycheck.exception.InitializationException;
import org.owasp.dependencycheck.utils.InvalidSettingException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.IOException;
import java.sql.*;
import java.util.HashMap;
import java.util.Map;
import com.github.packageurl.MalformedPackageURLException;
public class DllFindingDotNetEnhancerAnalyzer extends AbstractDotNetEnhancerAnalyzer {
private static final Logger LOGGER = LoggerFactory.getLogger(DllFindingDotNetEnhancerAnalyzer.class);
static final String DEPENDENCY_TYPE = "nuget";
private Connection connection;
@Override
public String getName() {
return ".NET Analyzer Enhancer finder";
}
@Override
public AnalysisPhase getAnalysisPhase() {
return AnalysisPhase.IDENTIFIER_ANALYSIS;
}
@Override
protected void prepareFileTypeAnalyzer(Engine engine) throws InitializationException {
try {
connection = DriverManager.getConnection(
getSettings().getString("com.ysoft.dotnetEnhancer.db.connectionString"),
getSettings().getString("com.ysoft.dotnetEnhancer.db.userName"),
getSettings().getString("com.ysoft.dotnetEnhancer.db.password")
);
} catch (SQLException e) {
throw new InitializationException("Cannot connect to the Nuget index DB", e);
}
}
@Override
protected void analyzeDependency(Dependency dependency, Engine engine) throws AnalysisException {
try {
final boolean isDotNet = DllAnalyzer.isDotNet(dependency.getActualFile());
if(!isDotNet){
// This prevents some noise like msvcr90.dll being identified as UmbracoCMS.
return;
}
final PreparedStatement statement = connection.prepareStatement(
"SELECT * FROM nuget_index_hashes WHERE digest_hex_sha1 = ? AND digest_hex_md5 = ?"
);
statement.setString(1, dependency.getSha1sum().toUpperCase());
statement.setString(2, dependency.getMd5sum().toUpperCase());
final ResultSet resultSet = statement.executeQuery();
boolean empty = true;
final Map<String, Integer> versionlessIdentifiersCounts = new HashMap<>();
final Map<String, Confidence> identifierToConfidence = new HashMap<>();
while(resultSet.next()){
empty = false;
final String name = resultSet.getString("name");
final String version = resultSet.getString("version");
assert name.indexOf(':') == -1;
assert version.indexOf(':') == -1;
final Confidence confidence = dependency.getFileName().toLowerCase().contains(name.toLowerCase()) ? Confidence.HIGHEST : Confidence.MEDIUM;
versionlessIdentifiersCounts.merge(name, 1, Integer::sum);
final String identifier = name+":"+version;
final Confidence existingConfidence = identifierToConfidence.get(identifier);
// Insert if it doesn't exist. Override if it exists with a lower confidence. (Use the highest confidence we have.)
// Note that ordinals are reversed, so I am using the “-” operator
if( (existingConfidence == null) || (-confidence.ordinal() > -existingConfidence.ordinal()) ){
identifierToConfidence.put(identifier, confidence);
}
}
LOGGER.info("Identifier counts: {}", versionlessIdentifiersCounts);
for (Map.Entry<String, Confidence> identifierEntry : identifierToConfidence.entrySet()) {
final String fullIdentifier = identifierEntry.getKey();
final String versionlessIdentifier = fullIdentifier.substring(0, fullIdentifier.indexOf(':'));
final String version = fullIdentifier.substring(fullIdentifier.indexOf(':') + 1);
LOGGER.info("Looking for versionless identifier: {}", versionlessIdentifier);
final boolean hasMultipleOccurences = versionlessIdentifiersCounts.get(versionlessIdentifier) > 1;
// Make confidence low if it occurs in multiple versions. It is likely some generic bundled library.
final Confidence confidence = hasMultipleOccurences ? Confidence.LOW : identifierEntry.getValue();
dependency.addSoftwareIdentifier(new PurlIdentifier(DEPENDENCY_TYPE, versionlessIdentifier, version, confidence));
}
//noinspection ConstantConditions because isDotNet is currently always true at this point, but it might change later
if(empty && isDotNet){
final String msg = "Unidentified dependency: ("+dependency.getSha1sum()+"-"+dependency.getMd5sum()+") " + dependency;
if(isStrict()){
throw new AnalysisException(msg);
}else{
LOGGER.warn(msg);
}
}
} catch (SQLException | IOException | MalformedPackageURLException e) {
throw new AnalysisException(e);
}
}
private boolean isStrict() throws InvalidSettingException {
return getSettings().getBoolean("com.ysoft.dotnetEnhancer.strictSearch", false);
}
@Override
protected void closeAnalyzer() throws Exception {
try{
super.closeAnalyzer();
}finally {
if(connection != null){
connection.close();
connection = null;
}
}
}
}

View File

@@ -0,0 +1,69 @@
package com.ysoft.security.odc.dotnet;
import org.apache.commons.compress.utils.Sets;
import org.owasp.dependencycheck.Engine;
import org.owasp.dependencycheck.analyzer.AnalysisPhase;
import org.owasp.dependencycheck.analyzer.exception.AnalysisException;
import org.owasp.dependencycheck.dependency.Dependency;
import org.owasp.dependencycheck.dependency.Vulnerability;
import org.owasp.dependencycheck.exception.InitializationException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.IOException;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;
public class FalsePositiveWarningAnalyzer extends AbstractDotNetEnhancerAnalyzer {
private static final Logger LOGGER = LoggerFactory.getLogger(FalsePositiveWarningAnalyzer.class);
@Override
protected void prepareFileTypeAnalyzer(Engine engine) throws InitializationException {}
@Override
protected void analyzeDependency(Dependency dependency, Engine engine) throws AnalysisException {
final List<DevAuditDotNetEnhancerAnalyzer> dotNetEnhancerAnalyzers = engine
.getAnalyzers(DevAuditDotNetEnhancerAnalyzer.ANALYSIS_PHASE)
.stream()
.filter(x -> x instanceof DevAuditDotNetEnhancerAnalyzer)
.map(x -> (DevAuditDotNetEnhancerAnalyzer)x)
.collect(Collectors.toList());
if(dotNetEnhancerAnalyzers.size() != 1){
throw new AssertionError("Expected exactly one Analyzer, "+dotNetEnhancerAnalyzers.size()+" found.");
}
final DevAuditDotNetEnhancerAnalyzer dotNetEnhancerAnalyzer = dotNetEnhancerAnalyzers.get(0);
try {
final Map<String, DAVulnerableDependency> resultsForEngine = dotNetEnhancerAnalyzer.getResultsForEngine(engine);
final Set<String> allVulnerabilityNames = dependency.getVulnerabilities().stream().map(Vulnerability::getName).collect(Collectors.toSet());
final Set<String> matchedVulnerabilityNames = dotNetEnhancerAnalyzer.findRelevantVulnerabilities(dependency, resultsForEngine).map(DAVulnerability::getIdentifier).collect(Collectors.toSet());
final Set<String> falsePositiveSuspects = diff(allVulnerabilityNames, matchedVulnerabilityNames);
if(falsePositiveSuspects.isEmpty()){
LOGGER.info("No false positive suspect for dependency {}", dependency);
}else{
final List<String> falsePositiveSuspectsList = new ArrayList<>(new TreeSet<>(falsePositiveSuspects));
LOGGER.warn("The following vulnerabilities for {} were not found by DevAudit, so they are suspected as false positive: {}", dependency, falsePositiveSuspectsList);
}
} catch (IOException e) {
throw new AnalysisException(e);
}
}
private <T> Set<T> diff(Set<T> set1, Set<T> set2) {
final HashSet<T> ts = new HashSet<>(set1);
ts.removeAll(set2);
return Collections.unmodifiableSet(ts);
}
@Override
public String getName() {
return ".NET Analyzer Enhancer False positive warnings";
}
@Override
public AnalysisPhase getAnalysisPhase() {
return AnalysisPhase.FINAL;
}
}

View File

@@ -0,0 +1,9 @@
package com.ysoft.security.odc.dotnet;
import java.io.IOException;
public class UnexpectedFormatException extends IOException {
public UnexpectedFormatException(String msg) {
super(msg);
}
}

View File

@@ -0,0 +1,3 @@
com.ysoft.security.odc.dotnet.DllFindingDotNetEnhancerAnalyzer
com.ysoft.security.odc.dotnet.DevAuditDotNetEnhancerAnalyzer
com.ysoft.security.odc.dotnet.FalsePositiveWarningAnalyzer

View File

@@ -0,0 +1,155 @@
package com.ysoft.security.odc.dotnet;
import org.junit.Test;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Collections;
import java.util.Map;
import java.util.Optional;
import static com.google.common.collect.Sets.newHashSet;
import static java.util.Collections.emptyMap;
import static org.junit.Assert.*;
public class DevAuditResultParserTest {
private final Map<String, DAVulnerableDependency> vulnerableDependencies;
public DevAuditResultParserTest() throws IOException {
try(final BufferedReader in = new BufferedReader(new InputStreamReader(getClass().getResourceAsStream("/out.new2.log")))) {
vulnerableDependencies = DevAuditResultParser.parse(in);
}
}
@Test
public void testEmptyResult() throws IOException {
try(final BufferedReader in = new BufferedReader(new InputStreamReader(getClass().getResourceAsStream("/empty.log")))) {
final Map<String, DAVulnerableDependency> dependencyMap = DevAuditResultParser.parse(in);
assertEquals(emptyMap(), dependencyMap);
}
}
@Test
public void testSingleResult() throws IOException {
try(final BufferedReader in = new BufferedReader(new InputStreamReader(getClass().getResourceAsStream("/single.log")))) {
final Map<String, DAVulnerableDependency> dependencyMap = DevAuditResultParser.parse(in);
assertEquals(1, dependencyMap.size());
assertEquals(newHashSet("LibGit2Sharp:0.20.0"), dependencyMap.keySet());
}
}
@Test
public void testListOfVulnerableDependencies() {
assertEquals(newHashSet(
"Backbone.js:0.3.3",
"Ember:1.4.0-beta1",
"jQuery:1.6",
"jQuery.Migrate:1.1.1",
"jQuery.UI.Combined:1.9.2",
"jQuery.Validation:1.6.0",
"LibGit2Sharp:0.20.0",
"Microsoft.AspNet.Mvc:5.0.0",
"Node.js:4.1.1",
"NServiceBus:3.2.7",
"Twilio.Mvc:3.2.0",
"UmbracoCms:6.0.0"
), vulnerableDependencies.keySet());
}
@Test
public void testName(){
assertEquals(
"UmbracoCms",
vulnerableDependencies.get("UmbracoCms:6.0.0").getName()
);
}
@Test
public void testVersion(){
assertEquals(
"6.0.0",
vulnerableDependencies.get("UmbracoCms:6.0.0").getVersion()
);
}
@Test
public void testVersionWithBeta(){
assertEquals(
"1.4.0-beta1",
vulnerableDependencies.get("Ember:1.4.0-beta1").getVersion()
);
}
@Test
public void testVulnerabilityList(){
assertEquals(
newHashSet(
"CVE-2017-15279",
"CVE-2017-15280",
"OSSINDEX-b23f9aaa-db0a-4eb5-9c57-0eec46017953",
"OSSINDEX-91d9b638-bab4-4ca6-aa2e-80ae05aa1f3e",
"OSSINDEX-b3f3299b-24d7-4ea0-b9c8-617abca38636",
"OSSINDEX-2e8376ab-993f-45ae-8739-b4d4b164d665",
"CVE-2013-4793",
"OSSINDEX-839c2594-0439-4583-aff0-2ac010299de4"
),
vulnerableDependencies.get("UmbracoCms:6.0.0").getVulnerabilities().keySet()
);
}
@Test
public void testCveVulnerabilityDetails(){
final DAVulnerability vulnerability = vulnerableDependencies.get("UmbracoCms:6.0.0").getVulnerabilities().get("CVE-2013-4793");
assertEquals("Improper Authentication", vulnerability.getTitle());
assertEquals("CVE-2013-4793", vulnerability.getIdentifier());
assertEquals(
"The update function in umbraco.webservices/templates/templateService.cs in the TemplateService" +
" component in Umbraco CMS before 6.0.4 does not require authentication, which allows remote" +
" attackers to execute arbitrary ASP.NET code via a crafted SOAP request.",
vulnerability.getDescription()
);
assertEquals(Optional.of("CVE-2013-4793"), vulnerability.getOptionalCve());
assertEquals("6.0.0", vulnerability.getAfectedVersions());
assertEquals("dcf81085-0de1-47a1-ae60-dfa6f18ca0b8", vulnerability.getOssIndexId());
assertEquals("OSS Index", vulnerability.getProvidedBy());
}
@Test
public void testOssIndexVulnerabilityDetails(){
final DAVulnerability vulnerability = vulnerableDependencies.get("UmbracoCms:6.0.0").getVulnerabilities().get("OSSINDEX-b23f9aaa-db0a-4eb5-9c57-0eec46017953");
assertEquals("Multiple vulnerabilities", vulnerability.getTitle());
assertEquals("OSSINDEX-b23f9aaa-db0a-4eb5-9c57-0eec46017953", vulnerability.getIdentifier());
assertEquals(
"> During one of the regular security audits that independent security firms (in this case: MWR Labs) do of the core, a severe security vulnerability was found in the integration web services of Umbraco and we recommend everyone to take immediate action to prevent any exploit.> > ...\n" +
"for now we ask you to remove the following file from all your Umbraco installations:> > /bin/umbraco.webservices.dll> > -- [umbraco.com](https://umbraco.com/blog/security-vulnerability-found-immediate-action-recommended/)",
vulnerability.getDescription()
);
assertEquals(Optional.empty(), vulnerability.getOptionalCve());
assertEquals("b23f9aaa-db0a-4eb5-9c57-0eec46017953", vulnerability.getOssIndexId());
assertEquals("OSS Index", vulnerability.getProvidedBy());
}
@Test
public void testManyLinesVulnerabilityDetails(){
final DAVulnerability vulnerability = vulnerableDependencies.get("LibGit2Sharp:0.20.0").getVulnerabilities().get("OSSINDEX-cfacab46-bdf8-40d4-8d50-06420a9c0013");
assertEquals("Git vulnerability requires git client updates", vulnerability.getTitle());
assertEquals("OSSINDEX-cfacab46-bdf8-40d4-8d50-06420a9c0013", vulnerability.getIdentifier());
assertEquals(
"A critical Git security vulnerability has been announced today, affecting all versions of the official Git client and all related software that interacts with Git repositories, including GitHub for Windows and GitHub for Mac.\n" +
"Because this is a client-side only vulnerability, github.com and GitHub Enterprise are not directly affected.The vulnerability concerns Git and Git-compatible clients that access Git repositories in a case-insensitive or case-normalizing filesystem.\n" +
"An attacker can craft a malicious Git tree that will cause Git to overwrite its own .git/config file when cloning or checking out a repository, leading to arbitrary command execution in the client machine.\n" +
"Git clients running on OS X (HFS+) or any version of Microsoft Windows (NTFS, FAT) are exploitable through this vulnerability.\n" +
"Linux clients are not affected if they run in a case-sensitive filesystem.",
vulnerability.getDescription()
);
assertEquals(Optional.empty(), vulnerability.getOptionalCve());
assertEquals("0.20.0", vulnerability.getAfectedVersions());
assertEquals("cfacab46-bdf8-40d4-8d50-06420a9c0013", vulnerability.getOssIndexId());
assertEquals("OSS Index", vulnerability.getProvidedBy());
}
}

View File

@@ -0,0 +1,65 @@
package com.ysoft.security.odc.dotnet;
import org.junit.Test;
import java.io.*;
import java.nio.file.Files;
import java.nio.file.Path;
import static org.junit.Assert.*;
public class DllAnalyzerTest {
private void assertIsDotNet(String name) throws IOException {
assertTrue(name + " is expected to be a .NET library.", isResourceDotNet(name));
}
private void assertIsNotDotNet(String name) throws IOException {
assertFalse(name + " is not expected to be a .NET library.", isResourceDotNet(name));
}
private boolean isResourceDotNet(String name) throws IOException {
final Path tempFile = Files.createTempFile(null, null);
try (InputStream in = getClass().getResourceAsStream("/dll-samples/"+name)) {
if(in == null){
throw new FileNotFoundException(name);
}
try (FileOutputStream outputStream = new FileOutputStream(tempFile.toFile())) {
final byte[] buffer = new byte[4096];
int size;
while((size = in.read(buffer)) != -1){
outputStream.write(buffer, 0, size);
}
}
return DllAnalyzer.isDotNet(tempFile.toFile());
} finally {
Files.delete(tempFile);
}
}
@Test
public void isDotNet() throws Exception {
// Just take a bunch of real libraries and test it…
assertIsDotNet("AutoMapper.dll");
assertIsDotNet("Google.Protobuf.dll");
assertIsDotNet("BouncyCastle.Crypto.dll");
assertIsDotNet("Microsoft.Owin.Host.SystemWeb.dll");
assertIsDotNet("wix.dll");
assertIsDotNet("Renci.SshNet.dll");
assertIsDotNet("Renci.SshNet.Silverlight.dll");
assertIsDotNet("EntityFramework.dll");
assertIsDotNet("Newtonsoft.Json.dll");
assertIsNotDotNet("grpc_csharp_ext.x64.dll");
assertIsNotDotNet("HanSoneConnect.dll");
assertIsNotDotNet("lilli.dll");
assertIsNotDotNet("msvcr90.dll");
assertIsNotDotNet("python27.dll");
assertIsNotDotNet("sqlceqp40.dll");
assertIsNotDotNet("SyncBraille.dll");
assertIsNotDotNet("VSDebugUI.dll");
assertIsNotDotNet("winterop.dll");
// And also some non-DLL file
assertIsNotDotNet("../out.new2.log");
}
}

View File

@@ -0,0 +1 @@
analyze-projects

View File

@@ -0,0 +1,34 @@
#!/bin/bash
# safety settings
set -u
set -e
set -o pipefail
# Generates DA reports for unit tests.
if [ $# != 1 ]; then
echo "Usage: $0 <path-to-DevAudit>"
exit 1
fi
if [ "$(basename "$0")" == analyze-missing-projects ]; then
ONLY_MISSING=1
else
ONLY_MISSING=0
fi
DA_PATH=$1
for i in out.new2 empty single two-versions two-versions-two-vulns; do
if [ -e "$i.log" ] && [ "$ONLY_MISSING" == 1 ]; then
echo "Skipping $i"
else
echo "Generating $i…"
if ! "$DA_PATH/devaudit.exe" nuget --file "projects/$i.config" > "$i.log.wip"; then # -n
echo "Failed to generate $i"
exit 1
fi
sync
mv "$i.log.wip" "$i.log"
fi
done

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -0,0 +1,19 @@
_____ _______ __ __ __
| \ .-----..--.--.| _ |.--.--..--| ||__|| |_
| -- || -__|| | || || | || _ || || _|
|_____/ |_____| \___/ |___|___||_____||_____||__||____|
v3.3.0.0
08:25:19<01> [AUDIT] [SUCCESS] Detected operating system of environment is debian.
08:25:19<01> [AUDIT] [SUCCESS] Detected operating system version of environment is 10.1.
08:25:19<01> [HOST] [INFO] Using OSS Index as default package vulnerabilities data source for NuGet package source.
08:25:19<01> [AUDIT] [STATUS] Scanning NuGet packages.
Scanning NuGet packages...Scanning NuGet packages.../ 08:25:19<01> [AUDIT] [SUCCESS] Scanned 0 NuGet packages.
08:25:19<01> [AUDIT] [INFO] Not reporting package source audit with zero vulnerabilities.
Package Source Audit Results
============================
0 total vulnerabilities found in NuGet package source audit. Total time for audit: 250 ms.

View File

@@ -0,0 +1,424 @@
_____ _______ __ __ __
| \ .-----..--.--.| _ |.--.--..--| ||__|| |_
| -- || -__|| | || || | || _ || || _|
|_____/ |_____| \___/ |___|___||_____||_____||__||____|
v3.3.0.0
08:25:18<01> [AUDIT] [SUCCESS] Detected operating system of environment is debian.
08:25:18<01> [AUDIT] [SUCCESS] Detected operating system version of environment is 10.1.
08:25:18<01> [HOST] [INFO] Using OSS Index as default package vulnerabilities data source for NuGet package source.
08:25:19<01> [AUDIT] [STATUS] Scanning NuGet packages.
Scanning NuGet packages...Scanning NuGet packages.../ 08:25:19<01> [AUDIT] [SUCCESS] Scanned 33 NuGet packages.
Searching OSS Index for vulnerabilities for 33 packages... Waiting.....- 08:25:19<04> [HOST] [SUCCESS] Got 47 total vulnerabilities for 33 packages from data source OSS Index.
\|/ 08:25:19<05> [AUDIT] [INFO] Evaluated 47 vulnerabilities with 47 matches to package version in 182 ms.
Package Source Audit Results
============================
47 total vulnerabilities found in NuGet package source audit. Total time for audit: 536 ms.
[1/33] Node.js [VULNERABLE] 17 known vulnerabilities, 17 affecting installed package version(s): [4.1.1]
--[1/17] [CVE-2016-6306] Out-of-bounds Read
--Description:
--The certificate parser in OpenSSL before 1.0.1u and 1.0.2 before 1.0.2i might allow remote attackers to cause a denial of service (out-of-bounds read) via crafted certificate operations, related to s3_clnt.c and s3_srvr.c.
4.1.1
--Id: 5cea2262-c893-45eb-9969-fc71d7d847c0
--Reference: https://ossindex.sonatype.org/vuln/5cea2262-c893-45eb-9969-fc71d7d847c0
--Provided by: OSS Index
--[2/17] [CVE-2016-6304] Resource Management Errors
--Description:
--Multiple memory leaks in t1_lib.c in OpenSSL before 1.0.1u, 1.0.2 before 1.0.2i, and 1.1.0 before 1.1.0a allow remote attackers to cause a denial of service (memory consumption) via large OCSP Status Request extensions.
4.1.1
--Id: 0aa6a4fb-b1e9-4ca1-be73-484b62190de7
--Reference: https://ossindex.sonatype.org/vuln/0aa6a4fb-b1e9-4ca1-be73-484b62190de7
--Provided by: OSS Index
--[3/17] [CVE-2016-6303] Integer overflow in the MDC2&#95;Update function in crypto/mdc2/mdc2dgst.c in OpenSS...
--Description:
--Integer overflow in the MDC2_Update function in crypto/mdc2/mdc2dgst.c in OpenSSL before 1.1.0 allows remote attackers to cause a denial of service (out-of-bounds write and application crash) or possibly have unspecified other impact via unknown vectors.
4.1.1
--Id: fbed5655-5b6e-479b-9fba-f407df5c1382
--Reference: https://ossindex.sonatype.org/vuln/fbed5655-5b6e-479b-9fba-f407df5c1382
--Provided by: OSS Index
--[4/17] [CVE-2016-3956] Information Exposure
--Description:
--The CLI in npm before 2.15.1 and 3.x before 3.8.3, as used in Node.js 0.10 before 0.10.44, 0.12 before 0.12.13, 4 before 4.4.2, and 5 before 5.10.0, includes bearer tokens with arbitrary requests, which allows remote HTTP servers to obtain sensitive information by reading Authorization headers.
4.1.1
--Id: d11982e3-0956-4b69-867b-9e4c77eb0444
--Reference: https://ossindex.sonatype.org/vuln/d11982e3-0956-4b69-867b-9e4c77eb0444
--Provided by: OSS Index
--[5/17] [CVE-2015-8855] Resource Management Errors
--Description:
--The semver package before 4.3.2 for Node.js allows attackers to cause a denial of service (CPU consumption) via a long version string, aka a "regular expression denial of service (ReDoS)."
4.1.1
--Id: 630522d1-8cab-41ea-9c11-c4978a195661
--Reference: https://ossindex.sonatype.org/vuln/630522d1-8cab-41ea-9c11-c4978a195661
--Provided by: OSS Index
--[6/17] [CVE-2016-2086] Improper Input Validation
--Description:
--Node.js 0.10.x before 0.10.42, 0.12.x before 0.12.10, 4.x before 4.3.0, and 5.x before 5.6.0 allow remote attackers to conduct HTTP request smuggling attacks via a crafted Content-Length HTTP header.
4.1.1
--Id: 2991a6ea-a02e-4552-a7f4-e2274ebbdc80
--Reference: https://ossindex.sonatype.org/vuln/2991a6ea-a02e-4552-a7f4-e2274ebbdc80
--Provided by: OSS Index
--[7/17] [CVE-2016-2216] Improper Input Validation
--Description:
--The HTTP header parsing code in Node.js 0.10.x before 0.10.42, 0.11.6 through 0.11.16, 0.12.x before 0.12.10, 4.x before 4.3.0, and 5.x before 5.6.0 allows remote attackers to bypass an HTTP response-splitting protection mechanism via UTF-8 encoded Unicode characters in the HTTP header, as demonstrated by %c4%8d%c4%8a.
4.1.1
--Id: 1cf77d11-50d1-4dd7-abed-1f3fac878518
--Reference: https://ossindex.sonatype.org/vuln/1cf77d11-50d1-4dd7-abed-1f3fac878518
--Provided by: OSS Index
--[8/17] [CVE-2017-11499] Improper Input Validation
--Description:
--Node.js v4.0 through v4.8.3, all versions of v5.x, v6.0 through v6.11.0, v7.0 through v7.10.0, and v8.0 through v8.1.3 was susceptible to hash flooding remote DoS attacks as the HashTable seed was constant across a given released version of Node.js.
This was a result of building with V8 snapshots enabled by default which caused the initially randomized seed to be overwritten on startup.
4.1.1
--Id: 64b384bb-02dd-4fd0-a5ce-7ccd98fc1542
--Reference: https://ossindex.sonatype.org/vuln/64b384bb-02dd-4fd0-a5ce-7ccd98fc1542
--Provided by: OSS Index
--[9/17] [CVE-2015-7384] Uncontrolled Resource Consumption ("Resource Exhaustion")
--Description:
--Node.js 4.0.0, 4.1.0, and 4.1.1 allows remote attackers to cause a denial of service.
4.1.1
--Id: 89ed4a5d-becb-4d41-9ebc-d46b249f37de
--Reference: https://ossindex.sonatype.org/vuln/89ed4a5d-becb-4d41-9ebc-d46b249f37de
--Provided by: OSS Index
--[10/17] [CVE-2016-5325] Improper Neutralization of CRLF Sequences in HTTP Headers ("HTTP Response Splitting")
--Description:
--CRLF injection vulnerability in the ServerResponse#writeHead function in Node.js 0.10.x before 0.10.47, 0.12.x before 0.12.16, 4.x before 4.6.0, and 6.x before 6.7.0 allows remote attackers to inject arbitrary HTTP headers and conduct HTTP response splitting attacks via the reason argument.
4.1.1
--Id: 03383b53-8d4f-4012-a2e9-6eefe01a7be1
--Reference: https://ossindex.sonatype.org/vuln/03383b53-8d4f-4012-a2e9-6eefe01a7be1
--Provided by: OSS Index
--[11/17] [CVE-2016-7099] Data Handling
--Description:
--The tls.checkServerIdentity function in Node.js 0.10.x before 0.10.47, 0.12.x before 0.12.16, 4.x before 4.6.0, and 6.x before 6.7.0 does not properly handle wildcards in name fields of X.509 certificates, which allows man-in-the-middle attackers to spoof servers via a crafted certificate.
4.1.1
--Id: 45994d74-44e3-4e1c-8ba4-384a8bd6c6a8
--Reference: https://ossindex.sonatype.org/vuln/45994d74-44e3-4e1c-8ba4-384a8bd6c6a8
--Provided by: OSS Index
--[12/17] [CVE-2018-7159] Improper Input Validation
--Description:
--The HTTP parser in all current versions of Node.js ignores spaces in the `Content-Length` header, allowing input such as `Content-Length: 1 2` to be interpreted as having a value of `12`.
The HTTP specification does not allow for spaces in the `Content-Length` value and the Node.js HTTP parser has been brought into line on this particular difference.
The security risk of this flaw to Node.js users is considered to be VERY LOW as it is difficult, and may be impossible, to craft an attack that makes use of this flaw in a way that could not already be achieved by supplying an incorrect value for `Content-Length`.
Vulnerabilities may exist in user-code that make incorrect assumptions about the potential accuracy of this value compared to the actual length of the data supplied.
Node.js users crafting lower-level HTTP utilities are advised to re-check the length of any input supplied after parsing is complete.
4.1.1
--Id: 9cc431eb-6510-4ec8-ada8-47780fbf287c
--Reference: https://ossindex.sonatype.org/vuln/9cc431eb-6510-4ec8-ada8-47780fbf287c
--Provided by: OSS Index
--[13/17] [CVE-2018-7158] Improper Input Validation
--Description:
--The `'path'` module in the Node.js 4.x release line contains a potential regular expression denial of service (ReDoS) vector.
The code in question was replaced in Node.js 6.x and later so this vulnerability only impacts all versions of Node.js 4.x.
The regular expression, `splitPathRe`, used within the `'path'` module for the various path parsing functions, including `path.dirname()`, `path.extname()` and `path.parse()` was structured in such a way as to allow an attacker to craft a string, that when passed through one of these functions, could take a significant amount of time to evaluate, potentially leading to a full denial of service.
4.1.1
--Id: b31798b7-0bf8-464b-a53f-5877a2a5a915
--Reference: https://ossindex.sonatype.org/vuln/b31798b7-0bf8-464b-a53f-5877a2a5a915
--Provided by: OSS Index
--[14/17] [CVE-2018-5407] Information Exposure
--Description:
--Simultaneous Multi-threading (SMT) in processors can enable local users to exploit software vulnerable to timing attacks via a side-channel timing attack on 'port contention'.
4.1.1
--Id: 56623b2d-6166-4edb-ace2-91bf525f44ff
--Reference: https://ossindex.sonatype.org/vuln/56623b2d-6166-4edb-ace2-91bf525f44ff
--Provided by: OSS Index
--[15/17] [CVE-2018-12115] In all versions of Node.js prior to 6.14.4, 8.11.4 and 10.9.0 when used with UCS...
--Description:
--In all versions of Node.js prior to 6.14.4, 8.11.4 and 10.9.0 when used with UCS-2 encoding (recognized by Node.js under the names `'ucs2'`, `'ucs-2'`, `'utf16le'` and `'utf-16le'`), `Buffer#write()` can be abused to write outside of the bounds of a single `Buffer`.
Writes that start from the second-to-last position of a buffer cause a miscalculation of the maximum length of the input bytes to be written.
4.1.1
--Id: 0f718d9c-5cca-44f6-8ca2-2cafe5bfe406
--Reference: https://ossindex.sonatype.org/vuln/0f718d9c-5cca-44f6-8ca2-2cafe5bfe406
--Provided by: OSS Index
--[16/17] CWE-770: Allocation of Resources Without Limits or Throttling
--Description:
--The software allocates a reusable resource or group of resources on behalf of an actor without imposing any restrictions on how many resources can be allocated, in violation of the intended security policy for that actor.
4.1.1
--Id: da7a1fb7-07c1-4066-a3b4-7c4d88823517
--Reference: https://ossindex.sonatype.org/vuln/da7a1fb7-07c1-4066-a3b4-7c4d88823517
--Provided by: OSS Index
--[17/17] [CVE-2019-5739] Uncontrolled Resource Consumption ("Resource Exhaustion")
--Description:
--Keep-alive HTTP and HTTPS connections can remain open and inactive for up to 2 minutes in Node.js 6.16.0 and earlier.
Node.js 8.0.0 introduced a dedicated server.keepAliveTimeout which defaults to 5 seconds.
The behavior in Node.js 6.16.0 and earlier is a potential Denial of Service (DoS) attack vector.
Node.js 6.17.0 introduces server.keepAliveTimeout and the 5-second default.
4.1.1
--Id: fdd192f7-06c4-4d33-add1-684a14e45435
--Reference: https://ossindex.sonatype.org/vuln/fdd192f7-06c4-4d33-add1-684a14e45435
--Provided by: OSS Index
[2/33] UmbracoCms [VULNERABLE] 8 known vulnerabilities, 8 affecting installed package version(s): [6.0.0]
--[1/8] [CVE-2017-15279] Improper Neutralization of Input During Web Page Generation ("Cross-site Scripting")
--Description:
--Cross-site scripting (XSS) vulnerability in Umbraco CMS before 7.7.3 allows remote attackers to inject arbitrary web script or HTML via the "page name" (aka nodename) parameter during the creation of a new page, related to Umbraco.Web.UI/umbraco/dialogs/Publish.aspx.cs and Umbraco.Web/umbraco.presentation/umbraco/dialogs/notifications.aspx.cs.
6.0.0
--Id: 13e34c16-bf2c-497d-9253-706185905129
--Reference: https://ossindex.sonatype.org/vuln/13e34c16-bf2c-497d-9253-706185905129
--Provided by: OSS Index
--[2/8] [CVE-2017-15280] Improper Restriction of XML External Entity Reference ("XXE")
--Description:
--XML external entity (XXE) vulnerability in Umbraco CMS before 7.7.3 allows attackers to obtain sensitive information by reading files on the server or sending TCP requests to intranet hosts (aka SSRF), related to Umbraco.Web/umbraco.presentation/umbraco/dialogs/importDocumenttype.aspx.cs.
6.0.0
--Id: 28e0a953-d001-48b2-acc3-39cedd595721
--Reference: https://ossindex.sonatype.org/vuln/28e0a953-d001-48b2-acc3-39cedd595721
--Provided by: OSS Index
--[3/8] Multiple vulnerabilities
--Description:
--> During one of the regular security audits that independent security firms (in this case: MWR Labs) do of the core, a severe security vulnerability was found in the integration web services of Umbraco and we recommend everyone to take immediate action to prevent any exploit.> > ...
for now we ask you to remove the following file from all your Umbraco installations:> > /bin/umbraco.webservices.dll> > -- [umbraco.com](https://umbraco.com/blog/security-vulnerability-found-immediate-action-recommended/)
6.0.0
--Id: b23f9aaa-db0a-4eb5-9c57-0eec46017953
--Reference: https://ossindex.sonatype.org/vuln/b23f9aaa-db0a-4eb5-9c57-0eec46017953
--Provided by: OSS Index
--[4/8] CWE-79: Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting')
--Description:
--The software does not neutralize or incorrectly neutralizes user-controllable input before it is placed in output that is used as a web page that is served to other users.
6.0.0
--Id: 91d9b638-bab4-4ca6-aa2e-80ae05aa1f3e
--Reference: https://ossindex.sonatype.org/vuln/91d9b638-bab4-4ca6-aa2e-80ae05aa1f3e
--Provided by: OSS Index
--[5/8] CWE-79: Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting')
--Description:
--The software does not neutralize or incorrectly neutralizes user-controllable input before it is placed in output that is used as a web page that is served to other users.
6.0.0
--Id: b3f3299b-24d7-4ea0-b9c8-617abca38636
--Reference: https://ossindex.sonatype.org/vuln/b3f3299b-24d7-4ea0-b9c8-617abca38636
--Provided by: OSS Index
--[6/8] CWE-79: Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting')
--Description:
--The software does not neutralize or incorrectly neutralizes user-controllable input before it is placed in output that is used as a web page that is served to other users.
6.0.0
--Id: 2e8376ab-993f-45ae-8739-b4d4b164d665
--Reference: https://ossindex.sonatype.org/vuln/2e8376ab-993f-45ae-8739-b4d4b164d665
--Provided by: OSS Index
--[7/8] [CVE-2013-4793] Improper Authentication
--Description:
--The update function in umbraco.webservices/templates/templateService.cs in the TemplateService component in Umbraco CMS before 6.0.4 does not require authentication, which allows remote attackers to execute arbitrary ASP.NET code via a crafted SOAP request.
6.0.0
--Id: dcf81085-0de1-47a1-ae60-dfa6f18ca0b8
--Reference: https://ossindex.sonatype.org/vuln/dcf81085-0de1-47a1-ae60-dfa6f18ca0b8
--Provided by: OSS Index
--[8/8] CWE-79: Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting')
--Description:
--The software does not neutralize or incorrectly neutralizes user-controllable input before it is placed in output that is used as a web page that is served to other users.
6.0.0
--Id: 839c2594-0439-4583-aff0-2ac010299de4
--Reference: https://ossindex.sonatype.org/vuln/839c2594-0439-4583-aff0-2ac010299de4
--Provided by: OSS Index
[3/33] jQuery [VULNERABLE] 7 known vulnerabilities, 7 affecting installed package version(s): [1.6]
--[1/7] CWE-79: Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting')
--Description:
--The software does not neutralize or incorrectly neutralizes user-controllable input before it is placed in output that is used as a web page that is served to other users.
1.6
--Id: 52f593c8-7729-435c-b9df-a7bb9ded8589
--Reference: https://ossindex.sonatype.org/vuln/52f593c8-7729-435c-b9df-a7bb9ded8589
--Provided by: OSS Index
--[2/7] [CVE-2011-4969] Improper Neutralization of Input During Web Page Generation ("Cross-site Scripting")
--Description:
--Cross-site scripting (XSS) vulnerability in jQuery before 1.6.3, when using location.hash to select elements, allows remote attackers to inject arbitrary web script or HTML via a crafted tag.
1.6
--Id: fe8b44f2-8604-4d1a-95be-ffce5f6f8f97
--Reference: https://ossindex.sonatype.org/vuln/fe8b44f2-8604-4d1a-95be-ffce5f6f8f97
--Provided by: OSS Index
--[3/7] [CVE-2015-9251] Improper Neutralization of Input During Web Page Generation ("Cross-site Scripting")
--Description:
--jQuery before 3.0.0 is vulnerable to Cross-site Scripting (XSS) attacks when a cross-domain Ajax request is performed without the dataType option, causing text/javascript responses to be executed.
1.6
--Id: 3b3ba2f8-9c2c-4afe-b593-75c6b3fd4bb7
--Reference: https://ossindex.sonatype.org/vuln/3b3ba2f8-9c2c-4afe-b593-75c6b3fd4bb7
--Provided by: OSS Index
--[4/7] [CVE-2012-6708] Improper Neutralization of Input During Web Page Generation ("Cross-site Scripting")
--Description:
--jQuery before 1.9.0 is vulnerable to Cross-site Scripting (XSS) attacks.
The jQuery(strInput) function does not differentiate selectors from HTML in a reliable fashion.
In vulnerable versions, jQuery determined whether the input was HTML by looking for the '<' character anywhere in the string, giving attackers more flexibility when attempting to construct a malicious payload.
In fixed versions, jQuery only deems the input to be HTML if it explicitly starts with the '<' character, limiting exploitability only to attackers who can control the beginning of a string, which is far less common.
1.6
--Id: b510dae9-a933-4169-b010-0325829abf42
--Reference: https://ossindex.sonatype.org/vuln/b510dae9-a933-4169-b010-0325829abf42
--Provided by: OSS Index
--[5/7] CWE-79: Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting')
--Description:
--The software does not neutralize or incorrectly neutralizes user-controllable input before it is placed in output that is used as a web page that is served to other users.
1.6
--Id: bb07990f-5984-4107-a7ee-27d0c09a1698
--Reference: https://ossindex.sonatype.org/vuln/bb07990f-5984-4107-a7ee-27d0c09a1698
--Provided by: OSS Index
--[6/7] [CVE-2019-11358] Improper Neutralization of Input During Web Page Generation ("Cross-site Scripting")
--Description:
--jQuery before 3.4.0, as used in Drupal, Backdrop CMS, and other products, mishandles jQuery.extend(true, {}, ...) because of Object.prototype pollution.
If an unsanitized source object contained an enumerable __proto__ property, it could extend the native Object.prototype.
1.6
--Id: 11b6563a-ead6-4040-83e5-455f36519d1b
--Reference: https://ossindex.sonatype.org/vuln/11b6563a-ead6-4040-83e5-455f36519d1b
--Provided by: OSS Index
--[7/7] CWE-79: Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting')
--Description:
--The software does not neutralize or incorrectly neutralizes user-controllable input before it is placed in output that is used as a web page that is served to other users.
1.6
--Id: 5143404a-0e8c-420a-aef1-dccfd1bb3ea4
--Reference: https://ossindex.sonatype.org/vuln/5143404a-0e8c-420a-aef1-dccfd1bb3ea4
--Provided by: OSS Index
[4/33] jQuery.UI.Combined [VULNERABLE] 3 known vulnerabilities, 3 affecting installed package version(s): [1.9.2]
--[1/3] [CVE-2016-7103] Improper Neutralization of Input During Web Page Generation ("Cross-site Scripting")
--Description:
--Cross-site scripting (XSS) vulnerability in jQuery UI before 1.12.0 might allow remote attackers to inject arbitrary web script or HTML via the closeText parameter of the dialog function.
1.9.2
--Id: 762dfcfb-790c-4c7e-9ef9-ec6aaf55b963
--Reference: https://ossindex.sonatype.org/vuln/762dfcfb-790c-4c7e-9ef9-ec6aaf55b963
--Provided by: OSS Index
--[2/3] [CVE-2010-5312] Improper Neutralization of Input During Web Page Generation ("Cross-site Scripting")
--Description:
--Cross-site scripting (XSS) vulnerability in jquery.ui.dialog.js in the Dialog widget in jQuery UI before 1.10.0 allows remote attackers to inject arbitrary web script or HTML via the title option.
1.9.2
--Id: a393fe48-486d-4ea4-bdd8-c7414c2a2aac
--Reference: https://ossindex.sonatype.org/vuln/a393fe48-486d-4ea4-bdd8-c7414c2a2aac
--Provided by: OSS Index
--[3/3] CWE-79: Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting')
--Description:
--The software does not neutralize or incorrectly neutralizes user-controllable input before it is placed in output that is used as a web page that is served to other users.
1.9.2
--Id: aac65754-b75e-49c2-a2dc-62ce9a556a6a
--Reference: https://ossindex.sonatype.org/vuln/aac65754-b75e-49c2-a2dc-62ce9a556a6a
--Provided by: OSS Index
[5/33] Backbone.js [VULNERABLE] 3 known vulnerabilities, 3 affecting installed package version(s): [0.3.3]
--[1/3] CWE-79: Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting')
--Description:
--The software does not neutralize or incorrectly neutralizes user-controllable input before it is placed in output that is used as a web page that is served to other users.
0.3.3
--Id: edc967e6-699d-4dd3-9f20-0496a1f1d1d8
--Reference: https://ossindex.sonatype.org/vuln/edc967e6-699d-4dd3-9f20-0496a1f1d1d8
--Provided by: OSS Index
--[2/3] Cross Site Scripting (XSS) in Todos example
--Description:
--The supplied "Todos" example does not escape its data, making it possible to inject and execute JavaScript code.
0.3.3
--Id: d8a5f278-b2b9-4b5b-8628-1721907b12e7
--Reference: https://ossindex.sonatype.org/vuln/d8a5f278-b2b9-4b5b-8628-1721907b12e7
--Provided by: OSS Index
--[3/3] CWE-79: Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting')
--Description:
--The software does not neutralize or incorrectly neutralizes user-controllable input before it is placed in output that is used as a web page that is served to other users.
0.3.3
--Id: dbe5b45e-0faf-495f-857f-732a6a4733c5
--Reference: https://ossindex.sonatype.org/vuln/dbe5b45e-0faf-495f-857f-732a6a4733c5
--Provided by: OSS Index
[6/33] jQuery.Migrate [VULNERABLE] 2 known vulnerabilities, 2 affecting installed package version(s): [1.1.1]
--[1/2] CWE-79: Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting')
--Description:
--The software does not neutralize or incorrectly neutralizes user-controllable input before it is placed in output that is used as a web page that is served to other users.
1.1.1
--Id: 07546a92-aaae-4213-b266-3183aa3a14d7
--Reference: https://ossindex.sonatype.org/vuln/07546a92-aaae-4213-b266-3183aa3a14d7
--Provided by: OSS Index
--[2/2] Cross-site-scripting (XSS) hole
--Description:
--The major change in this version is that we?ve re-closed a cross-site-scripting (XSS) hole that was fixed in jQuery 1.7 and reintroduced by the plugin.
Essentially, any use of $("#...
<tag>") will now always be interpreted as a selector and not as HTML.
This is due to some developers using $(window.location.hash) and not realizing that an attacker can often control the contents of the hash on the URL to run code.
Always assume that any data you get from an external source may contain harmful content!
1.1.1
--Id: 18d27b7e-8423-421b-ba23-c9c0b502b466
--Reference: https://ossindex.sonatype.org/vuln/18d27b7e-8423-421b-ba23-c9c0b502b466
--Provided by: OSS Index
[7/33] Ember [VULNERABLE] 2 known vulnerabilities, 2 affecting installed package version(s): [1.4.0-beta1]
--[1/2] [CVE-2014-0013] Improper Neutralization of Input During Web Page Generation ("Cross-site Scripting")
--Description:
--Ember.js 1.0.x before 1.0.1, 1.1.x before 1.1.3, 1.2.x before 1.2.1, 1.3.x before 1.3.1, and 1.4.x before 1.4.0-beta.2 allows remote attackers to conduct cross-site scripting (XSS) attacks by leveraging an application that contains templates whose context is set to a user-supplied primitive value and also contain the `{{this}}` special Handlebars variable.
1.4.0-beta1
--Id: 38928c97-9c12-435c-b852-b854ffc2d213
--Reference: https://ossindex.sonatype.org/vuln/38928c97-9c12-435c-b852-b854ffc2d213
--Provided by: OSS Index
--[2/2] [CVE-2014-0014] Improper Neutralization of Input During Web Page Generation ("Cross-site Scripting")
--Description:
--Ember.js 1.0.x before 1.0.1, 1.1.x before 1.1.3, 1.2.x before 1.2.1, 1.3.x before 1.3.1, and 1.4.x before 1.4.0-beta.2 allows remote attackers to conduct cross-site scripting (XSS) attacks by leveraging an application using the "{{group}}" Helper and a crafted payload.
1.4.0-beta1
--Id: 8207aae5-0ec7-4ad2-9a59-6422452278d3
--Reference: https://ossindex.sonatype.org/vuln/8207aae5-0ec7-4ad2-9a59-6422452278d3
--Provided by: OSS Index
[8/33] LibGit2Sharp [VULNERABLE] 1 known vulnerabilities, 1 affecting installed package version(s): [0.20.0]
--[1/1] Git vulnerability requires git client updates
--Description:
--A critical Git security vulnerability has been announced today, affecting all versions of the official Git client and all related software that interacts with Git repositories, including GitHub for Windows and GitHub for Mac.
Because this is a client-side only vulnerability, github.com and GitHub Enterprise are not directly affected.The vulnerability concerns Git and Git-compatible clients that access Git repositories in a case-insensitive or case-normalizing filesystem.
An attacker can craft a malicious Git tree that will cause Git to overwrite its own .git/config file when cloning or checking out a repository, leading to arbitrary command execution in the client machine.
Git clients running on OS X (HFS+) or any version of Microsoft Windows (NTFS, FAT) are exploitable through this vulnerability.
Linux clients are not affected if they run in a case-sensitive filesystem.
0.20.0
--Id: cfacab46-bdf8-40d4-8d50-06420a9c0013
--Reference: https://ossindex.sonatype.org/vuln/cfacab46-bdf8-40d4-8d50-06420a9c0013
--Provided by: OSS Index
[9/33] NServiceBus [VULNERABLE] 1 known vulnerabilities, 1 affecting installed package version(s): [3.2.7]
--[1/1] Missing encryption in systems which use WireEncryptedString on nested structures
--Description:
--Systems which use WireEncryptedString on nested structures in their messages did not have that data encrypted.
3.2.7
--Id: ddfed5c0-3bc2-4f2a-b864-42cf702ba36c
--Reference: https://ossindex.sonatype.org/vuln/ddfed5c0-3bc2-4f2a-b864-42cf702ba36c
--Provided by: OSS Index
[10/33] Twilio.Mvc [VULNERABLE] 1 known vulnerabilities, 1 affecting installed package version(s): [3.2.0]
--[1/1] XML External Entity (XXE)
--Description:
--TwiMLResult provides an additional (unused by the library)constructor that accepts a string value and will use`XDocument.Parse()` to turn it into an XML Document.Older versions of .Net allow DOCTYPE defined ENTITYs by default.Careless use of this class (passing in unsanitized user data) isvulnerable to an XXE Attack.
3.2.0
--Id: 07908746-dea1-4898-9334-1d2421e26c92
--Reference: https://ossindex.sonatype.org/vuln/07908746-dea1-4898-9334-1d2421e26c92
--Provided by: OSS Index
[11/33] Microsoft.AspNet.Mvc [VULNERABLE] 1 known vulnerabilities, 1 affecting installed package version(s): [5.0.0]
--[1/1] [CVE-2014-4075] Improper Neutralization of Input During Web Page Generation ("Cross-site Scripting")
--Description:
--Cross-site scripting (XSS) vulnerability in System.Web.Mvc.dll in Microsoft ASP.NET Model View Controller (MVC) 2.0 through 5.1 allows remote attackers to inject arbitrary web script or HTML via a crafted web page, aka "MVC XSS Vulnerability."
5.0.0
--Id: b81ac3fd-298b-4daf-a462-d92c9d742b9e
--Reference: https://ossindex.sonatype.org/vuln/b81ac3fd-298b-4daf-a462-d92c9d742b9e
--Provided by: OSS Index
[12/33] jQuery.Validation [VULNERABLE] 1 known vulnerabilities, 1 affecting installed package version(s): [1.6.0]
--[1/1] XSS attacks against included PHP files
--Description:
--These issues come down to XSS "attacks" via the included php files.
Not a big deal really, though instead of trying to patch those files, I'd rather get rid of them completely.
The unit tests already make use of mockjax to get rid of actual server side scripts, we should be able to do that for the other demo php files as well.
1.6.0
--Id: 10aaf64c-51ed-40ec-9671-d47118efc37f
--Reference: https://ossindex.sonatype.org/vuln/10aaf64c-51ed-40ec-9671-d47118efc37f
--Provided by: OSS Index
[13/33] AntiXSS no known vulnerabilities.
[14/33] Bytescout.Spreadsheet no known vulnerabilities.
[15/33] Aspose.Pdf no known vulnerabilities.
[16/33] Microsoft.Data.Services no known vulnerabilities.
[17/33] WiX.Toolset.UnofficialFork no known vulnerabilities.
[18/33] Premotion.AspNet.AppHarbor.Integration no known vulnerabilities.
[19/33] Microsoft.IdentityModel.Tokens no known vulnerabilities.
[20/33] Newtonsoft.Json no known vulnerabilities.
[21/33] EntityFramework no known vulnerabilities.
[22/33] AutoMapper no known vulnerabilities.
[23/33] log4net no known vulnerabilities.
[24/33] Microsoft.Owin.Host.SystemWeb no known vulnerabilities.
[25/33] Microsoft.AspNet.SignalR no known vulnerabilities.
[26/33] System.Data.SQLite no known vulnerabilities.
[27/33] Dapper no known vulnerabilities.
[28/33] System.Net.Http no known vulnerabilities.
[29/33] Microsoft.Net.Http no known vulnerabilities.
[30/33] SSH.NET no known vulnerabilities.
[31/33] Microsoft.jQuery.Unobtrusive.Ajax no known vulnerabilities.
[32/33] Microsoft.Owin.Security no known vulnerabilities.
[33/33] chocolatey no known vulnerabilities.
Vulnerabilities Data Providers
==============================
OSS Index https://ossindex.sonatype.org OSS Index is a free index of software information, focusing on vulnerabilities. The data has been made available to the community through a REST API as well as several open source tools. Particular focus is being made on software packages, both those used for development libraries as well as installation packages.

View File

@@ -0,0 +1,3 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
</packages>

View File

@@ -0,0 +1,48 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<!-- Mostly from https://github.com/OWASP/SafeNuGet/blob/master/feed/unsafepackages.xml -->
<!-- possible version descriptors are version, before, beforeOrAt, after, afterOrAt -->
<package id="AntiXSS" version="4.2.1" />
<package id="Bytescout.Spreadsheet" version="2.8.5.1639" />
<package id="Aspose.Pdf" version="7.3.0" />
<package id="LibGit2Sharp" version="0.20.0" />
<package id="NServiceBus" version="3.2.7" />
<package id="Microsoft.Data.Services" version="5.0.0.50403" />
<!-- <package id="MvvmLight" before="4.1.26.0" /> -->
<package id="UmbracoCms" version="6.0.0" />
<!-- <package id="UmbracoCms" version="4.5.0" /> -->
<package id="jQuery.Migrate" version="1.1.1"/>
<package id="jQuery" version="1.6" />
<package id="jQuery.UI.Combined" version="1.9.2" />
<package id="Ember" version="1.4.0-beta1" />
<!-- <package id="Ember" version="1.0.0-rc60" /> -->
<package id="Backbone.js" version="0.3.3" />
<!-- <package id="mustache.js" before="0.3.1" infoUri="https://github.com/janl/mustache.js/issues/112" /> -->
<!-- <package id="GleamTech.Core" before="1.0.6" infoUri="https://www.nuget.org/packages/GleamTech.Core/" /> -->
<package id="WiX.Toolset.UnofficialFork" version="3.10.1" />
<!-- <package id="bzip2.v100" before="1.0.6" infoUri="https://www.nuget.org/packages/bzip2.v100/" /> -->
<!-- <package id="FileUltimate" before="5.0.7" infoUri="https://www.nuget.org/packages/FileUltimate/5.0.7" /> -->
<package id="Twilio.Mvc" version="3.2.0" />
<package id="Node.js" version="4.1.1" />
<package id="Premotion.AspNet.AppHarbor.Integration" version="0.2.0" />
<package id="Microsoft.IdentityModel.Tokens" version="5.1.1" />
<package id="Newtonsoft.Json" version="6.0.6" />
<package id="EntityFramework" version="6.0.0" />
<package id="AutoMapper" version="4.0.4" />
<package id="Microsoft.AspNet.Mvc" version="5.0.0" />
<package id="log4net" version="2.0.0" />
<package id="Microsoft.Owin.Host.SystemWeb" version="2.0.0" />
<package id="Microsoft.AspNet.SignalR" version="2.0.1" />
<package id="System.Data.SQLite" version="1.0.105.1" />
<package id="jQuery.Validation" version="1.6.0" />
<package id="Dapper" version="1.0.0" />
<package id="System.Net.Http" version="2.0.20710" />
<package id="Microsoft.Net.Http" version="2.0.20505" />
<package id="SSH.NET" version="2012.20.12" />
<package id="Microsoft.jQuery.Unobtrusive.Ajax" version="2.0.20505" />
<package id="Microsoft.Owin.Security" version="1.1.0-beta1" />
<package id="chocolatey" version="0.9.10" />
</packages>

View File

@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="LibGit2Sharp" version="0.20.0" />
</packages>

View File

@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="jQuery.UI.Combined" version="1.9.2" />
<package id="jQuery.UI.Combined" version="1.9.1" />
</packages>

View File

@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="LibGit2Sharp" version="0.19.0" />
<package id="LibGit2Sharp" version="0.20.0" />
</packages>

View File

@@ -0,0 +1,37 @@
_____ _______ __ __ __
| \ .-----..--.--.| _ |.--.--..--| ||__|| |_
| -- || -__|| | || || | || _ || || _|
|_____/ |_____| \___/ |___|___||_____||_____||__||____|
v3.3.0.0
08:25:20<01> [AUDIT] [SUCCESS] Detected operating system of environment is debian.
08:25:20<01> [AUDIT] [SUCCESS] Detected operating system version of environment is 10.1.
08:25:20<01> [HOST] [INFO] Using OSS Index as default package vulnerabilities data source for NuGet package source.
08:25:20<01> [AUDIT] [STATUS] Scanning NuGet packages.
Scanning NuGet packages...Scanning NuGet packages.../ 08:25:20<01> [AUDIT] [SUCCESS] Scanned 1 NuGet packages.
Searching OSS Index for vulnerabilities for 1 packages... Waiting..... 08:25:20<07> [HOST] [SUCCESS] Got 1 total vulnerabilities for 1 packages from data source OSS Index.
-\| 08:25:20<04> [AUDIT] [INFO] Evaluated 1 vulnerabilities with 1 matches to package version in 142 ms.
Package Source Audit Results
============================
1 total vulnerability found in NuGet package source audit. Total time for audit: 416 ms.
[1/1] LibGit2Sharp [VULNERABLE] 1 known vulnerabilities, 1 affecting installed package version(s): [0.20.0]
--[1/1] Git vulnerability requires git client updates
--Description:
--A critical Git security vulnerability has been announced today, affecting all versions of the official Git client and all related software that interacts with Git repositories, including GitHub for Windows and GitHub for Mac.
Because this is a client-side only vulnerability, github.com and GitHub Enterprise are not directly affected.The vulnerability concerns Git and Git-compatible clients that access Git repositories in a case-insensitive or case-normalizing filesystem.
An attacker can craft a malicious Git tree that will cause Git to overwrite its own .git/config file when cloning or checking out a repository, leading to arbitrary command execution in the client machine.
Git clients running on OS X (HFS+) or any version of Microsoft Windows (NTFS, FAT) are exploitable through this vulnerability.
Linux clients are not affected if they run in a case-sensitive filesystem.
0.20.0
--Id: cfacab46-bdf8-40d4-8d50-06420a9c0013
--Reference: https://ossindex.sonatype.org/vuln/cfacab46-bdf8-40d4-8d50-06420a9c0013
--Provided by: OSS Index
Vulnerabilities Data Providers
==============================
OSS Index https://ossindex.sonatype.org OSS Index is a free index of software information, focusing on vulnerabilities. The data has been made available to the community through a REST API as well as several open source tools. Particular focus is being made on software packages, both those used for development libraries as well as installation packages.