mirror of
https://github.com/peass-ng/PEASS-ng.git
synced 2026-07-30 23:50:27 -07:00
Sort package vulnerabilities by criticality
This commit is contained in:
@@ -273,5 +273,43 @@ namespace winPEAS.Tests
|
||||
Assert.AreEqual(5, summary.NotShown);
|
||||
Assert.IsTrue(summary.Lines[0].StartsWith("- pkg1 1.1.0 [windows-registry]: CVE-2026-10001"));
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void PackageVulnerabilityFormatter_SortsByCriticalityBeforeCapping()
|
||||
{
|
||||
var responseJson =
|
||||
"{\"package_vulnerabilities\":{\"checked\":4,\"affected\":4,\"vulnerable_packages\":[" +
|
||||
"{\"name\":\"lowpkg\",\"version\":\"1.0\",\"manager\":\"windows-registry\",\"severity\":\"low\",\"vulns\":[\"CVE-2026-10001\"]}," +
|
||||
"{\"name\":\"criticalpkg\",\"version\":\"2.0\",\"manager\":\"windows-registry\",\"severity\":\"critical\",\"vulns\":[\"CVE-2026-10002\"]}," +
|
||||
"{\"name\":\"highpkg\",\"version\":\"3.0\",\"manager\":\"windows-registry\",\"severity\":\"high\",\"vulns\":[\"CVE-2026-10003\"]}," +
|
||||
"{\"name\":\"mediumpkg\",\"version\":\"4.0\",\"manager\":\"windows-registry\",\"severity\":\"medium\",\"vulns\":[\"CVE-2026-10004\"]}" +
|
||||
"]}}";
|
||||
|
||||
var summary = winPEAS.Info.NetworkInfo.HackTricksHostChecker.ParsePackageVulnerabilities(responseJson, 3);
|
||||
|
||||
Assert.AreEqual(3, summary.Lines.Count);
|
||||
Assert.AreEqual(1, summary.NotShown);
|
||||
Assert.IsTrue(summary.Lines[0].StartsWith("- criticalpkg 2.0 [windows-registry] [Critical]: CVE-2026-10002"));
|
||||
Assert.IsTrue(summary.Lines[1].StartsWith("- highpkg 3.0 [windows-registry] [High]: CVE-2026-10003"));
|
||||
Assert.IsTrue(summary.Lines[2].StartsWith("- mediumpkg 4.0 [windows-registry] [Medium]: CVE-2026-10004"));
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void PackageVulnerabilityFormatter_UsesCvssCriticalityWhenSeverityMissing()
|
||||
{
|
||||
var responseJson =
|
||||
"{\"package_vulnerabilities\":{\"checked\":3,\"affected\":3,\"vulnerable_packages\":[" +
|
||||
"{\"name\":\"mediumcvss\",\"version\":\"1.0\",\"manager\":\"windows-registry\",\"cvss_score\":5.0,\"vulns\":[\"CVE-2026-10001\"]}," +
|
||||
"{\"name\":\"criticalcvss\",\"version\":\"2.0\",\"manager\":\"windows-registry\",\"cvss_score\":9.8,\"vulns\":[\"CVE-2026-10002\"]}," +
|
||||
"{\"name\":\"highobject\",\"version\":\"3.0\",\"manager\":\"windows-registry\",\"vulns\":[{\"id\":\"CVE-2026-10003\",\"severity\":\"high\",\"cvss_score\":8.1}]}" +
|
||||
"]}}";
|
||||
|
||||
var summary = winPEAS.Info.NetworkInfo.HackTricksHostChecker.ParsePackageVulnerabilities(responseJson, 50);
|
||||
|
||||
Assert.AreEqual(3, summary.Lines.Count);
|
||||
Assert.IsTrue(summary.Lines[0].StartsWith("- criticalcvss 2.0 [windows-registry] [Critical]: CVE-2026-10002"));
|
||||
Assert.IsTrue(summary.Lines[1].StartsWith("- highobject 3.0 [windows-registry] [High]: CVE-2026-10003"));
|
||||
Assert.IsTrue(summary.Lines[2].StartsWith("- mediumcvss 1.0 [windows-registry] [Medium]: CVE-2026-10001"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -30,10 +30,30 @@ namespace winPEAS.Info.NetworkInfo
|
||||
public List<string> Lines { get; } = new List<string>();
|
||||
}
|
||||
|
||||
internal sealed class PackageVulnerabilityEntry
|
||||
{
|
||||
public int OriginalIndex { get; set; }
|
||||
public int SeverityPriority { get; set; }
|
||||
public double CvssScore { get; set; }
|
||||
public string Severity { get; set; }
|
||||
public string Line { get; set; }
|
||||
public List<string> VulnerabilityIds { get; } = new List<string>();
|
||||
}
|
||||
|
||||
internal sealed class VulnerabilityCriticality
|
||||
{
|
||||
public int SeverityPriority { get; set; }
|
||||
public double CvssScore { get; set; }
|
||||
public string Severity { get; set; }
|
||||
}
|
||||
|
||||
public static class HackTricksHostChecker
|
||||
{
|
||||
private const int TimeoutSeconds = 15;
|
||||
private const int OsvTimeoutSeconds = 12;
|
||||
private const int MaxOsvVulnerabilityLookups = 100;
|
||||
private const string DefaultUrl = "https://tools.hacktricks.wiki/api/host-checker";
|
||||
private const string OsvVulnerabilityUrl = "https://api.osv.dev/v1/vulns/";
|
||||
private static readonly object LockObj = new object();
|
||||
private static Task<HostCheckerResult> lookupTask;
|
||||
private static bool startedWithPackages;
|
||||
@@ -87,10 +107,21 @@ namespace winPEAS.Info.NetworkInfo
|
||||
return new PackageVulnerabilitySummary { Error = result.Error };
|
||||
}
|
||||
|
||||
return ParsePackageVulnerabilities(result.RawResponse, maxLines);
|
||||
return ParsePackageVulnerabilities(
|
||||
result.RawResponse,
|
||||
maxLines,
|
||||
ResolveVulnerabilityCriticalitiesFromOsv);
|
||||
}
|
||||
|
||||
public static PackageVulnerabilitySummary ParsePackageVulnerabilities(string responseJson, int maxLines)
|
||||
{
|
||||
return ParsePackageVulnerabilities(responseJson, maxLines, null);
|
||||
}
|
||||
|
||||
private static PackageVulnerabilitySummary ParsePackageVulnerabilities(
|
||||
string responseJson,
|
||||
int maxLines,
|
||||
Func<IEnumerable<string>, Dictionary<string, VulnerabilityCriticality>> vulnerabilityCriticalityResolver)
|
||||
{
|
||||
var summary = new PackageVulnerabilitySummary();
|
||||
if (string.IsNullOrWhiteSpace(responseJson))
|
||||
@@ -124,13 +155,10 @@ namespace winPEAS.Info.NetworkInfo
|
||||
return summary;
|
||||
}
|
||||
|
||||
var entries = new List<PackageVulnerabilityEntry>();
|
||||
var index = 0;
|
||||
foreach (var package in packages.EnumerateArray())
|
||||
{
|
||||
if (summary.Lines.Count >= maxLines)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
var name = GetString(package, "name");
|
||||
var version = GetString(package, "version");
|
||||
var ecosystem = GetString(package, "ecosystem");
|
||||
@@ -143,9 +171,30 @@ namespace winPEAS.Info.NetworkInfo
|
||||
|
||||
var source = !string.IsNullOrWhiteSpace(ecosystem) ? ecosystem : manager;
|
||||
var sourcePart = !string.IsNullOrWhiteSpace(source) ? $" [{source}]" : string.Empty;
|
||||
summary.Lines.Add($"- {name} {version}{sourcePart}: {string.Join(", ", vulns)}".Trim());
|
||||
var severity = GetPackageSeverity(package);
|
||||
var severityPart = !string.IsNullOrWhiteSpace(severity) ? $" [{severity}]" : string.Empty;
|
||||
var entry = new PackageVulnerabilityEntry
|
||||
{
|
||||
OriginalIndex = index,
|
||||
Severity = severity,
|
||||
SeverityPriority = GetSeverityPriority(severity),
|
||||
CvssScore = GetPackageCvssScore(package),
|
||||
Line = $"- {name} {version}{sourcePart}{severityPart}: {string.Join(", ", vulns)}".Trim()
|
||||
};
|
||||
entry.VulnerabilityIds.AddRange(vulns);
|
||||
entries.Add(entry);
|
||||
index++;
|
||||
}
|
||||
|
||||
ApplyResolvedCriticalities(entries, vulnerabilityCriticalityResolver);
|
||||
|
||||
summary.Lines.AddRange(entries
|
||||
.OrderByDescending(entry => entry.SeverityPriority)
|
||||
.ThenByDescending(entry => entry.CvssScore)
|
||||
.ThenBy(entry => entry.OriginalIndex)
|
||||
.Take(Math.Max(0, maxLines))
|
||||
.Select(entry => entry.Line));
|
||||
|
||||
summary.NotShown = Math.Max(0, summary.Affected - summary.Lines.Count);
|
||||
}
|
||||
}
|
||||
@@ -157,6 +206,165 @@ namespace winPEAS.Info.NetworkInfo
|
||||
return summary;
|
||||
}
|
||||
|
||||
private static void ApplyResolvedCriticalities(
|
||||
List<PackageVulnerabilityEntry> entries,
|
||||
Func<IEnumerable<string>, Dictionary<string, VulnerabilityCriticality>> vulnerabilityCriticalityResolver)
|
||||
{
|
||||
if (vulnerabilityCriticalityResolver == null || entries.Count == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var vulnerabilityIds = entries
|
||||
.SelectMany(entry => entry.VulnerabilityIds)
|
||||
.Where(value => !string.IsNullOrWhiteSpace(value))
|
||||
.Distinct(StringComparer.OrdinalIgnoreCase)
|
||||
.ToList();
|
||||
if (vulnerabilityIds.Count == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Dictionary<string, VulnerabilityCriticality> criticalities;
|
||||
try
|
||||
{
|
||||
criticalities = vulnerabilityCriticalityResolver(vulnerabilityIds);
|
||||
}
|
||||
catch
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (criticalities == null || criticalities.Count == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
foreach (var entry in entries)
|
||||
{
|
||||
var resolved = entry.VulnerabilityIds
|
||||
.Where(id => criticalities.ContainsKey(id))
|
||||
.Select(id => criticalities[id])
|
||||
.OrderByDescending(criticality => criticality.SeverityPriority)
|
||||
.ThenByDescending(criticality => criticality.CvssScore)
|
||||
.FirstOrDefault();
|
||||
if (resolved == null || resolved.SeverityPriority <= entry.SeverityPriority)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
entry.Severity = resolved.Severity;
|
||||
entry.SeverityPriority = resolved.SeverityPriority;
|
||||
entry.CvssScore = resolved.CvssScore;
|
||||
entry.Line = AddSeverityToLine(entry.Line, resolved.Severity);
|
||||
}
|
||||
}
|
||||
|
||||
private static string AddSeverityToLine(string line, string severity)
|
||||
{
|
||||
severity = FormatSeverity(severity);
|
||||
if (string.IsNullOrWhiteSpace(severity) || string.IsNullOrWhiteSpace(line))
|
||||
{
|
||||
return line;
|
||||
}
|
||||
|
||||
var separator = line.IndexOf(": ", StringComparison.Ordinal);
|
||||
if (separator < 0)
|
||||
{
|
||||
return line;
|
||||
}
|
||||
|
||||
return line.Substring(0, separator) + $" [{severity}]" + line.Substring(separator);
|
||||
}
|
||||
|
||||
private static Dictionary<string, VulnerabilityCriticality> ResolveVulnerabilityCriticalitiesFromOsv(IEnumerable<string> vulnerabilityIds)
|
||||
{
|
||||
var ids = vulnerabilityIds
|
||||
.Where(value => !string.IsNullOrWhiteSpace(value))
|
||||
.Distinct(StringComparer.OrdinalIgnoreCase)
|
||||
.Take(MaxOsvVulnerabilityLookups)
|
||||
.ToList();
|
||||
var results = new Dictionary<string, VulnerabilityCriticality>(StringComparer.OrdinalIgnoreCase);
|
||||
if (ids.Count == 0)
|
||||
{
|
||||
return results;
|
||||
}
|
||||
|
||||
using (var httpClient = new HttpClient())
|
||||
using (var cts = new CancellationTokenSource(TimeSpan.FromSeconds(OsvTimeoutSeconds)))
|
||||
{
|
||||
httpClient.Timeout = TimeSpan.FromSeconds(OsvTimeoutSeconds);
|
||||
httpClient.DefaultRequestHeaders.UserAgent.ParseAdd("winpeas");
|
||||
httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
|
||||
|
||||
var tasks = ids.Select(id => GetOsvCriticality(httpClient, cts.Token, id)).ToArray();
|
||||
Task.WaitAll(tasks, TimeSpan.FromSeconds(OsvTimeoutSeconds));
|
||||
foreach (var task in tasks)
|
||||
{
|
||||
if (task.Status == TaskStatus.RanToCompletion && task.Result.Value != null)
|
||||
{
|
||||
results[task.Result.Key] = task.Result.Value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return results;
|
||||
}
|
||||
|
||||
private static async Task<KeyValuePair<string, VulnerabilityCriticality>> GetOsvCriticality(
|
||||
HttpClient httpClient,
|
||||
CancellationToken cancellationToken,
|
||||
string vulnerabilityId)
|
||||
{
|
||||
try
|
||||
{
|
||||
var url = OsvVulnerabilityUrl + Uri.EscapeDataString(vulnerabilityId);
|
||||
var response = await httpClient.GetAsync(url, cancellationToken).ConfigureAwait(false);
|
||||
if (!response.IsSuccessStatusCode)
|
||||
{
|
||||
return new KeyValuePair<string, VulnerabilityCriticality>(vulnerabilityId, null);
|
||||
}
|
||||
|
||||
var body = await response.Content.ReadAsStringAsync().ConfigureAwait(false);
|
||||
using (var doc = JsonDocument.Parse(body))
|
||||
{
|
||||
return new KeyValuePair<string, VulnerabilityCriticality>(
|
||||
vulnerabilityId,
|
||||
GetOsvCriticality(doc.RootElement));
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
return new KeyValuePair<string, VulnerabilityCriticality>(vulnerabilityId, null);
|
||||
}
|
||||
}
|
||||
|
||||
private static VulnerabilityCriticality GetOsvCriticality(JsonElement root)
|
||||
{
|
||||
var best = new VulnerabilityCriticality();
|
||||
if (!root.TryGetProperty("severity", out var severities) || severities.ValueKind != JsonValueKind.Array)
|
||||
{
|
||||
return best;
|
||||
}
|
||||
|
||||
foreach (var severity in severities.EnumerateArray())
|
||||
{
|
||||
var scoreText = GetString(severity, "score");
|
||||
var cvssScore = GetCvssScore(scoreText);
|
||||
var severityName = GetSeverityFromCvss(cvssScore);
|
||||
var priority = GetSeverityPriority(severityName);
|
||||
if (priority > best.SeverityPriority ||
|
||||
(priority == best.SeverityPriority && cvssScore > best.CvssScore))
|
||||
{
|
||||
best.Severity = severityName;
|
||||
best.SeverityPriority = priority;
|
||||
best.CvssScore = cvssScore;
|
||||
}
|
||||
}
|
||||
|
||||
return best;
|
||||
}
|
||||
|
||||
private static void EnsureStarted(bool includePackages)
|
||||
{
|
||||
Start(
|
||||
@@ -306,6 +514,315 @@ namespace winPEAS.Info.NetworkInfo
|
||||
return string.Empty;
|
||||
}
|
||||
|
||||
private static string GetPackageSeverity(JsonElement package)
|
||||
{
|
||||
var severity = GetString(package, "severity");
|
||||
var priority = GetSeverityPriority(severity);
|
||||
|
||||
foreach (var propertyName in new[] { "max_severity", "criticality", "risk", "level" })
|
||||
{
|
||||
var candidate = GetString(package, propertyName);
|
||||
var candidatePriority = GetSeverityPriority(candidate);
|
||||
if (candidatePriority > priority)
|
||||
{
|
||||
severity = candidate;
|
||||
priority = candidatePriority;
|
||||
}
|
||||
}
|
||||
|
||||
if (package.TryGetProperty("severities", out var severities) && severities.ValueKind == JsonValueKind.Array)
|
||||
{
|
||||
foreach (var item in severities.EnumerateArray())
|
||||
{
|
||||
if (item.ValueKind != JsonValueKind.String)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
var candidate = item.GetString();
|
||||
var candidatePriority = GetSeverityPriority(candidate);
|
||||
if (candidatePriority > priority)
|
||||
{
|
||||
severity = candidate;
|
||||
priority = candidatePriority;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (package.TryGetProperty("vulns", out var vulns) && vulns.ValueKind == JsonValueKind.Array)
|
||||
{
|
||||
foreach (var vuln in vulns.EnumerateArray())
|
||||
{
|
||||
if (vuln.ValueKind != JsonValueKind.Object)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
foreach (var propertyName in new[] { "severity", "max_severity", "criticality", "risk", "level" })
|
||||
{
|
||||
var candidate = GetString(vuln, propertyName);
|
||||
var candidatePriority = GetSeverityPriority(candidate);
|
||||
if (candidatePriority > priority)
|
||||
{
|
||||
severity = candidate;
|
||||
priority = candidatePriority;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (priority == 0)
|
||||
{
|
||||
var cvssScore = GetPackageCvssScore(package);
|
||||
severity = GetSeverityFromCvss(cvssScore);
|
||||
}
|
||||
|
||||
return FormatSeverity(severity);
|
||||
}
|
||||
|
||||
private static double GetPackageCvssScore(JsonElement package)
|
||||
{
|
||||
var score = 0.0;
|
||||
foreach (var propertyName in new[] { "cvss", "cvss_score", "cvssScore", "max_cvss", "max_cvss_score", "score" })
|
||||
{
|
||||
score = Math.Max(score, GetScore(package, propertyName));
|
||||
}
|
||||
|
||||
if (package.TryGetProperty("vulns", out var vulns) && vulns.ValueKind == JsonValueKind.Array)
|
||||
{
|
||||
foreach (var vuln in vulns.EnumerateArray())
|
||||
{
|
||||
if (vuln.ValueKind != JsonValueKind.Object)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
foreach (var propertyName in new[] { "cvss", "cvss_score", "cvssScore", "max_cvss", "max_cvss_score", "score" })
|
||||
{
|
||||
score = Math.Max(score, GetScore(vuln, propertyName));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return score;
|
||||
}
|
||||
|
||||
private static int GetSeverityPriority(string severity)
|
||||
{
|
||||
switch ((severity ?? "").Trim().ToLowerInvariant())
|
||||
{
|
||||
case "critical":
|
||||
return 5;
|
||||
case "high":
|
||||
case "important":
|
||||
return 4;
|
||||
case "medium":
|
||||
case "moderate":
|
||||
return 3;
|
||||
case "low":
|
||||
return 2;
|
||||
case "none":
|
||||
case "informational":
|
||||
case "info":
|
||||
return 1;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
private static string GetSeverityFromCvss(double cvssScore)
|
||||
{
|
||||
if (cvssScore >= 9.0)
|
||||
{
|
||||
return "Critical";
|
||||
}
|
||||
if (cvssScore >= 7.0)
|
||||
{
|
||||
return "High";
|
||||
}
|
||||
if (cvssScore >= 4.0)
|
||||
{
|
||||
return "Medium";
|
||||
}
|
||||
if (cvssScore > 0)
|
||||
{
|
||||
return "Low";
|
||||
}
|
||||
|
||||
return string.Empty;
|
||||
}
|
||||
|
||||
private static string FormatSeverity(string severity)
|
||||
{
|
||||
severity = (severity ?? "").Trim();
|
||||
if (string.IsNullOrWhiteSpace(severity))
|
||||
{
|
||||
return string.Empty;
|
||||
}
|
||||
|
||||
return char.ToUpperInvariant(severity[0]) + severity.Substring(1).ToLowerInvariant();
|
||||
}
|
||||
|
||||
private static double GetScore(JsonElement element, string propertyName)
|
||||
{
|
||||
if (!element.TryGetProperty(propertyName, out var property))
|
||||
{
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
if (property.ValueKind == JsonValueKind.Number && property.TryGetDouble(out var value))
|
||||
{
|
||||
return value;
|
||||
}
|
||||
|
||||
if (property.ValueKind == JsonValueKind.String)
|
||||
{
|
||||
return GetCvssScore(property.GetString());
|
||||
}
|
||||
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
private static double GetCvssScore(string score)
|
||||
{
|
||||
score = (score ?? "").Trim();
|
||||
if (double.TryParse(
|
||||
score,
|
||||
System.Globalization.NumberStyles.Float,
|
||||
System.Globalization.CultureInfo.InvariantCulture,
|
||||
out var numericScore))
|
||||
{
|
||||
return numericScore;
|
||||
}
|
||||
|
||||
if (score.StartsWith("CVSS:3.", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
return GetCvssV3Score(score);
|
||||
}
|
||||
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
private static double GetCvssV3Score(string vector)
|
||||
{
|
||||
var metrics = vector
|
||||
.Split('/')
|
||||
.Skip(1)
|
||||
.Select(part => part.Split(':'))
|
||||
.Where(parts => parts.Length == 2)
|
||||
.ToDictionary(parts => parts[0], parts => parts[1], StringComparer.OrdinalIgnoreCase);
|
||||
|
||||
if (!metrics.TryGetValue("AV", out var av) ||
|
||||
!metrics.TryGetValue("AC", out var ac) ||
|
||||
!metrics.TryGetValue("PR", out var pr) ||
|
||||
!metrics.TryGetValue("UI", out var ui) ||
|
||||
!metrics.TryGetValue("S", out var scope) ||
|
||||
!metrics.TryGetValue("C", out var c) ||
|
||||
!metrics.TryGetValue("I", out var i) ||
|
||||
!metrics.TryGetValue("A", out var a))
|
||||
{
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
var scopeChanged = string.Equals(scope, "C", StringComparison.OrdinalIgnoreCase);
|
||||
var impact = 1 - ((1 - GetCvssImpactValue(c)) * (1 - GetCvssImpactValue(i)) * (1 - GetCvssImpactValue(a)));
|
||||
var impactSubScore = scopeChanged
|
||||
? 7.52 * (impact - 0.029) - 3.25 * Math.Pow(impact - 0.02, 15)
|
||||
: 6.42 * impact;
|
||||
if (impactSubScore <= 0)
|
||||
{
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
var exploitability = 8.22 *
|
||||
GetCvssAttackVectorValue(av) *
|
||||
GetCvssAttackComplexityValue(ac) *
|
||||
GetCvssPrivilegesRequiredValue(pr, scopeChanged) *
|
||||
GetCvssUserInteractionValue(ui);
|
||||
var rawScore = scopeChanged
|
||||
? Math.Min(1.08 * (impactSubScore + exploitability), 10)
|
||||
: Math.Min(impactSubScore + exploitability, 10);
|
||||
return RoundUpCvss(rawScore);
|
||||
}
|
||||
|
||||
private static double RoundUpCvss(double value)
|
||||
{
|
||||
return Math.Ceiling((value - 0.000001) * 10.0) / 10.0;
|
||||
}
|
||||
|
||||
private static double GetCvssAttackVectorValue(string value)
|
||||
{
|
||||
switch ((value ?? "").ToUpperInvariant())
|
||||
{
|
||||
case "N":
|
||||
return 0.85;
|
||||
case "A":
|
||||
return 0.62;
|
||||
case "L":
|
||||
return 0.55;
|
||||
case "P":
|
||||
return 0.20;
|
||||
default:
|
||||
return 0.0;
|
||||
}
|
||||
}
|
||||
|
||||
private static double GetCvssAttackComplexityValue(string value)
|
||||
{
|
||||
switch ((value ?? "").ToUpperInvariant())
|
||||
{
|
||||
case "L":
|
||||
return 0.77;
|
||||
case "H":
|
||||
return 0.44;
|
||||
default:
|
||||
return 0.0;
|
||||
}
|
||||
}
|
||||
|
||||
private static double GetCvssPrivilegesRequiredValue(string value, bool scopeChanged)
|
||||
{
|
||||
switch ((value ?? "").ToUpperInvariant())
|
||||
{
|
||||
case "N":
|
||||
return 0.85;
|
||||
case "L":
|
||||
return scopeChanged ? 0.68 : 0.62;
|
||||
case "H":
|
||||
return scopeChanged ? 0.50 : 0.27;
|
||||
default:
|
||||
return 0.0;
|
||||
}
|
||||
}
|
||||
|
||||
private static double GetCvssUserInteractionValue(string value)
|
||||
{
|
||||
switch ((value ?? "").ToUpperInvariant())
|
||||
{
|
||||
case "N":
|
||||
return 0.85;
|
||||
case "R":
|
||||
return 0.62;
|
||||
default:
|
||||
return 0.0;
|
||||
}
|
||||
}
|
||||
|
||||
private static double GetCvssImpactValue(string value)
|
||||
{
|
||||
switch ((value ?? "").ToUpperInvariant())
|
||||
{
|
||||
case "H":
|
||||
return 0.56;
|
||||
case "L":
|
||||
return 0.22;
|
||||
case "N":
|
||||
return 0.0;
|
||||
default:
|
||||
return 0.0;
|
||||
}
|
||||
}
|
||||
|
||||
private static List<string> GetStringArray(JsonElement element, string propertyName)
|
||||
{
|
||||
if (!element.TryGetProperty(propertyName, out var property) || property.ValueKind != JsonValueKind.Array)
|
||||
@@ -315,8 +832,27 @@ namespace winPEAS.Info.NetworkInfo
|
||||
|
||||
return property
|
||||
.EnumerateArray()
|
||||
.Where(item => item.ValueKind == JsonValueKind.String)
|
||||
.Select(item => item.GetString())
|
||||
.Select(item =>
|
||||
{
|
||||
if (item.ValueKind == JsonValueKind.String)
|
||||
{
|
||||
return item.GetString();
|
||||
}
|
||||
|
||||
if (item.ValueKind == JsonValueKind.Object)
|
||||
{
|
||||
foreach (var propertyNameCandidate in new[] { "id", "cve", "name", "vulnerability_id" })
|
||||
{
|
||||
var value = GetString(item, propertyNameCandidate);
|
||||
if (!string.IsNullOrWhiteSpace(value))
|
||||
{
|
||||
return value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return string.Empty;
|
||||
})
|
||||
.Where(value => !string.IsNullOrWhiteSpace(value))
|
||||
.ToList();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user