932 lines
25 KiB
PowerShell
932 lines
25 KiB
PowerShell
using namespace Microsoft.PowerShell.Commands
|
|
|
|
#region Initialization
|
|
|
|
$RootPath = Split-Path $MyInvocation.MyCommand.Path -Parent
|
|
. "$RootPath\Helpers\HashHelper.ps1"
|
|
|
|
$script:atapReportsPath = $env:ATAPReportPath
|
|
if (-not $script:atapReportsPath) {
|
|
$script:atapReportsPath = [Environment]::GetFolderPath('MyDocuments') | Join-Path -ChildPath 'ATAPReports'
|
|
}
|
|
|
|
# for license status function. if called multiple times the cache will be used
|
|
$LicenseStatusCache = $null
|
|
#endregion
|
|
|
|
#region Classes
|
|
class AuditTest {
|
|
[string] $Id
|
|
[string] $Task
|
|
[hashtable[]] $Constraints
|
|
[scriptblock] $Test
|
|
}
|
|
|
|
enum AuditInfoStatus {
|
|
True
|
|
False
|
|
Warning
|
|
None
|
|
Error
|
|
}
|
|
|
|
class AuditInfo {
|
|
[string] $Id
|
|
[string] $Task
|
|
[AuditInfoStatus] $Status
|
|
[string] $Message
|
|
}
|
|
|
|
class ReportSection {
|
|
[string] $Title
|
|
[string] $Description
|
|
[AuditInfo[]] $AuditInfos
|
|
[ReportSection[]] $SubSections
|
|
}
|
|
|
|
class Report {
|
|
[string] $Title
|
|
[string] $ModuleName
|
|
[string] $AuditorVersion
|
|
[hashtable] $HostInformation
|
|
[string[]] $BasedOn
|
|
[ReportSection[]] $Sections
|
|
[RSFullReport] $RSReport
|
|
[FoundationReport] $FoundationReport
|
|
}
|
|
|
|
|
|
###################################################
|
|
####### SYSTEM INFORMATION Classes ##########
|
|
###################################################
|
|
class SystemInformation {
|
|
[SoftwareInformation] $SoftwareInformation
|
|
[HardwareInformation] $HardwareInformation
|
|
}
|
|
|
|
class SoftwareInformation {
|
|
[string] $Hostname
|
|
[string] $SystemUptime
|
|
[string] $OperatingSystem
|
|
[string] $BuildNumber
|
|
[string] $OSArchitecture
|
|
[string] $LicenseStatus
|
|
[string] $InstallationLanguage
|
|
[string] $DomainRole
|
|
[string] $KernelVersion
|
|
}
|
|
|
|
class HardwareInformation {
|
|
[string] $SystemManufacturer
|
|
[string] $SystemSKU
|
|
[string] $SystemModel
|
|
[string] $SystemSerialnumber
|
|
[string] $BiosVersion
|
|
[string] $FreeDiskSpace
|
|
[string] $FreePhysicalMemory
|
|
}
|
|
### Begin Foundation Classes ###
|
|
class FoundationReport {
|
|
[ReportSection[]] $Sections
|
|
}
|
|
### End Foundation Classes
|
|
|
|
# RiskScore Classes
|
|
enum RSEndResult {
|
|
Critical
|
|
High
|
|
Medium
|
|
Low
|
|
Unknown
|
|
}
|
|
|
|
class RSFullReport {
|
|
[RSSeverityReport] $RSSeverityReport
|
|
[RSQuantityReport] $RSQuantityReport
|
|
}
|
|
|
|
class RSSeverityReport {
|
|
[AuditInfo[]] $AuditInfos
|
|
[ResultTable[]] $ResultTable
|
|
[RSEndResult] $Endresult
|
|
}
|
|
|
|
class RSQuantityReport {
|
|
|
|
}
|
|
|
|
class ResultTable {
|
|
[int] $Success
|
|
[int] $Failed
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region helpers
|
|
function IsIn-FullLanguageMode {
|
|
try {
|
|
$languageMode = $ExecutionContext.SessionState.LanguageMode
|
|
if ($languageMode -eq "FullLanguage") {
|
|
return $true
|
|
}
|
|
}
|
|
catch {
|
|
return $false
|
|
}
|
|
# returns alternate language modes if not FullLanguage
|
|
return $languageMode
|
|
}
|
|
|
|
function Start-ModuleTest {
|
|
$moduleList = @(Get-Module -ListAvailable).Name | Select-Object -Unique
|
|
$necessaryModules = @(
|
|
"Microsoft.PowerShell.LocalAccounts",
|
|
"Microsoft.PowerShell.Management",
|
|
"Microsoft.PowerShell.Security",
|
|
"Microsoft.PowerShell.Utility",
|
|
"TrustedPlatformModule",
|
|
"NetSecurity",
|
|
"CimCmdlets",
|
|
"SmbShare",
|
|
"Defender",
|
|
"DISM"
|
|
#Modules only necessary for specific server tests
|
|
#"IISAdministration",
|
|
#"SQLServer",
|
|
)
|
|
$missingModules = @()
|
|
foreach ($module in $necessaryModules) {
|
|
if ($moduleList -notcontains $module) {
|
|
$missingModules += $module
|
|
}
|
|
}
|
|
if ($missingModules.Count -gt 0) {
|
|
Write-Warning "Missing module(s) found. Missing modules can lead to errors. Following modules are missing:"
|
|
for ($i = 0; $i -lt $missingModules.Count; $i++) {
|
|
Write-Warning $missingModules[$i]
|
|
}
|
|
Write-Warning "Check out this link on how to install modules: https://learn.microsoft.com/en-us/powershell/module/powershellget/install-module?view=powershellget-3.x"
|
|
}
|
|
|
|
}
|
|
|
|
function Get-LicenseStatus {
|
|
param(
|
|
$SkipLicenseCheck
|
|
)
|
|
if ($LicenseStatusCache) {
|
|
return $LicenseStatusCache
|
|
}
|
|
|
|
if ($SkipLicenseCheck -eq $true) {
|
|
$LicenseStatusCache = "License check has been skipped."
|
|
return $LicenseStatusCache
|
|
}
|
|
|
|
Write-Host "Checking operating system activation status. This may take a while..."
|
|
$license = Get-CimInstance SoftwareLicensingProduct -Filter "Name like 'Windows%'" | Where-Object { $_.PartialProductKey } | Select-Object -First 1
|
|
$LicenseStatusCache = switch ($license.LicenseStatus) {
|
|
"0" { "Unlicensed" }
|
|
"1" { "Licensed" }
|
|
"2" { "OOBGrace" }
|
|
"3" { "OOTGrace" }
|
|
"4" { "NonGenuineGrace" }
|
|
"5" { "Notification" }
|
|
"6" { "ExtendedGrace" }
|
|
}
|
|
return $LicenseStatusCache
|
|
}
|
|
|
|
function IsIIS10Executable {
|
|
if ((Get-Module -ListAvailable IISAdministration) -eq $null) {
|
|
return $false
|
|
}
|
|
return $true
|
|
}
|
|
|
|
function Test-ArrayEqual {
|
|
[OutputType([bool])]
|
|
[CmdletBinding()]
|
|
param (
|
|
[Parameter(Mandatory = $true)]
|
|
[AllowNull()]
|
|
[AllowEmptyCollection()]
|
|
[array]
|
|
$Array1,
|
|
|
|
[Parameter(Mandatory = $true)]
|
|
[AllowNull()]
|
|
[AllowEmptyCollection()]
|
|
[array]
|
|
$Array2
|
|
)
|
|
|
|
if ($null -eq $Array1) {
|
|
$Array1 = @()
|
|
}
|
|
|
|
if ($null -eq $Array2) {
|
|
$Array2 = @()
|
|
}
|
|
|
|
if ($Array1.Count -ne $Array2.Count) {
|
|
return $false
|
|
}
|
|
|
|
foreach ($a in $Array1) {
|
|
if ($a -notin $Array2) {
|
|
return $false
|
|
}
|
|
}
|
|
return $true
|
|
}
|
|
|
|
# Get domain role
|
|
# 0 {"Standalone Workstation"}
|
|
# 1 {"Member Workstation"}
|
|
# 2 {"Standalone Server"}
|
|
# 3 {"Member Server"}
|
|
# 4 {"Backup Domain Controller"}
|
|
# 5 {"Primary Domain Controller"}
|
|
function Get-DomainRole {
|
|
$domainRole = (Get-CimInstance -Class Win32_ComputerSystem).DomainRole
|
|
switch ($domainRole) {
|
|
0 { $result = "Standalone Workstation" }
|
|
1 { $result = "Member Workstation" }
|
|
2 { $result = "Standalone Server" }
|
|
3 { $result = "Member Server" }
|
|
4 { $result = "Backup Domain Controller" }
|
|
5 { $result = "Primary Domain Controller" }
|
|
}
|
|
return $result
|
|
}
|
|
|
|
function checkReportNameWithOSSystem {
|
|
[CmdletBinding()]
|
|
param (
|
|
[Parameter()]
|
|
[string]
|
|
$ReportName
|
|
)
|
|
# helpers
|
|
function handleReportNameDiscrepancy {
|
|
param (
|
|
[Parameter()]
|
|
[string]
|
|
$ReportName,
|
|
[Parameter()]
|
|
[string]
|
|
$OsName,
|
|
[Parameter()]
|
|
[bool]
|
|
$ShouldBeStandAlone = $False
|
|
)
|
|
if ($ShouldBeStandAlone -eq $True) {
|
|
Write-Host "You chose the Reportname $ReportName but the operating system is domain-joined. Be aware that a different report type could affect the result."
|
|
}
|
|
else {
|
|
Write-Host "You chose the Reportname $ReportName but the operating system is $OsName. Be aware that a different report type could affect the result."
|
|
}
|
|
Write-Host ""
|
|
Write-Host "Choose one of the following options:"
|
|
Write-Host "[1] Continue [2] Exit Script" -ForegroundColor Yellow
|
|
$in = Read-Host
|
|
switch ($in) {
|
|
1 {
|
|
Write-Host "You chose to continue"
|
|
return $ReportName
|
|
}
|
|
2 {
|
|
Write-Host "You chose to exit the script"
|
|
return "Exit"
|
|
}
|
|
default {
|
|
Write-Host "Your input was invalid, call Save-ATAPHtmlReport again with your desired report"
|
|
return "Exit"
|
|
}
|
|
}
|
|
}
|
|
function returnSuitingReportName {
|
|
[CmdletBinding()]
|
|
param (
|
|
[Parameter()]
|
|
[string]
|
|
$ReportName,
|
|
[Parameter()]
|
|
[string]
|
|
$OsName,
|
|
[Parameter()]
|
|
[string]
|
|
$OsType,
|
|
[Parameter()]
|
|
[bool]
|
|
$ShouldBeStandAlone = $False
|
|
)
|
|
|
|
###
|
|
# similarity check
|
|
function isOsNameSimilarToType {
|
|
[CmdletBinding()]
|
|
param (
|
|
[Parameter()]
|
|
[string]
|
|
$OsName,
|
|
[Parameter()]
|
|
[string]
|
|
$OsType
|
|
)
|
|
if ($OsName -match $OsType) {
|
|
return $true
|
|
}
|
|
return $false
|
|
}
|
|
if (-not(isOsNameSimilarToType -OsName $osName -OsType $osType)) {
|
|
return handleReportNameDiscrepancy -ReportName $ReportName -OsName $osName
|
|
}
|
|
|
|
###
|
|
# should be standalone
|
|
if ($ShouldBeStandAlone -eq $True) {
|
|
function IsDomainedJoined {
|
|
if ((Get-CimInstance win32_computersystem).partofdomain) {
|
|
return $true
|
|
}
|
|
return $false
|
|
}
|
|
$isDomainJoined = IsDomainedJoined
|
|
if ($isDomainJoined -eq $True) {
|
|
return handleReportNameDiscrepancy -ReportName $ReportName -OsName $osName -ShouldBeStandAlone $True
|
|
}
|
|
}
|
|
return $ReportName
|
|
}
|
|
#helpers end
|
|
try {
|
|
$osName = (Get-ComputerInfo OsName).OsName
|
|
if ([string]::IsNullOrEmpty($osName)) {
|
|
return $ReportName # return initial ReportName and skip comparison
|
|
}
|
|
function Get-OsType {
|
|
switch ($ReportName) {
|
|
"Microsoft Windows Server 2025" { return "Microsoft Windows Server 2025" }
|
|
"Microsoft Windows Server 2022" { return "Microsoft Windows Server 2022" }
|
|
"Microsoft Windows Server 2019" { return "Microsoft Windows Server 2019" }
|
|
"Microsoft Windows Server 2016" { return "Microsoft Windows Server 2016" }
|
|
"Microsoft Windows Server 2012" { return "Microsoft Windows Server 2012" }
|
|
"Microsoft Windows 11" { return "Microsoft Windows 11" }
|
|
"Microsoft Windows 11 Stand-alone" { return "Microsoft Windows 11" }
|
|
"Microsoft Windows 10" { return "Microsoft Windows 10" }
|
|
"Microsoft Windows 10 Stand-alone" { return "Microsoft Windows 10" }
|
|
"Microsoft Windows 10 GDPR" { return "Microsoft Windows 10" }
|
|
"Microsoft Windows 10 BSI" { return "Microsoft Windows 10" }
|
|
"Microsoft Windows 7" { return "Microsoft Windows 7" }
|
|
}
|
|
}
|
|
$osType = Get-OsType
|
|
switch ($ReportName) {
|
|
"Microsoft Windows Server 2025" {
|
|
return returnSuitingReportName -ReportName $ReportName -OsName $osName -OsType $osType
|
|
}
|
|
"Microsoft Windows Server 2022" {
|
|
return returnSuitingReportName -ReportName $ReportName -OsName $osName -OsType $osType
|
|
}
|
|
"Microsoft Windows Server 2019" {
|
|
return returnSuitingReportName -ReportName $ReportName -OsName $osName -OsType $osType
|
|
}
|
|
"Microsoft Windows Server 2016" {
|
|
return returnSuitingReportName -ReportName $ReportName -OsName $osName -OsType $osType
|
|
}
|
|
"Microsoft Windows Server 2012" {
|
|
return returnSuitingReportName -ReportName $ReportName -OsName $osName -OsType $osType
|
|
}
|
|
"Microsoft Windows 11" {
|
|
return returnSuitingReportName -ReportName $ReportName -OsName $osName -OsType $osType
|
|
}
|
|
"Microsoft Windows 11 Stand-alone" {
|
|
return returnSuitingReportName -ReportName $ReportName -OsName $osName -OsType $osType -ShouldBeStandAlone $True
|
|
}
|
|
"Microsoft Windows 10" {
|
|
return returnSuitingReportName -ReportName $ReportName -OsName $osName -OsType $osType
|
|
}
|
|
"Microsoft Windows 10 Stand-alone" {
|
|
return returnSuitingReportName -ReportName $ReportName -OsName $osName -OsType $osType -ShouldBeStandAlone $True
|
|
}
|
|
"Microsoft Windows 10 GDPR" {
|
|
return returnSuitingReportName -ReportName $ReportName -OsName $osName -OsType $osType
|
|
}
|
|
"Microsoft Windows 10 BSI" {
|
|
return returnSuitingReportName -ReportName $ReportName -OsName $osName -OsType $osType
|
|
}
|
|
"Microsoft Windows 7" {
|
|
return returnSuitingReportName -ReportName $ReportName -OsName $osName -OsType $osType
|
|
}
|
|
}
|
|
return $ReportName
|
|
}
|
|
catch {
|
|
return $ReportName
|
|
}
|
|
|
|
}
|
|
|
|
### begin Foundation functions ###
|
|
function Get-FoundationReport {
|
|
[CmdletBinding()]
|
|
[OutputType([FoundationReport])]
|
|
|
|
$Sections = @(
|
|
[ReportSection] @{
|
|
Title = "Security Base Data"
|
|
SubSections = @(
|
|
[ReportSection] @{
|
|
Title = 'Platform Security'
|
|
AuditInfos = Test-AuditGroup "SBD - Platform Security"
|
|
}
|
|
[ReportSection] @{
|
|
Title = 'Windows Base Security'
|
|
AuditInfos = Test-AuditGroup "SBD - Windows Base Security"
|
|
}
|
|
[ReportSection] @{
|
|
Title = 'PowerShell Security'
|
|
AuditInfos = Test-AuditGroup "SBD - PowerShell Security"
|
|
}
|
|
[ReportSection] @{
|
|
Title = 'Connectivity Security'
|
|
AuditInfos = Test-AuditGroup "SBD - Connectivity Security"
|
|
}
|
|
[ReportSection] @{
|
|
Title = 'Application Control'
|
|
AuditInfos = Test-AuditGroup "SBD - Application Control"
|
|
}
|
|
)
|
|
}
|
|
)
|
|
|
|
return ([FoundationReport]@{
|
|
Sections = $Sections
|
|
})
|
|
}
|
|
|
|
|
|
# region for RiskScore functions
|
|
# function that calls all RiskScore-Subfunctions and generates the RSFullReport
|
|
function Get-RSFullReport {
|
|
[CmdletBinding()]
|
|
[OutputType([RSFullReport])]
|
|
|
|
$severity = Get-RSSeverityReport
|
|
|
|
|
|
return ([RSFullReport]@{
|
|
RSSeverityReport = $severity
|
|
})
|
|
}
|
|
# function to generate RiskSeverityReport
|
|
function Get-RSSeverityReport {
|
|
[CmdletBinding()]
|
|
[OutputType([RSSeverityReport])]
|
|
|
|
# Initialization
|
|
[AuditInfo[]]$tests = Test-AuditGroup "RSSeverityTests"
|
|
|
|
# gather results of tests and save it in resultTable
|
|
$resultTable = [ResultTable]::new()
|
|
foreach ($test in $tests) {
|
|
if ($test.AuditInfoStatus -EQ "True") {
|
|
$resultTable.Success += 1
|
|
}
|
|
if ($test.AuditInfostatus -ne "True") {
|
|
$resultTable.Failed += 1
|
|
}
|
|
}
|
|
|
|
return ([RSSeverityReport]@{
|
|
AuditInfos = $tests
|
|
ResultTable = $resultTable
|
|
Endresult = Get-RSSeverityEndResult($resultTable)
|
|
})
|
|
}
|
|
|
|
# helper for EndResult of RiskScoreSeverity
|
|
function Get-RSSeverityEndResult {
|
|
[CmdletBinding()]
|
|
[OutputType([RSEndResult])]
|
|
|
|
param (
|
|
[Parameter(Mandatory = $true)]
|
|
[ResultTable[]]
|
|
$resultTable
|
|
)
|
|
|
|
$result = "Unknown"
|
|
|
|
$f = $resultTable.Failed
|
|
if ($f -eq 0) {
|
|
$result = "Low"
|
|
}
|
|
if ($f -ge 1) {
|
|
$result = "Critical"
|
|
}
|
|
return $result
|
|
}
|
|
|
|
#endregion
|
|
|
|
<#
|
|
.SYNOPSIS
|
|
Tests a single AuditGroup.
|
|
.DESCRIPTION
|
|
This cmdlet tests a single AuditGroup from folder "AuditGroups". All tests are printed on the console. Can be combined to create own report.
|
|
.EXAMPLE
|
|
PS C:\> Test-AuditGroup "Google Chrome-CIS-2.0.0#RegistrySettings"
|
|
This runs tests defined in the AuditGroup file called 'Google Chrome-CIS-2.0.0#RegistrySettings'.
|
|
.PARAMETER GroupName
|
|
The name of the AuditGroup.
|
|
#>
|
|
function Test-AuditGroup {
|
|
[CmdletBinding()]
|
|
[OutputType([AuditInfo[]])]
|
|
param(
|
|
[Parameter(Mandatory = $true)]
|
|
[string]
|
|
$GroupName
|
|
)
|
|
|
|
#Windows OS
|
|
if ([System.Environment]::OSVersion.Platform -ne 'Unix') {
|
|
$tests = . "$RootPath\AuditGroups\$($GroupName).ps1"
|
|
}
|
|
#Linux OS
|
|
else {
|
|
$tests = . "$RootPath/AuditGroups/$($GroupName).ps1"
|
|
}
|
|
|
|
|
|
$i = 1
|
|
foreach ($test in $tests) {
|
|
[int]$p = $i++ / $tests.Count * 100
|
|
Write-Progress -Activity "Testing Report for '$GroupName'" -Status "Progress:" -PercentComplete $p
|
|
Write-Verbose "Testing $($test.Id)"
|
|
$message = "Test not implemented yet."
|
|
$status = [AuditInfoStatus]::None
|
|
#if audit test contains datatype "Constraints", proceed
|
|
if ($test.Constraints) {
|
|
$DomainRoleConstraint = $test.Constraints | Where-Object Property -EQ "DomainRole"
|
|
#get domain role of system
|
|
$currentRole = Get-DomainRole
|
|
#get domain roles, which are listed in AuditTest
|
|
$domainRoles = $DomainRoleConstraint.Values
|
|
if ($currentRole -notin $domainRoles) {
|
|
$roleValue = (Get-CimInstance -Class Win32_ComputerSystem).DomainRole
|
|
switch ($roleValue) {
|
|
0 {
|
|
$message = 'Not applicable. This audit does not apply to Standalone Workstation.'
|
|
$status = [AuditInfoStatus]::None
|
|
}
|
|
1 {
|
|
$message = 'Not applicable. This audit does not apply to Member Workstation.'
|
|
$status = [AuditInfoStatus]::None
|
|
}
|
|
2 {
|
|
$message = 'Not applicable. This audit does not apply to Standalone Server.'
|
|
$status = [AuditInfoStatus]::None
|
|
}
|
|
3 {
|
|
$message = 'Not applicable. This audit does not apply to Member Server.'
|
|
$status = [AuditInfoStatus]::None
|
|
}
|
|
4 {
|
|
$message = 'Not applicable. This audit does not apply to Backup Domain Controller.'
|
|
$status = [AuditInfoStatus]::None
|
|
}
|
|
5 {
|
|
$message = 'Not applicable. This audit does not apply to Primary Domain Controller.'
|
|
$status = [AuditInfoStatus]::None
|
|
}
|
|
}
|
|
Write-Output ([AuditInfo]@{
|
|
Id = $test.Id
|
|
Task = $test.Task
|
|
Message = $message
|
|
Status = $status
|
|
})
|
|
continue
|
|
}
|
|
}
|
|
|
|
#Windows OS
|
|
if ([System.Environment]::OSVersion.Platform -ne 'Unix') {
|
|
$role = Get-Wmiobject -Class 'Win32_computersystem' -ComputerName $env:computername | Select-Object domainrole
|
|
if ($test.Task -match "(DC only)") {
|
|
if ($role.domainRole -ne 4 -and $role.domainRole -ne 5) {
|
|
$message = 'Not applicable. This audit does not apply to Member Server systems.'
|
|
$status = [AuditInfoStatus]::None
|
|
Write-Output ([AuditInfo]@{
|
|
Id = $test.Id
|
|
Task = $test.Task
|
|
Message = $message
|
|
Status = $status
|
|
})
|
|
continue
|
|
}
|
|
}
|
|
}
|
|
try {
|
|
$innerResult = & $test.Test
|
|
|
|
if ($null -ne $innerResult) {
|
|
$message = $innerResult.Message
|
|
$status = [AuditInfoStatus]$innerResult.Status
|
|
}
|
|
}
|
|
catch {
|
|
Write-Error $_
|
|
$message = "An error occured!"
|
|
$status = [AuditInfoStatus]::Error
|
|
}
|
|
|
|
Write-Output ([AuditInfo]@{
|
|
Id = $test.Id
|
|
Task = $test.Task
|
|
Message = $message
|
|
Status = $status
|
|
})
|
|
}
|
|
}
|
|
|
|
<#
|
|
.SYNOPSIS
|
|
Get an audit resource.
|
|
.DESCRIPTION
|
|
A resource provides abstration over an existing system resource. It is used by AuditTests.
|
|
.PARAMETER Name
|
|
The name of the resource.
|
|
.EXAMPLE
|
|
PS C:\> Get-AuditResource -Name "WindowsSecurityPolicy"
|
|
Gets the WindowsSecurityPolicy resource.
|
|
#>
|
|
function Get-AuditResource {
|
|
[CmdletBinding()]
|
|
param (
|
|
[Parameter(Mandatory = $true)]
|
|
[string]
|
|
$Name
|
|
)
|
|
#Windows OS
|
|
if ([System.Environment]::OSVersion.Platform -ne 'Unix') {
|
|
if ($null -eq $script:loadedResources) {
|
|
return & "$RootPath\Resources\$($Name).ps1"
|
|
}
|
|
if (-not $script:loadedResources.ContainsKey($Name)) {
|
|
$script:loadedResources[$Name] = (& "$RootPath\Resources\$($Name).ps1")
|
|
}
|
|
}
|
|
#Linuxs OS
|
|
else {
|
|
if ($null -eq $script:loadedResources) {
|
|
return & "$RootPath/Resources/$($Name).ps1"
|
|
}
|
|
if (-not $script:loadedResources.ContainsKey($Name)) {
|
|
$script:loadedResources[$Name] = (& "$RootPath/Resources/$($Name).ps1")
|
|
}
|
|
}
|
|
return $script:loadedResources[$Name]
|
|
}
|
|
|
|
<#
|
|
.SYNOPSIS
|
|
Get all reports.
|
|
.DESCRIPTION
|
|
Find the reports installed on the system.
|
|
.PARAMETER ReportName
|
|
The name of the report.
|
|
.EXAMPLE
|
|
PS C:\> Get-ATAPReport
|
|
Gets all reports.
|
|
#>
|
|
function Get-ATAPReport {
|
|
[CmdletBinding()]
|
|
param (
|
|
[Parameter()]
|
|
[string]
|
|
$ReportName = "*"
|
|
)
|
|
#Windows OS
|
|
if ([System.Environment]::OSVersion.Platform -ne 'Unix') {
|
|
return Get-ChildItem "$RootPath\Reports\$ReportName.ps1" | Select-Object -Property BaseName
|
|
}
|
|
#Linux OS
|
|
return Get-ChildItem "$RootPath/Reports/$ReportName.ps1" | Select-Object -Property BaseName
|
|
}
|
|
|
|
<#
|
|
.SYNOPSIS
|
|
Invokes an ATAPReport
|
|
.DESCRIPTION
|
|
Long description
|
|
.EXAMPLE
|
|
PS C:\> ATAPReport -ReportName "Google Chrome"
|
|
This runs the report and outputs the logical report data.
|
|
.PARAMETER ReportName
|
|
The name of the report.
|
|
.OUTPUTS
|
|
Logical report data.
|
|
#>
|
|
function Invoke-ATAPReport {
|
|
[CmdletBinding()]
|
|
param (
|
|
[Alias('RN')]
|
|
[Parameter(Mandatory = $true)]
|
|
[string]
|
|
$ReportName
|
|
)
|
|
|
|
$script:loadedResources = @{}
|
|
# Load the module manifest
|
|
|
|
#Windows OS
|
|
try {
|
|
if ([System.Environment]::OSVersion.Platform -ne 'Unix') {
|
|
$moduleInfo = Import-PowerShellDataFile -Path "$RootPath\ATAPAuditor.psd1"
|
|
[string]$ReportName = checkReportNameWithOSSystem -ReportName $ReportName
|
|
try {
|
|
if ($ReportName -eq "Exit") {
|
|
throw
|
|
}
|
|
}
|
|
catch {
|
|
Write-Host "Script halted: Exiting..."
|
|
break
|
|
}
|
|
[Report]$report = (& "$RootPath\Reports\$ReportName.ps1")
|
|
$report.RSReport = Get-RSFullReport
|
|
$report.FoundationReport = Get-FoundationReport
|
|
}
|
|
#Linux OS
|
|
else {
|
|
$moduleInfo = Import-PowerShellDataFile -Path "$RootPath/ATAPAuditor.psd1"
|
|
[Report]$report = (& "$RootPath/Reports/$ReportName.ps1")
|
|
}
|
|
}
|
|
catch [System.Management.Automation.CommandNotFoundException] {
|
|
Write-Host "Either your input for -Reportname is faulty or the report does not resolve due to a bug. Please report this bug with the following errormessage:
|
|
1. ErrorException: $_
|
|
2. PositionMessage: $($_.InvocationInfo.PositionMessage)
|
|
3. ReportName: $ReportName"
|
|
break
|
|
}
|
|
$report.AuditorVersion = $moduleInfo.ModuleVersion
|
|
return $report
|
|
}
|
|
|
|
<#
|
|
.SYNOPSIS
|
|
The Audit Test Automation Package creates transparents reports about hardening compliance status
|
|
.DESCRIPTION
|
|
The Audit Test Automation Package gives you the ability to get an overview about the compliance status of several systems.
|
|
You can easily create HTML-reports and have a transparent overview over compliance and non-compliance of explicit setttings
|
|
and configurations in comparison to industry standards and hardening guides.
|
|
.EXAMPLE
|
|
PS C:\> Save-ATAPHtmlReport -ReportName "Microsoft Windows 10 Complete" -RiskScore -Path C:\Temp\report.html
|
|
This runs the 'Microsoft Windows 10 Complete' report, adding RiskScore to it and stores the resulting html file under C:\Temp using the file name report.html
|
|
.EXAMPLE
|
|
PS C:\> Save-ATAPHtmlReport -ReportName "Microsoft Windows 10 BSI" -RiskScore -Path C:\Temp
|
|
This runs the 'Microsoft Windows 10 BSI' report, adding RiskScore to it and stores the resulting html file under C:\Temp using the standard naming convention for file names <ReportName_Date_Time>.html
|
|
.EXAMPLE
|
|
PS C:\> Save-ATAPHtmlReport -ReportName "Microsoft Windows Server 2022" -Path C:\Temp
|
|
This runs the 'Microsoft Windows Server 2022' report, without adding RiskScore to it and stores the resulting html file under C:\Temp using the standard naming convention for file names <ReportName_Date_Time>.html
|
|
.EXAMPLE
|
|
PS C:\> Save-ATAPHtmlReport -ReportName "Google Chrome"
|
|
This runs the 'Google Chrome' report and stores the resulting html file (by default) under ~\Documents\ATAPReports
|
|
.EXAMPLE
|
|
PS C:\> Save-ATAPHtmlReport -ReportName "Ubuntu 20.04"
|
|
This runs the 'Ubuntu 20.04' report and stores the resulting html file (by default) under ~\Documents\ATAPReports
|
|
.PARAMETER ReportName
|
|
Determine, which OS shall be tested.
|
|
.PARAMETER Path
|
|
The path where the result html document should be stored.
|
|
.PARAMETER RiskScore
|
|
Add a RiskScore-Matrix to report (works only on Windows OS)
|
|
.PARAMETER MITRE
|
|
Add a MITRE ATT&CK headmap to report (works only on Windows OS)
|
|
.PARAMETER Force
|
|
If the parent directory doesn't exist it will be created.
|
|
.OUTPUTS
|
|
None.
|
|
#>
|
|
function Save-ATAPHtmlReport {
|
|
[CmdletBinding()]
|
|
param(
|
|
[Alias('RN')]
|
|
[Parameter(Mandatory = $true)]
|
|
[string]
|
|
$ReportName,
|
|
|
|
[Parameter(Mandatory = $false)]
|
|
[string]
|
|
$Path = ($script:atapReportsPath | Join-Path -ChildPath "$($ReportName)_$(Get-Date -UFormat %Y%m%d_%H%M%S).html"),
|
|
|
|
[Parameter(Mandatory = $false)]
|
|
[switch]
|
|
$RiskScore,
|
|
|
|
[Parameter(Mandatory = $false)]
|
|
[switch]
|
|
$SkipLicenseCheck,
|
|
# [Parameter(Mandatory = $false)]
|
|
# [switch]
|
|
# $MITRE,
|
|
|
|
[Parameter()]
|
|
[switch]
|
|
$Force
|
|
)
|
|
|
|
if ([Environment]::Is64BitProcess -eq $false) {
|
|
Write-Host "Please use 64-bit version of PowerShell in order to use AuditTAP. Closing..." -ForegroundColor red
|
|
return;
|
|
}
|
|
|
|
if (($languagemode = IsIn-FullLanguageMode) -ne $true) {
|
|
if ($languagemode -eq $false) {
|
|
Write-Host "The current language mode could not be determined. Ensure that AuditTAP is run in `"FullLanguage`" mode. For further information, contact your administrator. Closing..." -ForegroundColor red
|
|
}
|
|
else {
|
|
Write-Host "The current language mode is `"$languagemode`". Ensure that AuditTAP is run in `"FullLanguage`" mode. For further information, contact your administrator. Closing..." -ForegroundColor red
|
|
}
|
|
return
|
|
}
|
|
|
|
$parent = $path
|
|
if ($Path -match ".html") {
|
|
$parent = Split-Path -Path $Path
|
|
}
|
|
|
|
#if input path is not default one
|
|
if ($parent -ne $script:atapReportsPath) {
|
|
$pathCheck = Test-Path -Path $parent -PathType Container
|
|
#if path doesn't exist
|
|
if ($pathCheck -eq $False) {
|
|
if (-not [string]::IsNullOrEmpty($parent) -and -not (Test-Path $parent)) {
|
|
New-Item -ItemType Directory -Path $parent -Force | Out-Null
|
|
Write-Warning "Could not find Path. Path will be created: $parent"
|
|
}
|
|
else {
|
|
Write-Warning "Could not find Path. Report will be created inside default path: $($script:atapReportsPath)"
|
|
$Path = $($script:atapReportsPath)
|
|
}
|
|
}
|
|
}
|
|
Write-Verbose "OS-Check"
|
|
$isUnix = [System.Environment]::OSVersion.Platform -eq 'Unix'
|
|
if ($isUnix) {
|
|
[SystemInformation] $SystemInformation = (& "$PSScriptRoot\Helpers\ReportUnixOS.ps1")
|
|
}
|
|
else {
|
|
[SystemInformation] $SystemInformation = (& "$PSScriptRoot\Helpers\ReportWindowsOS.ps1")
|
|
Start-ModuleTest
|
|
if ($ReportName -eq "Microsoft IIS10") {
|
|
$isIIS10Executable = IsIIS10Executable
|
|
if ($isIIS10Executable -eq $false) {
|
|
Write-Warning "IIS10 Report not executable! IISAdministration module not available. Please install this module and try again. Exiting..."
|
|
return;
|
|
}
|
|
}
|
|
Write-Verbose "PS-Check"
|
|
$psVersion = $PSVersionTable.PSVersion
|
|
#PowerShell Major version not 5.*
|
|
if (($psVersion.Major -ne 5)) {
|
|
Write-Warning "ATAPAuditor is only compatible with PowerShell Version 5.1. Your version is $psVersion. Please open a PowerShell Version 5.1 session to continue!"
|
|
return;
|
|
}
|
|
#PowerShell version not 5.1
|
|
if (($psVersion.Major -eq 5) -and ($psVersion.Minor -eq 0)) {
|
|
Write-Warning "ATAPAuditor is only compatible with PowerShell Version 5.1. Your version is $psVersion. You need to upgrade to a higher Windows version!"
|
|
return;
|
|
}
|
|
}
|
|
|
|
$report = Invoke-ATAPReport -ReportName $ReportName
|
|
#hashes for each recommendation
|
|
if (!$isUnix) {
|
|
$SystemInformation.SoftwareInformation.LicenseStatus = Get-LicenseStatus $SkipLicenseCheck
|
|
}
|
|
$hashtable_sha256 = GenerateHashTable $report
|
|
|
|
$report | Get-ATAPHtmlReport -Path $Path -RiskScore:$RiskScore -MITRE:$MITRE -hashtable_sha256:$hashtable_sha256 -LicenseStatus:$LicenseStatus -SystemInformation:$SystemInformation
|
|
}
|
|
|
|
New-Alias -Name 'shr' -Value Save-ATAPHtmlReport
|
|
|
|
$completer = {
|
|
param($commandName, $parameterName, $wordToComplete, $commandAst, $fakeBoundParameters)
|
|
|
|
Get-ChildItem "$RootPath\Reports\*.ps1" `
|
|
| Select-Object -ExpandProperty BaseName `
|
|
| ForEach-Object { "`"$_`"" } `
|
|
| Where-Object { $_ -like "*$wordToComplete*" }
|
|
}.GetNewClosure()
|
|
|
|
Register-ArgumentCompleter -CommandName Save-ATAPHtmlReport -ParameterName ReportName -ScriptBlock $completer
|
|
Register-ArgumentCompleter -CommandName shr -ParameterName ReportName -ScriptBlock $completer
|