<# .SYNOPSIS This script performs an Active Directory Audit to gather key data about users, computers, and security policies. .DESCRIPTION This Script is designed to collect various pieces of information from an Active Directory environment, including the status and count of user accounts, computer accounts, security policies, and other key details. The collected data is then exported to an Excel file for analysis. .PARAMETER Path The output path for the Excel report. If not provided, the script will default to "C:\ADAudit". .EXAMPLE .NOTES It is recommended to run this script with an account that has sufficient permissions in the Active Directory to gather all necessary data. #> # Import required modules Import-Module ActiveDirectory # ---------------------------------------------------------------------------------------------------- # # Welcome message Write-Host @" -------------------------------------------------------------- Welcome to Secure Guard Consulting Auditing Tool -------------------------------------------------------------- "@ # Disclaimer Write-Host -ForegroundColor Yellow @" -------------------------------------------------------------- DISCLAIMER -------------------------------------------------------------- This script is designed to perform an audit of your Active Directory system. It will ONLY collect data and generate reports based on the specified categories. Please ensure that you have the necessary permissions to run this script. By continuing with the execution of this script, you acknowledge that Secure Guard Consulting and its representatives are not responsible for any issues or damages that may arise from the use of this script. Press Enter to continue or Ctrl+C to exit. "@ # Prompt the user to continue $null = Read-Host # ---------------------------------------------------------------------------------------------------- # # Compatibility check if (!(Get-Module -ListAvailable -Name "ActiveDirectory")) { Write-Host "The ActiveDirectory PowerShell module is not available. Install before proceeding." -ForegroundColor Red Exit } # ---------------------------------------------------------------------------------------------------- # # Get Export location # Default path $defaultPath = "C:\ADAudit" # Check if the default path is accessible if (!(Test-Path -Path $defaultPath -PathType Container -ErrorAction SilentlyContinue)) { Write-Host "Default path $defaultPath is not accessible." $defaultPathAccessible = $false } else { $defaultPathAccessible = $true } # Ask the user if they want to select a path $readHostParams = @{ 'Prompt' = 'Do you want to enter a custom path? If yes, please provide the path, otherwise hit Enter for default path. If choosing the default path, ensure a folder is created on the C: drive called ADAudit' 'AsSecureString' = $false } $Path = Read-Host @readHostParams # If the user doesn't enter a path, use the default path if ([string]::IsNullOrWhiteSpace($Path)) { if ($defaultPathAccessible) { $Path = $defaultPath } else { Write-Host "Default path $defaultPath is not accessible. Please enter a path manually." $Path = Read-Host @readHostParams } } # If the entered path is invalid while (!(Test-Path -Path $Path -PathType Container -ErrorAction SilentlyContinue)) { Write-Host "Invalid path. Please manually enter a valid path." $Path = Read-Host @readHostParams } if (!(Test-Path -Path $Path)) { Write-Host "Creating folder at $Path" New-Item -ItemType Directory -Force -Path $Path } # ---------------------------------------------------------------------------------------------------- # # Initialize progress bar variables $totalSteps = 4 $currentStep = 0 # Collect All User Data Write-Progress -Activity "Collecting data..." -PercentComplete (($currentStep / $totalSteps) * 100) $Users = Get-ADUser -Filter 'Enabled -eq $true' -Properties * $currentStep++ # ---------------------------------------------------------------------------------------------------- # # Policy Info Function Get-PolicyInfo { # Get tombstone policy $ADRootDSE = Get-ADRootDSE $ADConfigurationNamingContext = $ADRootDSE.configurationNamingContext $TombstoneLifetime = (Get-ADObject -Identity "CN=Directory Service,CN=Windows NT,CN=Services,$ADConfigurationNamingContext" ` -Partition "$ADConfigurationNamingContext" -Properties *).tombstoneLifetime $TombstonePolicy = $TombstoneLifetime # Get Kerberos account and last password set date $KerberosAccount = Get-ADUser -Identity 'KRBTGT' -Properties PasswordLastSet, Enabled $krbtgtPasswordLastSet = $KerberosAccount.PasswordLastSet $krbtgtAccountEnabled = $KerberosAccount.Enabled # Get default policy $DefaultPolicy = Get-ADDefaultDomainPasswordPolicy $DefaultPolicyInfo = "MaxPasswordAge: $($DefaultPolicy.MaxPasswordAge.Days), MinPasswordLength: $($DefaultPolicy.MinPasswordLength)" # Get default password policy $PasswordPolicy = Get-ADDefaultDomainPasswordPolicy $PasswordLength = $PasswordPolicy.MinPasswordLength $PasswordExpiration = $PasswordPolicy.MaxPasswordAge.Days $PasswordHistory = $PasswordPolicy.PasswordHistoryCount $PasswordComplexity = $PasswordPolicy.ComplexityEnabled # Get account lockout policy from the same command $LockoutThreshold = $PasswordPolicy.LockoutThreshold $LockoutDuration = $PasswordPolicy.LockoutDuration.TotalMinutes $LockoutWindow = $PasswordPolicy.LockoutObservationWindow.TotalMinutes # Combine all information $PolicyInfo = [ordered]@{ 'Tombstone Policy number of days' = $TombstonePolicy 'krbtgt Account Enabled' = $krbtgtAccountEnabled 'krbtgt Account Last Password Set' = $krbtgtPasswordLastSet 'Default Password Policy' = $DefaultPolicyInfo 'Password Length' = $PasswordLength 'Password Expiration (Days)' = $PasswordExpiration 'Password History Count' = $PasswordHistory 'Password Complexity Enabled' = $PasswordComplexity 'Account Lockout Threshold' = $LockoutThreshold 'Lockout Duration (Minutes)' = $LockoutDuration 'Lockout Observation Window (Minutes)' = $LockoutWindow } # Sort it alphabetically $PolicyInfo = $PolicyInfo.GetEnumerator() | Sort-Object Name return $PolicyInfo } # Enabled Accounts function Get-EnabledAccounts { param ( [Parameter(Mandatory=$true)] [array]$Users ) return $Users | Select-Object SamAccountName, Description, Enabled, whenCreated, PasswordNeverExpires, PasswordLastset } # Disabled Accounts function Get-DisabledAccounts { Get-ADUser -Filter 'Enabled -eq $false' -Properties whenCreated, Description | Select-Object SamAccountName, Description, Enabled, whenCreated } # Dormant accounts function Get-DormantAccounts { param ( [Parameter(Mandatory=$true)] [array]$Users ) # Define the dates for the intervals $date365 = (Get-Date).AddDays(-365) $date90 = (Get-Date).AddDays(-90) $date45 = (Get-Date).AddDays(-45) # Create custom PSObjects for each category $dormant365 = $Users | Where-Object { $_.LastLogonDate -le $date365 } | Select-Object SamAccountName, LastLogonDate, Description, whenCreated | Add-Member -MemberType NoteProperty -Name "Dormant Category" -Value "365 days Plus" -PassThru $dormant90 = $Users | Where-Object { $_.LastLogonDate -le $date90 -and $_.LastLogonDate -gt $date365 } | Select-Object SamAccountName, LastLogonDate, Description, whenCreated | Add-Member -MemberType NoteProperty -Name "Dormant Category" -Value "90 to 365 days" -PassThru $dormant45 = $Users | Where-Object { $_.LastLogonDate -le $date45 -and $_.LastLogonDate -gt $date90 } | Select-Object SamAccountName, LastLogonDate, Description, whenCreated | Add-Member -MemberType NoteProperty -Name "Dormant Category" -Value "45 to 90 days" -PassThru $neverLoggedOn = $Users | Where-Object { $null -eq $_.LastLogonDate } | Select-Object SamAccountName, LastLogonDate, Description, whenCreated | Add-Member -MemberType NoteProperty -Name "Dormant Category" -Value "Never logged on" -PassThru # Return all objects return @{ '365 days' = $dormant365 '90 days' = $dormant90 '45 days' = $dormant45 'Never logged on' = $neverLoggedOn } } # Password Never Expires function Get-AccountsWithPasswordNeverExpires { param ( [Parameter(Mandatory=$true)] [array]$Users ) return $Users | Where-Object { $_.PasswordNeverExpires -eq $true -and $_.Enabled -eq $true } | Select-Object SamAccountName, Description, PasswordNeverExpires, Passwordlastset } # Password Not Required function Get-AccountsWithPasswordNotRequired { param ( [Parameter(Mandatory=$true)] [array]$Users ) return $Users | Where-Object PasswordNotRequired -EQ $true | Select-Object SamAccountName, Description, PasswordNotRequired, PasswordlastSet } # Account with SID History function Get-AccountsWithSIDHistory { param ( [Parameter(Mandatory=$true)] [array]$Users ) return $Users | Where-Object SIDHistory -like "*" | Select-Object SamAccountName, SIDHistory } # Reversible Encryption Detected function Get-AccountsWithReversibleEncryption { param ( [Parameter(Mandatory=$true)] [array]$Users ) return $Users | Where-Object { $_.UserAccountControl -band 128 } | Select-Object SamAccountName, UserAccountControl } # DES Encryption function Get-AccountsWithDESEncryption { param ( [Parameter(Mandatory=$true)] [array]$Users ) return $Users | Where-Object { $_.UserAccountControl -band 32 } | Select-Object SamAccountName, UserAccountControl } # Kerberos Pre Auth function Get-AccountsWithoutKerberosPreAuth { param ( [Parameter(Mandatory=$true)] [array]$Users ) return $Users | Where-Object { $_.UserAccountControl -band 4194304 } | Select-Object SamAccountName, UserAccountControl } # Privileged Users function Get-PrivilegedUsers { param ( [Parameter(Mandatory=$true)] [array]$Users ) # Define the privileged groups $privilegedGroups = @( 'Administrators', 'Domain Admins', 'Enterprise Admins', 'Schema Admins', 'Account Operators', 'Server Operators', 'Group Policy Creator Owners', 'DNSAdmins', 'Enterprise Admins' 'Enterprise Key Admins', 'Exchange Domain Servers', 'Exchange Enterprise Servers', 'Exchange Admins', 'Organization Management', 'Exchange Windows Permissions' ) # Process each user foreach($User in $Users) { # Get group memberships $memberOf = $User.MemberOf | ForEach-Object { (Get-ADGroup $_).Name } # Find privileged group memberships $privilegedMemberships = $memberOf | Where-Object { $_ -in $privilegedGroups } if ($privilegedMemberships) { # Create custom object for output $output = New-Object PSObject $output | Add-Member -MemberType NoteProperty -Name "SamAccountName" -Value $User.SamAccountName $output | Add-Member -MemberType NoteProperty -Name "PrivilegedGroupMemberships" -Value ($privilegedMemberships -join ', ') $output } } } # All Computer Objects function Get-ADComputerDetails { Get-ADComputer -Filter * -Properties * | Select-Object Name, Description, Created, Enabled } # All Server Objects function Get-ADServerDetails { Get-ADComputer -Filter 'Name -like "Server*"' -Properties * | Select-Object Name, Description, Created, Enabled } # All Domain Controllers function Get-ADDomainControllerDetails { Get-ADDomainController -Filter * | Select-Object Name, HostName, Domain, Forest, Site, OperatingSystem } $currentStep++ Write-Progress -Activity "Grouping Data..." -PercentComplete (($currentStep / $totalSteps) * 100) # ---------------------------------------------------------------------------------------------------- # # Call each function and store the output in separate variables $PolicyInfo = Get-PolicyInfo $EnabledAccounts = Get-EnabledAccounts -Users $Users $DisabledAccounts = Get-DisabledAccounts -Users $Users $DormantAccounts = Get-DormantAccounts -Users $Users $AccountwithPasswordNeverExpires = Get-AccountsWithPasswordNeverExpires -Users $Users $AccountwithPasswordNotRequired = Get-AccountsWithPasswordNotRequired -Users $Users $AccountwithSIDHistory = Get-AccountsWithSIDHistory -Users $Users $AccountwithReversibleEncryption = Get-AccountsWithReversibleEncryption -Users $Users $AccountwithDESEncryption = Get-AccountsWithDESEncryption -Users $Users $AccountsWithoutKerberosPreAuth = Get-AccountsWithoutKerberosPreAuth -Users $Users $PrivilegedUsers = Get-PrivilegedUsers -Users $Users $ADComputerDetails = Get-ADComputerDetails $ADServerDetails = Get-ADServerDetails $ADDomainControllerDetails = Get-ADDomainControllerDetails $currentStep++ Write-Progress -Activity "Customizing Variables..." -PercentComplete (($currentStep / $totalSteps) * 100) # ---------------------------------------------------------------------------------------------------- # #Custom variables to manually transpose data # Main Page Variable $resultCounts = @( $allUsers = Get-aduser -Filter * [PSCustomObject]@{"Categories" = "All Account Count"; "Count" = if($allUsers -eq $null) {0} else {@($allUsers).Count}} #[PSCustomObject]@{"Categories" = "All Account Count"; "Count" = (Get-aduser -Filter *).count} [PSCustomObject]@{"Categories" = "Enabled Accounts Count"; "Count" = if($Users -eq $null) {0} else {@($Users).Count}} #[PSCustomObject]@{"Categories" = "Enabled Accounts Count"; "Count" = $Users.count} [PSCustomObject]@{"Categories" = "Disabled Accounts Count"; "Count" = if($DisabledAccounts -eq $null) {0} else {@($DisabledAccounts).Count}} #[PSCustomObject]@{"Categories" = "Disabled Accounts Count"; "Count" = $DisabledAccounts.count} $items1 = $DormantAccounts['365 days'] [PSCustomObject]@{"Categories" = "Dormant Accounts 365 Days Plus"; "Count" = if($items1 -eq $null) {0} else {@($items1).Count}} $items2 = $DormantAccounts['90 days'] [PSCustomObject]@{"Categories" = "Dormant Accounts 90 to 365"; "Count" = if($items2 -eq $null) {0} else {@($items2).Count}} $items3 = $DormantAccounts['45 days'] [PSCustomObject]@{"Categories" = "Dormant Accounts 45 to 90 Days"; "Count" = if($items3 -eq $null) {0} else {@($items3).Count}} $items4 = $DormantAccounts['Never logged on'] [PSCustomObject]@{"Categories" = "Never Logged On"; "Count" = if($items4 -eq $null) {0} else {@($items4).Count}} #[PSCustomObject]@{"Categories" = "Never Logged On"; "Count" = @(,$DormantAccounts['Never logged on']).count} [PSCustomObject]@{"Categories" = "Privileged Users Count"; "Count" = if($privilegedUsers -eq $null) {0} else {@($privilegedUsers).Count}} #[PSCustomObject]@{"Categories" = "Privileged Users Count"; "Count" = $privilegedUsers.count} [PSCustomObject]@{"Categories" = "Computer Accounts Count"; "Count" = if($ADComputerDetails -eq $null) {0} else {@($ADComputerDetails).Count}} #[PSCustomObject]@{"Categories" = "Computer Accounts Count"; "Count" = $ADComputerDetails.count} [PSCustomObject]@{"Categories" = "Server Accounts Count"; "Count" = if($ADServerDetails -eq $null) {0} else {@($ADServerDetails).Count}} #[PSCustomObject]@{"Categories" = "Server Accounts Count"; "Count" = $ADServerDetails.count} $names = $ADDomainControllerDetails.Name [PSCustomObject]@{"Categories" = "DC Accounts Count"; "Count" = if($names -eq $null) {0} else {@($names).Count}} #[PSCustomObject]@{"Categories" = "DC Accounts Count"; "Count" = ($ADDomainControllerDetails.Name).count} [PSCustomObject]@{"Categories" = "Accounts with Password Never Expires Count"; "Count" = if($AccountwithPasswordNeverExpires -eq $null) {0} else {@($AccountwithPasswordNeverExpires).Count}} #[PSCustomObject]@{"Categories" = "Accounts with Password Never Expires Count"; "Count" = $AccountwithPasswordNeverExpires.count} [PSCustomObject]@{"Categories" = "Accounts with Password Not Required Count"; "Count" = if($AccountwithPasswordNotRequired -eq $null) {0} else {@($AccountwithPasswordNotRequired).Count}} #[PSCustomObject]@{"Categories" = "Accounts with Password Not Required Count"; "Count" = $AccountwithPasswordNotRequired.count} [PSCustomObject]@{"Categories" = "Accounts with SID History Count"; "Count" = if($AccountwithSIDHistory -eq $null) {0} else {@($AccountwithSIDHistory).Count}} #[PSCustomObject]@{"Categories" = "Accounts with SID History Count"; "Count" = $AccountwithSIDHistory.count} [PSCustomObject]@{"Categories" = "Accounts with Reversible Encryption Count"; "Count" = if($AccountwithReversibleEncryption -eq $null) {0} else {@($AccountwithReversibleEncryption).Count}} #[PSCustomObject]@{"Categories" = "Accounts with Reversible Encryption Count"; "Count" = $AccountwithReversibleEncryption.count} [PSCustomObject]@{"Categories" = "Accounts with DES Encryption Count"; "Count" = if($AccountwithDESEncryption -eq $null) {0} else {@($AccountwithDESEncryption).Count}} #[PSCustomObject]@{"Categories" = "Accounts with DES Encryption Count"; "Count" = $AccountwithDESEncryption.count} [PSCustomObject]@{"Categories" = "Accounts without Kerberos Pre Auth Count"; "Count" = if($AccountsWithoutKerberosPreAuth -eq $null) {0} else {@($AccountsWithoutKerberosPreAuth).Count}} #[PSCustomObject]@{"Categories" = "Accounts without Kerberos Pre Auth Count"; "Count" = $AccountsWithoutKerberosPreAuth.count} ) $currentStep++ Write-Progress -Activity "Exporting data to Excel..." -Status "Finalizing" -PercentComplete (($currentStep / $totalSteps) * 100) # ---------------------------------------------------------------------------------------------------- # #Export to CSV Files function Export-DataToCsv { param ( [Parameter(Mandatory=$false)] [object]$Data, [Parameter(Mandatory=$true)] [string]$Path, [Parameter(Mandatory=$true)] [string]$FileName ) if ($null -eq $Data -or $Data.Count -eq 0) { @() | Export-Csv -Path ("$Path\" + $FileName + " NoData.csv") -NoTypeInformation } else { $Data | Export-Csv -Path ("$Path\" + $FileName + ".csv") -NoTypeInformation } } # Now use this function for your exports Export-DataToCsv -Data $resultCounts -Path $Path -FileName "A. ADAuditSummary" Export-DataToCsv -Data $PolicyInfo -Path $Path -FileName "B. PolicyInfo" Export-DataToCsv -Data $EnabledAccounts -Path $Path -FileName "C. EnabledAccounts" Export-DataToCsv -Data $DisabledAccounts -Path $Path -FileName "D. DisabledAccounts" Export-DataToCsv -Data $dormantAccounts['365 days'] -Path $Path -FileName "E. Dormant 365 Days Plus" Export-DataToCsv -Data $dormantAccounts['90 days'] -Path $Path -FileName "F. Dormant 90 to 365 Days" Export-DataToCsv -Data $dormantAccounts['45 days'] -Path $Path -FileName "G. Dormant 45 to 90 Days" Export-DataToCsv -Data $dormantAccounts['Never logged on'] -Path $Path -FileName "H. NeverLoggedOn" Export-DataToCsv -Data $privilegedUsers -Path $Path -FileName "I. PrivilegedUsers" Export-DataToCsv -Data $AccountwithPasswordNeverExpires -Path $Path -FileName "J. PasswordNeverExpires" Export-DataToCsv -Data $AccountwithPasswordNotRequired -Path $Path -FileName "K. PasswordNotRequired" Export-DataToCsv -Data $AccountwithSIDHistory -Path $Path -FileName "L. SIDHistory" Export-DataToCsv -Data $AccountwithReversibleEncryption -Path $Path -FileName "M. ReversibleEncryption" Export-DataToCsv -Data $AccountwithDESEncryption -Path $Path -FileName "N. DESEncryption" Export-DataToCsv -Data $AccountsWithoutKerberosPreAuth -Path $Path -FileName "O. WithoutKerberosPreAuth" Export-DataToCsv -Data $ADComputerDetails -Path $Path -FileName "P. ComputerAccounts" Export-DataToCsv -Data $ADServerDetails -Path $Path -FileName "Q. ServerAccounts" Export-DataToCsv -Data $ADDomainControllerDetails -Path $Path -FileName "R. DCAccounts" # Progress Bar complete $currentStep++ Write-Progress -Activity "Audit completed" -Completed # Show completion message Write-Host -ForegroundColor Green "Data export successful! The results were saved to $Path."