Пример #1
0
 public bool RegenerateHtmlTask()
 {
     return(StartTask("Regenerate html report",
                      () =>
     {
         if (!File.Exists(FileOrDirectory))
         {
             WriteInRed("The file " + FileOrDirectory + " doesn't exist");
             return;
         }
         if (FileOrDirectory.StartsWith("ad_cg_"))
         {
             CompromiseGraphData data = DataHelper <CompromiseGraphData> .LoadXml(FileOrDirectory);
             HealthCheckReportCompromiseGraph report = new HealthCheckReportCompromiseGraph(data, License);
             report.GenerateReportFile("ad_cg_" + data.DomainFQDN + ".html");
         }
         else
         {
             HealthcheckData healthcheckData = DataHelper <HealthcheckData> .LoadXml(FileOrDirectory);
             HealthCheckReportSingle report = new HealthCheckReportSingle(healthcheckData, License);
             report.GenerateReportFile("ad_hc_" + healthcheckData.DomainFQDN + ".html");
         }
     }
                      ));
 }
Пример #2
0
 public bool RegenerateHtmlTask()
 {
     return(StartTask("Regenerate html report",
                      () =>
     {
         if (!File.Exists(FileOrDirectory))
         {
             WriteInRed("The file " + FileOrDirectory + " doesn't exist");
             return;
         }
         var fi = new FileInfo(FileOrDirectory);
         if (fi.Name.StartsWith("ad_cg_"))
         {
             CompromiseGraphData data = DataHelper <CompromiseGraphData> .LoadXml(FileOrDirectory);
             var report = new ReportCompromiseGraph();
             report.GenerateReportFile(data, License, data.GetHumanReadableFileName());
         }
         else
         {
             var healthcheckData = DataHelper <HealthcheckData> .LoadXml(FileOrDirectory);
             var endUserReportGenerator = PingCastleFactory.GetEndUserReportGenerator <HealthcheckData>();
             endUserReportGenerator.GenerateReportFile(healthcheckData, License, healthcheckData.GetHumanReadableFileName());
         }
     }
                      ));
 }
Пример #3
0
 protected override int?AnalyzeDataNew(CompromiseGraphData compromiseGraphData)
 {
     foreach (var single in compromiseGraphData.Data)
     {
         if (single.Typology != CompromiseGraphDataTypology.PrivilegedAccount)
         {
             continue;
         }
         if (single.Name != "S-1-5-32-548" && single.Name != "S-1-5-32-549")
         {
             continue;
         }
         foreach (var obj in single.Nodes)
         {
             if (obj.Type != "user")
             {
                 continue;
             }
             if (obj.Suspicious)
             {
                 continue;
             }
             return(1);
         }
     }
     return(-1);
 }
Пример #4
0
 protected override int?AnalyzeDataNew(CompromiseGraphData compromiseGraphData)
 {
     foreach (var single in compromiseGraphData.Dependancies)
     {
     }
     return(-1);
 }
 public HealthCheckReportCompromiseGraph(CompromiseGraphData compromiseGraphData, ADHealthCheckingLicense license)
 {
     this.CompromiseGraphData = compromiseGraphData;
     _license = license;
     CompromiseGraphData.Data.Sort(
         (SingleCompromiseGraphData a, SingleCompromiseGraphData b)
         =>
     {
         return(String.Compare(a.Description, b.Description));
     });
 }
