├── .gitignore ├── ADWS ├── ADConnection.cs ├── ADDomainInfo.cs ├── ADItem.cs ├── ADWSConnection.cs ├── ADWebService.cs ├── BlockingQueue.cs ├── DomainLocator.cs ├── IADConnection.cs ├── LDAPConnection.cs ├── LinuxConnection.cs ├── LinuxFileConnection.cs ├── LinuxSidResolver.cs ├── WindowsFileConnection.cs ├── soapheader.cs └── wse.cs ├── Bot ├── Bot.cs ├── BotData.cs └── BotStream.cs ├── Cloud ├── Analyzer │ └── Analyzer.cs ├── Common │ ├── HttpClientHelper.cs │ └── JsonSerialization.cs ├── Constants.cs ├── CreateSecureAppCert.ps1 ├── Credentials │ ├── CertificateBuilder.cs │ ├── CertificateCredential.cs │ ├── CredentialBase.cs │ ├── IAzureCredential.cs │ ├── PRTCredential.cs │ └── UserCredential.cs ├── Data │ ├── AzureADKey.cs │ └── HealthCheckCloudData.cs ├── Export │ └── ExportAsGuest.cs ├── Logs │ ├── LoggingHandler.cs │ └── SazGenerator.cs ├── MsGraph │ ├── AzureCredentialTokenProvider.cs │ ├── GraphApiClientFactory.cs │ ├── GraphServiceClientFactory.cs │ ├── IGraphApiClient.cs │ ├── MsGraphApiFacade.cs │ └── SimpleAccessTokenProvider.cs ├── PingCastleCloudException.cs ├── PublicServices │ ├── OpenIDConfiguration.cs │ ├── PublicService.cs │ ├── TenantBrandingInfo.cs │ ├── UserRealmCT.cs │ ├── UserRealmCTRequest.cs │ ├── UserRealmSRF.cs │ ├── UserRealmV1.cs │ └── UserRealmV2.cs ├── RESTServices │ ├── Azure │ │ ├── AzureADConnectApi.cs │ │ ├── GraphAPI.cs │ │ ├── ManagementApi.cs │ │ ├── MicrosoftGraph.cs │ │ └── ProvisioningApi.cs │ ├── AzureServiceAttribute.cs │ ├── ClientIDs.cs │ ├── EndPointAttribute.cs │ ├── IAzureService.cs │ ├── O365 │ │ └── O365Api.cs │ └── RESTClientBase.cs ├── Rules │ ├── ADConnectVersion.cs │ ├── ADConnectVersion1.cs │ ├── GuestUserAccessRestriction1.cs │ ├── GuestUserAccessRestriction2.cs │ ├── RuleDescription.resx │ ├── UserConsentCompanyData.cs │ └── UserRegisterApplications.cs ├── Tokens │ ├── ChallengeResponse.cs │ ├── CookieManager.cs │ ├── JwtHeader.cs │ ├── JwtPayload.cs │ ├── JwtToken.cs │ ├── Token.cs │ ├── TokenCache.cs │ └── TokenFactory.cs └── UI │ ├── AuthenticationDialog.Designer.cs │ ├── AuthenticationDialog.cs │ └── AuthenticationDialog.resx ├── Compatibility.cs ├── ConsoleMenu.cs ├── Data ├── CompromiseGraphData.cs ├── DataHelper.cs ├── DomainKey.cs ├── HealthCheckBUEntityData.cs ├── HealthcheckData.cs ├── IPingCastleReport.cs ├── IPingCastleReportGenerator.cs ├── PingCastleReportCollection.cs ├── PingCastleReportDataExportLevel.cs ├── PingCastleReportHelper.cs ├── PingCastleReportHistoryCollection.cs └── SafeXmlWriter.cs ├── Directory.Build.props ├── Exports ├── ExportBase.cs ├── ExportChanges.cs ├── ExportComputers.cs ├── ExportUsers.cs └── IExport.cs ├── FodyWeavers.xml ├── FodyWeavers.xsd ├── Graph ├── Database │ ├── LiveDataStorage.cs │ ├── MappingType.cs │ ├── Node.cs │ ├── Relation.cs │ └── RelationType.cs ├── Export │ ├── ExportDataFromActiveDirectoryLive.cs │ └── RelationFactory.cs └── Reporting │ ├── GraphObjectReference.cs │ └── ReportGenerator.cs ├── Healthcheck ├── ADModel.cs ├── FakeHealthCheckDataGenerator.cs ├── HealthCheckEncryption.cs ├── Healthcheck.cs ├── HealthcheckAnalyzer.cs ├── HoneyPotSettings.cs ├── InfrastructureSettings.cs ├── LAPSAnalyzer.cs ├── Rules │ ├── HeatlcheckRuleAnomalyAdminSDHolder.cs │ ├── HeatlcheckRuleAnomalyAnonymousAuthorizedGPO.cs │ ├── HeatlcheckRuleAnomalyAuditDC.cs │ ├── HeatlcheckRuleAnomalyAuditPowershell.cs │ ├── HeatlcheckRuleAnomalyBackupMetadata.cs │ ├── HeatlcheckRuleAnomalyCertEnrollCB.cs │ ├── HeatlcheckRuleAnomalyCertEnrollHttp.cs │ ├── HeatlcheckRuleAnomalyCertMD2Intermediate.cs │ ├── HeatlcheckRuleAnomalyCertMD2Root.cs │ ├── HeatlcheckRuleAnomalyCertMD4Intermediate.cs │ ├── HeatlcheckRuleAnomalyCertMD4Root.cs │ ├── HeatlcheckRuleAnomalyCertMD5Intermediate.cs │ ├── HeatlcheckRuleAnomalyCertMD5Root.cs │ ├── HeatlcheckRuleAnomalyCertROCA.cs │ ├── HeatlcheckRuleAnomalyCertSHA0Intermediate.cs │ ├── HeatlcheckRuleAnomalyCertSHA0Root.cs │ ├── HeatlcheckRuleAnomalyCertSHA1Intermediate.cs │ ├── HeatlcheckRuleAnomalyCertSHA1Root.cs │ ├── HeatlcheckRuleAnomalyCertTempAgent.cs │ ├── HeatlcheckRuleAnomalyCertTempAnyPurpose.cs │ ├── HeatlcheckRuleAnomalyCertTempAnyone.cs │ ├── HeatlcheckRuleAnomalyCertTempCustomSubject.cs │ ├── HeatlcheckRuleAnomalyCertTempNoSecurity.cs │ ├── HeatlcheckRuleAnomalyCertWeakDSA.cs │ ├── HeatlcheckRuleAnomalyCertWeakRSA.cs │ ├── HeatlcheckRuleAnomalyCertWeakRSA2.cs │ ├── HeatlcheckRuleAnomalyCertWeakRSAComponent.cs │ ├── HeatlcheckRuleAnomalyDCCoerce.cs │ ├── HeatlcheckRuleAnomalyDCLdapSign.cs │ ├── HeatlcheckRuleAnomalyDCLdapsCB.cs │ ├── HeatlcheckRuleAnomalyDCLdapsSSL.cs │ ├── HeatlcheckRuleAnomalyDCLdapsSSLAdvanced.cs │ ├── HeatlcheckRuleAnomalyDCRefuseComputerPwdChange.cs │ ├── HeatlcheckRuleAnomalyDCSpooler.cs │ ├── HeatlcheckRuleAnomalyDCWebClient.cs │ ├── HeatlcheckRuleAnomalyDnsZoneAUCreateChild.cs │ ├── HeatlcheckRuleAnomalyDnsZoneTransfert.cs │ ├── HeatlcheckRuleAnomalyDnsZoneUnsecureUpdate1.cs │ ├── HeatlcheckRuleAnomalyDnsZoneUnsecureUpdate2.cs │ ├── HeatlcheckRuleAnomalyDsHeuristicsAnonNSPI.cs │ ├── HeatlcheckRuleAnomalyDsHeuristicsAnonymous.cs │ ├── HeatlcheckRuleAnomalyDsHeuristicsDoNotVerifyUniqueness.cs │ ├── HeatlcheckRuleAnomalyDsHeuristicsLDAPSecurity.cs │ ├── HeatlcheckRuleAnomalyGuest.cs │ ├── HeatlcheckRuleAnomalyHardenedPaths.cs │ ├── HeatlcheckRuleAnomalyKrbtgt.cs │ ├── HeatlcheckRuleAnomalyLAPS.cs │ ├── HeatlcheckRuleAnomalyLAPSJoinedComputers.cs │ ├── HeatlcheckRuleAnomalyLDAPSigningDisabled.cs │ ├── HeatlcheckRuleAnomalyLMHash.cs │ ├── HeatlcheckRuleAnomalyMembershipEveryone.cs │ ├── HeatlcheckRuleAnomalyMinPasswordLen.cs │ ├── HeatlcheckRuleAnomalyNTFRSOnSYSVOL.cs │ ├── HeatlcheckRuleAnomalyNoGPOLLMNR.cs │ ├── HeatlcheckRuleAnomalyNoNetSessionHardening.cs │ ├── HeatlcheckRuleAnomalyNotEnoughDC.cs │ ├── HeatlcheckRuleAnomalyNullSession.cs │ ├── HeatlcheckRuleAnomalyPasswordInGPO.cs │ ├── HeatlcheckRuleAnomalyPreWin2000Anonymous.cs │ ├── HeatlcheckRuleAnomalyPreWin2000AuthenticatedUsers.cs │ ├── HeatlcheckRuleAnomalyPreWin2000Other.cs │ ├── HeatlcheckRuleAnomalyRemoteBlankPasswordUse.cs │ ├── HeatlcheckRuleAnomalyReversiblePassword.cs │ ├── HeatlcheckRuleAnomalyRootDseAnonBinding.cs │ ├── HeatlcheckRuleAnomalySMB2SignatureNotEnabled.cs │ ├── HeatlcheckRuleAnomalySMB2SignatureNotRequired.cs │ ├── HeatlcheckRuleAnomalySchemaProtectedUsers.cs │ ├── HeatlcheckRuleAnomalyServicePolicy.cs │ ├── HeatlcheckRuleAnomalySmartCardExpirePassword.cs │ ├── HeatlcheckRuleAnomalySmartCardRequired.cs │ ├── HeatlcheckRuleAnomalyUnixPassword.cs │ ├── HeatlcheckRuleAnomalyWSUSSSL.cs │ ├── HeatlcheckRulePrivilegedAdminInactive.cs │ ├── HeatlcheckRulePrivilegedAdminLogin.cs │ ├── HeatlcheckRulePrivilegedAdminNumber.cs │ ├── HeatlcheckRulePrivilegedAdminPwdTooOld.cs │ ├── HeatlcheckRulePrivilegedControlPathIndirectEveryone.cs │ ├── HeatlcheckRulePrivilegedControlPathIndirectMany.cs │ ├── HeatlcheckRulePrivilegedDCOwner.cs │ ├── HeatlcheckRulePrivilegedDNSAdmin.cs │ ├── HeatlcheckRulePrivilegedDNSDelegation.cs │ ├── HeatlcheckRulePrivilegedDangerousDelegation.cs │ ├── HeatlcheckRulePrivilegedDelegated.cs │ ├── HeatlcheckRulePrivilegedDelegationDCa2d2.cs │ ├── HeatlcheckRulePrivilegedDelegationDCsourcedeleg.cs │ ├── HeatlcheckRulePrivilegedDelegationDCt2a4d.cs │ ├── HeatlcheckRulePrivilegedDelegationEveryone.cs │ ├── HeatlcheckRulePrivilegedDelegationFileDeployed.cs │ ├── HeatlcheckRulePrivilegedDelegationGPOData.cs │ ├── HeatlcheckRulePrivilegedDelegationKeyAdmin.cs │ ├── HeatlcheckRulePrivilegedDelegationLoginScript.cs │ ├── HeatlcheckRulePrivilegedDisplaySpecifier.cs │ ├── HeatlcheckRulePrivilegedDsHeuristicsAdminSDExMaskModified.cs │ ├── HeatlcheckRulePrivilegedDsHeuristicsDoListObject.cs │ ├── HeatlcheckRulePrivilegedEmailOn.cs │ ├── HeatlcheckRulePrivilegedExchangeAdminSDHolder.cs │ ├── HeatlcheckRulePrivilegedExchangePrivEsc.cs │ ├── HeatlcheckRulePrivilegedKerberoasting.cs │ ├── HeatlcheckRulePrivilegedLoginDCEveryone.cs │ ├── HeatlcheckRulePrivilegedLogonDenied.cs │ ├── HeatlcheckRulePrivilegedOperatorsEmpty.cs │ ├── HeatlcheckRulePrivilegedPrivilegeEveryone.cs │ ├── HeatlcheckRulePrivilegedProtectedUsers.cs │ ├── HeatlcheckRulePrivilegedRODCAdminRevealed.cs │ ├── HeatlcheckRulePrivilegedRODCAllowedGroup.cs │ ├── HeatlcheckRulePrivilegedRODCDeniedGroup.cs │ ├── HeatlcheckRulePrivilegedRODCKrbtgtOrphan.cs │ ├── HeatlcheckRulePrivilegedRODCNeverReveal.cs │ ├── HeatlcheckRulePrivilegedRODCRevealOnDemand.cs │ ├── HeatlcheckRulePrivilegedRODCSYSVOLWrite.cs │ ├── HeatlcheckRulePrivilegedRecoveryModeUnprotected.cs │ ├── HeatlcheckRulePrivilegedRecycleBin.cs │ ├── HeatlcheckRulePrivilegedSchemaAdmins.cs │ ├── HeatlcheckRulePrivilegedServiceDomainAdmin.cs │ ├── HeatlcheckRulePrivilegedTrustedCredManAccessPrivilege.cs │ ├── HeatlcheckRulePrivilegedUnconstrainedDelegation.cs │ ├── HeatlcheckRulePrivilegedUnknownDelegation.cs │ ├── HeatlcheckRulePrivilegedUnprotectedOU.cs │ ├── HeatlcheckRuleStaleADRegistrationEnabled.cs │ ├── HeatlcheckRuleStaleADRegistrationViaSchema.cs │ ├── HeatlcheckRuleStaleDCRegistration.cs │ ├── HeatlcheckRuleStaledAesNotEnabled.cs │ ├── HeatlcheckRuleStaledDCNotUpdated.cs │ ├── HeatlcheckRuleStaledDCSubnetMissing.cs │ ├── HeatlcheckRuleStaledDefaultOUChanged.cs │ ├── HeatlcheckRuleStaledDefenderASR.cs │ ├── HeatlcheckRuleStaledDesEnabled.cs │ ├── HeatlcheckRuleStaledDuplicateObjects.cs │ ├── HeatlcheckRuleStaledFolderOptions.cs │ ├── HeatlcheckRuleStaledInactive.cs │ ├── HeatlcheckRuleStaledInactiveComputer.cs │ ├── HeatlcheckRuleStaledInactiveDC.cs │ ├── HeatlcheckRuleStaledJavaSchema.cs │ ├── HeatlcheckRuleStaledKerberosArmoring.cs │ ├── HeatlcheckRuleStaledKerberosArmoringDC.cs │ ├── HeatlcheckRuleStaledMS14_068.cs │ ├── HeatlcheckRuleStaledMS17_010.cs │ ├── HeatlcheckRuleStaledNoPreAuth.cs │ ├── HeatlcheckRuleStaledNoPreAuthAdmin.cs │ ├── HeatlcheckRuleStaledObsolete2000.cs │ ├── HeatlcheckRuleStaledObsolete2003.cs │ ├── HeatlcheckRuleStaledObsolete2008.cs │ ├── HeatlcheckRuleStaledObsolete2012.cs │ ├── HeatlcheckRuleStaledObsoleteDC2000.cs │ ├── HeatlcheckRuleStaledObsoleteDC2003.cs │ ├── HeatlcheckRuleStaledObsoleteDC2008.cs │ ├── HeatlcheckRuleStaledObsoleteDC2012.cs │ ├── HeatlcheckRuleStaledObsoleteFunctionalLevel1.cs │ ├── HeatlcheckRuleStaledObsoleteFunctionalLevel3.cs │ ├── HeatlcheckRuleStaledObsoleteFunctionalLevel4.cs │ ├── HeatlcheckRuleStaledObsoleteNT4.cs │ ├── HeatlcheckRuleStaledObsoleteVista.cs │ ├── HeatlcheckRuleStaledObsoleteW10.cs │ ├── HeatlcheckRuleStaledObsoleteWin7.cs │ ├── HeatlcheckRuleStaledObsoleteWin8.cs │ ├── HeatlcheckRuleStaledObsoleteXP.cs │ ├── HeatlcheckRuleStaledOldNtlm.cs │ ├── HeatlcheckRuleStaledPrimaryGroup.cs │ ├── HeatlcheckRuleStaledPrimaryGroupComputer.cs │ ├── HeatlcheckRuleStaledPwdLastSet45.cs │ ├── HeatlcheckRuleStaledPwdLastSet90.cs │ ├── HeatlcheckRuleStaledPwdLastSetCluster.cs │ ├── HeatlcheckRuleStaledPwdLastSetDC.cs │ ├── HeatlcheckRuleStaledPwdNeverExpires.cs │ ├── HeatlcheckRuleStaledPwdNotRequired.cs │ ├── HeatlcheckRuleStaledReversibleEncryption.cs │ ├── HeatlcheckRuleStaledReversibleEncryptionComputer.cs │ ├── HeatlcheckRuleStaledSIDHistory.cs │ ├── HeatlcheckRuleStaledSIDHistoryComputer.cs │ ├── HeatlcheckRuleStaledSMBv1.cs │ ├── HeatlcheckRuleStaledScriptToInternet.cs │ ├── HeatlcheckRuleStaledTerminalServiceGPO.cs │ ├── HeatlcheckRuleStaledWSUSNoPinning.cs │ ├── HeatlcheckRuleStaledWSUSUserProxy.cs │ ├── HeatlcheckRuleStaledWSUShttp.cs │ ├── HeatlcheckRuleTrustAES.cs │ ├── HeatlcheckRuleTrustAzureADSSO.cs │ ├── HeatlcheckRuleTrustDownlevel.cs │ ├── HeatlcheckRuleTrustFileDeployedOutOfDomain.cs │ ├── HeatlcheckRuleTrustInactive.cs │ ├── HeatlcheckRuleTrustLoginScriptOutOfDomain.cs │ ├── HeatlcheckRuleTrustSIDFiltering.cs │ ├── HeatlcheckRuleTrustSIDHistoryAuditingGroup.cs │ ├── HeatlcheckRuleTrustSIDHistoryDangerous.cs │ ├── HeatlcheckRuleTrustSIDHistorySameDomain.cs │ ├── HeatlcheckRuleTrustSIDHistoryUnknownDomain.cs │ ├── HeatlcheckRuleTrustTGTDelegation.cs │ └── RuleDescription.resx └── TrustAnalyzer.cs ├── LICENSE.md ├── NativeMethods.cs ├── PingCastle.csproj ├── PingCastle.sln ├── PingCastleAutoUpdater ├── App.config ├── FodyWeavers.xml ├── FodyWeavers.xsd ├── PingCastleAutoUpdater.csproj ├── Program.cs ├── Properties │ └── AssemblyInfo.cs ├── packages.config └── pingcastle.ico ├── PingCastleCommon ├── FilesValidator.cs ├── PingCastleCommon.csproj └── SupportLink.cs ├── PingCastleException.cs ├── PingCastleFactory.cs ├── PingCastleLicense ├── ADHealthCheckingLicense.cs ├── ADHealthCheckingLicenseProvider.cs ├── ADHealthCheckingLicenseSettings.cs └── LicenseCache.cs ├── Program.cs ├── Properties └── AssemblyInfo.cs ├── README.md ├── RPC ├── SSPI.cs ├── dcom.cs ├── lsa.cs ├── nativemethods.cs ├── nrpc.cs ├── nullsession.cs ├── rpcapi.cs ├── rpcfirewallchecker.cs ├── samr.cs └── spool.cs ├── Report ├── IActionPlan.cs ├── IPingCastleReportUser.cs ├── ReportBase.cs ├── ReportBenchmark.cs ├── ReportCloud.cs ├── ReportCloudCompared.cs ├── ReportHealthCheckConsolidation.cs ├── ReportHealthCheckRules.cs ├── ReportHealthCheckSingle.cs ├── ReportHealthCheckSingleCompared.cs ├── ReportHelper.cs ├── ReportMapBuilder.cs ├── ReportNetworkMap.cs └── ReportRiskControls.cs ├── Rules ├── CustomRulesSettings.cs ├── IRiskEvaluation.cs ├── IRuleScore.cs ├── RiskModelCategory.cs ├── RiskRuleCategory.cs ├── RuleAttribute.cs ├── RuleBase.cs └── RuleSet.cs ├── RuntimeSettings.cs ├── Scanners ├── ACLScanner.cs ├── AntivirusScanner.cs ├── ComputerVersion.cs ├── ConsistencyScanner.cs ├── ForeignUsersScanner.cs ├── IScanner.cs ├── LAPSBitLocker.cs ├── NullSessionScanner.cs ├── OxidBindingScanner.cs ├── RemoteScanner.cs ├── ReplicationScanner.cs ├── ScannerBase.cs ├── Smb1Protocol.cs ├── Smb2Protocol.cs ├── Smb3QueryNetworkScanner.cs ├── SmbScanner.cs ├── SpoolerScanner.cs ├── ZeroLogonScanner.cs ├── bluekeepscanner.cs ├── localAdminsEnumerator.cs ├── localAdminsScanner.cs ├── ms17_010scanner.cs ├── nullsessionTrustScanner.cs └── startupScanner.cs ├── Tasks.cs ├── app.config ├── changelog.txt ├── license.rtf ├── misc ├── BlockingQueue.cs ├── ConnectionTester.cs ├── ConnectionTesterHttp.cs ├── ConnectionTesterLdap.cs ├── DnsQuery.cs ├── Extensions.cs ├── JSONParser.cs ├── NamedPipeTester.cs ├── ROCAVulnerabilityTester.cs ├── RegistryPolReader.cs ├── RestrictedToken.cs └── Subnet.cs ├── packages.config ├── pingcastle.ico ├── shares ├── ShareEnumerator.cs └── ShareScanner.cs ├── template ├── .gitignore ├── ProcessTemplate.ps1 ├── ReportBase.css ├── ReportBase.js ├── ReportCloudMain.js ├── ReportCompromiseGraph.css ├── ReportCompromiseGraph.js ├── ReportHealthCheckConsolidation.css ├── ReportHealthCheckRules.css ├── ReportMapBuilder.css ├── ReportMapBuilder.js ├── ReportNetworkMap.css ├── ReportNetworkMap.js ├── ReportRiskControls.css ├── TemplateManager.cs ├── bootstrap-table-export.min.js.gz ├── bootstrap-table.min.css.gz ├── bootstrap-table.min.js.gz ├── bootstrap.min.css.gz ├── bootstrap.min.js.gz ├── dashboardtest.html.gz ├── jquery.min.js.gz ├── popper.min.js.gz ├── responsivetemplate.html ├── tableExport.min.js.gz ├── vis.min.css.gz └── vis.min.js.gz └── testLDAPqueries.ps1 /ADWS/BlockingQueue.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | using System.Threading; 5 | 6 | namespace ADSecurityHealthCheck.ADWS 7 | { 8 | public class BlockingQueue 9 | { 10 | readonly int _Size = 0; 11 | readonly Queue _Queue = new Queue(); 12 | readonly object _Key = new object(); 13 | bool _Quit = false; 14 | 15 | public BlockingQueue(int size) 16 | { 17 | _Size = size; 18 | } 19 | 20 | public void Quit() 21 | { 22 | lock (_Key) 23 | { 24 | _Quit = true; 25 | Monitor.PulseAll(_Key); 26 | } 27 | } 28 | 29 | public bool Enqueue(T t) 30 | { 31 | lock (_Key) 32 | { 33 | while (!_Quit && _Queue.Count >= _Size) Monitor.Wait(_Key); 34 | if (_Quit) return false; 35 | _Queue.Enqueue(t); 36 | Monitor.PulseAll(_Key); 37 | } 38 | return true; 39 | } 40 | 41 | public bool Dequeue(out T t) 42 | { 43 | t = default(T); 44 | lock (_Key) 45 | { 46 | while (!_Quit && _Queue.Count == 0) Monitor.Wait(_Key); 47 | if (_Queue.Count == 0) return false; 48 | t = _Queue.Dequeue(); 49 | Monitor.PulseAll(_Key); 50 | } 51 | return true; 52 | } 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /ADWS/IADConnection.cs: -------------------------------------------------------------------------------- 1 | using System.Security.Principal; 2 | 3 | namespace PingCastle.ADWS 4 | { 5 | public interface IADConnection 6 | { 7 | ADDomainInfo GetDomainInfo(); 8 | 9 | void Enumerate(string distinguishedName, string filter, string[] properties, WorkOnReturnedObjectByADWS callback, string scope); 10 | 11 | string ConvertSIDToName(string sidstring, out string referencedDomain); 12 | 13 | SecurityIdentifier ConvertNameToSID(string nameToResolve); 14 | 15 | IFileConnection FileConnection { get; } 16 | 17 | void ThreadInitialization(); 18 | 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /Bot/BotData.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace PingCastle.Bot 4 | { 5 | public class BotInputOutput 6 | { 7 | public List Data { get; set; } 8 | 9 | } 10 | public class BotData 11 | { 12 | public BotData() 13 | { 14 | 15 | } 16 | public BotData(string Key, string Value) : this() 17 | { 18 | this.Key = Key; 19 | this.Value = Value; 20 | } 21 | 22 | public string Key { get; set; } 23 | public string Value { get; set; } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /Bot/BotStream.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.ComponentModel; 3 | using System.IO; 4 | using System.Runtime.InteropServices; 5 | 6 | namespace PingCastle.Bot 7 | { 8 | internal class BotStream 9 | { 10 | [DllImport("kernel32.dll", EntryPoint = "CreateFile", SetLastError = true)] 11 | private static extern IntPtr CreateFile(String lpFileName, 12 | UInt32 dwDesiredAccess, UInt32 dwShareMode, 13 | IntPtr lpSecurityAttributes, UInt32 dwCreationDisposition, 14 | UInt32 dwFlagsAndAttributes, 15 | IntPtr hTemplateFile); 16 | 17 | 18 | private const UInt32 GENERIC_READ = 0x80000000; 19 | private const UInt32 GENERIC_WRITE = 0x40000000; 20 | private const UInt32 OPEN_EXISTING = 3; 21 | 22 | public static FileStream OpenPipeStream(string pipeName) 23 | { 24 | Console.WriteLine("Opening pipe :" + pipeName); 25 | IntPtr p = CreateFile(@"\\.\pipe\" + pipeName, GENERIC_READ + GENERIC_WRITE, 0, IntPtr.Zero, OPEN_EXISTING, 0, IntPtr.Zero); 26 | if (p.ToInt32() == -1) 27 | { 28 | throw new Win32Exception(); 29 | } 30 | return new FileStream(new Microsoft.Win32.SafeHandles.SafeFileHandle(p, true), FileAccess.ReadWrite); 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /Cloud/Credentials/IAzureCredential.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Vincent LE TOUX for Ping Castle. All rights reserved. 3 | // https://www.pingcastle.com 4 | // 5 | // Licensed under the Non-Profit OSL. See LICENSE file in the project root for full license information. 6 | // 7 | using PingCastle.Cloud.RESTServices.Azure; 8 | using PingCastle.Cloud.Tokens; 9 | using System; 10 | using System.Collections.Generic; 11 | using System.Linq; 12 | using System.Text; 13 | using System.Threading.Tasks; 14 | 15 | namespace PingCastle.Cloud.Credentials 16 | { 17 | public interface IAzureCredential 18 | { 19 | string Tenantid { get; } 20 | string TenantidToQuery { get; set; } 21 | Task GetToken() where T : IAzureService; 22 | Token LastTokenQueried { get; } 23 | bool ForceRefreshByRefreshToken { get; set; } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /Cloud/Credentials/PRTCredential.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Vincent LE TOUX for Ping Castle. All rights reserved. 3 | // https://www.pingcastle.com 4 | // 5 | // Licensed under the Non-Profit OSL. See LICENSE file in the project root for full license information. 6 | // 7 | using PingCastle.Cloud.RESTServices.Azure; 8 | using PingCastle.Cloud.Tokens; 9 | using System; 10 | using System.Collections.Generic; 11 | using System.Linq; 12 | using System.Text; 13 | using System.Threading.Tasks; 14 | 15 | namespace PingCastle.Cloud.Credentials 16 | { 17 | 18 | public class PRTCredential : CredentialBase 19 | { 20 | public PRTCredential() : base() 21 | { 22 | } 23 | 24 | public PRTCredential(string tenantid) : base(tenantid) 25 | { 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /Cloud/Credentials/UserCredential.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Vincent LE TOUX for Ping Castle. All rights reserved. 3 | // https://www.pingcastle.com 4 | // 5 | // Licensed under the Non-Profit OSL. See LICENSE file in the project root for full license information. 6 | // 7 | using PingCastle.Cloud.RESTServices.Azure; 8 | using PingCastle.Cloud.Tokens; 9 | using System; 10 | using System.Collections.Generic; 11 | using System.Linq; 12 | using System.Text; 13 | using System.Threading.Tasks; 14 | 15 | namespace PingCastle.Cloud.Credentials 16 | { 17 | public class UserCredential : CredentialBase 18 | { 19 | public UserCredential() : base() 20 | { 21 | } 22 | 23 | public UserCredential(string tenantid) : base(tenantid) 24 | { 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /Cloud/Data/AzureADKey.cs: -------------------------------------------------------------------------------- 1 | using PingCastle.Data; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Diagnostics; 5 | using System.Linq; 6 | using System.Text; 7 | using System.Threading.Tasks; 8 | 9 | namespace PingCastle.Cloud.Data 10 | { 11 | public class AzureADKey 12 | { 13 | public string TenantName { get; set; } 14 | public string TenantID { get; set; } 15 | public bool IsComplete { get { return TenantID != null && TenantName != null; } } 16 | 17 | private AzureADKey() 18 | { 19 | } 20 | public static AzureADKey Create(string TenantName, string TenantID) 21 | { 22 | var key = new AzureADKey(TenantName, TenantID); 23 | return key; 24 | } 25 | 26 | protected AzureADKey(string tenantName, string tenantID) 27 | { 28 | if (!string.IsNullOrEmpty(tenantName)) 29 | { 30 | TenantName = tenantName.ToLowerInvariant(); 31 | } 32 | if (!string.IsNullOrEmpty(tenantID)) 33 | { 34 | Guid guid; 35 | if (!Guid.TryParse(tenantID, out guid)) 36 | { 37 | Trace.WriteLine("Unable to parse the TenantID " + tenantID); 38 | throw new PingCastleException("Unable to parse the TenantID \"" + tenantID + "\" - it should be a guid"); 39 | } 40 | TenantID = tenantID; 41 | } 42 | } 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /Cloud/Logs/LoggingHandler.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Vincent LE TOUX for Ping Castle. All rights reserved. 3 | // https://www.pingcastle.com 4 | // 5 | // Licensed under the Non-Profit OSL. See LICENSE file in the project root for full license information. 6 | // 7 | using System; 8 | using System.Collections.Generic; 9 | using System.Linq; 10 | using System.Net.Http; 11 | using System.Text; 12 | using System.Threading; 13 | using System.Threading.Tasks; 14 | 15 | namespace PingCastle.Cloud.Logs 16 | { 17 | public class LoggingHandler : DelegatingHandler 18 | { 19 | private SazGenerator _sazGenerator; 20 | 21 | public LoggingHandler(SazGenerator sazGenerator, HttpMessageHandler innerHandler) 22 | : base(innerHandler) 23 | { 24 | _sazGenerator = sazGenerator; 25 | } 26 | 27 | protected override async Task SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) 28 | { 29 | int num = _sazGenerator.RecordBeginQuery(request); 30 | 31 | HttpResponseMessage response = await base.SendAsync(request, cancellationToken); 32 | 33 | _sazGenerator.RecordEndQuery(num, response); 34 | 35 | return response; 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /Cloud/MsGraph/AzureCredentialTokenProvider.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Diagnostics; 4 | using System.Threading; 5 | using System.Threading.Tasks; 6 | using Microsoft.Kiota.Abstractions.Authentication; 7 | using PingCastle.Cloud.Credentials; 8 | using PingCastle.Cloud.RESTServices.Azure; 9 | 10 | namespace PingCastle.Cloud.MsGraph 11 | { 12 | public class AzureCredentialTokenProvider : IAccessTokenProvider where T : IAzureService 13 | { 14 | private readonly IAzureCredential _credential; 15 | 16 | public AzureCredentialTokenProvider(IAzureCredential credential) 17 | { 18 | _credential = credential; 19 | } 20 | 21 | public async Task GetAuthorizationTokenAsync(Uri uri, Dictionary additionalAuthenticationContext = default, CancellationToken cancellationToken = default) 22 | { 23 | Trace.WriteLine($"ACTP: the token has been requested {uri}"); 24 | var token = await _credential.GetToken(); 25 | return token.access_token; 26 | } 27 | 28 | public AllowedHostsValidator AllowedHostsValidator => new AllowedHostsValidator(); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /Cloud/MsGraph/GraphApiClientFactory.cs: -------------------------------------------------------------------------------- 1 | using PingCastle.Cloud.Credentials; 2 | 3 | namespace PingCastle.Cloud.MsGraph 4 | { 5 | public static class GraphApiClientFactory 6 | { 7 | public static IGraphApiClient Create(IAzureCredential credential) 8 | { 9 | var client = GraphServiceClientFactory.Create(credential); 10 | return new MsGraphApiFacade(client); 11 | } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /Cloud/MsGraph/GraphServiceClientFactory.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.Graph; 2 | using Microsoft.Graph.Beta; 3 | using Microsoft.Kiota.Abstractions.Authentication; 4 | using PingCastle.Cloud.Credentials; 5 | using PingCastle.Cloud.RESTServices.Azure; 6 | 7 | namespace PingCastle.Cloud.MsGraph 8 | { 9 | public static class GraphServiceClientFactory 10 | { 11 | public static GraphServiceClient Create(string accessToken) 12 | { 13 | return Create(new SimpleAccessTokenProvider(accessToken)); 14 | } 15 | 16 | public static GraphServiceClient Create(IAzureCredential credential) where T : IAzureService 17 | { 18 | return Create(new AzureCredentialTokenProvider(credential)); 19 | } 20 | 21 | public static GraphServiceClient Create(IAccessTokenProvider tokenProvider) 22 | { 23 | var authProvider = new BaseBearerTokenAuthenticationProvider(tokenProvider); 24 | var httpClient = GraphClientFactory.Create(authProvider, version: "beta"); 25 | 26 | return new GraphServiceClient(httpClient); 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /Cloud/MsGraph/IGraphApiClient.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Threading.Tasks; 3 | using Microsoft.Graph.Beta.Models; 4 | 5 | namespace PingCastle.Cloud.MsGraph 6 | { 7 | public interface IGraphApiClient 8 | { 9 | Task GetCompanyInfoAsync(); 10 | Task GetAuthorizationPolicyAsync(); 11 | Task GetOnPremisesDirectorySynchronizationAsync(); 12 | Task> GetUserLicensesAsync(string userId); 13 | IAsyncEnumerable GetRolesAsync(); 14 | IAsyncEnumerable GetRoleTemplatesAsync(); 15 | Task> GetDomainsAsync(); 16 | Task> GetDomainDnsRecordsAsync(string domainName); 17 | IAsyncEnumerable GetUserRegistrationDetailsAsync(); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /Cloud/MsGraph/SimpleAccessTokenProvider.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Threading; 3 | using System.Threading.Tasks; 4 | using Microsoft.Kiota.Abstractions.Authentication; 5 | using System; 6 | 7 | namespace PingCastle.Cloud.MsGraph 8 | { 9 | public class SimpleAccessTokenProvider : IAccessTokenProvider 10 | { 11 | private readonly string _accessToken; 12 | 13 | public SimpleAccessTokenProvider(string accessToken) 14 | { 15 | _accessToken = accessToken; 16 | } 17 | 18 | public async Task GetAuthorizationTokenAsync(Uri uri, Dictionary additionalAuthenticationContext = default, CancellationToken cancellationToken = default) 19 | { 20 | return await Task.FromResult(_accessToken); 21 | } 22 | 23 | public AllowedHostsValidator AllowedHostsValidator => new AllowedHostsValidator(); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /Cloud/PingCastleCloudException.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Vincent LE TOUX for Ping Castle. All rights reserved. 3 | // https://www.pingcastle.com 4 | // 5 | // Licensed under the Non-Profit OSL. See LICENSE file in the project root for full license information. 6 | // 7 | using System; 8 | using System.Collections.Generic; 9 | using System.Linq; 10 | using System.Text; 11 | 12 | namespace PingCastle.Cloud 13 | { 14 | class PingCastleCloudException : Exception 15 | { 16 | public PingCastleCloudException(string message) 17 | : base(message) 18 | { 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /Cloud/PublicServices/UserRealmCTRequest.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Vincent LE TOUX for Ping Castle. All rights reserved. 3 | // https://www.pingcastle.com 4 | // 5 | // Licensed under the Non-Profit OSL. See LICENSE file in the project root for full license information. 6 | // 7 | using PingCastle.Cloud.Common; 8 | using System; 9 | using System.Collections.Generic; 10 | using System.Linq; 11 | using System.Runtime.Serialization; 12 | using System.Text; 13 | using System.Threading.Tasks; 14 | 15 | namespace PingCastle.Cloud.PublicServices 16 | { 17 | [DataContractAttribute] 18 | public class UserRealmCTRequest : JsonSerialization 19 | { 20 | [DataMember] 21 | public string username { get; set; } 22 | [DataMember] 23 | public bool isOtherIdpSupported { get; set; } 24 | [DataMember] 25 | public bool checkPhones { get; set; } 26 | [DataMember] 27 | public bool isRemoteNGCSupported { get; set; } 28 | [DataMember] 29 | public bool isCookieBannerShown { get; set; } 30 | [DataMember] 31 | public bool isFidoSupported { get; set; } 32 | [DataMember] 33 | public string originalRequest { get; set; } 34 | [DataMember] 35 | public string flowToken { get; set; } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /Cloud/PublicServices/UserRealmSRF.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Vincent LE TOUX for Ping Castle. All rights reserved. 3 | // https://www.pingcastle.com 4 | // 5 | // Licensed under the Non-Profit OSL. See LICENSE file in the project root for full license information. 6 | // 7 | using PingCastle.Cloud.Common; 8 | using System; 9 | using System.Collections.Generic; 10 | using System.Linq; 11 | using System.Runtime.Serialization; 12 | using System.Text; 13 | using System.Threading.Tasks; 14 | 15 | namespace PingCastle.Cloud.PublicServices 16 | { 17 | [DataContractAttribute] 18 | public class UserRealmSRF : JsonSerialization 19 | { 20 | [DataMember] 21 | public int State { get; set; } 22 | [DataMember] 23 | public int UserState { get; set; } 24 | [DataMember] 25 | public string Login { get; set; } 26 | [DataMember] 27 | public string NameSpaceType { get; set; } 28 | [DataMember] 29 | public string DomainName { get; set; } 30 | [DataMember] 31 | public int FederationGlobalVersion { get; set; } 32 | [DataMember] 33 | public string AuthURL { get; set; } 34 | [DataMember] 35 | public string FederationBrandName { get; set; } 36 | [DataMember] 37 | public string CloudInstanceName { get; set; } 38 | [DataMember] 39 | public string CloudInstanceIssuerUri { get; set; } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /Cloud/PublicServices/UserRealmV1.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Vincent LE TOUX for Ping Castle. All rights reserved. 3 | // https://www.pingcastle.com 4 | // 5 | // Licensed under the Non-Profit OSL. See LICENSE file in the project root for full license information. 6 | // 7 | using PingCastle.Cloud.Common; 8 | using System; 9 | using System.Collections.Generic; 10 | using System.Linq; 11 | using System.Runtime.Serialization; 12 | using System.Text; 13 | using System.Threading.Tasks; 14 | 15 | namespace PingCastle.Cloud.PublicServices 16 | { 17 | [DataContractAttribute] 18 | public class UserRealmV1 : JsonSerialization 19 | { 20 | [DataMember] 21 | public string ver { get; set; } 22 | [DataMember] 23 | public string account_type { get; set; } 24 | [DataMember] 25 | public string domain_name { get; set; } 26 | [DataMember] 27 | public string federation_protocol { get; set; } 28 | [DataMember] 29 | public string federation_metadata_url { get; set; } 30 | [DataMember] 31 | public string federation_active_auth_url { get; set; } 32 | [DataMember] 33 | public string cloud_instance_name { get; set; } 34 | [DataMember] 35 | public string cloud_audience_urn { get; set; } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /Cloud/PublicServices/UserRealmV2.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Vincent LE TOUX for Ping Castle. All rights reserved. 3 | // https://www.pingcastle.com 4 | // 5 | // Licensed under the Non-Profit OSL. See LICENSE file in the project root for full license information. 6 | // 7 | using PingCastle.Cloud.Common; 8 | using System; 9 | using System.Collections.Generic; 10 | using System.Linq; 11 | using System.Runtime.Serialization; 12 | using System.Text; 13 | using System.Threading.Tasks; 14 | 15 | namespace PingCastle.Cloud.PublicServices 16 | { 17 | [DataContractAttribute] 18 | public class UserRealmV2 : JsonSerialization 19 | { 20 | [DataMember] 21 | public string NameSpaceType { get; set; } 22 | [DataMember] 23 | public string federation_protocol { get; set; } 24 | [DataMember] 25 | public string Login { get; set; } 26 | [DataMember] 27 | public string AuthURL { get; set; } 28 | [DataMember] 29 | public string DomainName { get; set; } 30 | [DataMember] 31 | public string FederationBrandName { get; set; } 32 | [DataMember] 33 | public List TenantBrandingInfo { get; set; } 34 | [DataMember] 35 | public string cloud_instance_name { get; set; } 36 | } 37 | 38 | 39 | } 40 | -------------------------------------------------------------------------------- /Cloud/RESTServices/AzureServiceAttribute.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Vincent LE TOUX for Ping Castle. All rights reserved. 3 | // https://www.pingcastle.com 4 | // 5 | // Licensed under the Non-Profit OSL. See LICENSE file in the project root for full license information. 6 | // 7 | using System; 8 | using System.Collections.Generic; 9 | using System.Linq; 10 | using System.Text; 11 | using System.Threading.Tasks; 12 | using System.Reflection; 13 | 14 | namespace PingCastle.Cloud.RESTServices.Azure 15 | { 16 | public class AzureServiceAttribute : Attribute 17 | { 18 | public AzureServiceAttribute(string ClientID, string Resource, string RedirectUri = Constants.redirectUri) 19 | { 20 | this.ClientID = Guid.Parse(ClientID); 21 | this.Resource = Resource; 22 | this.RedirectUri = RedirectUri; 23 | } 24 | public Guid ClientID { get; set; } 25 | public string Resource { get; set; } 26 | public string RedirectUri { get; set; } 27 | 28 | public static AzureServiceAttribute GetAzureServiceAttribute() where T : IAzureService 29 | { 30 | AzureServiceAttribute[] attrs = (AzureServiceAttribute[])typeof(T).GetCustomAttributes(typeof(AzureServiceAttribute)); 31 | if (attrs.Length > 0) 32 | return attrs[0]; 33 | throw new ApplicationException("no service attribute found"); 34 | } 35 | } 36 | 37 | 38 | } 39 | -------------------------------------------------------------------------------- /Cloud/RESTServices/ClientIDs.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Vincent LE TOUX for Ping Castle. All rights reserved. 3 | // https://www.pingcastle.com 4 | // 5 | // Licensed under the Non-Profit OSL. See LICENSE file in the project root for full license information. 6 | // 7 | using System; 8 | using System.Collections.Generic; 9 | using System.Linq; 10 | using System.Text; 11 | using System.Threading.Tasks; 12 | 13 | namespace PingCastle.Cloud.RESTServices.Azure 14 | { 15 | public class ClientIDs 16 | { 17 | public static readonly Guid GraphAPI = new Guid("1b730954-1685-4b74-9bfd-dac224a7b894"); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /Cloud/RESTServices/EndPointAttribute.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Vincent LE TOUX for Ping Castle. All rights reserved. 3 | // https://www.pingcastle.com 4 | // 5 | // Licensed under the Non-Profit OSL. See LICENSE file in the project root for full license information. 6 | // 7 | using System; 8 | using System.Reflection; 9 | 10 | namespace PingCastle.Cloud.RESTServices.Azure 11 | { 12 | public class EndPointAttribute : Attribute 13 | { 14 | public EndPointAttribute(string authorize, string token, string scope = null) 15 | { 16 | AuthorizeEndPoint = authorize; 17 | TokenEndPoint = token; 18 | Scope = scope; 19 | } 20 | 21 | public string AuthorizeEndPoint { get; private set; } 22 | public string TokenEndPoint { get; private set; } 23 | public string Scope { get; private set; } 24 | 25 | public static EndPointAttribute GetEndPointAttribute() where T : IAzureService 26 | { 27 | EndPointAttribute[] attrs = (EndPointAttribute[])typeof(T).GetCustomAttributes(typeof(EndPointAttribute)); 28 | if (attrs.Length > 0) 29 | return attrs[0]; 30 | return DefaultEndPointAttribute(); 31 | } 32 | 33 | private static EndPointAttribute DefaultEndPointAttribute() 34 | { 35 | return new EndPointAttribute(Constants.OAuth2AuthorizeEndPoint, Constants.OAuth2TokenEndPoint); 36 | } 37 | } 38 | 39 | 40 | } 41 | -------------------------------------------------------------------------------- /Cloud/RESTServices/IAzureService.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Vincent LE TOUX for Ping Castle. All rights reserved. 3 | // https://www.pingcastle.com 4 | // 5 | // Licensed under the Non-Profit OSL. See LICENSE file in the project root for full license information. 6 | // 7 | using System; 8 | using System.Collections.Generic; 9 | using System.Linq; 10 | using System.Text; 11 | using System.Threading.Tasks; 12 | 13 | namespace PingCastle.Cloud.RESTServices.Azure 14 | { 15 | public interface IAzureService 16 | { 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /Cloud/Rules/ADConnectVersion1.cs: -------------------------------------------------------------------------------- 1 | using PingCastle.Rules; 2 | // 3 | // Copyright (c) Vincent LE TOUX for Ping Castle. All rights reserved. 4 | // https://www.pingcastle.com 5 | // 6 | // Licensed under the Non-Profit OSL. See LICENSE file in the project root for full license information. 7 | // 8 | using PingCastle.Cloud.Data; 9 | using System; 10 | using System.Collections.Generic; 11 | using System.Linq; 12 | using System.Text; 13 | using System.Threading.Tasks; 14 | 15 | namespace PingCastle.Cloud.Rules 16 | { 17 | [RuleModel("ADConnectVersion1", RiskRuleCategory.Trusts, RiskModelCategory.TrustAzure)] 18 | [RuleComputation(RuleComputationType.TriggerOnPresence, 5)] 19 | [RuleMaturityLevel(2)] 20 | public class ADConnectVersion1 : RuleBase 21 | { 22 | protected override int? AnalyzeDataNew(HealthCheckCloudData healthCheckCloudData) 23 | { 24 | if (healthCheckCloudData.ProvisionDirectorySynchronizationStatus == "Enabled") 25 | { 26 | Version v; 27 | if (Version.TryParse(healthCheckCloudData.ProvisionDirSyncClientVersion, out v)) 28 | { 29 | if (v.Major == 1) 30 | { 31 | AddRawDetail(healthCheckCloudData.ProvisionDirSyncClientVersion); 32 | } 33 | } 34 | } 35 | return null; 36 | } 37 | 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /Cloud/Rules/GuestUserAccessRestriction1.cs: -------------------------------------------------------------------------------- 1 | using PingCastle.Rules; 2 | // 3 | // Copyright (c) Vincent LE TOUX for Ping Castle. All rights reserved. 4 | // https://www.pingcastle.com 5 | // 6 | // Licensed under the Non-Profit OSL. See LICENSE file in the project root for full license information. 7 | // 8 | using PingCastle.Cloud.Data; 9 | using System; 10 | using System.Collections.Generic; 11 | using System.Linq; 12 | using System.Text; 13 | using System.Threading.Tasks; 14 | 15 | namespace PingCastle.Cloud.Rules 16 | { 17 | [RuleModel("GuestUserAccessRestriction1", RiskRuleCategory.Anomalies, RiskModelCategory.WeakPassword)] 18 | [RuleComputation(RuleComputationType.TriggerOnPresence, 25)] 19 | [RuleMaturityLevel(1)] 20 | public class GuestUserAccessRestriction1 : RuleBase 21 | { 22 | protected override int? AnalyzeDataNew(HealthCheckCloudData healthCheckCloudData) 23 | { 24 | if (string.Equals(healthCheckCloudData.PolicyGuestUserRoleId, "a0b1b346-4d3e-4e8b-98f8-753987be4970", StringComparison.OrdinalIgnoreCase)) 25 | { 26 | AddRawDetail(healthCheckCloudData.PolicyGuestUserRoleId); 27 | } 28 | return null; 29 | } 30 | 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /Cloud/Rules/GuestUserAccessRestriction2.cs: -------------------------------------------------------------------------------- 1 | using PingCastle.Rules; 2 | // 3 | // Copyright (c) Vincent LE TOUX for Ping Castle. All rights reserved. 4 | // https://www.pingcastle.com 5 | // 6 | // Licensed under the Non-Profit OSL. See LICENSE file in the project root for full license information. 7 | // 8 | using PingCastle.Cloud.Data; 9 | using System; 10 | using System.Collections.Generic; 11 | using System.Linq; 12 | using System.Text; 13 | using System.Threading.Tasks; 14 | 15 | namespace PingCastle.Cloud.Rules 16 | { 17 | [RuleModel("GuestUserAccessRestriction2", RiskRuleCategory.Anomalies, RiskModelCategory.WeakPassword)] 18 | [RuleComputation(RuleComputationType.TriggerOnPresence, 0)] 19 | [RuleMaturityLevel(4)] 20 | public class GuestUserAccessRestriction2 : RuleBase 21 | { 22 | protected override int? AnalyzeDataNew(HealthCheckCloudData healthCheckCloudData) 23 | { 24 | if (string.Equals(healthCheckCloudData.PolicyGuestUserRoleId, "10dae51f-b6af-4016-8d66-8c2a99b929b3", StringComparison.OrdinalIgnoreCase)) 25 | { 26 | AddRawDetail(healthCheckCloudData.PolicyGuestUserRoleId); 27 | } 28 | return null; 29 | } 30 | 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /Cloud/Rules/UserConsentCompanyData.cs: -------------------------------------------------------------------------------- 1 | using PingCastle.Rules; 2 | // 3 | // Copyright (c) Vincent LE TOUX for Ping Castle. All rights reserved. 4 | // https://www.pingcastle.com 5 | // 6 | // Licensed under the Non-Profit OSL. See LICENSE file in the project root for full license information. 7 | // 8 | using PingCastle.Cloud.Data; 9 | using System; 10 | using System.Collections.Generic; 11 | using System.Linq; 12 | using System.Text; 13 | using System.Threading.Tasks; 14 | 15 | namespace PingCastle.Cloud.Rules 16 | { 17 | [RuleModel("UserConsentCompanyData", RiskRuleCategory.Anomalies, RiskModelCategory.Reconnaissance)] 18 | [RuleComputation(RuleComputationType.TriggerOnPresence, 5)] 19 | [RuleMaturityLevel(2)] 20 | public class UserConsentCompanyData : RuleBase 21 | { 22 | protected override int? AnalyzeDataNew(HealthCheckCloudData healthCheckCloudData) 23 | { 24 | // disable the rule since MS changed the rule logic 25 | /* 26 | if (healthCheckCloudData.UsersPermissionToUserConsentToAppEnabled == true) 27 | { 28 | AddRawDetail("true"); 29 | }*/ 30 | return null; 31 | } 32 | 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /Cloud/Rules/UserRegisterApplications.cs: -------------------------------------------------------------------------------- 1 | using PingCastle.Rules; 2 | // 3 | // Copyright (c) Vincent LE TOUX for Ping Castle. All rights reserved. 4 | // https://www.pingcastle.com 5 | // 6 | // Licensed under the Non-Profit OSL. See LICENSE file in the project root for full license information. 7 | // 8 | using PingCastle.Cloud.Data; 9 | using System; 10 | using System.Collections.Generic; 11 | using System.Linq; 12 | using System.Text; 13 | using System.Threading.Tasks; 14 | 15 | namespace PingCastle.Cloud.Rules 16 | { 17 | [RuleModel("UserRegisterApplications", RiskRuleCategory.StaleObjects, RiskModelCategory.Provisioning)] 18 | [RuleComputation(RuleComputationType.TriggerOnPresence, 5)] 19 | [RuleMaturityLevel(2)] 20 | public class UserRegisterApplications : RuleBase 21 | { 22 | protected override int? AnalyzeDataNew(HealthCheckCloudData healthCheckCloudData) 23 | { 24 | if (healthCheckCloudData.UsersPermissionToCreateLOBAppsEnabled == true) 25 | { 26 | AddRawDetail("true"); 27 | } 28 | return null; 29 | } 30 | 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /Cloud/Tokens/ChallengeResponse.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Vincent LE TOUX for Ping Castle. All rights reserved. 3 | // https://www.pingcastle.com 4 | // 5 | // Licensed under the Non-Profit OSL. See LICENSE file in the project root for full license information. 6 | // 7 | using PingCastle.Cloud.Common; 8 | using System; 9 | using System.Collections.Generic; 10 | using System.Linq; 11 | using System.Runtime.Serialization; 12 | using System.Text; 13 | using System.Threading.Tasks; 14 | 15 | namespace PingCastle.Cloud.RESTServices 16 | { 17 | [DataContractAttribute] 18 | public class ChallengeResponse : JsonSerialization 19 | { 20 | [DataMember] 21 | public string Nonce { get; set; } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /Cloud/Tokens/JwtHeader.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Vincent LE TOUX for Ping Castle. All rights reserved. 3 | // https://www.pingcastle.com 4 | // 5 | // Licensed under the Non-Profit OSL. See LICENSE file in the project root for full license information. 6 | // 7 | using PingCastle.Cloud.Common; 8 | using System; 9 | using System.Collections.Generic; 10 | using System.Linq; 11 | using System.Text; 12 | using System.Threading.Tasks; 13 | 14 | namespace PingCastle.Cloud.Tokens 15 | { 16 | public class JwtHeader : JsonSerialization 17 | { 18 | public string alg { get; set; } 19 | public string typ { get; set; } 20 | public string x5t { get; set; } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /Cloud/Tokens/JwtPayload.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Vincent LE TOUX for Ping Castle. All rights reserved. 3 | // https://www.pingcastle.com 4 | // 5 | // Licensed under the Non-Profit OSL. See LICENSE file in the project root for full license information. 6 | // 7 | using PingCastle.Cloud.Common; 8 | using System; 9 | using System.Collections.Generic; 10 | using System.Linq; 11 | using System.Text; 12 | using System.Threading.Tasks; 13 | 14 | namespace PingCastle.Cloud.Tokens 15 | { 16 | public class JwtPayload : JsonSerialization 17 | { 18 | public string aud { get; set; } 19 | public long exp { get; set; } 20 | public string iss { get; set; } 21 | 22 | 23 | public string jti { get; set; } 24 | public long nbf { get; set; } 25 | public string sub { get; set; } 26 | public long iat { get; set; } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /Cloud/Tokens/Token.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Vincent LE TOUX for Ping Castle. All rights reserved. 3 | // https://www.pingcastle.com 4 | // 5 | // Licensed under the Non-Profit OSL. See LICENSE file in the project root for full license information. 6 | // 7 | using PingCastle.Cloud.Common; 8 | using System; 9 | using System.Collections.Generic; 10 | using System.IO; 11 | using System.Linq; 12 | using System.Runtime.Serialization; 13 | using System.Runtime.Serialization.Json; 14 | using System.Text; 15 | using System.Threading.Tasks; 16 | 17 | namespace PingCastle.Cloud.Tokens 18 | { 19 | public class Token : JsonSerialization 20 | { 21 | 22 | public string token_type { get; set; } 23 | 24 | public string scope { get; set; } 25 | 26 | public uint expires_in { get; set; } 27 | 28 | public uint ext_expires_in { get; set; } 29 | 30 | public uint expires_on { get; set; } 31 | 32 | public uint not_before { get; set; } 33 | 34 | 35 | public string resource { get; set; } 36 | 37 | public string access_token { get; set; } 38 | 39 | public string refresh_token { get; set; } 40 | 41 | public string id_token { get; set; } 42 | 43 | public JwtToken ToJwtToken() 44 | { 45 | return JwtToken.LoadFromBase64String(access_token.Split('.')[1]); 46 | } 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /Cloud/Tokens/TokenCache.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Vincent LE TOUX for Ping Castle. All rights reserved. 3 | // https://www.pingcastle.com 4 | // 5 | // Licensed under the Non-Profit OSL. See LICENSE file in the project root for full license information. 6 | // 7 | using System; 8 | using System.Collections.Generic; 9 | using System.IO; 10 | using System.Linq; 11 | using System.Text; 12 | using System.Threading.Tasks; 13 | 14 | namespace PingCastle.Cloud.Tokens 15 | { 16 | public class TokenCache 17 | { 18 | const string DirectoryName = "Cache"; 19 | public static List GetTokens() 20 | { 21 | var output = new List(); 22 | foreach (var file in Directory.EnumerateFiles(DirectoryName, "*.json")) 23 | { 24 | output.Add(Token.LoadFromString(File.ReadAllText(file))); 25 | } 26 | return output; 27 | } 28 | 29 | public static void Save(Token token) 30 | { 31 | if (!Directory.Exists(DirectoryName)) 32 | Directory.CreateDirectory(DirectoryName); 33 | File.WriteAllText(Path.Combine(DirectoryName, token .resource.Replace("https://", "").Replace("/", "") + "-" + Guid.NewGuid() + ".json"), token.ToJsonString()); 34 | } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /Compatibility.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Ping Castle. All rights reserved. 3 | // https://www.pingcastle.com 4 | // 5 | // Licensed under the Non-Profit OSL. See LICENSE file in the project root for full license information. 6 | // 7 | 8 | namespace System.Runtime.Serialization 9 | { 10 | [AttributeUsage(AttributeTargets.Assembly | AttributeTargets.Module, Inherited = false, AllowMultiple = true)] 11 | internal sealed class ContractNamespaceAttribute : Attribute 12 | { 13 | private string clrNamespace; 14 | 15 | private string contractNamespace; 16 | 17 | public string ClrNamespace 18 | { 19 | get 20 | { 21 | return this.clrNamespace; 22 | } 23 | set 24 | { 25 | this.clrNamespace = value; 26 | } 27 | } 28 | 29 | public string ContractNamespace 30 | { 31 | get 32 | { 33 | return this.contractNamespace; 34 | } 35 | } 36 | 37 | public ContractNamespaceAttribute(string contractNamespace) 38 | { 39 | this.contractNamespace = contractNamespace; 40 | } 41 | } 42 | 43 | // available in dotnet 3 but not on dotnet 2 which is needed for Windows 2000 44 | [System.AttributeUsage(System.AttributeTargets.Field | System.AttributeTargets.Property, AllowMultiple = false, Inherited = false)] 45 | internal sealed class IgnoreDataMemberAttribute : Attribute 46 | { 47 | public IgnoreDataMemberAttribute() 48 | { 49 | } 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /Data/HealthCheckBUEntityData.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Ping Castle. All rights reserved. 3 | // https://www.pingcastle.com 4 | // 5 | // Licensed under the Non-Profit OSL. See LICENSE file in the project root for full license information. 6 | // 7 | using PingCastle.Data; 8 | using System; 9 | using System.Collections.Generic; 10 | 11 | namespace PingCastle.Healthcheck 12 | { 13 | public interface IMigrationChecker 14 | { 15 | bool IsMigrationTrust(DateTime evaluationDate, DomainKey source, DomainKey destination); 16 | } 17 | 18 | public class OwnerInformationReferences : List 19 | { 20 | } 21 | 22 | public interface OwnerInformation 23 | { 24 | DomainKey Domain { get; } 25 | bool ShouldDomainBeHidden { get; } 26 | string GetJasonOutput(); 27 | 28 | List> GetData(); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /Data/IPingCastleReport.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Ping Castle. All rights reserved. 3 | // https://www.pingcastle.com 4 | // 5 | // Licensed under the Non-Profit OSL. See LICENSE file in the project root for full license information. 6 | // 7 | using System; 8 | using System.Collections.Generic; 9 | 10 | namespace PingCastle.Data 11 | { 12 | public interface IPingCastleReport 13 | { 14 | DomainKey Domain { get; } 15 | DateTime GenerationDate { get; } 16 | string EngineVersion { get; } 17 | // used to get trusted domain and detect ubiquous name (ex: corp.local) 18 | IList DomainKnown { get; } 19 | string GetHumanReadableFileName(); 20 | string GetMachineReadableFileName(); 21 | void SetExportLevel(PingCastleReportDataExportLevel level); 22 | void SetIntegrity(); 23 | void CheckIntegrity(); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /Data/IPingCastleReportGenerator.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Net; 3 | 4 | namespace PingCastle.Data 5 | { 6 | 7 | public class PingCastleAnalyzerParameters 8 | { 9 | public string Server { get; set; } 10 | public int Port { get; set; } 11 | public NetworkCredential Credential { get; set; } 12 | public bool PerformExtendedTrustDiscovery { get; set; } 13 | public List AdditionalNamesForDelegationAnalysis { get; set; } 14 | } 15 | 16 | public interface IPingCastleAnalyzer where T : IPingCastleReport 17 | { 18 | T PerformAnalyze(PingCastleAnalyzerParameters parameters); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /Data/PingCastleReportDataExportLevel.cs: -------------------------------------------------------------------------------- 1 | namespace PingCastle.Data 2 | { 3 | public enum PingCastleReportDataExportLevel 4 | { 5 | Full, 6 | Normal, 7 | Light, 8 | Paranoid, 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /Directory.Build.props: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Netwrix Corporation 8 | PingCastle 9 | 10 | 11 | -------------------------------------------------------------------------------- /Exports/IExport.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Net; 4 | using System.Text; 5 | 6 | namespace PingCastle.Exports 7 | { 8 | public interface IExport 9 | { 10 | void Initialize(RuntimeSettings settings); 11 | void Export(string filename); 12 | string Name { get; } 13 | string Description { get; } 14 | DisplayState QueryForAdditionalParameterInInteractiveMode(); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /FodyWeavers.xml: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /Graph/Database/MappingType.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Ping Castle. All rights reserved. 3 | // https://www.pingcastle.com 4 | // 5 | // Licensed under the Non-Profit OSL. See LICENSE file in the project root for full license information. 6 | // 7 | 8 | namespace PingCastle.Graph.Database 9 | { 10 | public enum MappingType 11 | { 12 | Shortname, 13 | DistinguishedName, 14 | Sid, 15 | FileName, 16 | GPODirectory, 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /Graph/Database/Relation.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Ping Castle. All rights reserved. 3 | // https://www.pingcastle.com 4 | // 5 | // Licensed under the Non-Profit OSL. See LICENSE file in the project root for full license information. 6 | // 7 | using System.Collections.Generic; 8 | using System.Diagnostics; 9 | 10 | namespace PingCastle.Graph.Database 11 | { 12 | [DebuggerDisplay("From: {FromId} To: {ToId} Hints: {string.Join(\" \", Hint)}")] 13 | public class Relation 14 | { 15 | public int FromId { get; set; } 16 | public int ToId { get; set; } 17 | public List Hint { get; set; } 18 | 19 | public Relation() 20 | { 21 | Hint = new List(); 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /Healthcheck/Rules/HeatlcheckRuleAnomalyAnonymousAuthorizedGPO.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Ping Castle. All rights reserved. 3 | // https://www.pingcastle.com 4 | // 5 | // Licensed under the Non-Profit OSL. See LICENSE file in the project root for full license information. 6 | // 7 | using PingCastle.Rules; 8 | 9 | namespace PingCastle.Healthcheck.Rules 10 | { 11 | [RuleModel("A-AnonymousAuthorizedGPO", RiskRuleCategory.Anomalies, RiskModelCategory.Reconnaissance)] 12 | [RuleComputation(RuleComputationType.TriggerOnPresence, 5)] 13 | [RuleSTIG("V-14798", "Directory data (outside the root DSE) of a non-public directory must be configured to prevent anonymous access.", STIGFramework.ActiveDirectoryService2003)] 14 | [RuleMaturityLevel(2)] 15 | [RuleMitreAttackTechnique(MitreAttackTechnique.BruteForcePasswordSpraying)] 16 | public class HeatlcheckRuleAnomalyAnonymousAuthorizedGPO : RuleBase 17 | { 18 | protected override int? AnalyzeDataNew(HealthcheckData healthcheckData) 19 | { 20 | foreach (GPPSecurityPolicy policy in healthcheckData.GPPPasswordPolicy) 21 | { 22 | foreach (GPPSecurityPolicyProperty property in policy.Properties) 23 | { 24 | if (property.Property == "RestrictAnonymous" || property.Property == "RestrictAnonymousSAM") 25 | { 26 | if (property.Value == 0) 27 | { 28 | AddRawDetail(policy.GPOName); 29 | break; 30 | } 31 | } 32 | } 33 | } 34 | return null; 35 | } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /Healthcheck/Rules/HeatlcheckRuleAnomalyBackupMetadata.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Ping Castle. All rights reserved. 3 | // https://www.pingcastle.com 4 | // 5 | // Licensed under the Non-Profit OSL. See LICENSE file in the project root for full license information. 6 | // 7 | using PingCastle.Rules; 8 | using System; 9 | 10 | namespace PingCastle.Healthcheck.Rules 11 | { 12 | [RuleModel("A-BackupMetadata", RiskRuleCategory.Anomalies, RiskModelCategory.Backup)] 13 | [RuleComputation(RuleComputationType.TriggerOnThreshold, 15, Threshold: 7)] 14 | [RuleSTIG("V-25385", "Active Directory data must be backed up daily for systems with a Risk Management Framework categorization for Availability of moderate or high. Systems with a categorization of low must be backed up weekly.")] 15 | [RuleMaturityLevel(3)] 16 | [RuleMitreAttackMitigation(MitreAttackMitigation.DataBackup)] 17 | public class HeatlcheckRuleAnomalyBackupMetadata : RuleBase 18 | { 19 | protected override int? AnalyzeDataNew(HealthcheckData healthcheckData) 20 | { 21 | if (healthcheckData.LastADBackup < DateTime.MaxValue) 22 | { 23 | return (int)(healthcheckData.GenerationDate - healthcheckData.LastADBackup).TotalDays; 24 | } 25 | else if (healthcheckData.LastADBackup == DateTime.MaxValue) 26 | { 27 | return (int)(healthcheckData.GenerationDate - healthcheckData.DomainCreation).TotalDays; 28 | } 29 | return 0; 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /Healthcheck/Rules/HeatlcheckRuleAnomalyCertEnrollCB.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Ping Castle. All rights reserved. 3 | // https://www.pingcastle.com 4 | // 5 | // Licensed under the Non-Profit OSL. See LICENSE file in the project root for full license information. 6 | // 7 | using PingCastle.Rules; 8 | using System; 9 | using System.Diagnostics; 10 | using System.Security.Cryptography; 11 | using System.Security.Cryptography.X509Certificates; 12 | 13 | namespace PingCastle.Healthcheck.Rules 14 | { 15 | [RuleModel("A-CertEnrollChannelBinding", RiskRuleCategory.Anomalies, RiskModelCategory.CertificateTakeOver)] 16 | [RuleComputation(RuleComputationType.TriggerOnPresence, 5)] 17 | [RuleIntroducedIn(2, 11)] 18 | [RuleMaturityLevel(3)] 19 | [RuleMitreAttackTechnique(MitreAttackTechnique.ManintheMiddle)] 20 | public class HeatlcheckRuleAnomalyCertEnrollCB : RuleBase 21 | { 22 | protected override int? AnalyzeDataNew(HealthcheckData healthcheckData) 23 | { 24 | if (healthcheckData.CertificateEnrollments != null) 25 | { 26 | foreach (var ce in healthcheckData.CertificateEnrollments) 27 | { 28 | if (ce.WebEnrollmentChannelBindingDisabled) 29 | { 30 | AddRawDetail(ce.Name, "WebEnrollment"); 31 | } 32 | if (ce.CESChannelBindingDisabled) 33 | { 34 | AddRawDetail(ce.Name, "CES"); 35 | } 36 | } 37 | } 38 | return null; 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /Healthcheck/Rules/HeatlcheckRuleAnomalyCertEnrollHttp.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Ping Castle. All rights reserved. 3 | // https://www.pingcastle.com 4 | // 5 | // Licensed under the Non-Profit OSL. See LICENSE file in the project root for full license information. 6 | // 7 | using PingCastle.Rules; 8 | using System; 9 | using System.Diagnostics; 10 | using System.Security.Cryptography; 11 | using System.Security.Cryptography.X509Certificates; 12 | 13 | namespace PingCastle.Healthcheck.Rules 14 | { 15 | [RuleModel("A-CertEnrollHttp", RiskRuleCategory.Anomalies, RiskModelCategory.CertificateTakeOver)] 16 | [RuleComputation(RuleComputationType.TriggerOnPresence, 5)] 17 | [RuleIntroducedIn(2, 11)] 18 | [RuleMaturityLevel(3)] 19 | [RuleMitreAttackTechnique(MitreAttackTechnique.ManintheMiddle)] 20 | public class HeatlcheckRuleAnomalyCertEnrollHttp : RuleBase 21 | { 22 | protected override int? AnalyzeDataNew(HealthcheckData healthcheckData) 23 | { 24 | if (healthcheckData.CertificateEnrollments != null) 25 | { 26 | foreach (var ce in healthcheckData.CertificateEnrollments) 27 | { 28 | if (ce.CESHttp) 29 | { 30 | AddRawDetail(ce.Name, "CES"); 31 | } 32 | if (ce.WebEnrollmentHttp) 33 | { 34 | AddRawDetail(ce.Name, "WebEnrollment"); 35 | } 36 | } 37 | } 38 | return null; 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /Healthcheck/Rules/HeatlcheckRuleAnomalyCertTempAgent.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Ping Castle. All rights reserved. 3 | // https://www.pingcastle.com 4 | // 5 | // Licensed under the Non-Profit OSL. See LICENSE file in the project root for full license information. 6 | // 7 | using PingCastle.Rules; 8 | using System; 9 | using System.Diagnostics; 10 | using System.Security.Cryptography; 11 | using System.Security.Cryptography.X509Certificates; 12 | 13 | namespace PingCastle.Healthcheck.Rules 14 | { 15 | [RuleModel("A-CertTempAgent", RiskRuleCategory.Anomalies, RiskModelCategory.CertificateTakeOver)] 16 | [RuleComputation(RuleComputationType.TriggerOnPresence, 15)] 17 | [RuleIntroducedIn(2, 9, 3)] 18 | [RuleDurANSSI(1, "adcs_template_auth_enroll_with_name", "Dangerous enrollment permission on authentication certificate templates")] 19 | [RuleMitreAttackTechnique(MitreAttackTechnique.StealorForgeKerberosTickets)] 20 | public class HeatlcheckRuleAnomalyCertTempAgent : RuleBase 21 | { 22 | protected override int? AnalyzeDataNew(HealthcheckData healthcheckData) 23 | { 24 | if (healthcheckData.CertificateTemplates != null) 25 | { 26 | foreach (var ct in healthcheckData.CertificateTemplates) 27 | { 28 | if (!ct.CAManagerApproval && ct.IssuanceRequirementsEmpty && ct.LowPrivCanEnroll && ct.EnrollmentAgentTemplate) 29 | { 30 | AddRawDetail(ct.Name); 31 | } 32 | } 33 | } 34 | return null; 35 | } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /Healthcheck/Rules/HeatlcheckRuleAnomalyCertTempAnyPurpose.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Ping Castle. All rights reserved. 3 | // https://www.pingcastle.com 4 | // 5 | // Licensed under the Non-Profit OSL. See LICENSE file in the project root for full license information. 6 | // 7 | using PingCastle.Rules; 8 | using System; 9 | using System.Diagnostics; 10 | using System.Security.Cryptography; 11 | using System.Security.Cryptography.X509Certificates; 12 | 13 | namespace PingCastle.Healthcheck.Rules 14 | { 15 | [RuleModel("A-CertTempAnyPurpose", RiskRuleCategory.Anomalies, RiskModelCategory.CertificateTakeOver)] 16 | [RuleComputation(RuleComputationType.TriggerOnPresence, 15)] 17 | [RuleIntroducedIn(2, 9, 3)] 18 | [RuleDurANSSI(1, "adcs_template_auth_enroll_with_name", "Dangerous enrollment permission on authentication certificate templates")] 19 | [RuleMitreAttackTechnique(MitreAttackTechnique.StealorForgeKerberosTickets)] 20 | public class HeatlcheckRuleAnomalyCertTempAnyPurpose : RuleBase 21 | { 22 | protected override int? AnalyzeDataNew(HealthcheckData healthcheckData) 23 | { 24 | if (healthcheckData.CertificateTemplates != null) 25 | { 26 | foreach (var ct in healthcheckData.CertificateTemplates) 27 | { 28 | if (!ct.CAManagerApproval && ct.IssuanceRequirementsEmpty && ct.LowPrivCanEnroll && ct.HasAnyPurpose) 29 | { 30 | AddRawDetail(ct.Name); 31 | } 32 | } 33 | } 34 | return null; 35 | } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /Healthcheck/Rules/HeatlcheckRuleAnomalyCertTempAnyone.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Ping Castle. All rights reserved. 3 | // https://www.pingcastle.com 4 | // 5 | // Licensed under the Non-Profit OSL. See LICENSE file in the project root for full license information. 6 | // 7 | using PingCastle.Rules; 8 | using System; 9 | using System.Diagnostics; 10 | using System.Security.Cryptography; 11 | using System.Security.Cryptography.X509Certificates; 12 | 13 | namespace PingCastle.Healthcheck.Rules 14 | { 15 | [RuleModel("A-CertTempAnyone", RiskRuleCategory.Anomalies, RiskModelCategory.CertificateTakeOver)] 16 | [RuleComputation(RuleComputationType.TriggerOnPresence, 15)] 17 | [RuleIntroducedIn(2, 9, 3)] 18 | [RuleDurANSSI(1, "adcs_template_auth_enroll_with_name", "Dangerous enrollment permission on authentication certificate templates")] 19 | [RuleMitreAttackTechnique(MitreAttackTechnique.StealorForgeKerberosTickets)] 20 | public class HeatlcheckRuleAnomalyCertTempAnyone : RuleBase 21 | { 22 | protected override int? AnalyzeDataNew(HealthcheckData healthcheckData) 23 | { 24 | if (healthcheckData.CertificateTemplates != null) 25 | { 26 | foreach (var ct in healthcheckData.CertificateTemplates) 27 | { 28 | if (ct.VulnerableTemplateACL) 29 | { 30 | AddRawDetail(ct.Name); 31 | } 32 | } 33 | } 34 | return null; 35 | } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /Healthcheck/Rules/HeatlcheckRuleAnomalyCertTempCustomSubject.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Ping Castle. All rights reserved. 3 | // https://www.pingcastle.com 4 | // 5 | // Licensed under the Non-Profit OSL. See LICENSE file in the project root for full license information. 6 | // 7 | using PingCastle.Rules; 8 | using System; 9 | using System.Diagnostics; 10 | using System.Security.Cryptography; 11 | using System.Security.Cryptography.X509Certificates; 12 | 13 | namespace PingCastle.Healthcheck.Rules 14 | { 15 | [RuleModel("A-CertTempCustomSubject", RiskRuleCategory.Anomalies, RiskModelCategory.CertificateTakeOver)] 16 | [RuleComputation(RuleComputationType.TriggerOnPresence, 15)] 17 | [RuleIntroducedIn(2, 9, 3)] 18 | [RuleDurANSSI(1, "adcs_template_auth_enroll_with_name", "Dangerous enrollment permission on authentication certificate templates")] 19 | [RuleMitreAttackTechnique(MitreAttackTechnique.StealorForgeKerberosTickets)] 20 | public class HeatlcheckRuleAnomalyCertTempCustomSubject : RuleBase 21 | { 22 | protected override int? AnalyzeDataNew(HealthcheckData healthcheckData) 23 | { 24 | if (healthcheckData.CertificateTemplates != null) 25 | { 26 | foreach (var ct in healthcheckData.CertificateTemplates) 27 | { 28 | if (!ct.CAManagerApproval && ct.IssuanceRequirementsEmpty && ct.LowPrivCanEnroll && ct.HasAuthenticationEku && ct.EnrolleeSupplies > 0) 29 | { 30 | AddRawDetail(ct.Name); 31 | } 32 | } 33 | } 34 | return null; 35 | } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /Healthcheck/Rules/HeatlcheckRuleAnomalyCertTempNoSecurity.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Ping Castle. All rights reserved. 3 | // https://www.pingcastle.com 4 | // 5 | // Licensed under the Non-Profit OSL. See LICENSE file in the project root for full license information. 6 | // 7 | using PingCastle.Rules; 8 | using System; 9 | using System.Diagnostics; 10 | using System.Security.Cryptography; 11 | using System.Security.Cryptography.X509Certificates; 12 | 13 | namespace PingCastle.Healthcheck.Rules 14 | { 15 | [RuleModel("A-CertTempNoSecurity", RiskRuleCategory.Anomalies, RiskModelCategory.CertificateTakeOver)] 16 | [RuleComputation(RuleComputationType.TriggerOnPresence, 15)] 17 | [RuleIntroducedIn(2, 11, 0)] 18 | [RuleDurANSSI(1, "adcs_template_auth_enroll_with_name", "Dangerous enrollment permission on authentication certificate templates")] 19 | [RuleMitreAttackTechnique(MitreAttackTechnique.StealorForgeKerberosTickets)] 20 | public class HeatlcheckRuleAnomalyCertTempNoSecurity : RuleBase 21 | { 22 | protected override int? AnalyzeDataNew(HealthcheckData healthcheckData) 23 | { 24 | if (healthcheckData.CertificateTemplates != null) 25 | { 26 | foreach (var ct in healthcheckData.CertificateTemplates) 27 | { 28 | if (ct.NoSecurityExtension) 29 | { 30 | AddRawDetail(ct.Name); 31 | } 32 | } 33 | } 34 | return null; 35 | } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /Healthcheck/Rules/HeatlcheckRuleAnomalyDCLdapSign.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Ping Castle. All rights reserved. 3 | // https://www.pingcastle.com 4 | // 5 | // Licensed under the Non-Profit OSL. See LICENSE file in the project root for full license information. 6 | // 7 | using PingCastle.Rules; 8 | 9 | namespace PingCastle.Healthcheck.Rules 10 | { 11 | [RuleModel("A-DCLdapSign", RiskRuleCategory.Anomalies, RiskModelCategory.NetworkSniffing)] 12 | [RuleComputation(RuleComputationType.TriggerOnPresence, 5)] 13 | [RuleIntroducedIn(2, 11)] 14 | [RuleMaturityLevel(3)] 15 | [RuleMitreAttackTechnique(MitreAttackTechnique.ManintheMiddle)] 16 | public class HeatlcheckRuleAnomalyDCLdapSign : RuleBase 17 | { 18 | protected override int? AnalyzeDataNew(HealthcheckData healthcheckData) 19 | { 20 | foreach (var dc in healthcheckData.DomainControllers) 21 | { 22 | if (dc.LdapServerSigningRequirementDisabled) 23 | AddRawDetail(dc.DCName); 24 | } 25 | return null; 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /Healthcheck/Rules/HeatlcheckRuleAnomalyDCLdapsCB.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Ping Castle. All rights reserved. 3 | // https://www.pingcastle.com 4 | // 5 | // Licensed under the Non-Profit OSL. See LICENSE file in the project root for full license information. 6 | // 7 | using PingCastle.Rules; 8 | 9 | namespace PingCastle.Healthcheck.Rules 10 | { 11 | [RuleModel("A-DCLdapsChannelBinding", RiskRuleCategory.Anomalies, RiskModelCategory.NetworkSniffing)] 12 | [RuleComputation(RuleComputationType.TriggerOnPresence, 5)] 13 | [RuleIntroducedIn(2, 11)] 14 | [RuleMaturityLevel(3)] 15 | [RuleMitreAttackTechnique(MitreAttackTechnique.ManintheMiddle)] 16 | public class HeatlcheckRuleAnomalyDCLdapsCB : RuleBase 17 | { 18 | protected override int? AnalyzeDataNew(HealthcheckData healthcheckData) 19 | { 20 | foreach (var dc in healthcheckData.DomainControllers) 21 | { 22 | if (dc.ChannelBindingDisabled) 23 | AddRawDetail(dc.DCName); 24 | } 25 | return null; 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /Healthcheck/Rules/HeatlcheckRuleAnomalyDCLdapsSSL.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Ping Castle. All rights reserved. 3 | // https://www.pingcastle.com 4 | // 5 | // Licensed under the Non-Profit OSL. See LICENSE file in the project root for full license information. 6 | // 7 | using PingCastle.Rules; 8 | 9 | namespace PingCastle.Healthcheck.Rules 10 | { 11 | [RuleModel("A-DCLdapsProtocol", RiskRuleCategory.Anomalies, RiskModelCategory.CertificateTakeOver)] 12 | [RuleComputation(RuleComputationType.TriggerOnPresence, 10)] 13 | [RuleIntroducedIn(2, 8)] 14 | [RuleMaturityLevel(3)] 15 | [RuleMitreAttackTechnique(MitreAttackTechnique.WeakenEncryptionReduceKeySpace)] 16 | public class HeatlcheckRuleAnomalyDCLdapsSSL : RuleBase 17 | { 18 | protected override int? AnalyzeDataNew(HealthcheckData healthcheckData) 19 | { 20 | foreach (var dc in healthcheckData.DomainControllers) 21 | { 22 | if (dc.LDAPSProtocols == null) 23 | continue; 24 | foreach (var protocol in dc.LDAPSProtocols) 25 | { 26 | switch (protocol) 27 | { 28 | case "Ssl2": 29 | case "Ssl3": 30 | AddRawDetail(dc.DCName, protocol); 31 | break; 32 | } 33 | } 34 | } 35 | return null; 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /Healthcheck/Rules/HeatlcheckRuleAnomalyDCLdapsSSLAdvanced.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Ping Castle. All rights reserved. 3 | // https://www.pingcastle.com 4 | // 5 | // Licensed under the Non-Profit OSL. See LICENSE file in the project root for full license information. 6 | // 7 | using PingCastle.Rules; 8 | 9 | namespace PingCastle.Healthcheck.Rules 10 | { 11 | [RuleModel("A-DCLdapsProtocolAdvanced", RiskRuleCategory.Anomalies, RiskModelCategory.CertificateTakeOver)] 12 | [RuleComputation(RuleComputationType.TriggerOnPresence, 0)] 13 | [RuleIntroducedIn(3, 1)] 14 | [RuleMaturityLevel(5)] 15 | [RuleMitreAttackTechnique(MitreAttackTechnique.WeakenEncryptionReduceKeySpace)] 16 | public class HeatlcheckRuleAnomalyDCLdapsSSLAdvanced : RuleBase 17 | { 18 | protected override int? AnalyzeDataNew(HealthcheckData healthcheckData) 19 | { 20 | foreach (var dc in healthcheckData.DomainControllers) 21 | { 22 | if (dc.LDAPSProtocols == null) 23 | continue; 24 | foreach (var protocol in dc.LDAPSProtocols) 25 | { 26 | switch (protocol) 27 | { 28 | case "Tls": 29 | case "Tls11": 30 | AddRawDetail(dc.DCName, protocol); 31 | break; 32 | } 33 | } 34 | } 35 | return null; 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /Healthcheck/Rules/HeatlcheckRuleAnomalyDCSpooler.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Ping Castle. All rights reserved. 3 | // https://www.pingcastle.com 4 | // 5 | // Licensed under the Non-Profit OSL. See LICENSE file in the project root for full license information. 6 | // 7 | using PingCastle.Rules; 8 | 9 | namespace PingCastle.Healthcheck.Rules 10 | { 11 | [RuleModel("A-DC-Spooler", RiskRuleCategory.Anomalies, RiskModelCategory.PassTheCredential)] 12 | [RuleComputation(RuleComputationType.TriggerOnPresence, 10)] 13 | [RuleIntroducedIn(2, 6)] 14 | [RuleMaturityLevel(2)] 15 | [RuleMitreAttackTechnique(MitreAttackTechnique.ForcedAuthentication)] 16 | public class HeatlcheckRuleAnomalyDCSpooler : RuleBase 17 | { 18 | protected override int? AnalyzeDataNew(HealthcheckData healthcheckData) 19 | { 20 | foreach (var DC in healthcheckData.DomainControllers) 21 | { 22 | if (DC.RemoteSpoolerDetected) 23 | { 24 | AddRawDetail(DC.DCName); 25 | } 26 | } 27 | return null; 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /Healthcheck/Rules/HeatlcheckRuleAnomalyDCWebClient.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Ping Castle. All rights reserved. 3 | // https://www.pingcastle.com 4 | // 5 | // Licensed under the Non-Profit OSL. See LICENSE file in the project root for full license information. 6 | // 7 | using PingCastle.Rules; 8 | 9 | namespace PingCastle.Healthcheck.Rules 10 | { 11 | [RuleModel("A-DC-WebClient", RiskRuleCategory.Anomalies, RiskModelCategory.PassTheCredential)] 12 | [RuleComputation(RuleComputationType.TriggerOnPresence, 0)] 13 | [RuleIntroducedIn(2, 11)] 14 | [RuleMaturityLevel(4)] 15 | [RuleMitreAttackTechnique(MitreAttackTechnique.ForcedAuthentication)] 16 | public class HeatlcheckRuleAnomalyDCWebClient : RuleBase 17 | { 18 | protected override int? AnalyzeDataNew(HealthcheckData healthcheckData) 19 | { 20 | foreach (var DC in healthcheckData.DomainControllers) 21 | { 22 | if (DC.WebClientEnabled) 23 | { 24 | AddRawDetail(DC.DCName); 25 | } 26 | } 27 | return null; 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /Healthcheck/Rules/HeatlcheckRuleAnomalyDnsZoneAUCreateChild.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Ping Castle. All rights reserved. 3 | // https://www.pingcastle.com 4 | // 5 | // Licensed under the Non-Profit OSL. See LICENSE file in the project root for full license information. 6 | // 7 | using PingCastle.Rules; 8 | 9 | namespace PingCastle.Healthcheck.Rules 10 | { 11 | [RuleModel("A-DnsZoneAUCreateChild", RiskRuleCategory.Anomalies, RiskModelCategory.NetworkSniffing)] 12 | [RuleComputation(RuleComputationType.TriggerOnPresence, 0)] 13 | [RuleIntroducedIn(2, 10, 1)] 14 | [RuleMaturityLevel(4)] 15 | [RuleMitreAttackTechnique(MitreAttackTechnique.ManintheMiddle)] 16 | public class HeatlcheckRuleAnomalyDnsZoneAUCreateChild : RuleBase 17 | { 18 | protected override int? AnalyzeDataNew(HealthcheckData healthcheckData) 19 | { 20 | if (healthcheckData.DnsZones != null) 21 | { 22 | foreach (var zone in healthcheckData.DnsZones) 23 | { 24 | if (zone.AUCreateChild) 25 | { 26 | AddRawDetail(zone.name); 27 | } 28 | } 29 | } 30 | return null; 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /Healthcheck/Rules/HeatlcheckRuleAnomalyDnsZoneTransfert.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Ping Castle. All rights reserved. 3 | // https://www.pingcastle.com 4 | // 5 | // Licensed under the Non-Profit OSL. See LICENSE file in the project root for full license information. 6 | // 7 | using PingCastle.Rules; 8 | 9 | namespace PingCastle.Healthcheck.Rules 10 | { 11 | [RuleModel("A-DnsZoneTransfert", RiskRuleCategory.Anomalies, RiskModelCategory.Reconnaissance)] 12 | [RuleComputation(RuleComputationType.TriggerOnPresence, 5)] 13 | [RuleIntroducedIn(2, 9, 3)] 14 | [RuleMaturityLevel(2)] 15 | [RuleMitreAttackTechnique(MitreAttackTechnique.RemoteSystemDiscovery)] 16 | public class HeatlcheckRuleAnomalyDnsZoneTransfert : RuleBase 17 | { 18 | protected override int? AnalyzeDataNew(HealthcheckData healthcheckData) 19 | { 20 | if (healthcheckData.DnsZones != null) 21 | { 22 | foreach (var zone in healthcheckData.DnsZones) 23 | { 24 | if (!zone.ZoneTransfert) 25 | continue; 26 | AddRawDetail(zone.name); 27 | } 28 | } 29 | return null; 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /Healthcheck/Rules/HeatlcheckRuleAnomalyDnsZoneUnsecureUpdate1.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Ping Castle. All rights reserved. 3 | // https://www.pingcastle.com 4 | // 5 | // Licensed under the Non-Profit OSL. See LICENSE file in the project root for full license information. 6 | // 7 | using PingCastle.Rules; 8 | 9 | namespace PingCastle.Healthcheck.Rules 10 | { 11 | [RuleModel("A-DnsZoneUpdate1", RiskRuleCategory.Anomalies, RiskModelCategory.NetworkSniffing)] 12 | [RuleComputation(RuleComputationType.TriggerOnPresence, 15)] 13 | [RuleIntroducedIn(2, 9)] 14 | [RuleDurANSSI(1, "dnszone_bad_prop", "Misconfigured DNS zones")] 15 | [RuleMitreAttackTechnique(MitreAttackTechnique.ManintheMiddle)] 16 | public class HeatlcheckRuleAnomalyDnsZoneUnsecureUpdate1 : RuleBase 17 | { 18 | protected override int? AnalyzeDataNew(HealthcheckData healthcheckData) 19 | { 20 | if (healthcheckData.DnsZones != null) 21 | { 22 | foreach (var zone in healthcheckData.DnsZones) 23 | { 24 | if (!zone.InsecureUpdate) 25 | continue; 26 | if (zone.name == healthcheckData.DomainFQDN || zone.name == "RootDNSServers") 27 | { 28 | AddRawDetail(zone.name); 29 | } 30 | } 31 | } 32 | return null; 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /Healthcheck/Rules/HeatlcheckRuleAnomalyDnsZoneUnsecureUpdate2.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Ping Castle. All rights reserved. 3 | // https://www.pingcastle.com 4 | // 5 | // Licensed under the Non-Profit OSL. See LICENSE file in the project root for full license information. 6 | // 7 | using PingCastle.Rules; 8 | 9 | namespace PingCastle.Healthcheck.Rules 10 | { 11 | [RuleModel("A-DnsZoneUpdate2", RiskRuleCategory.Anomalies, RiskModelCategory.NetworkSniffing)] 12 | [RuleComputation(RuleComputationType.TriggerOnPresence, 1)] 13 | [RuleIntroducedIn(2, 9)] 14 | [RuleDurANSSI(3, "dnszone_bad_prop", "Misconfigured DNS zones")] 15 | [RuleMitreAttackTechnique(MitreAttackTechnique.ManintheMiddle)] 16 | public class HeatlcheckRuleAnomalyDnsZoneUnsecureUpdate2 : RuleBase 17 | { 18 | protected override int? AnalyzeDataNew(HealthcheckData healthcheckData) 19 | { 20 | if (healthcheckData.DnsZones != null) 21 | { 22 | foreach (var zone in healthcheckData.DnsZones) 23 | { 24 | if (!zone.InsecureUpdate) 25 | continue; 26 | if (!(zone.name == healthcheckData.DomainFQDN || zone.name == "RootDNSServers")) 27 | { 28 | AddRawDetail(zone.name); 29 | } 30 | } 31 | } 32 | return null; 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /Healthcheck/Rules/HeatlcheckRuleAnomalyDsHeuristicsAnonNSPI.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Ping Castle. All rights reserved. 3 | // https://www.pingcastle.com 4 | // 5 | // Licensed under the Non-Profit OSL. See LICENSE file in the project root for full license information. 6 | // 7 | using PingCastle.Rules; 8 | 9 | namespace PingCastle.Healthcheck.Rules 10 | { 11 | [RuleModel("A-DsHeuristicsAllowAnonNSPI", RiskRuleCategory.Anomalies, RiskModelCategory.Reconnaissance)] 12 | [RuleComputation(RuleComputationType.TriggerOnPresence, 5)] 13 | [RuleSTIG("V-8555", "Anonymous Access to AD forest data above the rootDSE level must be disabled. ", STIGFramework.Forest)] 14 | [RuleDurANSSI(1, "dsheuristics_bad", "Dangerous dsHeuristics settings")] 15 | [RuleIntroducedIn(2, 9)] 16 | [RuleMitreAttackTechnique(MitreAttackTechnique.BruteForcePasswordSpraying)] 17 | public class HeatlcheckRuleAnomalyDsHeuristicsAnonNSPI : RuleBase 18 | { 19 | protected override int? AnalyzeDataNew(HealthcheckData healthcheckData) 20 | { 21 | if (healthcheckData.DSHeuristics != null && healthcheckData.DSHeuristics.Length >= 8 && healthcheckData.DSHeuristics.Substring(7, 1) != "0") 22 | { 23 | return 1; 24 | } 25 | return 0; 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /Healthcheck/Rules/HeatlcheckRuleAnomalyDsHeuristicsAnonymous.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Ping Castle. All rights reserved. 3 | // https://www.pingcastle.com 4 | // 5 | // Licensed under the Non-Profit OSL. See LICENSE file in the project root for full license information. 6 | // 7 | using PingCastle.Rules; 8 | 9 | namespace PingCastle.Healthcheck.Rules 10 | { 11 | [RuleModel("A-DsHeuristicsAnonymous", RiskRuleCategory.Anomalies, RiskModelCategory.Reconnaissance)] 12 | [RuleComputation(RuleComputationType.TriggerOnPresence, 5)] 13 | [RuleSTIG("V-8555", "Anonymous Access to AD forest data above the rootDSE level must be disabled. ", STIGFramework.Forest)] 14 | [RuleDurANSSI(2, "dsheuristics_bad", "Dangerous dsHeuristics settings")] 15 | [RuleMitreAttackTechnique(MitreAttackTechnique.BruteForcePasswordSpraying)] 16 | public class HeatlcheckRuleAnomalyDsHeuristicsAnonymous : RuleBase 17 | { 18 | protected override int? AnalyzeDataNew(HealthcheckData healthcheckData) 19 | { 20 | if (healthcheckData.DSHeuristics != null && healthcheckData.DSHeuristics.Length >= 7 && healthcheckData.DSHeuristics.Substring(6, 1) == "2") 21 | { 22 | return 1; 23 | } 24 | return 0; 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /Healthcheck/Rules/HeatlcheckRuleAnomalyDsHeuristicsDoNotVerifyUniqueness.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Ping Castle. All rights reserved. 3 | // https://www.pingcastle.com 4 | // 5 | // Licensed under the Non-Profit OSL. See LICENSE file in the project root for full license information. 6 | // 7 | using PingCastle.Rules; 8 | 9 | namespace PingCastle.Healthcheck.Rules 10 | { 11 | [RuleModel("A-DsHeuristicsDoNotVerifyUniqueness", RiskRuleCategory.Anomalies, RiskModelCategory.Reconnaissance)] 12 | [RuleComputation(RuleComputationType.TriggerOnPresence, 5)] 13 | [RuleDurANSSI(2, "dsheuristics_bad", "Dangerous dsHeuristics settings")] 14 | [RuleIntroducedIn(2, 10, 1)] 15 | [RuleMitreAttackTechnique(MitreAttackTechnique.ForcedAuthentication)] 16 | public class HeatlcheckRuleAnomalyDsHeuristicsDoNotVerifyUniqueness : RuleBase 17 | { 18 | protected override int? AnalyzeDataNew(HealthcheckData healthcheckData) 19 | { 20 | if (healthcheckData.DSHeuristics != null && healthcheckData.DSHeuristics.Length >= 21 && healthcheckData.DSHeuristics.Substring(20, 1) != "0") 21 | { 22 | return 1; 23 | } 24 | return 0; 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /Healthcheck/Rules/HeatlcheckRuleAnomalyGuest.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Ping Castle. All rights reserved. 3 | // https://www.pingcastle.com 4 | // 5 | // Licensed under the Non-Profit OSL. See LICENSE file in the project root for full license information. 6 | // 7 | using PingCastle.Rules; 8 | using System; 9 | 10 | namespace PingCastle.Healthcheck.Rules 11 | { 12 | [RuleModel("A-Guest", RiskRuleCategory.Anomalies, RiskModelCategory.WeakPassword)] 13 | [RuleComputation(RuleComputationType.TriggerOnPresence, 15)] 14 | [RuleMaturityLevel(1)] 15 | [RuleMitreAttackTechnique(MitreAttackTechnique.ValidAccountsLocalAccounts)] 16 | [RuleMitreAttackMitigation(MitreAttackMitigation.ActiveDirectoryConfiguration)] 17 | [RuleIntroducedIn(2,10,1)] 18 | public class HeatlcheckRuleAnomalyGuest : RuleBase 19 | { 20 | protected override int? AnalyzeDataNew(HealthcheckData healthcheckData) 21 | { 22 | return healthcheckData.GuestEnabled ? 1 : 0; 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /Healthcheck/Rules/HeatlcheckRuleAnomalyKrbtgt.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Ping Castle. All rights reserved. 3 | // https://www.pingcastle.com 4 | // 5 | // Licensed under the Non-Profit OSL. See LICENSE file in the project root for full license information. 6 | // 7 | using PingCastle.Rules; 8 | 9 | namespace PingCastle.Healthcheck.Rules 10 | { 11 | [RuleModel("A-Krbtgt", RiskRuleCategory.Anomalies, RiskModelCategory.GoldenTicket)] 12 | [RuleComputation(RuleComputationType.TriggerOnThreshold, 50, Threshold: 1464, Order: 1)] 13 | [RuleComputation(RuleComputationType.TriggerOnThreshold, 40, Threshold: 1098, Order: 2)] 14 | [RuleComputation(RuleComputationType.TriggerOnThreshold, 30, Threshold: 732, Order: 3)] 15 | [RuleComputation(RuleComputationType.TriggerOnThreshold, 20, Threshold: 366, Order: 4)] 16 | [RuleCERTFR("CERTFR-2014-ACT-032", "SECTION00030000000000000000")] 17 | [RuleDurANSSI(2, "krbtgt", "Krbtgt account password unchanged for more than a year")] 18 | [RuleMitreAttackTechnique(MitreAttackTechnique.StealorForgeKerberosTicketsGoldenTicket)] 19 | public class HeatlcheckRuleAnomalyKrbtgt : RuleBase 20 | { 21 | protected override int? AnalyzeDataNew(HealthcheckData healthcheckData) 22 | { 23 | return (int)(healthcheckData.GenerationDate - healthcheckData.KrbtgtLastChangeDate).TotalDays; 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /Healthcheck/Rules/HeatlcheckRuleAnomalyLAPS.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Ping Castle. All rights reserved. 3 | // https://www.pingcastle.com 4 | // 5 | // Licensed under the Non-Profit OSL. See LICENSE file in the project root for full license information. 6 | // 7 | using PingCastle.Rules; 8 | using System; 9 | 10 | namespace PingCastle.Healthcheck.Rules 11 | { 12 | [RuleModel("A-LAPS-Not-Installed", RiskRuleCategory.Anomalies, RiskModelCategory.PassTheCredential)] 13 | [RuleComputation(RuleComputationType.TriggerOnPresence, 15)] 14 | [RuleSTIG("V-36438", "Local administrator accounts on domain systems must not share the same password.")] 15 | [RuleCERTFR("CERTFR-2015-ACT-046", "SECTION00020000000000000000")] 16 | [RuleMaturityLevel(3)] 17 | [RuleMitreAttackTechnique(MitreAttackTechnique.ValidAccountsLocalAccounts)] 18 | [RuleMitreAttackMitigation(MitreAttackMitigation.PrivilegedAccountManagement)] 19 | public class HeatlcheckRuleAnomalyLAPS : RuleBase 20 | { 21 | protected override int? AnalyzeDataNew(HealthcheckData healthcheckData) 22 | { 23 | return (healthcheckData.LAPSInstalled == DateTime.MaxValue && healthcheckData.NewLAPSInstalled == DateTime.MaxValue ? 1 : 0); 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /Healthcheck/Rules/HeatlcheckRuleAnomalyLAPSJoinedComputers.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Ping Castle. All rights reserved. 3 | // https://www.pingcastle.com 4 | // 5 | // Licensed under the Non-Profit OSL. See LICENSE file in the project root for full license information. 6 | // 7 | using PingCastle.Rules; 8 | using System; 9 | 10 | namespace PingCastle.Healthcheck.Rules 11 | { 12 | [RuleModel("A-LAPS-Joined-Computers", RiskRuleCategory.Anomalies, RiskModelCategory.PassTheCredential)] 13 | [RuleComputation(RuleComputationType.TriggerOnPresence, 5)] 14 | [RuleMaturityLevel(3)] 15 | [RuleIntroducedIn(2,9,3)] 16 | [RuleMitreAttackTechnique(MitreAttackTechnique.CredentialsfromPasswordStoresPasswordManagers)] 17 | public class HeatlcheckRuleAnomalyLAPSJoinedComputers : RuleBase 18 | { 19 | protected override int? AnalyzeDataNew(HealthcheckData healthcheckData) 20 | { 21 | if (healthcheckData.ListLAPSJoinedComputersToReview != null) 22 | { 23 | return healthcheckData.ListLAPSJoinedComputersToReview.Count; 24 | } 25 | return 0; 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /Healthcheck/Rules/HeatlcheckRuleAnomalyNotEnoughDC.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Ping Castle. All rights reserved. 3 | // https://www.pingcastle.com 4 | // 5 | // Licensed under the Non-Profit OSL. See LICENSE file in the project root for full license information. 6 | // 7 | using PingCastle.Rules; 8 | 9 | namespace PingCastle.Healthcheck.Rules 10 | { 11 | [RuleModel("A-NotEnoughDC", RiskRuleCategory.Anomalies, RiskModelCategory.Backup)] 12 | [RuleComputation(RuleComputationType.TriggerIfLessThan, 5, Threshold: 2)] 13 | [RuleIntroducedIn(2, 6)] 14 | [RuleMaturityLevel(3)] 15 | [RuleMitreAttackMitigation(MitreAttackMitigation.DataBackup)] 16 | public class HeatlcheckRuleAnomalyNotEnoughDC : RuleBase 17 | { 18 | protected override int? AnalyzeDataNew(HealthcheckData healthcheckData) 19 | { 20 | return healthcheckData.NumberOfDC; 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /Healthcheck/Rules/HeatlcheckRuleAnomalyNullSession.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Ping Castle. All rights reserved. 3 | // https://www.pingcastle.com 4 | // 5 | // Licensed under the Non-Profit OSL. See LICENSE file in the project root for full license information. 6 | // 7 | using PingCastle.Rules; 8 | 9 | namespace PingCastle.Healthcheck.Rules 10 | { 11 | [RuleModel("A-NullSession", RiskRuleCategory.Anomalies, RiskModelCategory.Reconnaissance)] 12 | [RuleComputation(RuleComputationType.TriggerOnPresence, 10)] 13 | //[RuleBSI("M 2.412")] 14 | [RuleSTIG("V-14798", "Directory data (outside the root DSE) of a non-public directory must be configured to prevent anonymous access.", STIGFramework.ActiveDirectoryService2003)] 15 | [RuleMaturityLevel(2)] 16 | [RuleMitreAttackTechnique(MitreAttackTechnique.BruteForcePasswordSpraying)] 17 | public class HeatlcheckRuleAnomalyNullSession : RuleBase 18 | { 19 | protected override int? AnalyzeDataNew(HealthcheckData healthcheckData) 20 | { 21 | if (healthcheckData.DomainControllers != null) 22 | { 23 | foreach (var DC in healthcheckData.DomainControllers) 24 | { 25 | if (DC.HasNullSession) 26 | { 27 | AddRawDetail(DC.DCName); 28 | } 29 | } 30 | } 31 | return null; 32 | } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /Healthcheck/Rules/HeatlcheckRuleAnomalyPasswordInGPO.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Ping Castle. All rights reserved. 3 | // https://www.pingcastle.com 4 | // 5 | // Licensed under the Non-Profit OSL. See LICENSE file in the project root for full license information. 6 | // 7 | using PingCastle.Rules; 8 | 9 | namespace PingCastle.Healthcheck.Rules 10 | { 11 | [RuleModel("A-PwdGPO", RiskRuleCategory.Anomalies, RiskModelCategory.PasswordRetrieval)] 12 | [RuleComputation(RuleComputationType.PerDiscover, 20)] 13 | [RuleCERTFR("CERTFR-2015-ACT-046", "SECTION00020000000000000000")] 14 | [RuleMaturityLevel(1)] 15 | [RuleMitreAttackTechnique(MitreAttackTechnique.UnsecuredCredentialsGroupPolicyPreferences)] 16 | public class HeatlcheckRuleAnomalyPasswordInGPO : RuleBase 17 | { 18 | protected override int? AnalyzeDataNew(HealthcheckData healthcheckData) 19 | { 20 | foreach (var pass in healthcheckData.GPPPassword) 21 | { 22 | AddRawDetail(pass.GPOName, pass.UserName, pass.Password); 23 | } 24 | return null; 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /Healthcheck/Rules/HeatlcheckRuleAnomalyPreWin2000Anonymous.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Ping Castle. All rights reserved. 3 | // https://www.pingcastle.com 4 | // 5 | // Licensed under the Non-Profit OSL. See LICENSE file in the project root for full license information. 6 | // 7 | using PingCastle.Rules; 8 | 9 | namespace PingCastle.Healthcheck.Rules 10 | { 11 | [RuleModel("A-PreWin2000Anonymous", RiskRuleCategory.Anomalies, RiskModelCategory.Reconnaissance)] 12 | [RuleComputation(RuleComputationType.TriggerOnPresence, 5)] 13 | [RuleSTIG("V-8547", "The Anonymous Logon and Everyone groups must not be members of the Pre-Windows 2000 Compatible Access group.")] 14 | //[RuleBSI("M 2.412")] 15 | [RuleDurANSSI(2, "compatible_2000_anonymous", "The \"Pre - Windows 2000 Compatible Access\" group includes \"Anonymous\"")] 16 | [RuleMitreAttackTechnique(MitreAttackTechnique.BruteForcePasswordSpraying)] 17 | public class HeatlcheckRuleAnomalyPreWin2000Anonymous : RuleBase 18 | { 19 | protected override int? AnalyzeDataNew(HealthcheckData healthcheckData) 20 | { 21 | if (healthcheckData.PreWindows2000AnonymousAccess) 22 | { 23 | return 1; 24 | } 25 | return 0; 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /Healthcheck/Rules/HeatlcheckRuleAnomalyPreWin2000AuthenticatedUsers.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Ping Castle. All rights reserved. 3 | // https://www.pingcastle.com 4 | // 5 | // Licensed under the Non-Profit OSL. See LICENSE file in the project root for full license information. 6 | // 7 | using PingCastle.Rules; 8 | 9 | namespace PingCastle.Healthcheck.Rules 10 | { 11 | [RuleModel("A-PreWin2000AuthenticatedUsers", RiskRuleCategory.Anomalies, RiskModelCategory.Reconnaissance)] 12 | [RuleComputation(RuleComputationType.TriggerOnPresence, 0)] 13 | //[RuleBSI("M 2.412")] 14 | [RuleMaturityLevel(5)] 15 | [RuleIntroducedIn(2,9,3)] 16 | [RuleMitreAttackTechnique(MitreAttackTechnique.ExploitationofRemoteServices)] 17 | public class HeatlcheckRuleAnomalyPreWin2000AuthenticatedUsers : RuleBase 18 | { 19 | protected override int? AnalyzeDataNew(HealthcheckData healthcheckData) 20 | { 21 | if (healthcheckData.PreWindows2000AuthenticatedUsers) 22 | { 23 | return 1; 24 | } 25 | return 0; 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /Healthcheck/Rules/HeatlcheckRuleAnomalyPreWin2000Other.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Ping Castle. All rights reserved. 3 | // https://www.pingcastle.com 4 | // 5 | // Licensed under the Non-Profit OSL. See LICENSE file in the project root for full license information. 6 | // 7 | using PingCastle.Rules; 8 | 9 | namespace PingCastle.Healthcheck.Rules 10 | { 11 | [RuleModel("A-PreWin2000Other", RiskRuleCategory.Anomalies, RiskModelCategory.Reconnaissance)] 12 | [RuleComputation(RuleComputationType.TriggerOnPresence, 2)] 13 | [RuleIntroducedIn(2, 9)] 14 | [RuleDurANSSI(3, "compatible_2000_not_default", "Use of the \"Pre-Windows 2000 Compatible Access\" group")] 15 | [RuleMitreAttackTechnique(MitreAttackTechnique.BruteForcePasswordSpraying)] 16 | public class HeatlcheckRuleAnomalyPreWin2000Other : RuleBase 17 | { 18 | protected override int? AnalyzeDataNew(HealthcheckData healthcheckData) 19 | { 20 | if (healthcheckData.PreWindows2000NoDefault) 21 | { 22 | for (int i = 0; i < healthcheckData.PreWindows2000Members.Count; i++) 23 | { 24 | AddRawDetail(healthcheckData.PreWindows2000Members[i]); 25 | } 26 | } 27 | return null; 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /Healthcheck/Rules/HeatlcheckRuleAnomalyRemoteBlankPasswordUse.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Ping Castle. All rights reserved. 3 | // https://www.pingcastle.com 4 | // 5 | // Licensed under the Non-Profit OSL. See LICENSE file in the project root for full license information. 6 | // 7 | using PingCastle.Rules; 8 | 9 | namespace PingCastle.Healthcheck.Rules 10 | { 11 | [RuleModel("A-LimitBlankPasswordUse", RiskRuleCategory.Anomalies, RiskModelCategory.WeakPassword)] 12 | [RuleComputation(RuleComputationType.TriggerOnPresence, 5)] 13 | [RuleMaturityLevel(2)] 14 | [RuleMitreAttackTechnique(MitreAttackTechnique.BruteForcePasswordSpraying)] 15 | public class HeatlcheckRuleAnomalyRemoteBlankPasswordUse : RuleBase 16 | { 17 | protected override int? AnalyzeDataNew(HealthcheckData healthcheckData) 18 | { 19 | foreach (GPPSecurityPolicy policy in healthcheckData.GPPPasswordPolicy) 20 | { 21 | foreach (GPPSecurityPolicyProperty property in policy.Properties) 22 | { 23 | if (property.Property == "LimitBlankPasswordUse") 24 | { 25 | if (property.Value == 0) 26 | { 27 | AddRawDetail(policy.GPOName); 28 | break; 29 | } 30 | } 31 | } 32 | } 33 | return null; 34 | } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /Healthcheck/Rules/HeatlcheckRuleAnomalyReversiblePassword.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Ping Castle. All rights reserved. 3 | // https://www.pingcastle.com 4 | // 5 | // Licensed under the Non-Profit OSL. See LICENSE file in the project root for full license information. 6 | // 7 | using PingCastle.Rules; 8 | 9 | namespace PingCastle.Healthcheck.Rules 10 | { 11 | [RuleModel("A-ReversiblePwd", RiskRuleCategory.Anomalies, RiskModelCategory.PasswordRetrieval)] 12 | [RuleComputation(RuleComputationType.TriggerOnPresence, 10)] 13 | [RuleDurANSSI(3, "reversible_password", "Accounts with passwords stored using reversible encryption")] 14 | [RuleMitreAttackTechnique(MitreAttackTechnique.BruteForcePasswordCracking)] 15 | public class HeatlcheckRuleAnomalyReversiblePassword : RuleBase 16 | { 17 | protected override int? AnalyzeDataNew(HealthcheckData healthcheckData) 18 | { 19 | foreach (GPPSecurityPolicy policy in healthcheckData.GPPPasswordPolicy) 20 | { 21 | foreach (GPPSecurityPolicyProperty property in policy.Properties) 22 | { 23 | if (property.Property == "ClearTextPassword") 24 | { 25 | if (property.Value > 0) 26 | { 27 | AddRawDetail(policy.GPOName); 28 | break; 29 | } 30 | } 31 | } 32 | } 33 | return null; 34 | } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /Healthcheck/Rules/HeatlcheckRuleAnomalySMB2SignatureNotEnabled.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Ping Castle. All rights reserved. 3 | // https://www.pingcastle.com 4 | // 5 | // Licensed under the Non-Profit OSL. See LICENSE file in the project root for full license information. 6 | // 7 | using PingCastle.Rules; 8 | 9 | namespace PingCastle.Healthcheck.Rules 10 | { 11 | [RuleModel("A-SMB2SignatureNotEnabled", RiskRuleCategory.Anomalies, RiskModelCategory.NetworkSniffing)] 12 | [RuleComputation(RuleComputationType.TriggerOnPresence, 5)] 13 | //[RuleBSI("M 2.412")] 14 | [RuleCERTFR("CERTFR-2015-ACT-021", "SECTION00010000000000000000")] 15 | [RuleIntroducedIn(2, 5)] 16 | [RuleMaturityLevel(3)] 17 | [RuleMitreAttackTechnique(MitreAttackTechnique.ManintheMiddle)] 18 | public class HeatlcheckRuleAnomalySMB2SignatureNotEnabled : RuleBase 19 | { 20 | protected override int? AnalyzeDataNew(HealthcheckData healthcheckData) 21 | { 22 | foreach (var DC in healthcheckData.DomainControllers) 23 | { 24 | if (DC.SupportSMB2OrSMB3) 25 | { 26 | if (DC.SMB2SecurityMode != SMBSecurityModeEnum.NotTested) 27 | { 28 | if ((DC.SMB2SecurityMode & SMBSecurityModeEnum.SmbSigningEnabled) == 0) 29 | { 30 | AddRawDetail(DC.DCName); 31 | } 32 | } 33 | } 34 | } 35 | return null; 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /Healthcheck/Rules/HeatlcheckRuleAnomalySMB2SignatureNotRequired.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Ping Castle. All rights reserved. 3 | // https://www.pingcastle.com 4 | // 5 | // Licensed under the Non-Profit OSL. See LICENSE file in the project root for full license information. 6 | // 7 | using PingCastle.Rules; 8 | 9 | namespace PingCastle.Healthcheck.Rules 10 | { 11 | [RuleModel("A-SMB2SignatureNotRequired", RiskRuleCategory.Anomalies, RiskModelCategory.NetworkSniffing)] 12 | [RuleComputation(RuleComputationType.TriggerOnPresence, 0)] 13 | //[RuleBSI("M 2.412")] 14 | [RuleCERTFR("CERTFR-2015-ACT-021", "SECTION00010000000000000000")] 15 | [RuleIntroducedIn(2, 5)] 16 | [RuleMaturityLevel(3)] 17 | [RuleMitreAttackTechnique(MitreAttackTechnique.ManintheMiddle)] 18 | public class HeatlcheckRuleAnomalySMB2SignatureNotRequired : RuleBase 19 | { 20 | protected override int? AnalyzeDataNew(HealthcheckData healthcheckData) 21 | { 22 | foreach (var DC in healthcheckData.DomainControllers) 23 | { 24 | if (DC.SupportSMB2OrSMB3) 25 | { 26 | if (DC.SMB2SecurityMode != SMBSecurityModeEnum.NotTested) 27 | { 28 | if ((DC.SMB2SecurityMode & SMBSecurityModeEnum.SmbSigningRequired) == 0) 29 | { 30 | AddRawDetail(DC.DCName); 31 | } 32 | } 33 | } 34 | } 35 | return null; 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /Healthcheck/Rules/HeatlcheckRuleAnomalySchemaProtectedUsers.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Ping Castle. All rights reserved. 3 | // https://www.pingcastle.com 4 | // 5 | // Licensed under the Non-Profit OSL. See LICENSE file in the project root for full license information. 6 | // 7 | using PingCastle.Rules; 8 | 9 | namespace PingCastle.Healthcheck.Rules 10 | { 11 | [RuleModel("A-ProtectedUsers", RiskRuleCategory.Anomalies, RiskModelCategory.PassTheCredential)] 12 | [RuleComputation(RuleComputationType.TriggerOnPresence, 0)] 13 | [RuleSTIG("V-78131", "Accounts with domain level administrative privileges must be members of the Protected Users group in domains with a domain functional level of Windows 2012 R2 or higher.")] 14 | [RuleCERTFR("CERTFR-2017-ALE-012")] 15 | [RuleMaturityLevel(3)] 16 | [RuleMitreAttackMitigation(MitreAttackMitigation.PrivilegedAccountManagement)] 17 | public class HeatlcheckRuleAnomalySchemaProtectedUsers : RuleBase 18 | { 19 | protected override int? AnalyzeDataNew(HealthcheckData healthcheckData) 20 | { 21 | if (healthcheckData.SchemaVersion < 69) 22 | return 1; 23 | return 0; 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /Healthcheck/Rules/HeatlcheckRuleAnomalyServicePolicy.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Ping Castle. All rights reserved. 3 | // https://www.pingcastle.com 4 | // 5 | // Licensed under the Non-Profit OSL. See LICENSE file in the project root for full license information. 6 | // 7 | using PingCastle.Rules; 8 | 9 | namespace PingCastle.Healthcheck.Rules 10 | { 11 | [RuleModel("A-NoServicePolicy", RiskRuleCategory.Anomalies, RiskModelCategory.WeakPassword)] 12 | [RuleComputation(RuleComputationType.TriggerOnPresence, 0)] 13 | [RuleMaturityLevel(4)] 14 | [RuleMitreAttackTechnique(MitreAttackTechnique.PasswordPolicyDiscovery)] 15 | public class HeatlcheckRuleAnomalyServicePolicy : RuleBase 16 | { 17 | protected override int? AnalyzeDataNew(HealthcheckData healthcheckData) 18 | { 19 | bool servicePolicy = false; 20 | foreach (GPPSecurityPolicy policy in healthcheckData.GPPPasswordPolicy) 21 | { 22 | foreach (GPPSecurityPolicyProperty property in policy.Properties) 23 | { 24 | if (property.Property == "MinimumPasswordLength") 25 | { 26 | if (property.Value >= 20) 27 | { 28 | servicePolicy = true; 29 | break; 30 | } 31 | } 32 | } 33 | } 34 | return (servicePolicy ? 0 : 1); 35 | } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /Healthcheck/Rules/HeatlcheckRuleAnomalySmartCardExpirePassword.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Ping Castle. All rights reserved. 3 | // https://www.pingcastle.com 4 | // 5 | // Licensed under the Non-Profit OSL. See LICENSE file in the project root for full license information. 6 | // 7 | using PingCastle.Rules; 8 | 9 | namespace PingCastle.Healthcheck.Rules 10 | { 11 | [RuleModel("A-SmartCardPwdRotation", RiskRuleCategory.Anomalies, RiskModelCategory.PassTheCredential)] 12 | [RuleComputation(RuleComputationType.TriggerOnPresence, 0)] 13 | [RuleSTIG("V-72821", "All accounts, privileged and unprivileged, that require smart cards must have the underlying NT hash rotated at least every 60 days.")] 14 | [RuleANSSI("R38", "paragraph.3.6.2.2")] 15 | [RuleDurANSSI(4, "smartcard_expire_passwords", "Missing password expiration for smart card users")] 16 | [RuleMitreAttackTechnique(MitreAttackTechnique.BruteForcePasswordCracking)] 17 | [RuleIntroducedIn(3,3)] 18 | public class HeatlcheckRuleAnomalySmartCardExpirePassword : RuleBase 19 | { 20 | protected override int? AnalyzeDataNew(HealthcheckData healthcheckData) 21 | { 22 | if (healthcheckData.DomainFunctionalLevel >= 7 && !healthcheckData.ExpirePasswordsOnSmartCardOnlyAccounts) 23 | return 1; 24 | return 0; 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /Healthcheck/Rules/HeatlcheckRuleAnomalySmartCardRequired.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Ping Castle. All rights reserved. 3 | // https://www.pingcastle.com 4 | // 5 | // Licensed under the Non-Profit OSL. See LICENSE file in the project root for full license information. 6 | // 7 | using PingCastle.Rules; 8 | 9 | namespace PingCastle.Healthcheck.Rules 10 | { 11 | [RuleModel("A-SmartCardRequired", RiskRuleCategory.Anomalies, RiskModelCategory.PassTheCredential)] 12 | [RuleComputation(RuleComputationType.TriggerOnPresence, 30)] 13 | [RuleSTIG("V-72821", "All accounts, privileged and unprivileged, that require smart cards must have the underlying NT hash rotated at least every 60 days.")] 14 | [RuleANSSI("R38", "paragraph.3.6.2.2")] 15 | [RuleMaturityLevel(3)] 16 | [RuleMitreAttackTechnique(MitreAttackTechnique.BruteForcePasswordCracking)] 17 | public class HeatlcheckRuleAnomalySmartCardRequired : RuleBase 18 | { 19 | protected override int? AnalyzeDataNew(HealthcheckData healthcheckData) 20 | { 21 | return healthcheckData.SmartCardNotOK.Count; 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /Healthcheck/Rules/HeatlcheckRuleAnomalyUnixPassword.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Ping Castle. All rights reserved. 3 | // https://www.pingcastle.com 4 | // 5 | // Licensed under the Non-Profit OSL. See LICENSE file in the project root for full license information. 6 | // 7 | using PingCastle.Rules; 8 | 9 | namespace PingCastle.Healthcheck.Rules 10 | { 11 | [RuleModel("A-UnixPwd", RiskRuleCategory.Anomalies, RiskModelCategory.PasswordRetrieval)] 12 | [RuleComputation(RuleComputationType.TriggerOnPresence, 0)] 13 | [RuleDurANSSI(3, "reversible_password", "Accounts with passwords stored using reversible encryption")] 14 | // TODO: ask a new mitre subtechnique ? 15 | [RuleMitreAttackTechnique(MitreAttackTechnique.UnsecuredCredentials)] 16 | public class HeatlcheckRuleAnomalyUnixPassword : RuleBase 17 | { 18 | protected override int? AnalyzeDataNew(HealthcheckData healthcheckData) 19 | { 20 | if (healthcheckData.UnixPasswordUsers != null) 21 | { 22 | foreach (var u in healthcheckData.UnixPasswordUsers) 23 | { 24 | AddRawDetail(u.Name); 25 | } 26 | } 27 | return healthcheckData.UnixPasswordUsersCount; 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /Healthcheck/Rules/HeatlcheckRulePrivilegedAdminInactive.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Ping Castle. All rights reserved. 3 | // https://www.pingcastle.com 4 | // 5 | // Licensed under the Non-Profit OSL. See LICENSE file in the project root for full license information. 6 | // 7 | using PingCastle.Rules; 8 | 9 | namespace PingCastle.Healthcheck.Rules 10 | { 11 | [RuleModel("P-Inactive", RiskRuleCategory.PrivilegedAccounts, RiskModelCategory.AdminControl)] 12 | [RuleComputation(RuleComputationType.TriggerOnThreshold, 30, Threshold: 30, Order: 1)] 13 | [RuleComputation(RuleComputationType.TriggerOnThreshold, 20, Threshold: 15, Order: 2)] 14 | [RuleANSSI("R36", "subsection.3.6")] 15 | [RuleMaturityLevel(3)] 16 | [RuleMitreAttackMitigation(MitreAttackMitigation.PrivilegedAccountManagement)] 17 | public class HeatlcheckRulePrivilegedAdminInactive : RuleBase 18 | { 19 | protected override int? AnalyzeDataNew(HealthcheckData healthcheckData) 20 | { 21 | 22 | int adminEnabledAndInactive = 0; 23 | if (healthcheckData.AllPrivilegedMembers.Count > 20) 24 | { 25 | foreach (var member in healthcheckData.AllPrivilegedMembers) 26 | { 27 | if (member.IsEnabled && !member.IsActive) 28 | adminEnabledAndInactive++; 29 | } 30 | return 100 * adminEnabledAndInactive / healthcheckData.AllPrivilegedMembers.Count; 31 | } 32 | return 0; 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /Healthcheck/Rules/HeatlcheckRulePrivilegedAdminNumber.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Ping Castle. All rights reserved. 3 | // https://www.pingcastle.com 4 | // 5 | // Licensed under the Non-Profit OSL. See LICENSE file in the project root for full license information. 6 | // 7 | using PingCastle.Rules; 8 | 9 | namespace PingCastle.Healthcheck.Rules 10 | { 11 | [RuleModel("P-AdminNum", RiskRuleCategory.PrivilegedAccounts, RiskModelCategory.AdminControl)] 12 | [RuleComputation(RuleComputationType.TriggerOnPresence, 10)] 13 | [RuleANSSI("R26", "subsection.3.5")] 14 | [RuleANSSI("R30", "subsubsection.3.5.7")] 15 | [RuleDurANSSI(1, "privileged_members", "Large privileged group member count")] 16 | [RuleMitreAttackMitigation(MitreAttackMitigation.PrivilegedAccountManagement)] 17 | public class HeatlcheckRulePrivilegedAdminNumber : RuleBase 18 | { 19 | protected override int? AnalyzeDataNew(HealthcheckData healthcheckData) 20 | { 21 | if (healthcheckData.UserAccountData.NumberActive <= 100) 22 | return 0; 23 | if (healthcheckData.AllPrivilegedMembers.Count == 0) 24 | return 0; 25 | if ((healthcheckData.AllPrivilegedMembers.Count * 100 / healthcheckData.UserAccountData.NumberActive) > 10) 26 | { 27 | return healthcheckData.AllPrivilegedMembers.Count; 28 | } 29 | if (healthcheckData.AllPrivilegedMembers.Count > 50) 30 | { 31 | return healthcheckData.AllPrivilegedMembers.Count; 32 | } 33 | return 0; 34 | } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /Healthcheck/Rules/HeatlcheckRulePrivilegedControlPathIndirectEveryone.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Ping Castle. All rights reserved. 3 | // https://www.pingcastle.com 4 | // 5 | // Licensed under the Non-Profit OSL. See LICENSE file in the project root for full license information. 6 | // 7 | using PingCastle.Rules; 8 | 9 | namespace PingCastle.Healthcheck.Rules 10 | { 11 | [RuleModel("P-ControlPathIndirectEveryone", RiskRuleCategory.PrivilegedAccounts, RiskModelCategory.ControlPath)] 12 | [RuleComputation(RuleComputationType.TriggerOnPresence, 25)] 13 | [RuleIntroducedIn(2, 8)] 14 | [RuleMaturityLevel(1)] 15 | [RuleMitreAttackTechnique(MitreAttackTechnique.PermissionGroupsDiscoveryDomainGroups)] 16 | public class HeatlcheckRulePrivilegedControlPathIndirectEveryone : RuleBase 17 | { 18 | protected override int? AnalyzeDataNew(HealthcheckData healthcheckData) 19 | { 20 | if (healthcheckData.ControlPaths == null) 21 | return 0; 22 | foreach (var analysis in healthcheckData.ControlPaths.Data) 23 | { 24 | if (analysis.Typology == Data.CompromiseGraphDataTypology.Infrastructure 25 | || analysis.Typology == Data.CompromiseGraphDataTypology.PrivilegedAccount) 26 | { 27 | if (analysis.CriticalObjectFound) 28 | { 29 | AddRawDetail(analysis.Description); 30 | } 31 | } 32 | } 33 | return null; 34 | } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /Healthcheck/Rules/HeatlcheckRulePrivilegedDCOwner.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Ping Castle. All rights reserved. 3 | // https://www.pingcastle.com 4 | // 5 | // Licensed under the Non-Profit OSL. See LICENSE file in the project root for full license information. 6 | // 7 | using PingCastle.Rules; 8 | using System.Security.Principal; 9 | 10 | namespace PingCastle.Healthcheck.Rules 11 | { 12 | [RuleModel("P-DCOwner", RiskRuleCategory.PrivilegedAccounts, RiskModelCategory.ACLCheck)] 13 | [RuleComputation(RuleComputationType.TriggerOnPresence, 10)] 14 | [RuleDurANSSI(3, "owner", "Incorrect object owners")] 15 | [RuleMitreAttackMitigation(MitreAttackMitigation.PrivilegedAccountManagement)] 16 | public class HeatlcheckRulePrivilegedDCOwner : RuleBase 17 | { 18 | protected override int? AnalyzeDataNew(HealthcheckData healthcheckData) 19 | { 20 | if (healthcheckData.DomainControllers != null) 21 | { 22 | foreach (var DC in healthcheckData.DomainControllers) 23 | { 24 | if (string.IsNullOrEmpty(DC.OwnerSID)) 25 | continue; 26 | SecurityIdentifier sid = new SecurityIdentifier(DC.OwnerSID); 27 | if (!sid.IsWellKnown(WellKnownSidType.AccountDomainAdminsSid) && !sid.IsWellKnown(WellKnownSidType.AccountEnterpriseAdminsSid)) 28 | { 29 | AddRawDetail(DC.DistinguishedName, DC.OwnerName); 30 | } 31 | } 32 | } 33 | return null; 34 | } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /Healthcheck/Rules/HeatlcheckRulePrivilegedDNSAdmin.cs: -------------------------------------------------------------------------------- 1 | using PingCastle.Graph.Reporting; 2 | // 3 | // Copyright (c) Ping Castle. All rights reserved. 4 | // https://www.pingcastle.com 5 | // 6 | // Licensed under the Non-Profit OSL. See LICENSE file in the project root for full license information. 7 | // 8 | using PingCastle.Rules; 9 | 10 | namespace PingCastle.Healthcheck.Rules 11 | { 12 | [RuleModel("P-DNSAdmin", RiskRuleCategory.PrivilegedAccounts, RiskModelCategory.ACLCheck)] 13 | [RuleComputation(RuleComputationType.TriggerOnPresence, 0)] 14 | [RuleIntroducedIn(2, 9)] 15 | [RuleDurANSSI(4, "dnsadmins", "DnsAdmins group members")] 16 | [RuleMitreAttackMitigation(MitreAttackMitigation.PrivilegedAccountManagement)] 17 | public class HeatlcheckRulePrivilegedDNSAdmin : RuleBase 18 | { 19 | protected override int? AnalyzeDataNew(HealthcheckData healthcheckData) 20 | { 21 | // rule is not active anymore 22 | return 0; 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /Healthcheck/Rules/HeatlcheckRulePrivilegedDangerousDelegation.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Ping Castle. All rights reserved. 3 | // https://www.pingcastle.com 4 | // 5 | // Licensed under the Non-Profit OSL. See LICENSE file in the project root for full license information. 6 | // 7 | using PingCastle.Rules; 8 | 9 | namespace PingCastle.Healthcheck.Rules 10 | { 11 | [RuleModel("P-DangerousExtendedRight", RiskRuleCategory.PrivilegedAccounts, RiskModelCategory.ACLCheck)] 12 | [RuleComputation(RuleComputationType.PerDiscover, 5)] 13 | [RuleANSSI("R18", "subsubsection.3.3.2")] 14 | [RuleMaturityLevel(2)] 15 | [RuleMitreAttackMitigation(MitreAttackMitigation.ActiveDirectoryConfiguration)] 16 | public class HeatlcheckRulePrivilegedDangerousDelegation : RuleBase 17 | { 18 | protected override int? AnalyzeDataNew(HealthcheckData healthcheckData) 19 | { 20 | foreach (HealthcheckDelegationData delegation in healthcheckData.Delegations) 21 | { 22 | if (delegation.Right.Contains("EXT_RIGHT_REANIMATE_TOMBSTONE") || delegation.Right.Contains("EXT_RIGHT_UNEXPIRE_PASSWORD") || delegation.Right.Contains("EXT_RIGHT_MIGRATE_SID_HISTORY")) 23 | { 24 | AddRawDetail(delegation.DistinguishedName, delegation.Account, delegation.Right); 25 | } 26 | } 27 | return null; 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /Healthcheck/Rules/HeatlcheckRulePrivilegedDelegationDCa2d2.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Ping Castle. All rights reserved. 3 | // https://www.pingcastle.com 4 | // 5 | // Licensed under the Non-Profit OSL. See LICENSE file in the project root for full license information. 6 | // 7 | using PingCastle.Graph.Database; 8 | using PingCastle.Rules; 9 | 10 | namespace PingCastle.Healthcheck.Rules 11 | { 12 | [RuleModel("P-DelegationDCa2d2", RiskRuleCategory.PrivilegedAccounts, RiskModelCategory.DelegationCheck)] 13 | [RuleComputation(RuleComputationType.PerDiscover, 25)] 14 | [RuleDurANSSI(1, "delegation_a2d2", "Constrained authentication delegation to a domain controller service")] 15 | [RuleIntroducedIn(2, 9)] 16 | [RuleMitreAttackTechnique(MitreAttackTechnique.ForcedAuthentication)] 17 | [RuleMitreAttackMitigation(MitreAttackMitigation.ActiveDirectoryConfiguration)] 18 | public class HeatlcheckRulePrivilegedDelegationDCa2d2 : RuleBase 19 | { 20 | protected override int? AnalyzeDataNew(HealthcheckData healthcheckData) 21 | { 22 | foreach (var dc in healthcheckData.DomainControllers) 23 | { 24 | if (dc.Delegations != null) 25 | { 26 | foreach (var delegation in dc.Delegations) 27 | { 28 | if (delegation.DelegationType == RelationType.msDS_Allowed_To_Delegate_To.ToString()) 29 | { 30 | AddRawDetail(dc.DCName, delegation.Delegate, delegation.DelegateSid); 31 | } 32 | } 33 | } 34 | } 35 | return null; 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /Healthcheck/Rules/HeatlcheckRulePrivilegedDelegationGPOData.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Ping Castle. All rights reserved. 3 | // https://www.pingcastle.com 4 | // 5 | // Licensed under the Non-Profit OSL. See LICENSE file in the project root for full license information. 6 | // 7 | using PingCastle.Rules; 8 | 9 | namespace PingCastle.Healthcheck.Rules 10 | { 11 | [RuleModel("P-DelegationGPOData", RiskRuleCategory.PrivilegedAccounts, RiskModelCategory.ACLCheck)] 12 | [RuleComputation(RuleComputationType.PerDiscover, 15)] 13 | [RuleANSSI("R18", "subsubsection.3.3.2")] 14 | [RuleSTIG("V-2370", "The access control permissions for the directory service site group policy must be configured to use the required access permissions.", STIGFramework.ActiveDirectoryService2003)] 15 | [RuleIntroducedIn(2, 6)] 16 | [RuleMaturityLevel(2)] 17 | [RuleMitreAttackMitigation(MitreAttackMitigation.ActiveDirectoryConfiguration)] 18 | public class HeatlcheckRulePrivilegedDelegationGPOData : RuleBase 19 | { 20 | protected override int? AnalyzeDataNew(HealthcheckData healthcheckData) 21 | { 22 | foreach (var delegation in healthcheckData.GPODelegation) 23 | { 24 | AddRawDetail(delegation.GPOName, delegation.Item, delegation.Account, delegation.Right); 25 | } 26 | return null; 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /Healthcheck/Rules/HeatlcheckRulePrivilegedDelegationKeyAdmin.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Ping Castle. All rights reserved. 3 | // https://www.pingcastle.com 4 | // 5 | // Licensed under the Non-Profit OSL. See LICENSE file in the project root for full license information. 6 | // 7 | using PingCastle.Rules; 8 | 9 | namespace PingCastle.Healthcheck.Rules 10 | { 11 | [RuleModel("P-DelegationKeyAdmin", RiskRuleCategory.PrivilegedAccounts, RiskModelCategory.ACLCheck)] 12 | [RuleComputation(RuleComputationType.TriggerOnPresence, 5)] 13 | [RuleANSSI("R18", "subsubsection.3.3.2")] 14 | [RuleIntroducedIn(2, 6)] 15 | [RuleDurANSSI(2, "adupdate_bad", "Bad Active Directory versions")] 16 | [RuleMitreAttackMitigation(MitreAttackMitigation.ActiveDirectoryConfiguration)] 17 | [RuleMitreAttackTechnique(MitreAttackTechnique.TwoFactorAuthenticationInterception)] 18 | public class HeatlcheckRulePrivilegedDelegationKeyAdmin : RuleBase 19 | { 20 | protected override int? AnalyzeDataNew(HealthcheckData healthcheckData) 21 | { 22 | foreach (HealthcheckDelegationData delegation in healthcheckData.Delegations) 23 | { 24 | if (delegation.DistinguishedName.StartsWith("DC=") && delegation.SecurityIdentifier.EndsWith("-527")) 25 | { 26 | AddRawDetail(delegation.DistinguishedName, delegation.Account, delegation.Right); 27 | } 28 | } 29 | return null; 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /Healthcheck/Rules/HeatlcheckRulePrivilegedDsHeuristicsAdminSDExMaskModified.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Ping Castle. All rights reserved. 3 | // https://www.pingcastle.com 4 | // 5 | // Licensed under the Non-Profit OSL. See LICENSE file in the project root for full license information. 6 | // 7 | using PingCastle.Rules; 8 | 9 | namespace PingCastle.Healthcheck.Rules 10 | { 11 | [RuleModel("P-DsHeuristicsAdminSDExMask", RiskRuleCategory.PrivilegedAccounts, RiskModelCategory.ACLCheck)] 12 | [RuleComputation(RuleComputationType.TriggerOnPresence, 5)] 13 | [RuleIntroducedIn(2, 7)] 14 | [RuleDurANSSI(1, "dsheuristics_bad", "Dangerous dsHeuristics settings")] 15 | [RuleMitreAttackMitigation(MitreAttackMitigation.PrivilegedAccountManagement)] 16 | public class HeatlcheckRulePrivilegedDsHeuristicsAdminSDExMaskModified : RuleBase 17 | { 18 | protected override int? AnalyzeDataNew(HealthcheckData healthcheckData) 19 | { 20 | if (healthcheckData.DSHeuristics != null && healthcheckData.DSHeuristics.Length >= 16 && healthcheckData.DSHeuristics.Substring(15, 1) != "0") 21 | { 22 | return 1; 23 | } 24 | return 0; 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /Healthcheck/Rules/HeatlcheckRulePrivilegedDsHeuristicsDoListObject.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Ping Castle. All rights reserved. 3 | // https://www.pingcastle.com 4 | // 5 | // Licensed under the Non-Profit OSL. See LICENSE file in the project root for full license information. 6 | // 7 | using PingCastle.Rules; 8 | 9 | namespace PingCastle.Healthcheck.Rules 10 | { 11 | [RuleModel("P-DsHeuristicsDoListObject", RiskRuleCategory.PrivilegedAccounts, RiskModelCategory.ACLCheck)] 12 | [RuleComputation(RuleComputationType.TriggerOnPresence, 0)] 13 | [RuleIntroducedIn(2, 7)] 14 | [RuleMaturityLevel(2)] 15 | [RuleMitreAttackMitigation(MitreAttackMitigation.ActiveDirectoryConfiguration)] 16 | public class HeatlcheckRulePrivilegedDsHeuristicsDoListObject : RuleBase 17 | { 18 | protected override int? AnalyzeDataNew(HealthcheckData healthcheckData) 19 | { 20 | if (healthcheckData.DSHeuristics != null && healthcheckData.DSHeuristics.Length >= 3 && healthcheckData.DSHeuristics.Substring(2, 1) != "0") 21 | { 22 | return 1; 23 | } 24 | return 0; 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /Healthcheck/Rules/HeatlcheckRulePrivilegedEmailOn.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Ping Castle. All rights reserved. 3 | // https://www.pingcastle.com 4 | // 5 | // Licensed under the Non-Profit OSL. See LICENSE file in the project root for full license information. 6 | // 7 | using PingCastle.Rules; 8 | 9 | namespace PingCastle.Healthcheck.Rules 10 | { 11 | [RuleModel("P-AdminEmailOn", RiskRuleCategory.PrivilegedAccounts, RiskModelCategory.ControlPath)] 12 | [RuleComputation(RuleComputationType.TriggerOnPresence, 0)] 13 | [RuleMaturityLevel(3)] 14 | [RuleIntroducedIn(3, 1)] 15 | [RuleMitreAttackMitigation(MitreAttackMitigation.PrivilegedAccountManagement)] 16 | public class HeatlcheckRulePrivilegedEmailOn : RuleBase 17 | { 18 | protected override int? AnalyzeDataNew(HealthcheckData healthcheckData) 19 | { 20 | foreach (var member in healthcheckData.AllPrivilegedMembers) 21 | { 22 | if (member.IsEnabled && !string.IsNullOrEmpty(member.Email)) 23 | { 24 | AddRawDetail(member.Name, member.Email); 25 | } 26 | } 27 | return null; 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /Healthcheck/Rules/HeatlcheckRulePrivilegedExchangeAdminSDHolder.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Ping Castle. All rights reserved. 3 | // https://www.pingcastle.com 4 | // 5 | // Licensed under the Non-Profit OSL. See LICENSE file in the project root for full license information. 6 | // 7 | using PingCastle.Rules; 8 | 9 | namespace PingCastle.Healthcheck.Rules 10 | { 11 | [RuleModel("P-ExchangeAdminSDHolder", RiskRuleCategory.PrivilegedAccounts, RiskModelCategory.ACLCheck)] 12 | [RuleComputation(RuleComputationType.TriggerOnPresence, 5)] 13 | [RuleANSSI("R18", "subsubsection.3.3.2")] 14 | [RuleIntroducedIn(2, 6)] 15 | [RuleMaturityLevel(2)] 16 | [RuleMitreAttackMitigation(MitreAttackMitigation.ActiveDirectoryConfiguration)] 17 | public class HeatlcheckRulePrivilegedExchangeAdminSDHolder : RuleBase 18 | { 19 | protected override int? AnalyzeDataNew(HealthcheckData healthcheckData) 20 | { 21 | foreach (HealthcheckDelegationData delegation in healthcheckData.Delegations) 22 | { 23 | if (delegation.DistinguishedName == "AdminSDHolder" 24 | && delegation.Account.Contains("Exchange")) 25 | { 26 | return 1; 27 | } 28 | } 29 | return 0; 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /Healthcheck/Rules/HeatlcheckRulePrivilegedExchangePrivEsc.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Ping Castle. All rights reserved. 3 | // https://www.pingcastle.com 4 | // 5 | // Licensed under the Non-Profit OSL. See LICENSE file in the project root for full license information. 6 | // 7 | using PingCastle.Rules; 8 | 9 | namespace PingCastle.Healthcheck.Rules 10 | { 11 | [RuleModel("P-ExchangePrivEsc", RiskRuleCategory.PrivilegedAccounts, RiskModelCategory.ACLCheck)] 12 | [RuleIntroducedIn(2, 7)] 13 | [RuleComputation(RuleComputationType.PerDiscover, 15)] 14 | [RuleANSSI("R18", "subsubsection.3.3.2")] 15 | [RuleMaturityLevel(2)] 16 | [RuleMitreAttackMitigation(MitreAttackMitigation.ActiveDirectoryConfiguration)] 17 | public class HeatlcheckRulePrivilegedExchangePrivEsc : RuleBase 18 | { 19 | protected override int? AnalyzeDataNew(HealthcheckData healthcheckData) 20 | { 21 | if (healthcheckData.ExchangePrivEscVulnerable) 22 | return 1; 23 | return 0; 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /Healthcheck/Rules/HeatlcheckRulePrivilegedOperatorsEmpty.cs: -------------------------------------------------------------------------------- 1 | using PingCastle.Graph.Reporting; 2 | // 3 | // Copyright (c) Ping Castle. All rights reserved. 4 | // https://www.pingcastle.com 5 | // 6 | // Licensed under the Non-Profit OSL. See LICENSE file in the project root for full license information. 7 | // 8 | using PingCastle.Rules; 9 | 10 | namespace PingCastle.Healthcheck.Rules 11 | { 12 | [RuleModel("P-OperatorsEmpty", RiskRuleCategory.PrivilegedAccounts, RiskModelCategory.AdminControl)] 13 | [RuleComputation(RuleComputationType.TriggerOnPresence, 0)] 14 | [RuleANSSI("R27", "subsection.3.5")] 15 | [RuleMaturityLevel(3)] 16 | [RuleMitreAttackMitigation(MitreAttackMitigation.PrivilegedAccountManagement)] 17 | public class HeatlcheckRulePrivilegedOperatorsEmpty : RuleBase 18 | { 19 | protected override int? AnalyzeDataNew(HealthcheckData healthcheckData) 20 | { 21 | foreach (var group in healthcheckData.PrivilegedGroups) 22 | { 23 | if (group.GroupName == GraphObjectReference.AccountOperators || group.GroupName == GraphObjectReference.ServerOperators) 24 | { 25 | if (group.NumberOfMember > 0) 26 | { 27 | AddRawDetail(group.GroupName, group.NumberOfMember); 28 | } 29 | } 30 | } 31 | return null; 32 | } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /Healthcheck/Rules/HeatlcheckRulePrivilegedRODCAllowedGroup.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Ping Castle. All rights reserved. 3 | // https://www.pingcastle.com 4 | // 5 | // Licensed under the Non-Profit OSL. See LICENSE file in the project root for full license information. 6 | // 7 | using PingCastle.Rules; 8 | 9 | namespace PingCastle.Healthcheck.Rules 10 | { 11 | [RuleModel("P-RODCAllowedGroup", RiskRuleCategory.PrivilegedAccounts, RiskModelCategory.RODC)] 12 | [RuleComputation(RuleComputationType.TriggerOnPresence, 5)] 13 | [RuleIntroducedIn(2, 9)] 14 | [RuleDurANSSI(3, "rodc_allowed_group", "Dangerous configuration of replication groups for read-only domain controllers (RODCs) (allow)")] 15 | [RuleMitreAttackMitigation(MitreAttackMitigation.ActiveDirectoryConfiguration)] 16 | public class HeatlcheckRulePrivilegedRODCAllowedGroup : RuleBase 17 | { 18 | protected override int? AnalyzeDataNew(HealthcheckData healthcheckData) 19 | { 20 | if (healthcheckData.DomainFunctionalLevel < 3) 21 | return 0; 22 | foreach (var member in healthcheckData.AllowedRODCPasswordReplicationGroup) 23 | { 24 | AddRawDetail(member); 25 | } 26 | return null; 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /Healthcheck/Rules/HeatlcheckRulePrivilegedRODCKrbtgtOrphan.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Ping Castle. All rights reserved. 3 | // https://www.pingcastle.com 4 | // 5 | // Licensed under the Non-Profit OSL. See LICENSE file in the project root for full license information. 6 | // 7 | using PingCastle.Rules; 8 | 9 | namespace PingCastle.Healthcheck.Rules 10 | { 11 | [RuleModel("P-RODCKrbtgtOrphan", RiskRuleCategory.PrivilegedAccounts, RiskModelCategory.RODC)] 12 | [RuleComputation(RuleComputationType.TriggerOnPresence, 1)] 13 | [RuleIntroducedIn(3, 3)] 14 | [RuleDurANSSI(3, "rodc_orphan_krbtgt", "Orphan RODC krbtgt accounts")] 15 | [RuleMitreAttackMitigation(MitreAttackMitigation.ActiveDirectoryConfiguration)] 16 | public class HeatlcheckRulePrivilegedRODCKrbtgtOrphan : RuleBase 17 | { 18 | protected override int? AnalyzeDataNew(HealthcheckData healthcheckData) 19 | { 20 | if (healthcheckData.DomainFunctionalLevel < 3) 21 | return 0; 22 | if (healthcheckData.RODCKrbtgtOrphans != null) 23 | { 24 | foreach (var member in healthcheckData.RODCKrbtgtOrphans) 25 | { 26 | AddRawDetail(member.DistinguishedName, member.CreationDate); 27 | } 28 | } 29 | return null; 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /Healthcheck/Rules/HeatlcheckRulePrivilegedRODCSYSVOLWrite.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Ping Castle. All rights reserved. 3 | // https://www.pingcastle.com 4 | // 5 | // Licensed under the Non-Profit OSL. See LICENSE file in the project root for full license information. 6 | // 7 | using PingCastle.Rules; 8 | 9 | namespace PingCastle.Healthcheck.Rules 10 | { 11 | [RuleModel("P-RODCSYSVOLWrite", RiskRuleCategory.PrivilegedAccounts, RiskModelCategory.RODC)] 12 | [RuleComputation(RuleComputationType.PerDiscover, 5)] 13 | [RuleIntroducedIn(2, 9)] 14 | [RuleMaturityLevel(2)] 15 | [RuleMitreAttackTechnique(MitreAttackTechnique.RogueDomainController)] 16 | [RuleMitreAttackMitigation(MitreAttackMitigation.ActiveDirectoryConfiguration)] 17 | public class HeatlcheckRulePrivilegedRODCSYSVOLWrite : RuleBase 18 | { 19 | protected override int? AnalyzeDataNew(HealthcheckData healthcheckData) 20 | { 21 | if (healthcheckData.DomainFunctionalLevel < 3) 22 | return 0; 23 | 24 | foreach (var dc in healthcheckData.DomainControllers) 25 | { 26 | if (!dc.RODC) 27 | continue; 28 | if (dc.SYSVOLOverwrite) 29 | { 30 | AddRawDetail(dc.DCName); 31 | } 32 | } 33 | return null; 34 | } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /Healthcheck/Rules/HeatlcheckRulePrivilegedRecycleBin.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Ping Castle. All rights reserved. 3 | // https://www.pingcastle.com 4 | // 5 | // Licensed under the Non-Profit OSL. See LICENSE file in the project root for full license information. 6 | // 7 | using PingCastle.Rules; 8 | 9 | namespace PingCastle.Healthcheck.Rules 10 | { 11 | [RuleModel("P-RecycleBin", RiskRuleCategory.PrivilegedAccounts, RiskModelCategory.IrreversibleChange)] 12 | [RuleComputation(RuleComputationType.TriggerOnPresence, 10)] 13 | [RuleIntroducedIn(2, 7)] 14 | [RuleMaturityLevel(3)] 15 | [RuleMitreAttackMitigation(MitreAttackMitigation.Audit)] 16 | public class HeatlcheckRulePrivilegedRecycleBin : RuleBase 17 | { 18 | protected override int? AnalyzeDataNew(HealthcheckData healthcheckData) 19 | { 20 | if (healthcheckData.IsRecycleBinEnabled) 21 | { 22 | return 0; 23 | } 24 | return 1; 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /Healthcheck/Rules/HeatlcheckRulePrivilegedSchemaAdmins.cs: -------------------------------------------------------------------------------- 1 | using PingCastle.Graph.Reporting; 2 | // 3 | // Copyright (c) Ping Castle. All rights reserved. 4 | // https://www.pingcastle.com 5 | // 6 | // Licensed under the Non-Profit OSL. See LICENSE file in the project root for full license information. 7 | // 8 | using PingCastle.Rules; 9 | 10 | namespace PingCastle.Healthcheck.Rules 11 | { 12 | [RuleModel("P-SchemaAdmin", RiskRuleCategory.PrivilegedAccounts, RiskModelCategory.IrreversibleChange)] 13 | [RuleComputation(RuleComputationType.TriggerOnPresence, 10)] 14 | [RuleSTIG("V-72835", "Membership to the Schema Admins group must be limited", STIGFramework.Forest)] 15 | [RuleANSSI("R13", "subsection.3.2")] 16 | [RuleMaturityLevel(3)] 17 | [RuleMitreAttackMitigation(MitreAttackMitigation.PrivilegedAccountManagement)] 18 | public class HeatlcheckRulePrivilegedSchemaAdmins : RuleBase 19 | { 20 | protected override int? AnalyzeDataNew(HealthcheckData healthcheckData) 21 | { 22 | foreach (HealthCheckGroupData group in healthcheckData.PrivilegedGroups) 23 | { 24 | if (group.GroupName == GraphObjectReference.SchemaAdministrators) 25 | { 26 | if (group.NumberOfMember > 0) 27 | { 28 | return group.NumberOfMember; 29 | } 30 | } 31 | } 32 | return 0; 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /Healthcheck/Rules/HeatlcheckRulePrivilegedUnprotectedOU.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Ping Castle. All rights reserved. 3 | // https://www.pingcastle.com 4 | // 5 | // Licensed under the Non-Profit OSL. See LICENSE file in the project root for full license information. 6 | // 7 | using PingCastle.Rules; 8 | 9 | namespace PingCastle.Healthcheck.Rules 10 | { 11 | [RuleModel("P-UnprotectedOU", RiskRuleCategory.PrivilegedAccounts, RiskModelCategory.IrreversibleChange)] 12 | [RuleComputation(RuleComputationType.TriggerOnPresence, 0)] 13 | [RuleMaturityLevel(4)] 14 | [RuleIntroducedIn(3, 1)] 15 | [RuleMitreAttackMitigation(MitreAttackMitigation.ActiveDirectoryConfiguration)] 16 | public class HeatlcheckRulePrivilegedUnprotectedOU : RuleBase 17 | { 18 | protected override int? AnalyzeDataNew(HealthcheckData healthcheckData) 19 | { 20 | int i = 0; 21 | if (healthcheckData.UnprotectedOU != null) 22 | { 23 | foreach (var ou in healthcheckData.UnprotectedOU) 24 | { 25 | AddRawDetail(ou); 26 | if (i++ >= 10) 27 | break; 28 | } 29 | } 30 | return null; 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /Healthcheck/Rules/HeatlcheckRuleStaleADRegistrationViaSchema.cs: -------------------------------------------------------------------------------- 1 | using PingCastle.Graph.Reporting; 2 | // 3 | // Copyright (c) Ping Castle. All rights reserved. 4 | // https://www.pingcastle.com 5 | // 6 | // Licensed under the Non-Profit OSL. See LICENSE file in the project root for full license information. 7 | // 8 | using PingCastle.Rules; 9 | using System.Collections.Generic; 10 | using System.Diagnostics; 11 | 12 | namespace PingCastle.Healthcheck.Rules 13 | { 14 | [RuleModel("S-ADRegistrationSchema", RiskRuleCategory.StaleObjects, RiskModelCategory.Provisioning)] 15 | [RuleComputation(RuleComputationType.TriggerOnPresence, 10)] 16 | [RuleDurANSSI(2, "warning_schema_posssuperiors", "Schema class allowing dangerous object creation")] 17 | [RuleMitreAttackMitigation(MitreAttackMitigation.UserAccountManagement)] 18 | [RuleIntroducedIn(2,9,3)] 19 | public class HeatlcheckRuleStaleADRegistrationViaSchema : RuleBase 20 | { 21 | protected override int? AnalyzeDataNew(HealthcheckData healthcheckData) 22 | { 23 | if (healthcheckData.SchemaClassVulnerable != null) 24 | { 25 | foreach(var Class in healthcheckData.SchemaClassVulnerable) 26 | { 27 | AddRawDetail(Class.Class, Class.Vulnerability); 28 | } 29 | } 30 | return null; 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /Healthcheck/Rules/HeatlcheckRuleStaledAesNotEnabled.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Ping Castle. All rights reserved. 3 | // https://www.pingcastle.com 4 | // 5 | // Licensed under the Non-Profit OSL. See LICENSE file in the project root for full license information. 6 | // 7 | using PingCastle.Rules; 8 | using System; 9 | 10 | namespace PingCastle.Healthcheck.Rules 11 | { 12 | [RuleModel("S-AesNotEnabled", RiskRuleCategory.StaleObjects, RiskModelCategory.OldAuthenticationProtocols)] 13 | [RuleComputation(RuleComputationType.TriggerOnPresence, 0)] 14 | [RuleDurANSSI(3, "kerberos_properties_encryption", "Service accounts supported encryption algorithms")] 15 | [RuleMitreAttackTechnique(MitreAttackTechnique.StealorForgeKerberosTicketsASREPRoasting)] 16 | [RuleIntroducedIn(3, 3)] 17 | public class HeatlcheckRuleStaledAesNotEnabled : RuleBase 18 | { 19 | protected override int? AnalyzeDataNew(HealthcheckData healthcheckData) 20 | { 21 | // ignore for older OS 22 | if (healthcheckData.DCWin2008Install == default(DateTime)) 23 | return 0; 24 | 25 | return healthcheckData.UserAccountData.NumberNotAesEnabled + healthcheckData.ComputerAccountData.NumberNotAesEnabled; 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /Healthcheck/Rules/HeatlcheckRuleStaledDefaultOUChanged.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Ping Castle. All rights reserved. 3 | // https://www.pingcastle.com 4 | // 5 | // Licensed under the Non-Profit OSL. See LICENSE file in the project root for full license information. 6 | // 7 | using PingCastle.Rules; 8 | 9 | namespace PingCastle.Healthcheck.Rules 10 | { 11 | [RuleModel("S-DefaultOUChanged", RiskRuleCategory.StaleObjects, RiskModelCategory.ObjectConfig)] 12 | [RuleComputation(RuleComputationType.TriggerOnPresence, 0)] 13 | [RuleMaturityLevel(4)] 14 | [RuleIntroducedIn(3, 1)] 15 | [RuleMitreAttackMitigation(MitreAttackMitigation.UserAccountManagement)] 16 | public class HeatlcheckRuleStaledDefaultOUChanged : RuleBase 17 | { 18 | protected override int? AnalyzeDataNew(HealthcheckData healthcheckData) 19 | { 20 | if (healthcheckData.DefaultOUChanged == null) 21 | return null; 22 | foreach (var c in healthcheckData.DefaultOUChanged) 23 | { 24 | AddRawDetail(c.Expected, c.Found); 25 | } 26 | return null; 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /Healthcheck/Rules/HeatlcheckRuleStaledDuplicateObjects.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Ping Castle. All rights reserved. 3 | // https://www.pingcastle.com 4 | // 5 | // Licensed under the Non-Profit OSL. See LICENSE file in the project root for full license information. 6 | // 7 | using PingCastle.Rules; 8 | 9 | namespace PingCastle.Healthcheck.Rules 10 | { 11 | [RuleModel("S-Duplicate", RiskRuleCategory.StaleObjects, RiskModelCategory.Replication)] 12 | [RuleComputation(RuleComputationType.TriggerOnPresence, 5)] 13 | [RuleMaturityLevel(4)] 14 | [RuleMitreAttackMitigation(MitreAttackMitigation.ActiveDirectoryConfiguration)] 15 | public class HeatlcheckRuleStaledDuplicateObjects : RuleBase 16 | { 17 | protected override int? AnalyzeDataNew(HealthcheckData healthcheckData) 18 | { 19 | return healthcheckData.ComputerAccountData.NumberDuplicate + healthcheckData.UserAccountData.NumberDuplicate; 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /Healthcheck/Rules/HeatlcheckRuleStaledFolderOptions.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Ping Castle. All rights reserved. 3 | // https://www.pingcastle.com 4 | // 5 | // Licensed under the Non-Profit OSL. See LICENSE file in the project root for full license information. 6 | // 7 | using PingCastle.Rules; 8 | using System; 9 | using System.Collections.Generic; 10 | 11 | namespace PingCastle.Healthcheck.Rules 12 | { 13 | [RuleModel("S-FolderOptions", RiskRuleCategory.StaleObjects, RiskModelCategory.ObjectConfig)] 14 | [RuleComputation(RuleComputationType.TriggerOnPresence, 0)] 15 | [RuleMitreAttackMitigation(MitreAttackMitigation.ActiveDirectoryConfiguration)] 16 | [RuleMaturityLevel(5)] 17 | [RuleIntroducedIn(3, 3)] 18 | public class HeatlcheckRuleStaledFolderOptions : RuleBase 19 | { 20 | protected override int? AnalyzeDataNew(HealthcheckData healthcheckData) 21 | { 22 | var dangerousFileExtensions = new string[] { "js", "jse" }; 23 | var found = new List(); 24 | if (healthcheckData.GPOFolderOptions != null) 25 | { 26 | foreach (var option in healthcheckData.GPOFolderOptions) 27 | { 28 | if (!found.Contains(option.FileExt.ToLowerInvariant())) 29 | found.Add(option.FileExt.ToLowerInvariant()); 30 | } 31 | } 32 | foreach (var ext in dangerousFileExtensions) 33 | { 34 | if (!found.Contains(ext)) 35 | { 36 | AddRawDetail(ext, "Not found in Folder Options"); 37 | } 38 | } 39 | return null; 40 | } 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /Healthcheck/Rules/HeatlcheckRuleStaledInactive.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Ping Castle. All rights reserved. 3 | // https://www.pingcastle.com 4 | // 5 | // Licensed under the Non-Profit OSL. See LICENSE file in the project root for full license information. 6 | // 7 | using PingCastle.Rules; 8 | 9 | namespace PingCastle.Healthcheck.Rules 10 | { 11 | [RuleModel("S-Inactive", RiskRuleCategory.StaleObjects, RiskModelCategory.InactiveUserOrComputer)] 12 | [RuleComputation(RuleComputationType.TriggerOnThreshold, 10, Threshold: 25)] 13 | [RuleANSSI("R45", "paragraph.3.6.6.2")] 14 | [RuleDurANSSI(1, "user_accounts_dormant", "Dormant accounts")] 15 | [RuleMitreAttackMitigation(MitreAttackMitigation.UserAccountManagement)] 16 | public class HeatlcheckRuleStaledInactive : RuleBase 17 | { 18 | protected override int? AnalyzeDataNew(HealthcheckData healthcheckData) 19 | { 20 | if (healthcheckData.UserAccountData.NumberActive <= 10) 21 | return 0; 22 | if (healthcheckData.UserAccountData.Number == 0) 23 | return 0; 24 | return 100 * healthcheckData.UserAccountData.NumberInactive / healthcheckData.UserAccountData.Number; 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /Healthcheck/Rules/HeatlcheckRuleStaledInactiveComputer.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Ping Castle. All rights reserved. 3 | // https://www.pingcastle.com 4 | // 5 | // Licensed under the Non-Profit OSL. See LICENSE file in the project root for full license information. 6 | // 7 | using PingCastle.Rules; 8 | 9 | namespace PingCastle.Healthcheck.Rules 10 | { 11 | [RuleModel("S-C-Inactive", RiskRuleCategory.StaleObjects, RiskModelCategory.InactiveUserOrComputer)] 12 | [RuleComputation(RuleComputationType.TriggerOnThreshold, 30, Threshold: 30, Order: 1)] 13 | [RuleComputation(RuleComputationType.TriggerOnThreshold, 10, Threshold: 20, Order: 2)] 14 | [RuleComputation(RuleComputationType.TriggerOnThreshold, 5, Threshold: 15, Order: 3)] 15 | [RuleANSSI("R45", "paragraph.3.6.6.2")] 16 | [RuleDurANSSI(3, "password_change_inactive_servers", "Inactive servers")] 17 | [RuleMitreAttackMitigation(MitreAttackMitigation.UserAccountManagement)] 18 | public class HeatlcheckRuleStaledInactiveComputer : RuleBase 19 | { 20 | protected override int? AnalyzeDataNew(HealthcheckData healthcheckData) 21 | { 22 | if (healthcheckData.ComputerAccountData.NumberActive <= 20) 23 | return 0; 24 | if (healthcheckData.ComputerAccountData.Number == 0) 25 | return 0; 26 | return 100 * healthcheckData.ComputerAccountData.NumberInactive / healthcheckData.ComputerAccountData.Number; 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /Healthcheck/Rules/HeatlcheckRuleStaledJavaSchema.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Ping Castle. All rights reserved. 3 | // https://www.pingcastle.com 4 | // 5 | // Licensed under the Non-Profit OSL. See LICENSE file in the project root for full license information. 6 | // 7 | using PingCastle.Rules; 8 | 9 | namespace PingCastle.Healthcheck.Rules 10 | { 11 | [RuleModel("S-JavaSchema", RiskRuleCategory.StaleObjects, RiskModelCategory.ObjectConfig)] 12 | [RuleComputation(RuleComputationType.TriggerOnPresence, 0)] 13 | [RuleMitreAttackMitigation(MitreAttackMitigation.ActiveDirectoryConfiguration)] 14 | [RuleMaturityLevel(3)] 15 | [RuleIntroducedIn(2,10,1)] 16 | public class HeatlcheckRuleStaledJavaSchema : RuleBase 17 | { 18 | protected override int? AnalyzeDataNew(HealthcheckData healthcheckData) 19 | { 20 | if (healthcheckData.JavaClassFound) 21 | { 22 | return 1; 23 | } 24 | return 0; 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /Healthcheck/Rules/HeatlcheckRuleStaledMS14_068.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Ping Castle. All rights reserved. 3 | // https://www.pingcastle.com 4 | // 5 | // Licensed under the Non-Profit OSL. See LICENSE file in the project root for full license information. 6 | // 7 | using PingCastle.Rules; 8 | using System; 9 | 10 | namespace PingCastle.Healthcheck.Rules 11 | { 12 | [RuleModel("S-Vuln-MS14-068", RiskRuleCategory.StaleObjects, RiskModelCategory.VulnerabilityManagement)] 13 | [RuleComputation(RuleComputationType.TriggerOnPresence, 100)] 14 | [RuleCERTFR("CERTFR-2014-ALE-011")] 15 | [RuleMaturityLevel(1)] 16 | [RuleMitreAttackMitigation(MitreAttackMitigation.UpdateSoftware)] 17 | public class HeatlcheckRuleStaledMS14_068 : RuleBase 18 | { 19 | protected override int? AnalyzeDataNew(HealthcheckData healthcheckData) 20 | { 21 | DateTime alertDate = new DateTime(2014, 11, 18); 22 | if (healthcheckData.DomainControllers != null && healthcheckData.DomainControllers.Count > 0) 23 | { 24 | foreach (var DC in healthcheckData.DomainControllers) 25 | { 26 | if (DC.StartupTime != DateTime.MinValue) 27 | { 28 | if (DC.StartupTime < alertDate) 29 | { 30 | AddRawDetail(DC.DCName, "StartupTime=" + DC.StartupTime); 31 | } 32 | } 33 | } 34 | } 35 | return null; 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /Healthcheck/Rules/HeatlcheckRuleStaledObsolete2000.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Ping Castle. All rights reserved. 3 | // https://www.pingcastle.com 4 | // 5 | // Licensed under the Non-Profit OSL. See LICENSE file in the project root for full license information. 6 | // 7 | using PingCastle.Rules; 8 | 9 | namespace PingCastle.Healthcheck.Rules 10 | { 11 | [RuleModel("S-OS-2000", RiskRuleCategory.StaleObjects, RiskModelCategory.ObsoleteOS)] 12 | [RuleComputation(RuleComputationType.TriggerOnPresence, 40)] 13 | [RuleCERTFR("CERTFR-2005-INF-003", "SECTION00032400000000000000")] 14 | [RuleMaturityLevel(2)] 15 | [RuleMitreAttackMitigation(MitreAttackMitigation.UpdateSoftware)] 16 | public class HeatlcheckRuleStaledObsolete2000 : RuleBase 17 | { 18 | protected override int? AnalyzeDataNew(HealthcheckData healthcheckData) 19 | { 20 | foreach (HealthcheckOSData os in healthcheckData.OperatingSystem) 21 | { 22 | if (os.OperatingSystem == "Windows 2000") 23 | { 24 | return os.NumberOfOccurence; 25 | } 26 | } 27 | return 0; 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /Healthcheck/Rules/HeatlcheckRuleStaledObsolete2003.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Ping Castle. All rights reserved. 3 | // https://www.pingcastle.com 4 | // 5 | // Licensed under the Non-Profit OSL. See LICENSE file in the project root for full license information. 6 | // 7 | using PingCastle.Rules; 8 | 9 | namespace PingCastle.Healthcheck.Rules 10 | { 11 | [RuleModel("S-OS-2003", RiskRuleCategory.StaleObjects, RiskModelCategory.ObsoleteOS)] 12 | [RuleComputation(RuleComputationType.TriggerOnThreshold, 30, Threshold: 15, Order: 1)] 13 | [RuleComputation(RuleComputationType.TriggerOnThreshold, 25, Threshold: 6, Order: 2)] 14 | [RuleComputation(RuleComputationType.TriggerOnPresence, 20, Order: 3)] 15 | [RuleCERTFR("CERTFR-2005-INF-003", "SECTION00032400000000000000")] 16 | [RuleMaturityLevel(2)] 17 | [RuleMitreAttackMitigation(MitreAttackMitigation.UpdateSoftware)] 18 | public class HeatlcheckRuleStaledObsolete2003 : RuleBase 19 | { 20 | protected override int? AnalyzeDataNew(HealthcheckData healthcheckData) 21 | { 22 | foreach (HealthcheckOSData os in healthcheckData.OperatingSystem) 23 | { 24 | if (os.OperatingSystem == "Windows 2003") 25 | { 26 | return os.NumberOfOccurence; 27 | } 28 | } 29 | return 0; 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /Healthcheck/Rules/HeatlcheckRuleStaledObsolete2008.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Ping Castle. All rights reserved. 3 | // https://www.pingcastle.com 4 | // 5 | // Licensed under the Non-Profit OSL. See LICENSE file in the project root for full license information. 6 | // 7 | using PingCastle.Rules; 8 | 9 | namespace PingCastle.Healthcheck.Rules 10 | { 11 | [RuleModel("S-OS-2008", RiskRuleCategory.StaleObjects, RiskModelCategory.ObsoleteOS)] 12 | [RuleComputation(RuleComputationType.TriggerOnThreshold, 15, Threshold: 15, Order: 1)] 13 | [RuleComputation(RuleComputationType.TriggerOnThreshold, 10, Threshold: 6, Order: 2)] 14 | [RuleComputation(RuleComputationType.TriggerOnPresence, 5, Order: 3)] 15 | [RuleCERTFR("CERTFR-2005-INF-003", "SECTION00032400000000000000")] 16 | [RuleMaturityLevel(2)] 17 | [RuleMitreAttackMitigation(MitreAttackMitigation.UpdateSoftware)] 18 | public class HeatlcheckRuleStaledObsolete2008 : RuleBase 19 | { 20 | protected override int? AnalyzeDataNew(HealthcheckData healthcheckData) 21 | { 22 | foreach (HealthcheckOSData os in healthcheckData.OperatingSystem) 23 | { 24 | if (os.OperatingSystem == "Windows 2008") 25 | { 26 | return os.NumberOfOccurence; 27 | } 28 | } 29 | return 0; 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /Healthcheck/Rules/HeatlcheckRuleStaledObsolete2012.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Ping Castle. All rights reserved. 3 | // https://www.pingcastle.com 4 | // 5 | // Licensed under the Non-Profit OSL. See LICENSE file in the project root for full license information. 6 | // 7 | using PingCastle.Rules; 8 | using System; 9 | 10 | namespace PingCastle.Healthcheck.Rules 11 | { 12 | [RuleModel("S-OS-2012", RiskRuleCategory.StaleObjects, RiskModelCategory.ObsoleteOS)] 13 | [RuleComputation(RuleComputationType.TriggerOnThreshold, 10, Threshold: 15, Order: 1)] 14 | [RuleComputation(RuleComputationType.TriggerOnThreshold, 5, Threshold: 6, Order: 2)] 15 | [RuleComputation(RuleComputationType.TriggerOnPresence, 2, Order: 3)] 16 | [RuleCERTFR("CERTFR-2005-INF-003", "SECTION00032400000000000000")] 17 | [RuleMaturityLevel(2)] 18 | [RuleIntroducedIn(3, 1)] 19 | [RuleMitreAttackMitigation(MitreAttackMitigation.UpdateSoftware)] 20 | public class HeatlcheckRuleStaledObsolete2012 : RuleBase 21 | { 22 | public static bool IPaidSupportWin2012 { get; set; } 23 | 24 | protected override int? AnalyzeDataNew(HealthcheckData healthcheckData) 25 | { 26 | if (DateTime.Now < new DateTime(2023, 10, 10)) 27 | return null; 28 | if (IPaidSupportWin2012) 29 | return 0; 30 | foreach (HealthcheckOSData os in healthcheckData.OperatingSystem) 31 | { 32 | if (os.OperatingSystem == "Windows 2012") 33 | { 34 | return os.NumberOfOccurence; 35 | } 36 | } 37 | return 0; 38 | } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /Healthcheck/Rules/HeatlcheckRuleStaledObsoleteDC2000.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Ping Castle. All rights reserved. 3 | // https://www.pingcastle.com 4 | // 5 | // Licensed under the Non-Profit OSL. See LICENSE file in the project root for full license information. 6 | // 7 | using PingCastle.Rules; 8 | 9 | namespace PingCastle.Healthcheck.Rules 10 | { 11 | [RuleModel("S-DC-2000", RiskRuleCategory.StaleObjects, RiskModelCategory.ObsoleteOS)] 12 | [RuleComputation(RuleComputationType.TriggerOnPresence, 40)] 13 | [RuleSTIG("V-8551", "The domain functional level must be at a Windows Server version still supported by Microsoft.")] 14 | [RuleANSSI("R12", "subsection.3.1")] 15 | [RuleDurANSSI(1, "warning_dc_obsolete", "DC/RODC with an obsolete operating system")] 16 | [RuleMitreAttackMitigation(MitreAttackMitigation.UpdateSoftware)] 17 | public class HeatlcheckRuleStaledObsoleteDC2000 : RuleBase 18 | { 19 | protected override int? AnalyzeDataNew(HealthcheckData healthcheckData) 20 | { 21 | int w2000 = 0; 22 | foreach (var dc in healthcheckData.DomainControllers) 23 | { 24 | if (dc.OperatingSystem == "Windows 2000") 25 | { 26 | w2000++; 27 | } 28 | } 29 | return w2000; 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /Healthcheck/Rules/HeatlcheckRuleStaledObsoleteDC2003.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Ping Castle. All rights reserved. 3 | // https://www.pingcastle.com 4 | // 5 | // Licensed under the Non-Profit OSL. See LICENSE file in the project root for full license information. 6 | // 7 | using PingCastle.Rules; 8 | 9 | namespace PingCastle.Healthcheck.Rules 10 | { 11 | [RuleModel("S-DC-2003", RiskRuleCategory.StaleObjects, RiskModelCategory.ObsoleteOS)] 12 | [RuleComputation(RuleComputationType.TriggerOnPresence, 20)] 13 | [RuleSTIG("V-8551", "The domain functional level must be at a Windows Server version still supported by Microsoft.")] 14 | [RuleANSSI("R12", "subsection.3.1")] 15 | [RuleDurANSSI(1, "warning_dc_obsolete", "DC/RODC with an obsolete operating system")] 16 | [RuleMitreAttackMitigation(MitreAttackMitigation.UpdateSoftware)] 17 | public class HeatlcheckRuleStaledObsoleteDC2003 : RuleBase 18 | { 19 | protected override int? AnalyzeDataNew(HealthcheckData healthcheckData) 20 | { 21 | int w2003 = 0; 22 | foreach (var dc in healthcheckData.DomainControllers) 23 | { 24 | if (dc.OperatingSystem == "Windows 2003") 25 | { 26 | w2003++; 27 | } 28 | } 29 | return w2003; 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /Healthcheck/Rules/HeatlcheckRuleStaledObsoleteDC2008.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Ping Castle. All rights reserved. 3 | // https://www.pingcastle.com 4 | // 5 | // Licensed under the Non-Profit OSL. See LICENSE file in the project root for full license information. 6 | // 7 | using PingCastle.Rules; 8 | 9 | namespace PingCastle.Healthcheck.Rules 10 | { 11 | [RuleModel("S-DC-2008", RiskRuleCategory.StaleObjects, RiskModelCategory.ObsoleteOS)] 12 | [RuleComputation(RuleComputationType.TriggerOnPresence, 5)] 13 | [RuleSTIG("V-8551", "The domain functional level must be at a Windows Server version still supported by Microsoft.")] 14 | [RuleANSSI("R12", "subsection.3.1")] 15 | [RuleDurANSSI(1, "warning_dc_obsolete", "DC/RODC with an obsolete operating system")] 16 | [RuleMitreAttackMitigation(MitreAttackMitigation.UpdateSoftware)] 17 | public class HeatlcheckRuleStaledObsoleteDC2008 : RuleBase 18 | { 19 | protected override int? AnalyzeDataNew(HealthcheckData healthcheckData) 20 | { 21 | int w2008 = 0; 22 | foreach (var dc in healthcheckData.DomainControllers) 23 | { 24 | if (dc.OperatingSystem == "Windows 2008") 25 | { 26 | w2008++; 27 | } 28 | } 29 | return w2008; 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /Healthcheck/Rules/HeatlcheckRuleStaledObsoleteDC2012.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Ping Castle. All rights reserved. 3 | // https://www.pingcastle.com 4 | // 5 | // Licensed under the Non-Profit OSL. See LICENSE file in the project root for full license information. 6 | // 7 | using PingCastle.Rules; 8 | using System; 9 | 10 | namespace PingCastle.Healthcheck.Rules 11 | { 12 | [RuleModel("S-DC-2012", RiskRuleCategory.StaleObjects, RiskModelCategory.ObsoleteOS)] 13 | [RuleComputation(RuleComputationType.TriggerOnPresence, 5)] 14 | [RuleSTIG("V-8551", "The domain functional level must be at a Windows Server version still supported by Microsoft.")] 15 | [RuleANSSI("R12", "subsection.3.1")] 16 | [RuleDurANSSI(1, "warning_dc_obsolete", "DC/RODC with an obsolete operating system")] 17 | [RuleIntroducedIn(3, 1)] 18 | [RuleMitreAttackMitigation(MitreAttackMitigation.UpdateSoftware)] 19 | public class HeatlcheckRuleStaledObsoleteDC2012 : RuleBase 20 | { 21 | protected override int? AnalyzeDataNew(HealthcheckData healthcheckData) 22 | { 23 | if (DateTime.Now < new DateTime(2023, 10, 10)) 24 | return null; 25 | if (HeatlcheckRuleStaledObsolete2012.IPaidSupportWin2012) 26 | return 0; 27 | int w2012 = 0; 28 | foreach (var dc in healthcheckData.DomainControllers) 29 | { 30 | if (dc.OperatingSystem == "Windows 2012") 31 | { 32 | w2012++; 33 | } 34 | } 35 | return w2012; 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /Healthcheck/Rules/HeatlcheckRuleStaledObsoleteFunctionalLevel1.cs: -------------------------------------------------------------------------------- 1 | using PingCastle.Report; 2 | // 3 | // Copyright (c) Ping Castle. All rights reserved. 4 | // https://www.pingcastle.com 5 | // 6 | // Licensed under the Non-Profit OSL. See LICENSE file in the project root for full license information. 7 | // 8 | using PingCastle.Rules; 9 | 10 | namespace PingCastle.Healthcheck.Rules 11 | { 12 | [RuleModel("S-FunctionalLevel1", RiskRuleCategory.StaleObjects, RiskModelCategory.ObsoleteOS)] 13 | [RuleComputation(RuleComputationType.TriggerOnPresence, 5)] 14 | [RuleDurANSSI(1, "functional_level", "Insufficient forest and domains functional levels")] 15 | [RuleIntroducedIn(2, 11, 2)] 16 | [RuleMitreAttackMitigation(MitreAttackMitigation.UpdateSoftware)] 17 | public class HeatlcheckRuleStaledObsoleteFunctionalLevel1 : RuleBase 18 | { 19 | protected override int? AnalyzeDataNew(HealthcheckData healthcheckData) 20 | { 21 | if (healthcheckData.DomainFunctionalLevel < 4) 22 | { 23 | AddRawDetail("Domain", ReportHelper.DecodeDomainFunctionalLevel(healthcheckData.DomainFunctionalLevel)); 24 | } 25 | if (healthcheckData.ForestFunctionalLevel < 4) 26 | { 27 | AddRawDetail("Forest", ReportHelper.DecodeForestFunctionalLevel(healthcheckData.ForestFunctionalLevel)); 28 | } 29 | return null; 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /Healthcheck/Rules/HeatlcheckRuleStaledObsoleteFunctionalLevel3.cs: -------------------------------------------------------------------------------- 1 | using PingCastle.Report; 2 | // 3 | // Copyright (c) Ping Castle. All rights reserved. 4 | // https://www.pingcastle.com 5 | // 6 | // Licensed under the Non-Profit OSL. See LICENSE file in the project root for full license information. 7 | // 8 | using PingCastle.Rules; 9 | 10 | namespace PingCastle.Healthcheck.Rules 11 | { 12 | [RuleModel("S-FunctionalLevel3", RiskRuleCategory.StaleObjects, RiskModelCategory.ObsoleteOS)] 13 | [RuleComputation(RuleComputationType.TriggerOnPresence, 0)] 14 | [RuleDurANSSI(3, "functional_level", "Insufficient forest and domains functional levels")] 15 | [RuleIntroducedIn(2, 11, 2)] 16 | [RuleMitreAttackMitigation(MitreAttackMitigation.UpdateSoftware)] 17 | public class HeatlcheckRuleStaledObsoleteFunctionalLevel3 : RuleBase 18 | { 19 | protected override int? AnalyzeDataNew(HealthcheckData healthcheckData) 20 | { 21 | if (healthcheckData.DomainFunctionalLevel >= 4 && healthcheckData.DomainFunctionalLevel < 6) 22 | { 23 | AddRawDetail("Domain", ReportHelper.DecodeDomainFunctionalLevel(healthcheckData.DomainFunctionalLevel)); 24 | } 25 | if (healthcheckData.ForestFunctionalLevel >= 4 && healthcheckData.ForestFunctionalLevel < 6) 26 | { 27 | AddRawDetail("Forest", ReportHelper.DecodeForestFunctionalLevel(healthcheckData.ForestFunctionalLevel)); 28 | } 29 | return null; 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /Healthcheck/Rules/HeatlcheckRuleStaledObsoleteFunctionalLevel4.cs: -------------------------------------------------------------------------------- 1 | using PingCastle.Report; 2 | // 3 | // Copyright (c) Ping Castle. All rights reserved. 4 | // https://www.pingcastle.com 5 | // 6 | // Licensed under the Non-Profit OSL. See LICENSE file in the project root for full license information. 7 | // 8 | using PingCastle.Rules; 9 | 10 | namespace PingCastle.Healthcheck.Rules 11 | { 12 | [RuleModel("S-FunctionalLevel4", RiskRuleCategory.StaleObjects, RiskModelCategory.ObsoleteOS)] 13 | [RuleComputation(RuleComputationType.TriggerOnPresence, 0)] 14 | [RuleDurANSSI(3, "functional_level", "Insufficient forest and domains functional levels")] 15 | [RuleIntroducedIn(2, 11, 2)] 16 | [RuleMitreAttackMitigation(MitreAttackMitigation.UpdateSoftware)] 17 | public class HeatlcheckRuleStaledObsoleteFunctionalLevel4 : RuleBase 18 | { 19 | protected override int? AnalyzeDataNew(HealthcheckData healthcheckData) 20 | { 21 | if (healthcheckData.DomainFunctionalLevel >= 6 && healthcheckData.DomainFunctionalLevel < 7) 22 | { 23 | AddRawDetail("Domain", ReportHelper.DecodeDomainFunctionalLevel(healthcheckData.DomainFunctionalLevel)); 24 | } 25 | if (healthcheckData.ForestFunctionalLevel >= 6 && healthcheckData.ForestFunctionalLevel < 7) 26 | { 27 | AddRawDetail("Forest", ReportHelper.DecodeForestFunctionalLevel(healthcheckData.ForestFunctionalLevel)); 28 | } 29 | return null; 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /Healthcheck/Rules/HeatlcheckRuleStaledObsoleteNT4.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Ping Castle. All rights reserved. 3 | // https://www.pingcastle.com 4 | // 5 | // Licensed under the Non-Profit OSL. See LICENSE file in the project root for full license information. 6 | // 7 | using PingCastle.Rules; 8 | 9 | namespace PingCastle.Healthcheck.Rules 10 | { 11 | [RuleModel("S-OS-NT", RiskRuleCategory.StaleObjects, RiskModelCategory.ObsoleteOS)] 12 | [RuleComputation(RuleComputationType.TriggerOnPresence, 60)] 13 | [RuleCERTFR("CERTFR-2005-INF-003", "SECTION00032400000000000000")] 14 | [RuleMaturityLevel(2)] 15 | [RuleMitreAttackMitigation(MitreAttackMitigation.UpdateSoftware)] 16 | public class HeatlcheckRuleStaledObsoleteNT4 : RuleBase 17 | { 18 | protected override int? AnalyzeDataNew(HealthcheckData healthcheckData) 19 | { 20 | foreach (HealthcheckOSData os in healthcheckData.OperatingSystem) 21 | { 22 | if (os.OperatingSystem == "Windows NT") 23 | { 24 | return os.NumberOfOccurence; 25 | } 26 | } 27 | return 0; 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /Healthcheck/Rules/HeatlcheckRuleStaledObsoleteVista.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Ping Castle. All rights reserved. 3 | // https://www.pingcastle.com 4 | // 5 | // Licensed under the Non-Profit OSL. See LICENSE file in the project root for full license information. 6 | // 7 | using PingCastle.Rules; 8 | 9 | namespace PingCastle.Healthcheck.Rules 10 | { 11 | [RuleModel("S-OS-Vista", RiskRuleCategory.StaleObjects, RiskModelCategory.ObsoleteOS)] 12 | [RuleComputation(RuleComputationType.TriggerOnThreshold, 20, Threshold: 15, Order: 1)] 13 | [RuleComputation(RuleComputationType.TriggerOnThreshold, 15, Threshold: 6, Order: 2)] 14 | [RuleComputation(RuleComputationType.TriggerOnPresence, 10, Order: 3)] 15 | [RuleCERTFR("CERTFR-2005-INF-003", "SECTION00032400000000000000")] 16 | [RuleIntroducedIn(2, 8)] 17 | [RuleMaturityLevel(2)] 18 | [RuleMitreAttackMitigation(MitreAttackMitigation.UpdateSoftware)] 19 | public class HeatlcheckRuleStaledObsoleteVista : RuleBase 20 | { 21 | protected override int? AnalyzeDataNew(HealthcheckData healthcheckData) 22 | { 23 | foreach (HealthcheckOSData os in healthcheckData.OperatingSystem) 24 | { 25 | if (os.OperatingSystem == "Windows Vista") 26 | { 27 | return os.NumberOfOccurence; 28 | } 29 | } 30 | return 0; 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /Healthcheck/Rules/HeatlcheckRuleStaledObsoleteXP.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Ping Castle. All rights reserved. 3 | // https://www.pingcastle.com 4 | // 5 | // Licensed under the Non-Profit OSL. See LICENSE file in the project root for full license information. 6 | // 7 | using PingCastle.Rules; 8 | 9 | namespace PingCastle.Healthcheck.Rules 10 | { 11 | [RuleModel("S-OS-XP", RiskRuleCategory.StaleObjects, RiskModelCategory.ObsoleteOS)] 12 | [RuleComputation(RuleComputationType.TriggerOnThreshold, 20, Threshold: 15, Order: 1)] 13 | [RuleComputation(RuleComputationType.TriggerOnThreshold, 15, Threshold: 6, Order: 2)] 14 | [RuleComputation(RuleComputationType.TriggerOnPresence, 10, Order: 3)] 15 | [RuleCERTFR("CERTFR-2005-INF-003", "SECTION00032400000000000000")] 16 | [RuleMaturityLevel(2)] 17 | [RuleMitreAttackMitigation(MitreAttackMitigation.UpdateSoftware)] 18 | public class HeatlcheckRuleStaledObsoleteXP : RuleBase 19 | { 20 | protected override int? AnalyzeDataNew(HealthcheckData healthcheckData) 21 | { 22 | foreach (HealthcheckOSData os in healthcheckData.OperatingSystem) 23 | { 24 | if (os.OperatingSystem == "Windows XP") 25 | { 26 | return os.NumberOfOccurence; 27 | } 28 | } 29 | return 0; 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /Healthcheck/Rules/HeatlcheckRuleStaledPrimaryGroup.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Ping Castle. All rights reserved. 3 | // https://www.pingcastle.com 4 | // 5 | // Licensed under the Non-Profit OSL. See LICENSE file in the project root for full license information. 6 | // 7 | using PingCastle.Rules; 8 | 9 | namespace PingCastle.Healthcheck.Rules 10 | { 11 | [RuleModel("S-PrimaryGroup", RiskRuleCategory.StaleObjects, RiskModelCategory.ObjectConfig)] 12 | [RuleComputation(RuleComputationType.TriggerOnPresence, 15)] 13 | [RuleDurANSSI(3, "primary_group_id_nochange", "Accounts with modified PrimaryGroupID")] 14 | [RuleMitreAttackMitigation(MitreAttackMitigation.ActiveDirectoryConfiguration)] 15 | public class HeatlcheckRuleStaledPrimaryGroup : RuleBase 16 | { 17 | protected override int? AnalyzeDataNew(HealthcheckData healthcheckData) 18 | { 19 | if (healthcheckData.UserAccountData.ListBadPrimaryGroup != null) 20 | { 21 | if (healthcheckData.UserAccountData.NumberBadPrimaryGroup < maxNumDisplayAccount) 22 | { 23 | for (int i = 0; i < healthcheckData.UserAccountData.NumberBadPrimaryGroup; i++) 24 | { 25 | AddRawDetail(healthcheckData.UserAccountData.ListBadPrimaryGroup[i].DistinguishedName); 26 | } 27 | return null; 28 | } 29 | } 30 | return healthcheckData.UserAccountData.NumberBadPrimaryGroup; 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /Healthcheck/Rules/HeatlcheckRuleStaledPrimaryGroupComputer.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Ping Castle. All rights reserved. 3 | // https://www.pingcastle.com 4 | // 5 | // Licensed under the Non-Profit OSL. See LICENSE file in the project root for full license information. 6 | // 7 | using PingCastle.Rules; 8 | 9 | namespace PingCastle.Healthcheck.Rules 10 | { 11 | [RuleModel("S-C-PrimaryGroup", RiskRuleCategory.StaleObjects, RiskModelCategory.ObjectConfig)] 12 | [RuleComputation(RuleComputationType.TriggerOnPresence, 15)] 13 | [RuleDurANSSI(3, "primary_group_id_nochange", "Accounts with modified PrimaryGroupID")] 14 | [RuleMitreAttackMitigation(MitreAttackMitigation.ActiveDirectoryConfiguration)] 15 | public class HeatlcheckRuleStaledPrimaryGroupComputer : RuleBase 16 | { 17 | protected override int? AnalyzeDataNew(HealthcheckData healthcheckData) 18 | { 19 | return healthcheckData.ComputerAccountData.NumberBadPrimaryGroup; 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /Healthcheck/Rules/HeatlcheckRuleStaledPwdNeverExpires.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Ping Castle. All rights reserved. 3 | // https://www.pingcastle.com 4 | // 5 | // Licensed under the Non-Profit OSL. See LICENSE file in the project root for full license information. 6 | // 7 | using PingCastle.Rules; 8 | 9 | namespace PingCastle.Healthcheck.Rules 10 | { 11 | [RuleModel("S-PwdNeverExpires", RiskRuleCategory.StaleObjects, RiskModelCategory.ObjectConfig)] 12 | [RuleComputation(RuleComputationType.TriggerOnPresence, 1)] 13 | [RuleIntroducedIn(2, 9)] 14 | [RuleDurANSSI(2, "dont_expire", "Accounts with never-expiring passwords")] 15 | [RuleMitreAttackMitigation(MitreAttackMitigation.ActiveDirectoryConfiguration)] 16 | public class HeatlcheckRuleStaledPwdNeverExpires : RuleBase 17 | { 18 | protected override int? AnalyzeDataNew(HealthcheckData healthcheckData) 19 | { 20 | if (healthcheckData.UserAccountData.ListPwdNeverExpires != null) 21 | { 22 | if (healthcheckData.UserAccountData.NumberPwdNeverExpires < maxNumDisplayAccount) 23 | { 24 | for (int i = 0; i < healthcheckData.UserAccountData.NumberPwdNeverExpires; i++) 25 | { 26 | AddRawDetail(healthcheckData.UserAccountData.ListPwdNeverExpires[i].DistinguishedName); 27 | } 28 | return null; 29 | } 30 | } 31 | return healthcheckData.UserAccountData.NumberPwdNeverExpires; 32 | } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /Healthcheck/Rules/HeatlcheckRuleStaledPwdNotRequired.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Ping Castle. All rights reserved. 3 | // https://www.pingcastle.com 4 | // 5 | // Licensed under the Non-Profit OSL. See LICENSE file in the project root for full license information. 6 | // 7 | using PingCastle.Rules; 8 | 9 | namespace PingCastle.Healthcheck.Rules 10 | { 11 | [RuleModel("S-PwdNotRequired", RiskRuleCategory.StaleObjects, RiskModelCategory.ObjectConfig)] 12 | [RuleComputation(RuleComputationType.TriggerOnPresence, 15)] 13 | [RuleANSSI("R36", "subsection.3.6")] 14 | [RuleMaturityLevel(3)] 15 | [RuleMitreAttackMitigation(MitreAttackMitigation.ActiveDirectoryConfiguration)] 16 | public class HeatlcheckRuleStaledPwdNotRequired : RuleBase 17 | { 18 | protected override int? AnalyzeDataNew(HealthcheckData healthcheckData) 19 | { 20 | if (healthcheckData.UserAccountData.ListPwdNotRequired != null) 21 | { 22 | if (healthcheckData.UserAccountData.NumberPwdNotRequired < maxNumDisplayAccount) 23 | { 24 | for (int i = 0; i < healthcheckData.UserAccountData.NumberPwdNotRequired; i++) 25 | { 26 | AddRawDetail(healthcheckData.UserAccountData.ListPwdNotRequired[i].DistinguishedName); 27 | } 28 | return null; 29 | } 30 | } 31 | return healthcheckData.UserAccountData.NumberPwdNotRequired; 32 | } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /Healthcheck/Rules/HeatlcheckRuleStaledReversibleEncryption.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Ping Castle. All rights reserved. 3 | // https://www.pingcastle.com 4 | // 5 | // Licensed under the Non-Profit OSL. See LICENSE file in the project root for full license information. 6 | // 7 | using PingCastle.Rules; 8 | 9 | namespace PingCastle.Healthcheck.Rules 10 | { 11 | [RuleModel("S-Reversible", RiskRuleCategory.StaleObjects, RiskModelCategory.ObjectConfig)] 12 | [RuleComputation(RuleComputationType.TriggerOnPresence, 5)] 13 | [RuleDurANSSI(3, "reversible_password", "Accounts with passwords stored using reversible encryption")] 14 | [RuleMitreAttackTechnique(MitreAttackTechnique.BruteForcePasswordCracking)] 15 | public class HeatlcheckRuleStaledReversibleEncryption : RuleBase 16 | { 17 | protected override int? AnalyzeDataNew(HealthcheckData healthcheckData) 18 | { 19 | return healthcheckData.UserAccountData.NumberReversibleEncryption; 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /Healthcheck/Rules/HeatlcheckRuleStaledReversibleEncryptionComputer.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Ping Castle. All rights reserved. 3 | // https://www.pingcastle.com 4 | // 5 | // Licensed under the Non-Profit OSL. See LICENSE file in the project root for full license information. 6 | // 7 | using PingCastle.Rules; 8 | 9 | namespace PingCastle.Healthcheck.Rules 10 | { 11 | [RuleModel("S-C-Reversible", RiskRuleCategory.StaleObjects, RiskModelCategory.ObjectConfig)] 12 | [RuleComputation(RuleComputationType.TriggerOnPresence, 5)] 13 | [RuleDurANSSI(3, "reversible_password", "Accounts with passwords stored using reversible encryption")] 14 | [RuleMitreAttackTechnique(MitreAttackTechnique.BruteForcePasswordCracking)] 15 | public class HeatlcheckRuleStaledReversibleEncryptionComputer : RuleBase 16 | { 17 | protected override int? AnalyzeDataNew(HealthcheckData healthcheckData) 18 | { 19 | return healthcheckData.ComputerAccountData.NumberReversibleEncryption; 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /Healthcheck/Rules/HeatlcheckRuleStaledSIDHistoryComputer.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace ADSecurityHealthCheck.Healthcheck.Rules 6 | { 7 | public class HeatlcheckRuleStaledSIDHistoryComputer : HeatlcheckRuleBase 8 | { 9 | public HeatlcheckRuleStaledSIDHistoryComputer() 10 | { 11 | Category = HealthcheckRiskRuleCategory.StaleObjects; 12 | Id = "S-C-SIDHistory"; 13 | Description = @"Check SIDHistory"; 14 | Solution = @"SID History is an attribute used when migrating users or computers from one domain to another 15 | It can be used to take control of foreign domain or setting backdoors. 16 | You can list the objects using the command: 17 | Get-ADObject -ldapfilter ""(sidhistory=*)"" -properties sidhistory 18 | The SIDHistory attribute can then be removed using the migration tool or the powershell snippet Remove-SIDHistory"; 19 | Points = 15; 20 | } 21 | public override bool Analyze(HealthcheckData healthcheckData) 22 | { 23 | if (healthcheckData.ComputerAccountData.NumberSidHistory > 0) 24 | { 25 | if (healthcheckData.ComputerAccountData.NumberSidHistory * 100 > healthcheckData.ComputerAccountData.Number * 10) 26 | Points = 30; 27 | else 28 | Points = 15; 29 | Rationale = "Computer accounts with SID History = " + healthcheckData.ComputerAccountData.NumberSidHistory + " (migration should be completed)"; 30 | return true; 31 | } 32 | return false; 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /Healthcheck/Rules/HeatlcheckRuleStaledSMBv1.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Ping Castle. All rights reserved. 3 | // https://www.pingcastle.com 4 | // 5 | // Licensed under the Non-Profit OSL. See LICENSE file in the project root for full license information. 6 | // 7 | using PingCastle.Rules; 8 | 9 | namespace PingCastle.Healthcheck.Rules 10 | { 11 | [RuleModel("S-SMB-v1", RiskRuleCategory.StaleObjects, RiskModelCategory.OldAuthenticationProtocols)] 12 | [RuleComputation(RuleComputationType.TriggerOnPresence, 10)] 13 | //[RuleBSI("M 2.412")] 14 | [RuleCERTFR("CERTFR-2017-ACT-019", "SECTION00010000000000000000")] 15 | [RuleCERTFR("CERTFR-2016-ACT-039", "SECTION00010000000000000000")] 16 | [RuleMaturityLevel(3)] 17 | [RuleMitreAttackTechnique(MitreAttackTechnique.ManintheMiddleLLMNRNBTNSPoisoningandSMBRelay)] 18 | public class HeatlcheckRuleStaledSMBv1 : RuleBase 19 | { 20 | protected override int? AnalyzeDataNew(HealthcheckData healthcheckData) 21 | { 22 | // smb v1 enabled ? 23 | if (healthcheckData.DomainControllers != null && healthcheckData.DomainControllers.Count > 0) 24 | { 25 | foreach (var DC in healthcheckData.DomainControllers) 26 | { 27 | if (DC.SupportSMB1) 28 | { 29 | AddRawDetail(DC.DCName); 30 | } 31 | } 32 | } 33 | return null; 34 | } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /Healthcheck/Rules/HeatlcheckRuleStaledWSUSNoPinning.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Ping Castle. All rights reserved. 3 | // https://www.pingcastle.com 4 | // 5 | // Licensed under the Non-Profit OSL. See LICENSE file in the project root for full license information. 6 | // 7 | using PingCastle.Rules; 8 | using System; 9 | 10 | namespace PingCastle.Healthcheck.Rules 11 | { 12 | [RuleModel("S-WSUS-NoPinning", RiskRuleCategory.StaleObjects, RiskModelCategory.VulnerabilityManagement)] 13 | [RuleComputation(RuleComputationType.TriggerOnPresence, 2)] 14 | [RuleMaturityLevel(2)] 15 | [RuleMitreAttackMitigation(MitreAttackMitigation.UpdateSoftware)] 16 | [RuleIntroducedIn(2, 10, 1)] 17 | public class HeatlcheckRuleStaledWSUSNoPinning : RuleBase 18 | { 19 | protected override int? AnalyzeDataNew(HealthcheckData healthcheckData) 20 | { 21 | if (healthcheckData.GPOWSUS != null && healthcheckData.GPOWSUS.Count > 0) 22 | { 23 | foreach (var gpo in healthcheckData.GPOWSUS) 24 | { 25 | if (gpo.Options != null) 26 | { 27 | foreach (var o in gpo.Options) 28 | { 29 | if (o.Name == "DoNotEnforceEnterpriseTLSCertPinningForUpdateDetection" && o.Value != 0) 30 | { 31 | AddRawDetail(gpo.GPOName); 32 | } 33 | } 34 | } 35 | } 36 | } 37 | return null; 38 | } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /Healthcheck/Rules/HeatlcheckRuleTrustAES.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Ping Castle. All rights reserved. 3 | // https://www.pingcastle.com 4 | // 5 | // Licensed under the Non-Profit OSL. See LICENSE file in the project root for full license information. 6 | // 7 | using PingCastle.Rules; 8 | 9 | namespace PingCastle.Healthcheck.Rules 10 | { 11 | [RuleModel("T-AlgsAES", RiskRuleCategory.Trusts, RiskModelCategory.OldTrustProtocol)] 12 | [RuleComputation(RuleComputationType.TriggerOnPresence, 1)] 13 | [RuleMaturityLevel(4)] 14 | [RuleIntroducedIn(2, 11)] 15 | [RuleMitreAttackMitigation(MitreAttackMitigation.ActiveDirectoryConfiguration)] 16 | public class HeatlcheckRuleTrustAES : RuleBase 17 | { 18 | protected override int? AnalyzeDataNew(HealthcheckData healthcheckData) 19 | { 20 | // trust 21 | foreach (HealthCheckTrustData trust in healthcheckData.Trusts) 22 | { 23 | if (trust.TrustDirection == 2) 24 | { 25 | continue; 26 | } 27 | if (trust.msDSSupportedEncryptionTypes == 0) 28 | { 29 | AddRawDetail(trust.TrustPartner, "Not Configured"); 30 | } 31 | else if ((trust.msDSSupportedEncryptionTypes & (8 + 16)) == 0) 32 | { 33 | AddRawDetail(trust.TrustPartner, "AES not enabled"); 34 | } 35 | } 36 | return null; 37 | } 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /Healthcheck/Rules/HeatlcheckRuleTrustAzureADSSO.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Ping Castle. All rights reserved. 3 | // https://www.pingcastle.com 4 | // 5 | // Licensed under the Non-Profit OSL. See LICENSE file in the project root for full license information. 6 | // 7 | using PingCastle.Rules; 8 | using System; 9 | 10 | namespace PingCastle.Healthcheck.Rules 11 | { 12 | [RuleModel("T-AzureADSSO", RiskRuleCategory.Trusts, RiskModelCategory.TrustAzure)] 13 | [RuleComputation(RuleComputationType.TriggerOnPresence, 20)] 14 | [RuleDurANSSI(2, "trusts_accounts", "Trust account passwords unchanged for more than a year")] 15 | [RuleMitreAttackTechnique(MitreAttackTechnique.OSCredentialDumping)] 16 | public class HeatlcheckRuleTrustAzureADSSO : RuleBase 17 | { 18 | protected override int? AnalyzeDataNew(HealthcheckData healthcheckData) 19 | { 20 | if (healthcheckData.AzureADSSOLastPwdChange != DateTime.MinValue && healthcheckData.AzureADSSOLastPwdChange.AddYears(1) < DateTime.Now) 21 | { 22 | return 1; 23 | } 24 | return null; 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /Healthcheck/Rules/HeatlcheckRuleTrustDownlevel.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Ping Castle. All rights reserved. 3 | // https://www.pingcastle.com 4 | // 5 | // Licensed under the Non-Profit OSL. See LICENSE file in the project root for full license information. 6 | // 7 | using PingCastle.Rules; 8 | 9 | namespace PingCastle.Healthcheck.Rules 10 | { 11 | [RuleModel("T-Downlevel", RiskRuleCategory.Trusts, RiskModelCategory.OldTrustProtocol)] 12 | [RuleComputation(RuleComputationType.TriggerOnPresence, 20)] 13 | [RuleMaturityLevel(3)] 14 | [RuleMitreAttackMitigation(MitreAttackMitigation.PrivilegedAccountManagement)] 15 | public class HeatlcheckRuleTrustDownlevel : RuleBase 16 | { 17 | protected override int? AnalyzeDataNew(HealthcheckData healthcheckData) 18 | { 19 | // trust 20 | foreach (HealthCheckTrustData trust in healthcheckData.Trusts) 21 | { 22 | if (trust.TrustType == 1) 23 | { 24 | AddRawDetail(trust.TrustPartner); 25 | } 26 | } 27 | return null; 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /Healthcheck/Rules/HeatlcheckRuleTrustInactive.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Ping Castle. All rights reserved. 3 | // https://www.pingcastle.com 4 | // 5 | // Licensed under the Non-Profit OSL. See LICENSE file in the project root for full license information. 6 | // 7 | using PingCastle.Rules; 8 | 9 | namespace PingCastle.Healthcheck.Rules 10 | { 11 | [RuleModel("T-Inactive", RiskRuleCategory.Trusts, RiskModelCategory.TrustInactive)] 12 | [RuleComputation(RuleComputationType.TriggerOnPresence, 20)] 13 | [RuleDurANSSI(2, "trusts_accounts", "Trust account passwords unchanged for more than a year")] 14 | [RuleMitreAttackTechnique(MitreAttackTechnique.ManintheMiddle)] 15 | public class HeatlcheckRuleTrustInactive : RuleBase 16 | { 17 | protected override int? AnalyzeDataNew(HealthcheckData healthcheckData) 18 | { 19 | foreach (HealthCheckTrustData trust in healthcheckData.Trusts) 20 | { 21 | if (!trust.IsActive) 22 | { 23 | AddRawDetail(trust.TrustPartner); 24 | } 25 | } 26 | return null; 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /Healthcheck/Rules/HeatlcheckRuleTrustSIDHistoryAuditingGroup.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Ping Castle. All rights reserved. 3 | // https://www.pingcastle.com 4 | // 5 | // Licensed under the Non-Profit OSL. See LICENSE file in the project root for full license information. 6 | // 7 | using PingCastle.Rules; 8 | 9 | namespace PingCastle.Healthcheck.Rules 10 | { 11 | [RuleModel("S-Domain$$$", RiskRuleCategory.Trusts, RiskModelCategory.SIDHistory)] 12 | [RuleComputation(RuleComputationType.TriggerOnPresence, 5)] 13 | [RuleANSSI("R15", "paragraph.3.3.1.5")] 14 | [RuleMaturityLevel(3)] 15 | [RuleMitreAttackMitigation(MitreAttackMitigation.PrivilegedAccountManagement)] 16 | public class HeatlcheckRuleTrustSIDHistoryAuditingGroup : RuleBase 17 | { 18 | protected override int? AnalyzeDataNew(HealthcheckData healthcheckData) 19 | { 20 | if (healthcheckData.SIDHistoryAuditingGroupPresent) 21 | { 22 | return 1; 23 | } 24 | return 0; 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/netwrix/pingcastle/548de82eb0d9631e7a244deffaaf63cfcd4fb460/LICENSE.md -------------------------------------------------------------------------------- /PingCastleAutoUpdater/App.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /PingCastleAutoUpdater/FodyWeavers.xml: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /PingCastleAutoUpdater/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // Les informations générales relatives à un assembly dépendent de 6 | // l'ensemble d'attributs suivant. Changez les valeurs de ces attributs pour modifier les informations 7 | // associées à un assembly. 8 | [assembly: AssemblyTitle("PingCastleAutoUpdater")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("Netwrix Corporation")] 12 | [assembly: AssemblyProduct("PingCastle")] 13 | [assembly: AssemblyCopyright("Copyright © Netwrix Corporation")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // L'affectation de la valeur false à ComVisible rend les types invisibles dans cet assembly 18 | // aux composants COM. Si vous devez accéder à un type dans cet assembly à partir de 19 | // COM, affectez la valeur true à l'attribut ComVisible sur ce type. 20 | [assembly: ComVisible(false)] 21 | 22 | // Le GUID suivant est pour l'ID de la typelib si ce projet est exposé à COM 23 | [assembly: Guid("74ba30cc-dda4-4174-9ae4-04262720d773")] 24 | 25 | // Les informations de version pour un assembly se composent des quatre valeurs suivantes : 26 | // 27 | // Version principale 28 | // Version secondaire 29 | // Numéro de build 30 | // Révision 31 | // 32 | // Vous pouvez spécifier toutes les valeurs ou indiquer les numéros de build et de révision par défaut 33 | // en utilisant '*', comme indiqué ci-dessous : 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("3.3.0.12")] 36 | [assembly: AssemblyFileVersion("3.3.0.12")] 37 | -------------------------------------------------------------------------------- /PingCastleAutoUpdater/pingcastle.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/netwrix/pingcastle/548de82eb0d9631e7a244deffaaf63cfcd4fb460/PingCastleAutoUpdater/pingcastle.ico -------------------------------------------------------------------------------- /PingCastleCommon/PingCastleCommon.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | netstandard2.0 5 | false 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /PingCastleCommon/SupportLink.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.Extensions.Configuration; 2 | 3 | namespace PingCastleCommon 4 | { 5 | public static class SupportLink 6 | { 7 | public static string Url { get; private set; } 8 | public static string Text { get; } = "contact our support"; 9 | public static string NetwrixSupportUrl = "https://www.netwrix.com/support.html"; 10 | 11 | public static void Initialize(IConfiguration configuration) 12 | { 13 | Url = configuration["supportLink"] ?? NetwrixSupportUrl; 14 | } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /PingCastleException.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Runtime.Serialization; 3 | 4 | namespace PingCastle 5 | { 6 | [Serializable] 7 | public class PingCastleException : Exception 8 | { 9 | public PingCastleException() 10 | { 11 | } 12 | 13 | public PingCastleException(string message) 14 | : base(message) 15 | { 16 | } 17 | 18 | public PingCastleException(string message, Exception innerException) 19 | : base(message, innerException) 20 | { 21 | } 22 | 23 | protected PingCastleException(SerializationInfo info, StreamingContext context) 24 | : base(info, context) 25 | { 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /PingCastleLicense/ADHealthCheckingLicenseProvider.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Ping Castle. All rights reserved. 3 | // https://www.pingcastle.com 4 | // 5 | // Licensed under the Non-Profit OSL. See LICENSE file in the project root for full license information. 6 | // 7 | using System; 8 | using System.ComponentModel; 9 | 10 | namespace PingCastle 11 | { 12 | 13 | public interface IPingCastleLicenseInfo 14 | { 15 | string GetSerialNumber(); 16 | } 17 | 18 | public class ADHealthCheckingLicenseProvider : LicenseProvider 19 | { 20 | 21 | #region Public Methods 22 | 23 | /// 24 | /// Gets a license for an instance or type of component. 25 | /// 26 | /// A that specifies where you can use the licensed object. 27 | /// A that represents the component requesting the license. 28 | /// An object that is requesting the license. 29 | /// true if a should be thrown when the component cannot be granted a license; otherwise, false. 30 | /// A valid . 31 | public override License GetLicense(LicenseContext context, Type type, object instance, bool allowExceptions) 32 | { 33 | IPingCastleLicenseInfo licenseInfo = (IPingCastleLicenseInfo)instance; 34 | return new ADHealthCheckingLicense(licenseInfo.GetSerialNumber()); 35 | } 36 | #endregion 37 | 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /PingCastleLicense/ADHealthCheckingLicenseSettings.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Ping Castle. All rights reserved. 3 | // https://www.pingcastle.com 4 | // 5 | // Licensed under the Non-Profit OSL. See LICENSE file in the project root for full license information. 6 | // 7 | using System.Configuration; 8 | 9 | namespace PingCastle 10 | { 11 | internal class ADHealthCheckingLicenseSettings : ConfigurationSection 12 | { 13 | private static ADHealthCheckingLicenseSettings settings; 14 | 15 | public static ADHealthCheckingLicenseSettings Settings 16 | { 17 | get 18 | { 19 | if (settings == null) 20 | settings = ConfigurationManager.GetSection("LicenseSettings") as ADHealthCheckingLicenseSettings; 21 | return settings; 22 | } 23 | } 24 | 25 | [ConfigurationProperty("license", IsRequired = false)] 26 | public string License 27 | { 28 | get { return (string)this["license"]; } 29 | set { this["license"] = value; } 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /PingCastleLicense/LicenseCache.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace PingCastle.PingCastleLicense 4 | { 5 | public class LicenseCache 6 | { 7 | private ADHealthCheckingLicense _license; 8 | private static LicenseCache _instance; 9 | 10 | private LicenseCache() { } 11 | 12 | public static LicenseCache Instance 13 | { 14 | get 15 | { 16 | if (_instance == null) 17 | { 18 | _instance = new LicenseCache(); 19 | } 20 | return _instance; 21 | } 22 | } 23 | 24 | public ADHealthCheckingLicense GetLicense() 25 | { 26 | return _license; 27 | } 28 | 29 | public void StoreLicense(ADHealthCheckingLicense license) 30 | { 31 | if (license == null) 32 | { 33 | throw new ArgumentException("License cannot be null."); 34 | } 35 | 36 | _license = license; 37 | } 38 | } 39 | 40 | } 41 | -------------------------------------------------------------------------------- /Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.InteropServices; 3 | 4 | // Les informations générales relatives à un assembly dépendent de 5 | // l'ensemble d'attributs suivant. Changez les valeurs de ces attributs pour modifier les informations 6 | // associées à un assembly. 7 | [assembly: AssemblyTitle("PingCastle")] 8 | [assembly: AssemblyDescription("")] 9 | [assembly: AssemblyConfiguration("")] 10 | [assembly: AssemblyCompany("Netwrix Corporation")] 11 | [assembly: AssemblyProduct("PingCastle")] 12 | [assembly: AssemblyCopyright("Copyright © Netwrix Corporation")] 13 | [assembly: AssemblyTrademark("")] 14 | [assembly: AssemblyCulture("")] 15 | 16 | // L'affectation de la valeur false à ComVisible rend les types invisibles dans cet assembly 17 | // aux composants COM. Si vous devez accéder à un type dans cet assembly à partir de 18 | // COM, affectez la valeur true à l'attribut ComVisible sur ce type. 19 | [assembly: ComVisible(false)] 20 | 21 | // Le GUID suivant est pour l'ID de la typelib si ce projet est exposé à COM 22 | [assembly: Guid("ce59f8ff-0ecf-41e9-a1fd-1776ca0b703d")] 23 | 24 | // Les informations de version pour un assembly se composent des quatre valeurs suivantes : 25 | // 26 | // Version principale 27 | // Version secondaire 28 | // Numéro de build 29 | // Révision 30 | // 31 | [assembly: AssemblyVersion("3.3.0.12")] 32 | [assembly: AssemblyFileVersion("3.3.0.12")] 33 | -------------------------------------------------------------------------------- /Report/IActionPlan.cs: -------------------------------------------------------------------------------- 1 | using PingCastle.Cloud.Data; 2 | using PingCastle.Healthcheck; 3 | using PingCastle.Rules; 4 | using System; 5 | using System.Collections.Generic; 6 | using System.Text; 7 | 8 | namespace PingCastle.Report 9 | { 10 | public interface IActionPlan 11 | { 12 | void GenerateMainActionPlan(StringBuilder sb, Healthcheck.HealthcheckRiskRule rule, Rules.RuleBase hcrule); 13 | 14 | void GenerateDetailledActionPlan(StringBuilder sb, HealthcheckRiskRule rule, Rules.RuleBase hcrule, string d); 15 | } 16 | 17 | public interface IAADActionPlan 18 | { 19 | void GenerateMainActionPlan(StringBuilder sb, HealthCheckCloudDataRiskRule rule, RuleBase hcrule); 20 | void GenerateDetailledActionPlan(StringBuilder sb, HealthCheckCloudDataRiskRule rule, RuleBase hcrule, string d); 21 | 22 | } 23 | 24 | 25 | public interface IActionPlanConsolidation : IActionPlan 26 | { 27 | void LoadDomain(HealthcheckData data); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /Report/IPingCastleReportUser.cs: -------------------------------------------------------------------------------- 1 | using PingCastle.Cloud.Data; 2 | using PingCastle.Data; 3 | 4 | namespace PingCastle.Report 5 | { 6 | public delegate string GetUrlDelegateDomain(DomainKey domainKey, string displayName, string optionalRiskId); 7 | public delegate string GetUrlDelegateAzureAD(AzureADKey domainKey, string displayName, string optionalRiskId); 8 | public delegate string GetAdditionInfoDelegate(DomainKey domainKey); 9 | public delegate string AddHtmlToTabSection(string section); 10 | 11 | public interface IPingCastleReportUser where T : IPingCastleReport 12 | { 13 | string GenerateReportFile(T report, ADHealthCheckingLicense license, string filename); 14 | string GenerateRawContent(T report); 15 | void SetUrlDisplayDelegate(GetUrlDelegateDomain uRLDelegate); 16 | void SetUrlDisplayDelegate(GetUrlDelegateAzureAD uRLDelegate); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /Report/ReportCloudCompared.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Vincent LE TOUX for Ping Castle. All rights reserved. 3 | // https://www.pingcastle.com 4 | // 5 | // Licensed under the Non-Profit OSL. See LICENSE file in the project root for full license information. 6 | // 7 | using Newtonsoft.Json; 8 | using PingCastle.Rules; 9 | using PingCastle.template; 10 | using PingCastle.Cloud.Data; 11 | using PingCastle.Cloud.Rules; 12 | using System; 13 | using System.Collections.Generic; 14 | using System.Linq; 15 | using System.Net.Mail; 16 | using PingCastle.Healthcheck; 17 | 18 | namespace PingCastle.Report 19 | { 20 | public class ReportCloudCompared : ReportCloud 21 | { 22 | HealthCheckCloudData[] Reports; 23 | 24 | public string GenerateRawContent(HealthCheckCloudData[] reports, ADHealthCheckingLicense aDHealthCheckingLicense) 25 | { 26 | _license = aDHealthCheckingLicense; 27 | Reports = reports; 28 | //reports[0].InitializeReportingData(); 29 | //reports[1].InitializeReportingData(); 30 | Report = Reports[0]; 31 | sb.Length = 0; 32 | GenerateContent(); 33 | return sb.ToString(); 34 | } 35 | 36 | protected override void GenerateSection(string title, GenerateContentDelegate generateContent) 37 | { 38 | Report = Reports[0]; 39 | base.GenerateSection(title + " - " + Report.GenerationDate.ToString("u"), generateContent); 40 | Report = Reports[1]; 41 | base.GenerateSection(title + " - " + Report.GenerationDate.ToString("u"), generateContent); 42 | } 43 | } 44 | } 45 | 46 | -------------------------------------------------------------------------------- /Report/ReportHealthCheckSingleCompared.cs: -------------------------------------------------------------------------------- 1 | using PingCastle.Healthcheck; 2 | 3 | namespace PingCastle.Report 4 | { 5 | public class ReportHealthCheckSingleCompared : ReportHealthCheckSingle 6 | { 7 | HealthcheckData[] Reports; 8 | 9 | public string GenerateRawContent(HealthcheckData[] reports, ADHealthCheckingLicense aDHealthCheckingLicense) 10 | { 11 | _license = aDHealthCheckingLicense; 12 | Reports = reports; 13 | reports[0].InitializeReportingData(); 14 | reports[1].InitializeReportingData(); 15 | Report = Reports[0]; 16 | sb.Length = 0; 17 | GenerateContent(); 18 | return sb.ToString(); 19 | } 20 | 21 | protected override void GenerateSection(string title, GenerateContentDelegate generateContent) 22 | { 23 | Report = Reports[0]; 24 | base.GenerateSection(title + " - " + Report.GenerationDate.ToString("u"), generateContent); 25 | Report = Reports[1]; 26 | base.GenerateSection(title + " - " + Report.GenerationDate.ToString("u"), generateContent); 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /Rules/IRiskEvaluation.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Ping Castle. All rights reserved. 3 | // https://www.pingcastle.com 4 | // 5 | // Licensed under the Non-Profit OSL. See LICENSE file in the project root for full license information. 6 | // 7 | using System.Collections.Generic; 8 | 9 | namespace PingCastle.Rules 10 | { 11 | public interface IRiskEvaluation 12 | { 13 | int GlobalScore { get; set; } 14 | int StaleObjectsScore { get; set; } 15 | int PrivilegiedGroupScore { get; set; } 16 | int TrustScore { get; set; } 17 | int AnomalyScore { get; set; } 18 | int MaturityLevel { get; set; } 19 | IList AllRiskRules { get; } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /Rules/IRuleScore.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Ping Castle. All rights reserved. 3 | // https://www.pingcastle.com 4 | // 5 | // Licensed under the Non-Profit OSL. See LICENSE file in the project root for full license information. 6 | // 7 | 8 | namespace PingCastle.Rules 9 | { 10 | public interface IRuleScore 11 | { 12 | RiskRuleCategory Category { get; } 13 | RiskModelCategory Model { get; } 14 | string RiskId { get; } 15 | int Points { get; } 16 | 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /Rules/RiskRuleCategory.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Ping Castle. All rights reserved. 3 | // https://www.pingcastle.com 4 | // 5 | // Licensed under the Non-Profit OSL. See LICENSE file in the project root for full license information. 6 | // 7 | using System.ComponentModel; 8 | 9 | namespace PingCastle.Rules 10 | { 11 | public enum RiskRuleCategory 12 | { 13 | Unknown, 14 | [Description("Stale Objects")] 15 | StaleObjects, 16 | [Description("Privileged Accounts")] 17 | PrivilegedAccounts, 18 | Trusts, 19 | Anomalies, 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /Scanners/ComputerVersion.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Ping Castle. All rights reserved. 3 | // https://www.pingcastle.com 4 | // 5 | // Licensed under the Non-Profit OSL. See LICENSE file in the project root for full license information. 6 | // 7 | using PingCastle.ADWS; 8 | using PingCastle.misc; 9 | using System; 10 | using System.Collections.Generic; 11 | using System.Diagnostics; 12 | using System.IO; 13 | using System.Net; 14 | using System.Net.Sockets; 15 | using System.Security.Principal; 16 | using System.Text; 17 | using System.Threading; 18 | 19 | namespace PingCastle.Scanners 20 | { 21 | public class ComputerVersion : ScannerBase 22 | { 23 | public override string Name { get { return "computerversion"; } } 24 | 25 | public override string Description { get { return "Get the version of a computer. Can be used to determine if obsolete operating systems are still present."; } } 26 | 27 | override protected string GetCsvHeader() 28 | { 29 | return "Computer\tVersion"; 30 | } 31 | 32 | override protected string GetCsvData(string computer) 33 | { 34 | string version = NativeMethods.GetComputerVersion(computer); 35 | if (version != "not found") 36 | { 37 | return computer + "\t" + version; 38 | } 39 | return null; 40 | } 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /Scanners/IScanner.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Ping Castle. All rights reserved. 3 | // https://www.pingcastle.com 4 | // 5 | // Licensed under the Non-Profit OSL. See LICENSE file in the project root for full license information. 6 | // 7 | using System.Net; 8 | 9 | namespace PingCastle.Scanners 10 | { 11 | public interface IScanner 12 | { 13 | void Initialize(RuntimeSettings settings); 14 | void Export(string filename); 15 | string Name { get; } 16 | string Description { get; } 17 | 18 | // return false if the user query has been cancelled 19 | DisplayState QueryForAdditionalParameterInInteractiveMode(); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /Scanners/localAdminsScanner.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Ping Castle. All rights reserved. 3 | // https://www.pingcastle.com 4 | // 5 | // Licensed under the Non-Profit OSL. See LICENSE file in the project root for full license information. 6 | // 7 | using System; 8 | using System.Collections.Generic; 9 | using System.Security.Principal; 10 | 11 | namespace PingCastle.Scanners 12 | { 13 | public class localAdminsScanner : ScannerBase 14 | { 15 | 16 | public override string Name { get { return "localadmin"; } } 17 | public override string Description { get { return "Enumerate the local administrators of a computer."; } } 18 | 19 | override protected string GetCsvHeader() 20 | { 21 | return "Computer\tSID\tAccount"; 22 | } 23 | 24 | override protected string GetCsvData(string computer) 25 | { 26 | string output = null; 27 | List users = localAdminsEnumerator.Export(computer); 28 | 29 | foreach (SecurityIdentifier user in users) 30 | { 31 | string account = ConvertSIDToName(user.Value, computer); 32 | if (!String.IsNullOrEmpty(output)) 33 | output += "\r\n"; 34 | output += computer + "\t" + user.Value + "\t" + account; 35 | } 36 | return output; 37 | } 38 | 39 | static string ConvertSIDToName(string sidstring, string server) 40 | { 41 | string referencedDomain = null; 42 | return NativeMethods.ConvertSIDToNameWithWindowsAPI(sidstring, server, out referencedDomain); 43 | } 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /Scanners/startupScanner.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Ping Castle. All rights reserved. 3 | // https://www.pingcastle.com 4 | // 5 | // Licensed under the Non-Profit OSL. See LICENSE file in the project root for full license information. 6 | // 7 | using System; 8 | 9 | namespace PingCastle.Scanners 10 | { 11 | public class startupScanner : ScannerBase 12 | { 13 | 14 | public override string Name { get { return "startup"; } } 15 | public override string Description { get { return "Get the last startup date of a computer. Can be used to determine if latest patches have been applied."; } } 16 | 17 | override protected string GetCsvHeader() 18 | { 19 | return "Computer\tStartup"; 20 | } 21 | 22 | override protected string GetCsvData(string computer) 23 | { 24 | DateTime startup = NativeMethods.GetStartupTime(computer); 25 | if (startup != DateTime.MinValue) 26 | { 27 | return computer + "\t" + startup.ToString("yyyy-MM-dd HH:mm:ss"); 28 | } 29 | return null; 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /changelog.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/netwrix/pingcastle/548de82eb0d9631e7a244deffaaf63cfcd4fb460/changelog.txt -------------------------------------------------------------------------------- /misc/BlockingQueue.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Ping Castle. All rights reserved. 3 | // https://www.pingcastle.com 4 | // 5 | // Licensed under the Non-Profit OSL. See LICENSE file in the project root for full license information. 6 | // 7 | using System.Collections.Generic; 8 | using System.Threading; 9 | 10 | namespace PingCastle.misc 11 | { 12 | public class BlockingQueue 13 | { 14 | readonly int _Size = 0; 15 | readonly Queue _Queue = new Queue(); 16 | readonly object _Key = new object(); 17 | bool _Quit = false; 18 | 19 | public BlockingQueue(int size) 20 | { 21 | _Size = size; 22 | } 23 | 24 | public void Quit() 25 | { 26 | lock (_Key) 27 | { 28 | _Quit = true; 29 | Monitor.PulseAll(_Key); 30 | } 31 | } 32 | 33 | public bool Enqueue(T t) 34 | { 35 | lock (_Key) 36 | { 37 | while (!_Quit && _Queue.Count >= _Size) Monitor.Wait(_Key); 38 | if (_Quit) return false; 39 | _Queue.Enqueue(t); 40 | Monitor.PulseAll(_Key); 41 | } 42 | return true; 43 | } 44 | 45 | public bool Dequeue(out T t) 46 | { 47 | t = default(T); 48 | lock (_Key) 49 | { 50 | while (!_Quit && _Queue.Count == 0) Monitor.Wait(_Key); 51 | if (_Queue.Count == 0) return false; 52 | t = _Queue.Dequeue(); 53 | Monitor.PulseAll(_Key); 54 | } 55 | return true; 56 | } 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /misc/Extensions.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Threading.Tasks; 4 | 5 | namespace PingCastle.misc 6 | { 7 | public static class Extensions 8 | { 9 | public static async Task> ToDictionaryAsync(this IAsyncEnumerable collection, Func key) 10 | { 11 | var dictionary = new Dictionary(); 12 | 13 | await foreach (var item in collection) 14 | { 15 | dictionary[key(item)] = item; 16 | } 17 | 18 | return dictionary; 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /pingcastle.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/netwrix/pingcastle/548de82eb0d9631e7a244deffaaf63cfcd4fb460/pingcastle.ico -------------------------------------------------------------------------------- /template/.gitignore: -------------------------------------------------------------------------------- 1 | *.min.css 2 | *.min.js 3 | *.gz 4 | -------------------------------------------------------------------------------- /template/ReportHealthCheckRules.css: -------------------------------------------------------------------------------- 1 | .model_table { 2 | 3 | } 4 | .model_table th { 5 | padding: 5px; 6 | } 7 | .model_cell { 8 | border: 2px solid black; 9 | padding: 5px; 10 | } 11 | .model_empty_cell { 12 | } 13 | div_model { 14 | 15 | } 16 | .model_cell.model_good { 17 | 18 | } 19 | .model_cell.model_toimprove 20 | { 21 | background-color: #ffd800; 22 | } 23 | .model_cell.model_info { 24 | background-color: #00AAFF; 25 | color: #FFFFFF; 26 | } 27 | .model_cell.model_warning { 28 | background-color: #ff6a00; 29 | color: #FFFFFF; 30 | } 31 | .model_cell.model_danger { 32 | background-color: #f12828; 33 | color: #FFFFFF; 34 | } 35 | .model_cell .popover{ 36 | max-width: 100%; 37 | } 38 | .model_cell .popover-content { 39 | color: #000000; 40 | } 41 | .model_cell .popover-title { 42 | color: #000000; 43 | } 44 | -------------------------------------------------------------------------------- /template/ReportMapBuilder.css: -------------------------------------------------------------------------------- 1 | .legend_carto 2 | { 3 | position: absolute; 4 | top: 65px; 5 | left: 0px; 6 | } 7 | .legend_criticalscore { 8 | background: #A856AA; 9 | border: #19231a; 10 | border-style: solid; 11 | border-width: 1px; 12 | padding: 5px; 13 | } 14 | .legend_superhighscore { 15 | background: #E75351; 16 | border: #19231a; 17 | border-style: solid; 18 | border-width: 1px; 19 | padding: 5px; 20 | } 21 | .legend_highscore { 22 | background: #FA9426; 23 | border: #19231a; 24 | border-style: solid; 25 | border-width: 1px; 26 | padding: 5px; 27 | } 28 | .legend_mediumscore { 29 | background: #FDC334; 30 | border: #19231a; 31 | border-style: solid; 32 | border-width: 1px; 33 | padding: 5px; 34 | } 35 | 36 | .legend_lowscore { 37 | background: #74C25C; 38 | border: #19231a; 39 | border-style: solid; 40 | border-width: 1px; 41 | padding: 5px; 42 | } 43 | .legend_unknown { 44 | background: #ffffff; 45 | border: #a352cc; 46 | border-style: solid; 47 | border-width: 1px; 48 | padding: 5px; 49 | } 50 | .network-area 51 | { 52 | height: 100%; 53 | min-height: 100%; 54 | border-width:1px; 55 | } 56 | -------------------------------------------------------------------------------- /template/ReportNetworkMap.css: -------------------------------------------------------------------------------- 1 | .map_view_tooltip { 2 | position: absolute !important; 3 | } 4 | .map_view_tooltip { 5 | pointer-events: none; 6 | } 7 | -------------------------------------------------------------------------------- /template/ReportRiskControls.css: -------------------------------------------------------------------------------- 1 | .model_table { 2 | } 3 | 4 | .model_table th { 5 | padding: 5px; 6 | } 7 | 8 | .model_cell { 9 | border: 2px solid black; 10 | padding: 5px; 11 | } 12 | 13 | .model_empty_cell { 14 | } 15 | 16 | div_model { 17 | } 18 | 19 | .model_cell.model_toimprove { 20 | background-color: #ffd800; 21 | cursor: pointer; 22 | } 23 | 24 | .model_cell.model_info { 25 | background-color: #00AAFF; 26 | color: #FFFFFF; 27 | cursor: pointer; 28 | } 29 | 30 | .model_cell.model_warning { 31 | background-color: #ff6a00; 32 | color: #FFFFFF; 33 | cursor: pointer; 34 | } 35 | 36 | .model_cell.model_danger { 37 | background-color: #f12828; 38 | color: #FFFFFF; 39 | cursor: pointer; 40 | } 41 | 42 | .model_cell .popover { 43 | max-width: 100%; 44 | } 45 | 46 | .model_cell .popover-content { 47 | color: #000000; 48 | } 49 | 50 | .model_cell .popover-title { 51 | color: #000000; 52 | } 53 | 54 | /* gauge */ 55 | .arc { 56 | } 57 | 58 | .chart-first { 59 | fill: #83e043; 60 | } 61 | 62 | .chart-second { 63 | fill: #ffd800; 64 | } 65 | 66 | .chart-third { 67 | fill: #ff6a00; 68 | } 69 | 70 | .chart-quart { 71 | fill: #f12828; 72 | } 73 | 74 | .needle, .needle-center { 75 | fill: #000000; 76 | } 77 | 78 | .text { 79 | color: #112864; 80 | } 81 | 82 | svg { 83 | font: 10px sans-serif; 84 | } 85 | 86 | .indicators-border { 87 | border: 2px solid #Fa9C1A; 88 | margin: 2px; 89 | padding: 2px; 90 | } 91 | -------------------------------------------------------------------------------- /template/bootstrap-table-export.min.js.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/netwrix/pingcastle/548de82eb0d9631e7a244deffaaf63cfcd4fb460/template/bootstrap-table-export.min.js.gz -------------------------------------------------------------------------------- /template/bootstrap-table.min.css.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/netwrix/pingcastle/548de82eb0d9631e7a244deffaaf63cfcd4fb460/template/bootstrap-table.min.css.gz -------------------------------------------------------------------------------- /template/bootstrap-table.min.js.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/netwrix/pingcastle/548de82eb0d9631e7a244deffaaf63cfcd4fb460/template/bootstrap-table.min.js.gz -------------------------------------------------------------------------------- /template/bootstrap.min.css.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/netwrix/pingcastle/548de82eb0d9631e7a244deffaaf63cfcd4fb460/template/bootstrap.min.css.gz -------------------------------------------------------------------------------- /template/bootstrap.min.js.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/netwrix/pingcastle/548de82eb0d9631e7a244deffaaf63cfcd4fb460/template/bootstrap.min.js.gz -------------------------------------------------------------------------------- /template/dashboardtest.html.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/netwrix/pingcastle/548de82eb0d9631e7a244deffaaf63cfcd4fb460/template/dashboardtest.html.gz -------------------------------------------------------------------------------- /template/jquery.min.js.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/netwrix/pingcastle/548de82eb0d9631e7a244deffaaf63cfcd4fb460/template/jquery.min.js.gz -------------------------------------------------------------------------------- /template/popper.min.js.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/netwrix/pingcastle/548de82eb0d9631e7a244deffaaf63cfcd4fb460/template/popper.min.js.gz -------------------------------------------------------------------------------- /template/responsivetemplate.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | <%=Header%> 12 | 13 | 14 | 15 | 16 | <%=Body%> 17 | 18 | <%=Footer%> 19 | 20 | 21 | -------------------------------------------------------------------------------- /template/tableExport.min.js.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/netwrix/pingcastle/548de82eb0d9631e7a244deffaaf63cfcd4fb460/template/tableExport.min.js.gz -------------------------------------------------------------------------------- /template/vis.min.css.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/netwrix/pingcastle/548de82eb0d9631e7a244deffaaf63cfcd4fb460/template/vis.min.css.gz -------------------------------------------------------------------------------- /template/vis.min.js.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/netwrix/pingcastle/548de82eb0d9631e7a244deffaaf63cfcd4fb460/template/vis.min.js.gz -------------------------------------------------------------------------------- /testLDAPqueries.ps1: -------------------------------------------------------------------------------- 1 | Clear-Host 2 | $RootDSE = [System.DirectoryServices.DirectoryEntry]([ADSI]"LDAP://RootDSE") 3 | $NC = $RootDSE.Get("defaultNamingContext") 4 | 5 | $dn = New-Object System.DirectoryServices.DirectoryEntry ("LDAP://CN=Users," + $NC) 6 | 7 | $Rech = new-object System.DirectoryServices.DirectorySearcher($dn) 8 | $Rech.filter = "(description=DNS Administrators Group)" 9 | $Rech.SearchScope = "onelevel" 10 | #$a=$Rech.PropertiesToLoad.Add("distinguishedName"); 11 | #$a=$Rech.PropertiesToLoad.Add("name"); 12 | #$a=$Rech.PropertiesToLoad.Add("nTSecurityDescriptor"); 13 | $Rech.PageSize = 500; 14 | 15 | $colResults = $Rech.FindAll() 16 | 17 | foreach ($objResult in $colResults) 18 | { 19 | $objItem = $objResult.Properties; 20 | Write-host $objItem.distinguishedname; 21 | } --------------------------------------------------------------------------------