387 lines
14 KiB
C#
387 lines
14 KiB
C#
<Query Kind="Program">
|
|
<Reference><ProgramFilesX64>\Microsoft SDKs\Azure\.NET SDK\v2.9\bin\plugins\Diagnostics\Newtonsoft.Json.dll</Reference>
|
|
<NuGetReference>Amazon.Lambda.S3Events</NuGetReference>
|
|
<NuGetReference>AWSSDK.Core</NuGetReference>
|
|
<NuGetReference>AWSSDK.S3</NuGetReference>
|
|
<Namespace>Amazon</Namespace>
|
|
<Namespace>Amazon.Auth.AccessControlPolicy</Namespace>
|
|
<Namespace>Amazon.Auth.AccessControlPolicy.ActionIdentifiers</Namespace>
|
|
<Namespace>Amazon.Internal</Namespace>
|
|
<Namespace>Amazon.Lambda.S3Events</Namespace>
|
|
<Namespace>Amazon.MissingTypes</Namespace>
|
|
<Namespace>Amazon.Runtime</Namespace>
|
|
<Namespace>Amazon.Runtime.CredentialManagement</Namespace>
|
|
<Namespace>Amazon.Runtime.CredentialManagement.Internal</Namespace>
|
|
<Namespace>Amazon.Runtime.EventStreams</Namespace>
|
|
<Namespace>Amazon.Runtime.EventStreams.Internal</Namespace>
|
|
<Namespace>Amazon.Runtime.Internal</Namespace>
|
|
<Namespace>Amazon.Runtime.Internal.Auth</Namespace>
|
|
<Namespace>Amazon.Runtime.Internal.Settings</Namespace>
|
|
<Namespace>Amazon.Runtime.Internal.Transform</Namespace>
|
|
<Namespace>Amazon.Runtime.Internal.Util</Namespace>
|
|
<Namespace>Amazon.Runtime.SharedInterfaces</Namespace>
|
|
<Namespace>Amazon.Runtime.SharedInterfaces.Internal</Namespace>
|
|
<Namespace>Amazon.S3</Namespace>
|
|
<Namespace>Amazon.S3.Encryption</Namespace>
|
|
<Namespace>Amazon.S3.Encryption.Internal</Namespace>
|
|
<Namespace>Amazon.S3.Internal</Namespace>
|
|
<Namespace>Amazon.S3.IO</Namespace>
|
|
<Namespace>Amazon.S3.Model</Namespace>
|
|
<Namespace>Amazon.S3.Model.Internal.MarshallTransformations</Namespace>
|
|
<Namespace>Amazon.S3.Transfer</Namespace>
|
|
<Namespace>Amazon.S3.Util</Namespace>
|
|
<Namespace>Amazon.Util</Namespace>
|
|
<Namespace>Amazon.Util.Internal</Namespace>
|
|
<Namespace>Amazon.Util.Internal.PlatformServices</Namespace>
|
|
<Namespace>Newtonsoft.Json</Namespace>
|
|
<Namespace>Newtonsoft.Json.Converters</Namespace>
|
|
<Namespace>Newtonsoft.Json.Linq</Namespace>
|
|
<Namespace>Newtonsoft.Json.Schema</Namespace>
|
|
<Namespace>Newtonsoft.Json.Serialization</Namespace>
|
|
<Namespace>System</Namespace>
|
|
<Namespace>System.ComponentModel.Composition</Namespace>
|
|
<Namespace>System.ComponentModel.Composition.Hosting</Namespace>
|
|
<Namespace>System.ComponentModel.Composition.Primitives</Namespace>
|
|
<Namespace>System.ComponentModel.Composition.ReflectionModel</Namespace>
|
|
<Namespace>System.Diagnostics</Namespace>
|
|
<Namespace>System.Diagnostics.Tracing</Namespace>
|
|
<Namespace>System.IO.Compression</Namespace>
|
|
<Namespace>System.Net.Http</Namespace>
|
|
<Namespace>System.Net.Http.Headers</Namespace>
|
|
<Namespace>System.Numerics</Namespace>
|
|
<Namespace>ThirdParty.BouncyCastle.Asn1</Namespace>
|
|
<Namespace>ThirdParty.BouncyCastle.Asn1.Utilities</Namespace>
|
|
<Namespace>ThirdParty.BouncyCastle.Math</Namespace>
|
|
<Namespace>ThirdParty.BouncyCastle.OpenSsl</Namespace>
|
|
<Namespace>ThirdParty.BouncyCastle.Utilities.IO.Pem</Namespace>
|
|
<Namespace>ThirdParty.Ionic.Zlib</Namespace>
|
|
<Namespace>ThirdParty.Json.LitJson</Namespace>
|
|
<Namespace>ThirdParty.MD5</Namespace>
|
|
</Query>
|
|
|
|
private XDocument xmlDoc = XDocument.Load(@"C:\Users\tlamb\Downloads\detailedreport_Strata_Jazz_Web_Jazz_web_201911511115217.xml");
|
|
|
|
void Main()
|
|
{
|
|
//xmlDoc.DumpFormatted();
|
|
var cwes = ParseVeracodeReport(xmlDoc).Where(cwe => cwe.count > 0);
|
|
var flaws = (from cwe in xmlDoc.Descendants()
|
|
where cwe.Name.LocalName == "cwe"
|
|
&& cwe.Attributes().Any(a => a.Name == "cweid")
|
|
orderby Int32.Parse(cwe.Attribute("cweid").Value)
|
|
select cwe.Descendants().Where(c => c.Name.LocalName == "flaw"));
|
|
flaws
|
|
.SelectMany(f => f.Select(x => new Flaw(x)))
|
|
.Where(x => new[] { 4, 5 }.Contains(x.severity) && !x.hasMitigations && x.remediation_status == "New")
|
|
.OrderByDescending(x => x.severity)
|
|
.ThenBy(x => x.categoryid)
|
|
.ThenBy(x => x.cweid)
|
|
.ThenBy(x => x.issueid).Dump();
|
|
//DumpTop20(cwes);
|
|
// DumpSummary(cwes);
|
|
// DumpModules(cwes);
|
|
// DumpByCweID(cwes);
|
|
}
|
|
|
|
void DumpTop20(IEnumerable<Cwe> cwes)
|
|
{
|
|
cwes.Where(cwe => cwe.count > 1 && new[] { 78, 15, 89 }.Contains(cwe.id))
|
|
.Select(cwe => new { cwe.severity, cwe.category, cwe.details })
|
|
.OrderByDescending(cwe => cwe.severity)
|
|
.Dump($"Top 20: ({cwes.Where(cwe => cwe.count > 1).Count()})");
|
|
}
|
|
|
|
void DumpSummary(IEnumerable<Cwe> cwes)
|
|
{
|
|
cwes.Where(cwe => cwe.count > 1)
|
|
.OrderByDescending(cwe => cwe.severity).ThenByDescending(cwe => cwe.count)
|
|
.Dump($"Summary: ({cwes.Where(cwe => cwe.count > 1).Count()})");
|
|
|
|
}
|
|
|
|
void DumpModules(IEnumerable<Cwe> cwes)
|
|
{
|
|
var regex = new Regex(@"\.Test\.|\.IntegrationTests\.|\.UnitTests\.");
|
|
var modules = from m in xmlDoc.Descendants()
|
|
where m.Name.LocalName == "module" && m.Parent.Name.LocalName == "modules"
|
|
select new Module(m, cwes);
|
|
modules.Where(m => !regex.IsMatch(m.name) && m.totalNumberOfFlaws > 0)
|
|
.OrderBy(m => m.score).ThenByDescending(m => m.numberOfImportantFlaws)
|
|
.Dump($"Modules: ({modules.Count(m => !regex.IsMatch(m.name) && m.totalNumberOfFlaws > 0)})");
|
|
}
|
|
|
|
void DumpByCweID(IEnumerable<Cwe> cwes)
|
|
{
|
|
cwes.Where(cwe => cwe.count > 1)
|
|
.OrderBy(cwe => cwe.id).ToList()
|
|
.ForEach(cwe => cwe.details.Dump($"ID: {cwe.id} {cwe.name} ({cwe.count})"));
|
|
//JsonConvert.SerializeObject(cwes, Newtonsoft.Json.Formatting.Indented).Dump("Json");
|
|
}
|
|
|
|
internal IEnumerable<Cwe> ParseVeracodeReport(XDocument xmlDoc)
|
|
{
|
|
return from module in xmlDoc.Descendants()
|
|
where module.Name.LocalName == "cwe"
|
|
&& module.Attributes().Any(a => a.Name == "cweid")
|
|
orderby Int32.Parse(module.Attribute("cweid").Value)
|
|
select new Cwe(module);
|
|
}
|
|
|
|
public static class IntExtensions
|
|
{
|
|
public static string SeverityLabel(this int severity)
|
|
{
|
|
switch (severity)
|
|
{
|
|
case 5: return "Very High";
|
|
case 4: return "High";
|
|
case 3: return "Medium";
|
|
case 2: return "Low";
|
|
case 1: return "Very Low";
|
|
default: return "Informational";
|
|
}
|
|
}
|
|
public static string CategoryLabel(this int category)
|
|
{
|
|
switch (category)
|
|
{
|
|
case 18: return "OS Command Injection";
|
|
case 19: return "SQL Injections";
|
|
case 24: return "Untrusted Initialization";
|
|
case 21: return "CRLF Injection";
|
|
case 10: return "Credentials Management";
|
|
default: return $"{category}";
|
|
}
|
|
}
|
|
}
|
|
|
|
internal class Module
|
|
{
|
|
public string name { get; set; }
|
|
public int score { get; set; }
|
|
public int totalNumberOfFlaws => flawsBySeverity.Values.Sum();
|
|
public int numberOfImportantFlaws => flawsBySeverity.Where(f => f.Key > 2).Select(f => f.Value).Sum();
|
|
private Dictionary<int, int> flawsBySeverity { get; set; }
|
|
|
|
public string flawsSummaryInfo => totalNumberOfFlaws > 0
|
|
? flawsBySeverity.Where(f => f.Value > 0).OrderByDescending(f => f.Key).Aggregate(new StringBuilder("Severity\n"), (x, y) =>
|
|
x.Append($"{y.Key.SeverityLabel()}: {y.Value}\r\n")).ToString().TrimEnd(new[] { '\r', '\n' })
|
|
: "";
|
|
|
|
public List<Severity> summary => totalNumberOfFlaws > 0
|
|
? flawsBySeverity.Where(f => f.Value > 0)
|
|
.OrderByDescending(f => f.Key)
|
|
.Select(y => new Severity
|
|
{
|
|
severity = y.Key,
|
|
Count = y.Value
|
|
}).ToList()
|
|
: new List<Severity>();
|
|
|
|
public string flawListInfo => !flaws.Any()
|
|
? "" : flaws.Aggregate(new StringBuilder("path\tfile\tline\ttype\n"), (x, y) =>
|
|
x.AppendLine($"{(string.IsNullOrEmpty(y.source.sourcefile) ? "na" : Path.GetDirectoryName(y.source.sourcefile))}\t"
|
|
+ $"{(string.IsNullOrEmpty(y.source.sourcefile) ? "na" : Path.GetFileName(y.source.sourcefile))}\t{y.source.line}\t{y.source.type}")).ToString();
|
|
|
|
public List<ModuleFlaw> flawList => !flaws.Any() ? null : flaws
|
|
.ConvertAll(y => (ModuleFlaw)y.source);
|
|
|
|
private List<ModuleSummary> flaws { get; set; }
|
|
|
|
public Module(XElement module, IEnumerable<Cwe> cwes)
|
|
{
|
|
name = module.Attribute("name")?.Value;
|
|
score = Convert.ToInt32(module.Attribute("score")?.Value ?? "0");
|
|
flawsBySeverity = new Dictionary<int, int>();
|
|
flawsBySeverity[0] = Convert.ToInt32(module.Attribute("numflawssev0")?.Value ?? "0");
|
|
flawsBySeverity[1] = Convert.ToInt32(module.Attribute("numflawssev1")?.Value ?? "0");
|
|
flawsBySeverity[2] = Convert.ToInt32(module.Attribute("numflawssev2")?.Value ?? "0");
|
|
flawsBySeverity[3] = Convert.ToInt32(module.Attribute("numflawssev3")?.Value ?? "0");
|
|
flawsBySeverity[4] = Convert.ToInt32(module.Attribute("numflawssev4")?.Value ?? "0");
|
|
flawsBySeverity[5] = Convert.ToInt32(module.Attribute("numflawssev5")?.Value ?? "0");
|
|
var cx = cwes.Where(c => c.details.Any(d => d.module.Equals(name, StringComparison.CurrentCultureIgnoreCase)));
|
|
flaws = cx.SelectMany(c => c.details.Where(d => d.module.Equals(name, StringComparison.CurrentCultureIgnoreCase)).Select(d => new ModuleFlaw(d)))
|
|
.GroupBy(d => $"{d.type}{d.sourcefile}{d.line}")
|
|
.Select(grp => new ModuleSummary
|
|
{
|
|
key = grp.Key,
|
|
source = grp.First(),
|
|
count = grp.Count()
|
|
})
|
|
.OrderBy(grp => grp.source.sourcefile).ThenBy(grp => grp.source.line).ThenBy(grp => grp.source.type).ToList();
|
|
}
|
|
|
|
object ToDump() => new
|
|
{
|
|
Info = new
|
|
{
|
|
name,
|
|
score = score.ToString().PadLeft(3),
|
|
totalNumberOfFlaws = totalNumberOfFlaws.ToString().PadLeft(5),
|
|
numberOfImportantFlaws = numberOfImportantFlaws.ToString().PadLeft(5)
|
|
},
|
|
summary,
|
|
flaws = flawList
|
|
};
|
|
}
|
|
|
|
internal class ModuleSummary
|
|
{
|
|
public string key { get; set; }
|
|
public ModuleFlaw source { get; set; }
|
|
public int count { get; set; }
|
|
}
|
|
|
|
internal class Severity
|
|
{
|
|
public string Level => severity.SeverityLabel();
|
|
internal int severity { get; set; }
|
|
public int Count { get; set; }
|
|
|
|
object ToDump() => new
|
|
{
|
|
Level,
|
|
Count = Count.ToString().PadLeft(4)
|
|
};
|
|
}
|
|
|
|
internal class ModuleFlaw
|
|
{
|
|
public string type { get; set; }
|
|
internal string sourcefile { get; set; }
|
|
public string path => string.IsNullOrEmpty(sourcefile) ? "n/a" : System.IO.Path.GetDirectoryName(sourcefile);
|
|
public string file => string.IsNullOrEmpty(sourcefile) ? "n/a" : System.IO.Path.GetFileName(sourcefile);
|
|
public int count { get; set; }
|
|
public int line { get; set; }
|
|
public int issueid { get; set; }
|
|
public int severity { get; set; }
|
|
public int cweid { get; set; }
|
|
public string cwename { get; set; }
|
|
public string remediation_status{ get; set; }
|
|
public int categoryid { get; set; }
|
|
public bool hasMitigations { get; set; }
|
|
|
|
public ModuleFlaw(XElement element)
|
|
{
|
|
var cwe = element.Ancestors().Where(e => e.Name.LocalName == "cwe").LastOrDefault();
|
|
cwename = cwe.Attribute("cwename")?.Value ?? "";
|
|
hasMitigations = element.Descendants().Any(sfd => sfd.Name.LocalName == "mitigations");
|
|
var regex = new Regex(@"\.!newinit_0_[0-9]|mscorlib_dll|system_xml_dll|system_web_dll|system_data_dll|system_directoryservices_dll|system_dll\.");
|
|
type = regex.Replace(element.Attribute("type")?.Value, "").Trim(new[] { '.' });
|
|
sourcefile = System.IO.Path.Combine((element.Attribute("sourcefilepath")?.Value ?? "").Replace("/jazz new", ""),
|
|
element.Attribute("sourcefile")?.Value ?? "");
|
|
remediation_status = element.Attribute("remediation_status")?.Value ?? "";
|
|
line = Convert.ToInt32(element.Attribute("line")?.Value ?? "0");
|
|
count = Convert.ToInt32(element.Attribute("count")?.Value ?? "0");
|
|
issueid = Convert.ToInt32(element.Attribute("issueid")?.Value ?? "0");
|
|
severity = Convert.ToInt32(element.Attribute("severity")?.Value ?? "0");
|
|
cweid = Convert.ToInt32(element.Attribute("cweid")?.Value ?? "0");
|
|
categoryid = Convert.ToInt32(element.Attribute("categoryid")?.Value ?? "0");
|
|
}
|
|
|
|
public ModuleFlaw(Flaw flaw)
|
|
{
|
|
hasMitigations = flaw.hasMitigations;
|
|
type = flaw.type;
|
|
sourcefile = flaw.sourcefile;
|
|
line = flaw.line;
|
|
}
|
|
|
|
object ToDump() => new
|
|
{
|
|
categoryid = categoryid.ToString().PadLeft(5),
|
|
cweid = cweid.ToString().PadLeft(5),
|
|
hasMitigations,
|
|
type,
|
|
path,
|
|
file,
|
|
line = line.ToString().PadLeft(5),
|
|
count = count.ToString().PadLeft(5),
|
|
issueid = issueid.ToString().PadLeft(5),
|
|
severity = severity.SeverityLabel()
|
|
};
|
|
|
|
}
|
|
|
|
internal class Flaw : ModuleFlaw
|
|
{
|
|
public string module { get; set; }
|
|
public string description { get; set; }
|
|
|
|
public Flaw(XElement element)
|
|
: base(element)
|
|
{
|
|
module = string.Join("\r\n", element.Attribute("module")?.Value.Split("/".ToCharArray()));
|
|
description = element.Attribute("description")?.Value;
|
|
}
|
|
|
|
object ToDump() => new
|
|
{
|
|
Info = new
|
|
{
|
|
categoryid = $"{categoryid.CategoryLabel()} ({categoryid})",
|
|
cweid = cweid.ToString().PadLeft(5),
|
|
cwename,
|
|
hasMitigations,
|
|
type,
|
|
path,
|
|
file,
|
|
line = line.ToString().PadLeft(5),
|
|
count = count.ToString().PadLeft(5),
|
|
issueid = issueid.ToString().PadLeft(5),
|
|
severity = severity.SeverityLabel()
|
|
},
|
|
description
|
|
};
|
|
}
|
|
|
|
internal class Cwe
|
|
{
|
|
public int id { get; set; }
|
|
public string category { get; set; }
|
|
public string name { get; set; }
|
|
public int severity { get; set; }
|
|
public int count { get; set; }
|
|
public string recommendation { get; set; }
|
|
public IEnumerable<Flaw> details { get; set; }
|
|
|
|
public Cwe(XElement module)
|
|
{
|
|
var categoryElement = module.Parent;
|
|
var severityElement = categoryElement.Parent;
|
|
severity = Convert.ToInt32(severityElement.Attribute("level")?.Value ?? "0");
|
|
|
|
category = categoryElement.Attribute("categoryname")?.Value ?? "";
|
|
var recommendations = categoryElement.Descendants().Where(d => d.Name.LocalName == "recommendations");
|
|
var content = recommendations.Descendants();
|
|
recommendation = string.Join("\r\n", content.ToList().Select(n => (n.Name.LocalName == "bulletitem" ? "- " : "") + n.Attribute("text")?.Value));
|
|
|
|
id = Convert.ToInt32(module.Attribute("cweid").Value);
|
|
name = module.Attribute("cwename").Value;
|
|
|
|
var staticFlaws = module.XPathSelectElements("./*").Where(m => m.Name.LocalName == "staticflaws");
|
|
var flaws = (staticFlaws.SelectMany(m => m.XPathSelectElements("./*").Where(sf => sf.Name.LocalName == "flaw")))?.ToList()
|
|
.Select(f => new Flaw(f))
|
|
.GroupBy(grp => new { grp.module, grp.type, grp.description })
|
|
.Select(x => x.First());
|
|
|
|
details = flaws
|
|
.Where(f => !f.hasMitigations)
|
|
.OrderBy(d => d.type).ThenBy(d => d.module).ThenBy(d => d.description);
|
|
|
|
count = details.Count();
|
|
}
|
|
|
|
object ToDump() => new
|
|
{
|
|
Info = new
|
|
{
|
|
Name = name,
|
|
Category = $"{category} ({id})",
|
|
Severity = severity.SeverityLabel(),
|
|
wo_Tests = count
|
|
},
|
|
recommendation
|
|
|
|
};
|
|
} |