Пример #6
0
        private void PrepareAnomalyAnalysisData(CompromiseGraphData data)
        {
            var reference = new Dictionary <CompromiseGraphDataObjectRisk, CompromiseGraphAnomalyAnalysisData>();

            foreach (var sg in data.Data)
            {
                CompromiseGraphAnomalyAnalysisData analysis = null;
                if (!reference.ContainsKey(sg.ObjectRisk))
                {
                    analysis = new CompromiseGraphAnomalyAnalysisData()
                    {
                        ObjectRisk = sg.ObjectRisk,
                    };
                    reference[sg.ObjectRisk] = analysis;
                }
                else
                {
                    analysis = reference[sg.ObjectRisk];
                }
                analysis.NumberOfObjectsScreened++;
                if (sg.CriticalObjectFound)
                {
                    analysis.CriticalObjectFound = true;
                }
                if (sg.IndirectMembers != null && sg.IndirectMembers.Count > 0)
                {
                    if (analysis.MaximumIndirectNumber < sg.IndirectMembers.Count)
                    {
                        analysis.MaximumIndirectNumber = sg.IndirectMembers.Count;
                    }
                    analysis.NumberOfObjectsWithIndirect++;
                    if (sg.DirectUserMembers != null && sg.DirectUserMembers.Count > 0)
                    {
                        int ratio = 100 * sg.IndirectMembers.Count / sg.DirectUserMembers.Count;
                        if (ratio > analysis.MaximumDirectIndirectRatio)
                        {
                            analysis.MaximumDirectIndirectRatio = ratio;
                        }
                    }
                }
            }
            data.AnomalyAnalysis = new List <CompromiseGraphAnomalyAnalysisData>();
            data.AnomalyAnalysis.AddRange(reference.Values);
            data.AnomalyAnalysis.Sort(
                (CompromiseGraphAnomalyAnalysisData a, CompromiseGraphAnomalyAnalysisData b)
                =>
            {
                return(((int)a.ObjectRisk).CompareTo((int)b.ObjectRisk));
            });
        }
Пример #7
0
 protected override int?AnalyzeDataNew(CompromiseGraphData compromiseGraphData)
 {
     foreach (var single in compromiseGraphData.Dependancies)
     {
         foreach (var detail in single.Details)
         {
             if (detail.Typology == CompromiseGraphDataTypology.UserDefined)
             {
                 return(1);
             }
         }
     }
     return(-1);
 }
Пример #8
0
 protected override int?AnalyzeDataNew(CompromiseGraphData compromiseGraphData)
 {
     foreach (var single in compromiseGraphData.Data)
     {
         if (single.Typology != CompromiseGraphDataTypology.PrivilegedAccount && single.Typology != CompromiseGraphDataTypology.PrivilegedAccount)
         {
             continue;
         }
         if (single.DeletedObjects != null && single.DeletedObjects.Count > 0)
         {
             return(1);
         }
     }
     return(-1);
 }
Пример #9
0
        public CompromiseGraphData GenerateReport(List <string> AdditionalNames)
        {
            CompromiseGraphData data = new CompromiseGraphData();

            data.GenerationDate = DateTime.Now;
            Version version = Assembly.GetExecutingAssembly().GetName().Version;

            data.EngineVersion = version.ToString(4);
#if DEBUG
            data.EngineVersion += " Beta";
#endif

            Dictionary <string, string> databaseProperties = storage.GetDatabaseInformation();
            data.DomainSid  = databaseProperties["DomainSid"];
            data.DomainFQDN = databaseProperties["DomainName"];
            data.Data       = new List <SingleCompromiseGraphData>();

            ProduceReportFile(data, "Account Operator", "S-1-5-32-548");
            ProduceReportFile(data, "Administrators", "S-1-5-32-544");
            ProduceReportFile(data, "Domain Administrators", data.DomainSid + "-512");
            ProduceReportFile(data, "Enterprise Administrators", data.DomainSid + "-519");
            ProduceReportFile(data, "Schema Administrators", data.DomainSid + "-518");
            ProduceReportFile(data, "Administrator", data.DomainSid + "-500");
            ProduceReportFile(data, "Backup Operators", "S-1-5-32-551");
            ProduceReportFile(data, "Certificate Publishers", data.DomainSid + "-517");
            ProduceReportFile(data, "Certificate Operators", "S-1-5-32-569");
            ProduceReportFile(data, "Domain Controllers", data.DomainSid + "-516");
            ProduceReportFile(data, "Enterprise Read Only Domain Controllers", data.DomainSid + "-498");
            ProduceReportFile(data, "Group Policy Creator Owners", data.DomainSid + "-520");
            ProduceReportFile(data, "Incoming Forest Trust Builders", "S-1-5-32-557");
            ProduceReportFile(data, "Krbtgt account", data.DomainSid + "-502");
            ProduceReportFile(data, "Network Operators", "S-1-5-32-556");
            ProduceReportFile(data, "Pre-Windows 2000 Compatible Access", "S-1-5-32-554");
            ProduceReportFile(data, "Print Operators", "S-1-5-32-550");
            ProduceReportFile(data, "Domain Root", data.DomainSid);
            ProduceReportFile(data, "Read Only Domain Controllers", data.DomainSid + "-521");
            ProduceReportFile(data, "Server Operators", "S-1-5-32-549");
            foreach (string name in AdditionalNames)
            {
                ProduceReportFile(data, name, name, true);
            }
            return(data);
        }
