Пример #1
0
        public string SolvePart2()
        {
            var workGroup = new WorkGroup(5);

            var completedSteps = new List <Node?>();
            var availableSteps = new List <Node>(_graph.Roots);

            availableSteps.Sort();

            // Initialise
            foreach (Worker worker in workGroup.Workers)
            {
                if (availableSteps.Any())
                {
                    worker.AssignStep(availableSteps.First());
                    availableSteps.RemoveAt(0);
                }
            }

            // Tick
            var totalTime = 0;

            while (completedSteps.Count < _graph.Nodes.Count)
            {
                List <Node?> workResult = workGroup.DoWork();
                if (workResult.Any())
                {
                    completedSteps.AddRange(workResult);

                    // Get newly available steps
                    foreach (var stepsReadyToComplete in completedSteps.Where(c => c != null).Select(completedStep =>
                                                                                                     _graph.GetStepsReadyToComplete(completedStep !.Name,
                                                                                                                                    string.Join(string.Empty, completedSteps.Select(c => c !.Name)))))
                    {
                        availableSteps.AddRange(stepsReadyToComplete.Select(s => new Node {
                            Name = s
                        }));
                    }

                    availableSteps = DistinctByExtension.DistinctBy(availableSteps, s => s.Name).ToList();
                    availableSteps.Sort();

                    // Need to account for "in progress" steps.
                    foreach (int index in workGroup.BusyWorkers
                             .Select(worker => availableSteps.FindIndex(s => s.Name == worker.WorkingOn?.Name))
                             .Where(index => index >= 0))
                    {
                        availableSteps.RemoveAt(index);
                    }
                }

                foreach (Worker worker in workGroup.AvailableWorkers.Where(_ => availableSteps.Any()))
                {
                    worker.AssignStep(availableSteps.First());
                    availableSteps.RemoveAt(0);
                }

                totalTime++;
            }

            return($"Part 2: {totalTime}");
        }
Пример #2
0
        public List <DeviceModel> ScanVulnerabilities(List <Host> devices)
        {
            RestClient  restClient  = new RestClient("https://exploits.shodan.io/");
            RestRequest restRequest = new RestRequest("api/search", Method.GET);

            restRequest.AddParameter("key", _APIKEY);

            var vulnerableDevices = new List <DeviceModel>();

            foreach (var device in devices)
            {
                var vulnerabilities = new List <VulnerabilityModel>();
                var openPorts       = new List <int>();

                foreach (var port in device.Ports.Where(p => p.Service.Product != null))
                {
                    var product = "";
                    var version = "";
                    openPorts.Add(port.PortNumber);

                    if (port.Service.Version == null || port.Service.Product == null)
                    {
                        continue;
                    }

                    if (port.Service.Product != null)
                    {
                        if (port.Service.Product.Contains(" "))
                        {
                            product = port.Service.Product.Substring(0,
                                                                     port.Service.Product.IndexOf(" ", StringComparison.Ordinal) + 1);
                        }
                        else
                        {
                            product = port.Service.Product;
                        }
                    }

                    if (port.Service.Version != null)
                    {
                        if (port.Service.Version.Contains(" "))
                        {
                            version = port.Service.Version.Substring(0,
                                                                     port.Service.Version.IndexOf(" ", StringComparison.Ordinal) + 1);
                        }
                        else
                        {
                            version = port.Service.Version;
                        }

                        int index = -1;

                        for (int i = 0; i < 3; i++)
                        {
                            index = version.IndexOf(".", index + 1, StringComparison.Ordinal);

                            if (index == -1)
                            {
                                break;
                            }
                        }

                        if (index > 3)
                        {
                            version = version.Substring(0, index);
                        }
                    }

                    var searchTerm = $"{product} {version}";
                    restRequest.AddParameter("query", searchTerm);

                    // Limited to 1 request per second with Shodan, in case a request returns no results we'll wait 1 second before the next.
                    Thread.Sleep(1000);

                    var     query = restClient.Execute((IRestRequest)restRequest);
                    JObject parsedQuery;

                    try
                    {
                        parsedQuery = JObject.Parse(query.Content);
                        var array = parsedQuery.GetValue("matches");

                        foreach (var jObject in array)
                        {
                            var vulnerability = new VulnerabilityModel();

                            vulnerability.Port    = port.PortNumber;
                            vulnerability.Service =
                                $"{port.Service.Name} ({port.Service.Product})";
                            vulnerability.Version = port.Service.Version;
                            if (jObject["source"] != null)
                            {
                                vulnerability.Source = jObject["source"].ToString();
                            }
                            if (jObject["type"] != null)
                            {
                                vulnerability.Type = jObject["type"].ToString();
                            }
                            if (jObject["cve"] != null && jObject["cve"].HasValues)
                            {
                                vulnerability.CVE = jObject["cve"].ToObject <string[]>()[0];
                            }
                            if (jObject["date"] != null)
                            {
                                vulnerability.Date = DateTime.Parse(jObject["date"].ToString());
                            }

                            if (jObject["description"] != null)
                            {
                                var description = jObject["description"].ToString();
                                if (description.Length > 100)
                                {
                                    //Truncate long descriptions to display to users.
                                    var tempString = description.Substring(0, 100);
                                    if (tempString.LastIndexOf(' ') > 0)
                                    {
                                        description = tempString.Substring(0, tempString.LastIndexOf(' ')) + " ...";
                                    }
                                }

                                vulnerability.Description = description;
                            }

                            vulnerabilities.Add(vulnerability);
                        }
                    }
                    catch (Exception e)
                    {
                        Console.WriteLine($"There was an error during the search.");
                    }
                }

                if (vulnerabilities.Any())
                {
                    var vulnerableDevice = new DeviceModel();
                    vulnerableDevice.OpenPorts       = openPorts;
                    vulnerableDevice.IP              = device.Address.ToString();
                    vulnerableDevice.PhysicalAddress = device.PhysicalAddress;
                    vulnerableDevice.Vendor          = device.Vendor;

                    try
                    {
                        vulnerableDevice.Hostname = Dns.GetHostEntry(device.Address).HostName;
                    }
                    catch (Exception e)
                    {
                        //GetHostEntry throws an exception if host not found.
                        vulnerableDevice.Hostname = "Hostname not found.";
                    }

                    // Remove duplicate instances of vulnerabilities by CVE
                    var vulnerabilitiesTest = DistinctByExtension.DistinctBy(vulnerabilities, x => x.CVE).ToList();

                    //Only keep top 5 most recent vulnerabilities

                    /*vulnerabilities = vulnerabilities.Where(x => x.Date.HasValue)
                     *  .OrderByDescending(x => x.Date.Value)
                     *  .Take(5).ToList();*/

                    vulnerableDevice.Vulnerabilities = vulnerabilities;

                    vulnerableDevices.Add(vulnerableDevice);

                    Console.WriteLine($"Vulnerability scan completed for {device.Address}. {vulnerableDevice.Vulnerabilities.Count} vulnerabilities found.");
                }
            }

            return(vulnerableDevices);
        }