private void GenerateUserData(FakeHealthCheckDataGeneratorDomainModel model, HealthcheckData healthcheckData) { healthcheckData.UserAccountData = new HealthcheckAccountData(); healthcheckData.AdminLastLoginDate = DateBetween2Dates(healthcheckData.DomainCreation, DateTime.Now);; healthcheckData.AdminAccountName = "Administrator"; int size = GetCountFromSize(model); for (int i = 0; i < size; i++) { ADItem x = new ADItem(); x.DistinguishedName = "CN=123"; // disabled x.UserAccountControl += BoolOnChance(15) * 0x00000002; //preauth x.UserAccountControl += BoolOnChance(1) * 0x400000; // locked x.UserAccountControl += BoolOnChance(4) * 0x00000010; // pwd never expires x.UserAccountControl += BoolOnChance(10) * 0x00010000; // pwd not required x.UserAccountControl += BoolOnChance(2) * 0x00000020; // trusted to authenticate x.UserAccountControl += BoolOnChance(2) * 0x80000; x.PrimaryGroupID = 515 + BoolOnChance(1); new HealthcheckAnalyzer().ProcessAccountData(healthcheckData.UserAccountData, x, false); } healthcheckData.LoginScript = new List <HealthcheckLoginScriptData>(); }
public static void ReComputeTotals(HealthcheckData healthcheckData) { // consolidate scores healthcheckData.GlobalScore = 0; healthcheckData.StaleObjectsScore = 0; healthcheckData.PrivilegiedGroupScore = 0; healthcheckData.TrustScore = 0; healthcheckData.AnomalyScore = 0; foreach (HealthcheckRiskRule rule in healthcheckData.RiskRules) { switch (rule.Category) { case HealthcheckRiskRuleCategory.Anomalies: healthcheckData.AnomalyScore += rule.Points; break; case HealthcheckRiskRuleCategory.PrivilegedAccounts: healthcheckData.PrivilegiedGroupScore += rule.Points; break; case HealthcheckRiskRuleCategory.StaleObjects: healthcheckData.StaleObjectsScore += rule.Points; break; case HealthcheckRiskRuleCategory.Trusts: healthcheckData.TrustScore += rule.Points; break; } } // limit to 100 if (healthcheckData.StaleObjectsScore > 100) { healthcheckData.StaleObjectsScore = 100; } if (healthcheckData.PrivilegiedGroupScore > 100) { healthcheckData.PrivilegiedGroupScore = 100; } if (healthcheckData.TrustScore > 100) { healthcheckData.TrustScore = 100; } if (healthcheckData.AnomalyScore > 100) { healthcheckData.AnomalyScore = 100; } // max of all scores healthcheckData.GlobalScore = Math.Max(healthcheckData.StaleObjectsScore, Math.Max(healthcheckData.PrivilegiedGroupScore, Math.Max(healthcheckData.TrustScore, healthcheckData.AnomalyScore))); }
private void GenerateGPOData(FakeHealthCheckDataGeneratorDomainModel model, HealthcheckData healthcheckData) { healthcheckData.GPPPassword = new List <GPPPassword>(); healthcheckData.GPPRightAssignment = new List <GPPRightAssignment>(); healthcheckData.GPPLoginAllowedOrDeny = new List <GPPRightAssignment>(); healthcheckData.GPPPasswordPolicy = new List <GPPSecurityPolicy>(); healthcheckData.GPOLsaPolicy = new List <GPPSecurityPolicy>(); healthcheckData.GPOScreenSaverPolicy = new List <GPPSecurityPolicy>(); healthcheckData.TrustedCertificates = new List <HealthcheckCertificateData>(); healthcheckData.GPOLoginScript = new List <HealthcheckGPOLoginScriptData>(); healthcheckData.GPOLocalMembership = new List <GPOMembership>(); healthcheckData.GPOEventForwarding = new List <GPOEventForwardingInfo>(); healthcheckData.GPODelegation = new List <GPODelegationData>(); healthcheckData.GPPFileDeployed = new List <GPPFileDeployed>(); healthcheckData.GPOAuditSimple = new List <GPOAuditSimpleData>(); healthcheckData.GPOAuditAdvanced = new List <GPOAuditAdvancedData>(); }
private static void CheckForHCDataUnknownModel(HealthcheckData data) { foreach (var rule in data.RiskRules) { // report was generated by an older version of PingCastle if (rule.Model == HealthcheckRiskModelCategory.Unknown) { foreach (var r in HealthcheckRules.Rules) { if (r.Id == rule.RiskId) { rule.Model = r.Model; break; } } } } }
public HealthcheckData GenerateSingleReport(FakeHealthCheckDataGeneratorDomainModel model) { var healthcheckData = new HealthcheckData(); Trace.WriteLine("Gathering general data"); GenerateGeneralData(model, healthcheckData); Trace.WriteLine("Gathering user data"); GenerateUserData(model, healthcheckData); Trace.WriteLine("Gathering computer data"); GenerateComputerData(model, healthcheckData); Trace.WriteLine("Gathering trust data"); GenerateTrust(model, healthcheckData); Trace.WriteLine("Gathering privileged group and permissions data"); GeneratePrivilegedData(model, healthcheckData); Trace.WriteLine("Gathering delegation data"); GenerateDelegation(model, healthcheckData); Trace.WriteLine("Gathering gpo data"); GenerateGPOData(model, healthcheckData); Trace.WriteLine("Gathering anomaly data"); GenerateAnomalyData(model, healthcheckData); Trace.WriteLine("Gathering domain controller data"); Trace.WriteLine("Gathering network data"); GenerateNetworkData(model, healthcheckData); Trace.WriteLine("Computing risks"); var rules = new RuleSet <HealthcheckData>(); healthcheckData.RiskRules = new List <HealthcheckRiskRule>(); foreach (var rule in rules.ComputeRiskRules(healthcheckData)) { HealthcheckRiskRule risk = new HealthcheckRiskRule(); risk.Points = rule.Points; risk.Category = rule.Category; risk.Model = rule.Model; risk.RiskId = rule.RiskId; risk.Rationale = rule.Rationale; risk.Details = rule.Details; healthcheckData.RiskRules.Add(risk); } Trace.WriteLine("Done"); return(healthcheckData); }
private void GenerateSimplifiedJason(StringBuilder sb, GraphNode node) { sb.Append("{"); sb.Append(" \"name\": \"" + EscapeJsonString(node.Domain.DomainName) + "\"\r\n"); sb.Append(" ,\"shortname\": \"" + EscapeJsonString(node.Domain.DomainName.Split('.')[0]) + "\"\r\n"); if (node.Forest != null && node.Forest != node.Domain) { sb.Append(" ,\"forest\": \"" + EscapeJsonString(node.Forest.DomainName) + "\""); } HealthcheckData data = node.HealthCheckData; if (data != null) { sb.Append(" ,\"score\": " + data.GlobalScore); sb.Append(" ,\"staleObjectsScore\": " + data.StaleObjectsScore); sb.Append(" ,\"privilegiedGroupScore\": " + data.PrivilegiedGroupScore); sb.Append(" ,\"trustScore\": " + data.TrustScore); sb.Append(" ,\"anomalyScore\": " + data.AnomalyScore); } var entity = node.Entity; if (entity != null) { sb.Append(entity.GetJasonOutput()); } if (node.Trusts.Count > 0) { sb.Append(" ,\"children\": [\r\n"); int numChildren = 0; foreach (GraphEdge edge in node.Trusts.Values) { if (numChildren != 0) { sb.Append(",\r\n"); } GenerateSimplifiedJason(sb, edge.Destination); numChildren++; } sb.Append(" ]\r\n"); } sb.Append("}"); }
public void ComputeRiskRules(HealthcheckData healthcheckData) { healthcheckData.RiskRules = new List <HealthcheckRiskRule>(); Trace.WriteLine("Begining to run risk rule"); foreach (HeatlcheckRuleBase rule in Rules) { Trace.WriteLine("Rule: " + rule.GetType().ToString()); ReInitRule(rule); if (rule.Analyze(healthcheckData)) { Trace.WriteLine(" matched"); HealthcheckRiskRule risk = new HealthcheckRiskRule(); risk.Points = rule.Points; risk.Category = rule.Category; risk.Model = rule.Model; risk.RiskId = rule.Id; risk.Rationale = rule.Rationale; risk.Details = rule.Details; healthcheckData.RiskRules.Add(risk); } } Trace.WriteLine("Risk rule run stopped"); ReComputeTotals(healthcheckData); }
public GraphNode Locate(HealthcheckData data) { return(Locate(data.Domain)); }
private static void GenerateGeneralData(FakeHealthCheckDataGeneratorDomainModel model, HealthcheckData healthcheckData) { string fqdn; if (model.Forest == null) { fqdn = FQDNGenerator(); healthcheckData.ForestFQDN = fqdn; } else { fqdn = ChildGenerator() + "." + model.Forest.ForestFQDN; healthcheckData.ForestFQDN = model.Forest.ForestFQDN; } healthcheckData.DomainFQDN = fqdn; healthcheckData.DomainSid = GenerateRandomSid(); if (model.Forest != null) { healthcheckData.DomainCreation = DateBetween2Dates(model.Forest.DomainCreation, DateTime.Now); healthcheckData.ForestFunctionalLevel = model.Forest.ForestFunctionalLevel; } else { healthcheckData.DomainCreation = DateTime.Now.AddYears(-5).AddDays(-1 * rnd.Next(10 * 365)); healthcheckData.ForestFunctionalLevel = rnd.Next(0, 8); } // adding the domain Netbios name healthcheckData.NetBIOSName = healthcheckData.DomainFQDN.Split('.')[0]; healthcheckData.DomainFunctionalLevel = rnd.Next(healthcheckData.ForestFunctionalLevel, 8); healthcheckData.SchemaVersion = SchemaVersion(healthcheckData.ForestFunctionalLevel); healthcheckData.SchemaInternalVersion = 1; healthcheckData.SchemaLastChanged = DateBetween2Dates(healthcheckData.DomainCreation, DateTime.Now); healthcheckData.GenerationDate = DateTime.Now; healthcheckData.IsRecycleBinEnabled = true; Version version = Assembly.GetExecutingAssembly().GetName().Version; healthcheckData.EngineVersion = version.ToString(4); healthcheckData.Level = PingCastleReportDataExportLevel.Full; }
private void GenerateComputerData(FakeHealthCheckDataGeneratorDomainModel model, HealthcheckData healthcheckData) { healthcheckData.OperatingSystem = new List <HealthcheckOSData>(); healthcheckData.ComputerAccountData = new HealthcheckAccountData(); int size = GetCountFromSize(model); for (int i = 0; i < size; i++) { ADItem x = new ADItem(); x.DistinguishedName = "CN=123"; // disabled x.UserAccountControl += BoolOnChance(15) * 0x00000002; //preauth x.UserAccountControl += BoolOnChance(1) * 0x400000; // locked x.UserAccountControl += BoolOnChance(4) * 0x00000010; // pwd never expires x.UserAccountControl += BoolOnChance(10) * 0x00010000; // pwd not required x.UserAccountControl += BoolOnChance(2) * 0x00000020; // trusted to authenticate x.UserAccountControl += BoolOnChance(2) * 0x80000; x.PrimaryGroupID = 515 + BoolOnChance(1); new HealthcheckAnalyzer().ProcessAccountData(healthcheckData.ComputerAccountData, x, true); } healthcheckData.LoginScript = new List <HealthcheckLoginScriptData>(); healthcheckData.DomainControllers = new List <HealthcheckDomainController>(); size = (int)Math.Exp(Math.Log10(size) / 2); if (size < 1) { size = 1; } for (int i = 0; i < size; i++) { HealthcheckDomainController dc = new HealthcheckDomainController(); dc.DCName = "DC" + i; dc.CreationDate = DateBetween2Dates(healthcheckData.DomainCreation, DateTime.Now); // last logon timestam can have a delta of 14 days dc.LastComputerLogonDate = DateTime.Now.AddDays(-1 * rnd.Next(180)); dc.DistinguishedName = "DC=DC"; dc.OperatingSystem = "Windows 2019"; healthcheckData.DomainControllers.Add(dc); } }
private void GenerateAnomalyData(FakeHealthCheckDataGeneratorDomainModel model, HealthcheckData healthcheckData) { healthcheckData.SmartCardNotOK = new List <HealthcheckAccountDetailData>(); }
private void GenerateDelegation(FakeHealthCheckDataGeneratorDomainModel model, HealthcheckData healthcheckData) { healthcheckData.Delegations = new List <HealthcheckDelegationData>(); }
private void GeneratePrivilegedData(FakeHealthCheckDataGeneratorDomainModel model, HealthcheckData healthcheckData) { healthcheckData.Delegations = new List <HealthcheckDelegationData>(); healthcheckData.ControlPaths = new CompromiseGraphData(); healthcheckData.ControlPaths.Data = new List <SingleCompromiseGraphData>(); healthcheckData.PrivilegedGroups = new List <HealthCheckGroupData>(); healthcheckData.AllPrivilegedMembers = new List <HealthCheckGroupMemberData>(); }
private void GenerateNetworkData(FakeHealthCheckDataGeneratorDomainModel model, HealthcheckData healthcheckData) { healthcheckData.Sites = new List <HealthcheckSite>(); }
private void GenerateTrust(FakeHealthCheckDataGeneratorDomainModel model, HealthcheckData healthcheckData) { healthcheckData.Trusts = new List <HealthCheckTrustData>(); }
public string GenerateJsonFileFull(MigrationChecker migrationChecker) { Dictionary <int, int> idconversiontable = new Dictionary <int, int>(); StringBuilder sb = new StringBuilder(); sb.Append("{"); // START OF NODES sb.Append(" \"nodes\": ["); // it is important to put the root node as the first node for correct display int nodenumber = 0; bool firstnode = true; foreach (GraphNode node in Nodes) { if (!firstnode) { sb.Append(" },"); } else { firstnode = false; } sb.Append(" {"); sb.Append(" \"id\": " + nodenumber + ","); sb.Append(" \"shortname\": \"" + EscapeJsonString(node.Domain.DomainName.Split('.')[0]) + "\""); if (node.IsPartOfARealForest()) { sb.Append(" ,\"forest\": \"" + EscapeJsonString(node.Forest.DomainName) + "\""); } var entity = node.Entity; if (entity != null) { sb.Append(entity.GetJasonOutput()); } HealthcheckData data = node.HealthCheckData; sb.Append(" ,\"name\": \"" + EscapeJsonString(node.Domain.DomainName) + "\""); if (data != null) { sb.Append(" ,\"score\": " + data.GlobalScore); sb.Append(" ,\"staleObjectsScore\": " + data.StaleObjectsScore); sb.Append(" ,\"privilegiedGroupScore\": " + data.PrivilegiedGroupScore); sb.Append(" ,\"trustScore\": " + data.TrustScore); sb.Append(" ,\"anomalyScore\": " + data.AnomalyScore); if (data.UserAccountData != null) { sb.Append(" ,\"activeusers\": " + data.UserAccountData.NumberActive); } if (data.ComputerAccountData != null) { sb.Append(" ,\"activecomputers\": " + data.ComputerAccountData.NumberActive); } } sb.Append(" ,\"dist\": null"); idconversiontable[node.Id] = nodenumber++; } if (Nodes.Count > 0) { sb.Append(" }"); } sb.Append(" ],"); // END OF NODES // START LINKS sb.Append(" \"links\": ["); // avoid a final "," bool absenceOfLinks = true; // subtility: try to regroup 2 links at one if all the properties match // SkipLink contains the edge to ignore List <GraphEdge> SkipLink = new List <GraphEdge>(); // foreach edge foreach (GraphNode node in Nodes) { foreach (GraphEdge edge in node.Trusts.Values) { if (SkipLink.Contains(edge)) { continue; } // for unidirectional trusts // keep only the remote part of the trust. SID Filtering is unknown (avoid evaluating SID Filtering when no value is available) if (edge.TrustDirection == 2 && edge.IsAuthoritative == false) { continue; } // keep only the reception of the trust. SID Filtering status is sure if (edge.TrustDirection == 1 && edge.Destination.Trusts[edge.Source.Domain].IsAuthoritative == true) { continue; } // trying to simplify bidirectional trusts bool isBidirectional = false; if (edge.IsEquivalentToReverseEdge(migrationChecker)) { GraphEdge reverseEdge = edge.Destination.Trusts[edge.Source.Domain]; // keep only one of the two part of the bidirectional trust SkipLink.Add(reverseEdge); isBidirectional = true; } if (!absenceOfLinks) { sb.Append(" },"); } else { absenceOfLinks = false; } sb.Append(" {"); if (edge.TrustDirection == 2) { sb.Append(" \"source\": " + idconversiontable[edge.Destination.Id] + ","); sb.Append(" \"target\": " + idconversiontable[edge.Source.Id] + ","); } else { sb.Append(" \"source\": " + idconversiontable[edge.Source.Id] + ","); sb.Append(" \"target\": " + idconversiontable[edge.Destination.Id] + ","); } // blue: 25AEE4 // orange: FA9426 string sidFiltering = edge.GetSIDFilteringStatus(migrationChecker); if (!edge.IsActive) { // purple sb.Append(" \"color\": \"#A856AA\","); } else { switch (sidFiltering) { case "Remote": // yellow sb.Append(" \"color\": \"#FDC334\","); break; case "Migration": // blue sb.Append(" \"color\": \"#25AEE4\","); break; case "No": // red sb.Append(" \"color\": \"#E75351\","); break; case "Yes": // green sb.Append(" \"color\": \"#74C25C\","); break; } } if (isBidirectional) { sb.Append(" \"type\": \"double\","); } sb.Append(" \"rels\": [\""); sb.Append("Attributes=" + edge.GetTrustAttributes() + ","); if (edge.CreationDate != DateTime.MinValue) { sb.Append("CreationDate=" + edge.CreationDate.ToString("yyyy-MM-dd") + ","); } sb.Append("SIDFiltering=" + sidFiltering); sb.Append((edge.IsActive ? null : ",Inactive")); sb.Append("\"]"); } } if (!absenceOfLinks) { sb.Append(" }"); } sb.Append(" ]"); // END OF LINKS sb.Append("}"); return(sb.ToString()); }