Пример #10
0
 private void BuildDeletedObjects(ADDomainInfo domainInfo, CompromiseGraphData data, SingleCompromiseGraphData singleCompromiseData, Dictionary <int, Node> chartNodes)
 {
     singleCompromiseData.DeletedObjects = new List <SingleCompromiseGraphDeletedData>();
     foreach (var node in chartNodes.Values)
     {
         if (String.Equals(node.Type, "foreignsecurityprincipal", StringComparison.InvariantCultureIgnoreCase))
         {
             // ignore everything but deleted accounts
             if (node.Sid.StartsWith(domainInfo.DomainSid.Value + "-"))
             {
                 singleCompromiseData.DeletedObjects.Add(new SingleCompromiseGraphDeletedData()
                 {
                     Sid = node.Sid,
                 }
                                                         );
             }
         }
     }
     singleCompromiseData.NumberOfDeletedObjects = singleCompromiseData.DeletedObjects.Count;
 }
Пример #11
0
        protected int?AnalyzeDataNew(CompromiseGraphData compromiseGraphData, int trigger)
        {
            int domainCount = 0;

            foreach (var single in compromiseGraphData.Dependancies)
            {
                foreach (var detail in single.Details)
                {
                    if (detail.Typology == CompromiseGraphDataTypology.PrivilegedAccount ||
                        detail.Typology == CompromiseGraphDataTypology.Infrastructure)
                    {
                        domainCount++;
                        break;
                    }
                }
            }
            if (domainCount > trigger)
            {
                return(1);
            }
            return(-1);
        }
Пример #12
0
 protected int?AnalyzeDataNew(CompromiseGraphData compromiseGraphData, CompromiseGraphDataObjectRisk risk, int trigger)
 {
     foreach (var analysis in compromiseGraphData.AnomalyAnalysis)
     {
         if (analysis.ObjectRisk != risk)
         {
             continue;
         }
         if (trigger == -1)
         {
             if (analysis.CriticalObjectFound)
             {
                 return(1);
             }
         }
         else if (analysis.MaximumIndirectNumber > trigger)
         {
             return(1);
         }
     }
     return(-1);
 }
Пример #13
0
 private void ProduceReportFile(CompromiseGraphData data, string description, string name, bool onDemand = false)
 {
     try
     {
         Dictionary <string, string> databaseProperties = storage.GetDatabaseInformation();
         DateTime exportDate = DateTime.Parse(databaseProperties["Date"]);
         Trace.WriteLine("Generating Description:" + description + " Name=" + name);
         int rootNodeId = storage.SearchItem(name);
         if (rootNodeId < 0)
         {
             Trace.WriteLine("Id not found for name=" + name);
             Console.WriteLine("The report " + description + " starting from " + name + " couldn't be built because the object wasn't found");
             return;
         }
         List <int> nodesid = new List <int>();
         Dictionary <int, List <Relation> > links = RetrieveLinks(rootNodeId, nodesid);
         Dictionary <int, Node>             nodes = storage.RetrieveNodes(nodesid);
         SimplifyGraph(nodes, links);
         ComputeDistance(rootNodeId, links, nodes);
         var singleCompromiseData = BuildSingleCompromiseGraphData(rootNodeId, nodes, links);
         singleCompromiseData.Name             = name;
         singleCompromiseData.Description      = description;
         singleCompromiseData.OnDemandAnalysis = onDemand;
         data.Data.Add(singleCompromiseData);
     }
     catch (Exception ex)
     {
         Console.ForegroundColor = ConsoleColor.Red;
         Console.WriteLine("Exception: " + ex.Message);
         Console.WriteLine(ex.StackTrace);
         Trace.WriteLine(ex.Message);
         Trace.WriteLine(ex.StackTrace);
         if (ex.InnerException != null)
         {
             Trace.WriteLine("innerexception: " + ex.InnerException.Message);
         }
     }
 }
 protected override int?AnalyzeDataNew(CompromiseGraphData compromiseGraphData)
 {
     return(AnalyzeDataNew(compromiseGraphData, CompromiseGraphDataObjectRisk.High, 100));
 }
