Skip to content

Commit

Permalink
Merge pull request #34 from Kretchen001/31-search-dependency-tree
Browse files Browse the repository at this point in the history
31 search dependency tree
  • Loading branch information
KnYL3R authored Feb 22, 2024
2 parents 9d78d72 + 19f36d2 commit 188d454
Show file tree
Hide file tree
Showing 12 changed files with 502 additions and 181 deletions.
9 changes: 6 additions & 3 deletions code/AmIVulnerable/AmIVulnerable/Controllers/DbController.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using LiteDbLib.Controller;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Routing;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Modells;
using Newtonsoft.Json;
using SerilogTimings;
Expand Down Expand Up @@ -146,11 +147,13 @@ public async Task<IActionResult> CheckPackageListAsync([FromBody] List<Tuple<str
if (item.Item1.Equals("")) {
continue;
}
using (Operation.Time($"")) {
//results.AddRange(searchDbController.SearchSinglePackage(item.Item1));
using (Operation.Time($"Time by mono {item.Item1}")) {
results.AddRange(searchDbController.SearchSinglePackage(item.Item1));
}
}
results = await searchDbController.SearchPackagesAsList(strings);
using (Operation.Time($"Time by pipe")) {
results = await searchDbController.SearchPackagesAsList(strings);
}
if (results.Count > 0) {
return Ok(JsonConvert.SerializeObject(results));
}
Expand Down
114 changes: 112 additions & 2 deletions code/AmIVulnerable/AmIVulnerable/Controllers/DependeciesController.cs
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
using Microsoft.AspNetCore.Mvc;
using LiteDbLib.Controller;
using Microsoft.AspNetCore.Mvc;
using Modells;
using Modells.Packages;
using Newtonsoft.Json;
using System.Diagnostics;
using System.Text.Json;

using F = System.IO.File;

namespace AmIVulnerable.Controllers {
Expand All @@ -14,6 +14,7 @@ namespace AmIVulnerable.Controllers {
public class DependeciesController : ControllerBase {

[HttpGet]
[Route("ExtractTree")]
public IActionResult ExtractDependencies([FromHeader] ProjectType projectType) {
switch (projectType) {
case ProjectType.NodeJs: {
Expand All @@ -29,6 +30,29 @@ public IActionResult ExtractDependencies([FromHeader] ProjectType projectType) {
}
}

[HttpGet]
[Route("ExtractAndAnalyzeTree")]
public async Task<IActionResult> ExtractAndAnalyzeTreeAsync([FromHeader] ProjectType projectType) {
switch (projectType) {
case ProjectType.NodeJs: {
ExecuteCommand("npm", "install");
ExecuteCommand("del", "tree.json");
ExecuteCommand("npm", "list --all --json >> tree.json");
List<NodePackage> depTree = ExtractTree(AppDomain.CurrentDomain.BaseDirectory + "rawAnalyze/tree.json");
List<NodePackageResult> resTree = await analyzeTreeAsync(depTree) ?? [];

Check warning on line 42 in code/AmIVulnerable/AmIVulnerable/Controllers/DependeciesController.cs

View workflow job for this annotation

GitHub Actions / build-and-test-ubuntu-latest

Nullability of reference types in value of type 'List<NodePackageResult?>' doesn't match target type 'List<NodePackageResult>'.

Check warning on line 42 in code/AmIVulnerable/AmIVulnerable/Controllers/DependeciesController.cs

View workflow job for this annotation

GitHub Actions / build-and-test-ubuntu-latest

Nullability of reference types in value of type 'List<NodePackageResult?>' doesn't match target type 'List<NodePackageResult>'.

Check warning on line 42 in code/AmIVulnerable/AmIVulnerable/Controllers/DependeciesController.cs

View workflow job for this annotation

GitHub Actions / build-and-test-windows-latest

Nullability of reference types in value of type 'List<NodePackageResult?>' doesn't match target type 'List<NodePackageResult>'.

Check warning on line 42 in code/AmIVulnerable/AmIVulnerable/Controllers/DependeciesController.cs

View workflow job for this annotation

GitHub Actions / build-and-test-windows-latest

Nullability of reference types in value of type 'List<NodePackageResult?>' doesn't match target type 'List<NodePackageResult>'.

Check warning on line 42 in code/AmIVulnerable/AmIVulnerable/Controllers/DependeciesController.cs

View workflow job for this annotation

GitHub Actions / build-and-test-macOS-latest

Nullability of reference types in value of type 'List<NodePackageResult?>' doesn't match target type 'List<NodePackageResult>'.

Check warning on line 42 in code/AmIVulnerable/AmIVulnerable/Controllers/DependeciesController.cs

View workflow job for this annotation

GitHub Actions / build-and-test-macOS-latest

Nullability of reference types in value of type 'List<NodePackageResult?>' doesn't match target type 'List<NodePackageResult>'.
if (resTree.Count != 0) {
return Ok(JsonConvert.SerializeObject(resTree));
}
else {
return StatusCode(299, "Keine Schwachstelle gefunden.");
}
}
default: {
return BadRequest();
}
}
}

private void ExecuteCommand(string prog, string command) {
ProcessStartInfo process = new ProcessStartInfo {
FileName = "cmd",
Expand Down Expand Up @@ -74,5 +98,91 @@ private NodePackage ExtractDependencyInfo(JsonProperty dependency) {

return nodePackage;
}

private async Task<List<NodePackageResult?>?> analyzeTreeAsync(List<NodePackage> depTree) {
List<Tuple<string, string>> nodePackages = [];
// preperation list
foreach (NodePackage x in depTree) {
List<NodePackage> y = analyzeSubtree(x);
foreach (NodePackage z in y) {
Tuple<string, string> tuple = new Tuple<string, string>(z.Name, z.Version);
if (!nodePackages.Contains(tuple)) {
nodePackages.Add(tuple);
}
}
}
// analyze list
SearchDbController searchDbController = new SearchDbController();
List<string> designation = [];
foreach (Tuple<string, string> x in nodePackages) {
designation.Add(x.Item1);
}

List<CveResult> results = await searchDbController.SearchPackagesAsList(designation);
//List<CveResult> results = searchDbController.SearchPackagesAsListMono(designation);

// find the critical points
if (results.Count == 0) {
return null;
}
List<NodePackageResult?> resulstList = [];
foreach (NodePackage x in depTree) {
NodePackageResult? temp = checkVulnerabilities(x, results);
if (temp is not null) {
resulstList.Add(temp);
}
}
return resulstList ?? [];
}

private List<NodePackage> analyzeSubtree(NodePackage nodePackage) {
List<NodePackage> res = [];
foreach(NodePackage x in nodePackage.Dependencies) {
res.AddRange(analyzeSubtree(x));
}
res.Add(nodePackage);
return res;
}

private NodePackageResult? checkVulnerabilities(NodePackage package, List<CveResult> cveData) {
NodePackageResult r = new NodePackageResult() {
Name = "",
isCveTracked = false
};
foreach (NodePackage x in package.Dependencies) {
NodePackageResult? temp = checkVulnerabilities(x, cveData);
if (temp is not null) {
r.Dependencies.Add(temp);
}
}
foreach (CveResult x in cveData) { // check
if (x.Designation.Equals(package.Name)) {
r.isCveTracked = true;
}
}
if (r.isCveTracked == false && !depCheck(r)) {
return null;
}
r.Name = package.Name;
r.Version = package.Version;
return r;
}

private bool depCheck(NodePackageResult package) {
foreach (NodePackageResult x in package.Dependencies) {
bool isTracked = depCheck(x);
if (isTracked) {
goto isTrue;
}
}
if (package.isCveTracked) {
return true;
}
else {
return false;
}
isTrue:
return true;
}
}
}
138 changes: 74 additions & 64 deletions code/AmIVulnerable/LiteDbLib/Controller/SearchDbController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ public SearchDbController() {
public List<CveResult> SearchSinglePackage(string designation) {
List<CveResult> results = [];
foreach (string dbFile in dbFiles) {
Console.WriteLine($"Akutell - {dbFile}");
//Console.WriteLine($"Akutell - {dbFile}");
using (LiteDatabase db = new LiteDatabase($"{SaveDir}\\{dbFile}")) {
ILiteCollection<CVEcomp> col = db.GetCollection<CVEcomp>(tableName);

Expand Down Expand Up @@ -73,21 +73,25 @@ public List<CveResult> SearchSinglePackage(string designation) {

public async Task<List<CveResult>> SearchPackagesAsList(List<string> designations) {
List<CveResult> results = [];
int pipeCount = 0;
int designtaionSeriesSum = Enumerable.Range(1, designations.Count).Sum();
int runCounter = 0, fillPipeCount = 0, absoluteRun = designations.Count * dbFiles.Count, fullPipeCount = 0, drainCount = 0;
if (designations.Count > dbFiles.Count) {
fillPipeCount = Enumerable.Range(1, dbFiles.Count).Sum();
}
else {
fillPipeCount = Enumerable.Range(1, designations.Count).Sum();
}
for (int i = 0; i < designations.Count; i += 1) {
if (pipeCount < designtaionSeriesSum) { // fill pipe
int j = i;
int dbFilePosition = dbFiles.Count - 1;
while (j >= 0 && dbFilePosition >= 0) {
Task<List<CveResult>>[] tasks = new Task<List<CveResult>>[j + 1];
foreach (int taskDbIndex in Enumerable.Range(0, dbFiles.Count - 1)) {
if (runCounter < fillPipeCount) { //fill the pipe
int tempI = i, dbFilePosition = dbFiles.Count - 1;
while (tempI >= 0 && dbFilePosition >= 0) {
Task<List<CveResult>>[] tasks = new Task<List<CveResult>>[tempI + 1];
foreach (int taskDbIndex in Enumerable.Range(0, dbFiles.Count)) {
string db = dbFiles[dbFilePosition];
string des = designations[j];
string des = designations[tempI];
tasks[taskDbIndex] = Task.Run(() => SearchInDb(db, des));
pipeCount += 1;
dbFilePosition -= 1; j -= 1;
if (j < 0) {
runCounter += 1;
dbFilePosition -= 1; tempI -= 1;
if (tempI < 0) {
break;
}
}
Expand All @@ -101,77 +105,83 @@ public async Task<List<CveResult>> SearchPackagesAsList(List<string> designation
i -= 1; // if pipe filled let check the pipeCount again and reset so the highest element
}
}
else if ((pipeCount != (designtaionSeriesSum - designations.Count))
&& (
(
(designations.Count > dbFiles.Count) && ((pipeCount - dbFiles.Count) < designtaionSeriesSum)
) // more designations, so check the dbCounter
||
(
(designations.Count < dbFiles.Count) && (pipeCount - designations.Count) < designtaionSeriesSum)
) // more dbFiles, so check the designationCounter
)
{ // fill the pipe with new items and remove old
int j = i;
int dbFilePosition = dbFiles.Count - 2;
while (j >= 0 && dbFilePosition >= 0) {
Task<List<CveResult>>[] tasks = new Task<List<CveResult>>[j + 1];
foreach (int taskDbIndex in Enumerable.Range(0, dbFiles.Count - 1)) {
string db = dbFiles[dbFilePosition];
string des = designations[j];
tasks[taskDbIndex] = Task.Run(() => SearchInDb(db, des));
pipeCount += 1;
dbFilePosition -= 1; j -= 1;
if (j < 0) {
break;
}
}
List<CveResult>[] res = await Task.WhenAll(tasks);
//await Console.Out.WriteLineAsync(); // only for debug check
foreach (List<CveResult> x in res) {
results.AddRange(x);
}
if (dbFilePosition >= 0) {
j = i;
dbFilePosition += (designations.Count - 1);
}
else if (runCounter <= (absoluteRun - fillPipeCount)) { // fill constant the pipe with new items
int taskAmount = dbFiles.Count - 1;
if (dbFiles.Count > designations.Count) {
taskAmount = designations.Count - 1;
}
int dbFilePosition = dbFiles.Count - 1;
Task<List<CveResult>>[] tasks = new Task<List<CveResult>>[taskAmount];
for (int taskDbIndex = 0; taskDbIndex < taskAmount; taskDbIndex += 1) {
//await Console.Out.WriteLineAsync($"{dbFilePosition - taskDbIndex - fullPipeCount} - i:{i} - {i - taskDbIndex}");
string db = dbFiles[dbFilePosition - taskDbIndex - fullPipeCount];
string des = designations[i - taskDbIndex];
tasks[taskDbIndex] = Task.Run(() => SearchInDb(db, des));
runCounter += 1;
}
List<CveResult>[] res = await Task.WhenAll(tasks);
//await Console.Out.WriteLineAsync(); // only for debug check
foreach (List<CveResult> x in res) {
results.AddRange(x);
}
if (i == (designations.Count - 1)) {
i -= 1; // if pipe filled let check the pipeCount again and reset so the highest element
}
if (dbFiles.Count > designations.Count) {
fullPipeCount += 1;
}
}
else { // drain the pipe
int j = i;
int drainCount = 1;
int dbFilePosition = designations.Count - 2;
while (j >= drainCount && dbFilePosition >= 0) {
Task<List<CveResult>>[] tasks = new Task<List<CveResult>>[dbFilePosition + 1];
foreach (int taskDbIndex in Enumerable.Range(0, dbFiles.Count - 1)) {
string db = dbFiles[dbFilePosition];
string des = designations[j];
else /* runCounter >= (absoluteRun - fillPipeCount) */ {
int finishedCount = 0;
for (int j = fillPipeCount; j != (-1 * fillPipeCount); /*nothing*/) {
int rest = dbFiles.Count - 1 - drainCount + finishedCount;
if (dbFiles.Count > designations.Count) {
rest = i - drainCount;
}
if (rest < 0) {
break;
}
//await Console.Out.WriteLineAsync($"Rest: {rest}");
int dbFilePosition = dbFiles.Count - 1;
Task<List<CveResult>>[] tasks = new Task<List<CveResult>>[rest];
for (int taskDbIndex = 0; taskDbIndex < rest; taskDbIndex += 1) {
string db, des;
db = dbFiles[dbFilePosition - taskDbIndex - drainCount + finishedCount];
des = designations[i - taskDbIndex - drainCount];

//await Console.Out.WriteLineAsync($"{dbFilePosition - taskDbIndex - drainCount + finishedCount} | {db} - {i - taskDbIndex} | {des}");
tasks[taskDbIndex] = Task.Run(() => SearchInDb(db, des));
pipeCount += 1;
dbFilePosition -= 1; j -= 1;
if (j < 0 || dbFilePosition == -1) {
break;
}
runCounter += 1;
j -= 1;
}
List<CveResult>[] res = await Task.WhenAll(tasks);
//await Console.Out.WriteLineAsync(); // only for debug check
foreach (List<CveResult> x in res) {
results.AddRange(x);
}
drainCount += 1;
if (dbFilePosition <= 0) {
j = i;
dbFilePosition += (designations.Count - drainCount);
if (dbFiles.Count < designations.Count && (dbFiles.Count + drainCount <= designations.Count)) {
finishedCount += 1;
}
}
}
}
return results;
}

public List<CveResult> SearchPackagesAsListMono(List<string> designations) {
List<CveResult> results = [];
foreach (string designation in designations) {
foreach (string dbfile in dbFiles) {
results.AddRange(SearchInDb(dbfile, designation));
//Console.WriteLine($"{dbfile} search after {designation}");
}
//results.ForEach(x => Console.Write(x.Designation + " "));
//Console.WriteLine();
}
return results;
}

private List<CveResult> SearchInDb(string dbFile, string designation) {
//await Console.Out.WriteLineAsync($"{dbFile} search for {designation}"); // only for debug check
List<CveResult> results = [];
Expand Down
12 changes: 12 additions & 0 deletions code/AmIVulnerable/Modells/Packages/NodePackageResult.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
namespace Modells.Packages {
public class NodePackageResult {
public string Name { get; set; } = "";
public string Version { get; set; } = "";
public bool isCveTracked { get; set; } = false;
public List<NodePackageResult> Dependencies { get; set; } = [];

/// <summary>Empty ctor</summary>
public NodePackageResult() {
}
}
}
Loading

0 comments on commit 188d454

Please sign in to comment.