Пример #15
0
 public bool ReloadXmlReport()
 {
     return(StartTask("Reload report",
                      () =>
     {
         if (!File.Exists(FileOrDirectory))
         {
             WriteInRed("The file " + FileOrDirectory + " doesn't exist");
             return;
         }
         string newfile = FileOrDirectory.Replace(".xml", "_reloaded.xml");
         string xml = null;
         string domainFQDN = null;
         if (FileOrDirectory.StartsWith("ad_hc_"))
         {
             HealthcheckData healthcheckData = DataHelper <HealthcheckData> .LoadXml(FileOrDirectory);
             domainFQDN = healthcheckData.DomainFQDN;
             DisplayAdvancement("Regenerating xml " + (EncryptReport ? " (encrypted)" : ""));
             healthcheckData.Level = ExportLevel;
             xml = DataHelper <HealthcheckData> .SaveAsXml(healthcheckData, newfile, EncryptReport);
         }
         else if (FileOrDirectory.StartsWith("ad_cg_"))
         {
             CompromiseGraphData data = DataHelper <CompromiseGraphData> .LoadXml(FileOrDirectory);
             domainFQDN = data.DomainFQDN;
             DisplayAdvancement("Regenerating xml " + (EncryptReport ? " (encrypted)" : ""));
             xml = DataHelper <CompromiseGraphData> .SaveAsXml(data, newfile, EncryptReport);
         }
         if (!String.IsNullOrEmpty(apiKey) && !String.IsNullOrEmpty(apiEndpoint))
         {
             SendViaAPI(new Dictionary <string, string>()
             {
                 { FileOrDirectory, xml }
             });
         }
         if (!String.IsNullOrEmpty(sharepointdirectory))
         {
             UploadToWebsite(newfile, xml);
         }
         if (!String.IsNullOrEmpty(sendXmlTo))
         {
             SendEmail(sendXmlTo, new List <string> {
                 domainFQDN
             },
                       new List <Attachment> {
                 Attachment.CreateAttachmentFromString(xml, newfile)
             });
         }
         if (!String.IsNullOrEmpty(sendHtmlTo))
         {
             WriteInRed("Html report ignored when xml file used as input");
         }
         if (!String.IsNullOrEmpty(sendAllTo))
         {
             WriteInRed("Html report ignored when xml file used as input");
             SendEmail(sendAllTo, new List <string> {
                 domainFQDN
             },
                       new List <Attachment> {
                 Attachment.CreateAttachmentFromString(xml, newfile)
             });
         }
     }
                      ));
 }
Пример #16
0
        private void PrepareDependancyGlobalData(CompromiseGraphData data)
        {
            var reference = new Dictionary <string, CompromiseGraphDependancyData>();

            foreach (var sg in data.Data)
            {
                foreach (SingleCompromiseGraphDependancyData d in sg.Dependancies)
                {
                    // beware: we are using exising SingleCompromiseGraphDependancyData with data a key
                    // do not modify the object !!!!
                    if (!reference.ContainsKey(d.Sid))
                    {
                        reference[d.Sid]         = new CompromiseGraphDependancyData();
                        reference[d.Sid].Details = new List <CompromiseGraphDependancyDetailData>();
                        reference[d.Sid].FQDN    = d.FQDN;
                        reference[d.Sid].Netbios = d.Netbios;
                        reference[d.Sid].Sid     = d.Sid;
                    }
                    var gdData = reference[d.Sid];
                    CompromiseGraphDependancyDetailData detail = null;
                    foreach (var a in gdData.Details)
                    {
                        if (a.Typology == sg.Typology)
                        {
                            detail = a;
                        }
                    }
                    if (detail == null)
                    {
                        detail = new CompromiseGraphDependancyDetailData()
                        {
                            Typology = sg.Typology,
                            Items    = new List <string>(),
                        };
                        reference[d.Sid].Details.Add(detail);
                    }
                    detail.NumberOfGroupImpacted++;
                    foreach (var item in d.Items)
                    {
                        if (!detail.Items.Contains(item.Sid))
                        {
                            detail.Items.Add(item.Sid);
                            if (item.Name.Contains("\\"))
                            {
                                detail.NumberOfResolvedItems++;
                            }
                            else
                            {
                                detail.NumberOfUnresolvedItems++;
                            }
                        }
                    }
                }
            }
            data.Dependancies = new List <CompromiseGraphDependancyData>(reference.Values);
            data.Dependancies.Sort((CompromiseGraphDependancyData a, CompromiseGraphDependancyData b)
                                   =>
            {
                return(string.Compare(a.Netbios, b.Netbios));
            });
        }
Пример #17
0
        private void BuildDependancies(ADDomainInfo domainInfo, CompromiseGraphData refData, SingleCompromiseGraphData singleCompromiseData, Dictionary <int, Node> chartNodes)
        {
            var reference = new Dictionary <SecurityIdentifier, SingleCompromiseGraphDependancyData>();
            var domains   = storage.GetKnownDomains();

            foreach (var node in chartNodes.Values)
            {
                if (String.Equals(node.Type, "foreignsecurityprincipal", StringComparison.InvariantCultureIgnoreCase))
                {
                    // ignore deleted accounts
                    if (node.Sid.StartsWith(domainInfo.DomainSid.Value + "-"))
                    {
                        continue;
                    }
                    SingleCompromiseGraphDependancyData data;
                    var sid       = new SecurityIdentifier(node.Sid);
                    var domainSid = sid.AccountDomainSid;
                    if (domainSid == null)
                    {
                        continue;
                    }
                    if (!reference.ContainsKey(domainSid))
                    {
                        data = new SingleCompromiseGraphDependancyData();
                        reference[domainSid] = data;
                        data.Sid             = domainSid.Value;
                        foreach (var domain in domains)
                        {
                            if (String.Equals(domain.DomainSid.Value, data.Sid, StringComparison.InvariantCultureIgnoreCase))
                            {
                                data.FQDN    = domain.DnsDomainName;
                                data.Netbios = domain.NetbiosDomainName;
                                break;
                            }
                        }
                        data.Items = new List <SingleCompromiseGraphDependancyMemberData>();
                    }
                    else
                    {
                        data = reference[domainSid];
                    }
                    if (node.Shortname.Contains("\\"))
                    {
                        if (String.IsNullOrEmpty(data.Netbios))
                        {
                            data.Netbios = node.Shortname.Split('\\')[0];
                        }
                        data.NumberOfResolvedItems++;
                    }
                    else
                    {
                        data.NumberOfUnresolvedItems++;
                    }
                    data.Items.Add(new SingleCompromiseGraphDependancyMemberData()
                    {
                        Name = node.Shortname,
                        Sid  = node.Sid,
                    }
                                   );
                }
            }
            singleCompromiseData.Dependancies = new List <SingleCompromiseGraphDependancyData>(reference.Values);
            singleCompromiseData.Dependancies.Sort(
                (SingleCompromiseGraphDependancyData a, SingleCompromiseGraphDependancyData b)
                =>
            {
                return(String.Compare(a.Netbios, b.Netbios));
            }
                );
        }
Пример #18
0
 protected override int?AnalyzeDataNew(CompromiseGraphData compromiseGraphData)
 {
     return(AnalyzeDataNew(compromiseGraphData, 0));
 }
Пример #19
0
 protected override int?AnalyzeDataNew(CompromiseGraphData compromiseGraphData)
 {
     return(AnalyzeDataNew(compromiseGraphData, CompromiseGraphDataObjectRisk.Critical, -1));
 }