629 lines
32 KiB
PowerShell
629 lines
32 KiB
PowerShell
<#--
|
|
=====================================
|
|
Veeam Security & Compliance Analyzer
|
|
Enforcement Script
|
|
=====================================
|
|
|
|
This script provides reporting on the current
|
|
status and enforces recommended security settings
|
|
on a backup server. It is designed to be executed
|
|
locally on the backup server.
|
|
|
|
# PowerShell version 7.0+ is required.
|
|
# If script execution is blocked, run this command first in PowerShell:
|
|
# Set-ExecutionPolicy -ExecutionPolicy Bypass -Scope Process -Force
|
|
|
|
Version: 1.93 (Updated on 25/02/2026)
|
|
|
|
--#>
|
|
|
|
#Requires -RunAsAdministrator
|
|
#Requires -Version 7.0
|
|
|
|
# Validate environment before proceeding
|
|
Write-Host "Validating environment..." -ForegroundColor Cyan
|
|
|
|
# Check for Veeam Backup Service presence
|
|
$backupService = Get-Service VeeamBackupSvc -ErrorAction SilentlyContinue
|
|
if (-not $backupService) {
|
|
Write-Host "ERROR: Veeam Backup Service not detected on this machine." -ForegroundColor Red
|
|
Write-Host "Ensure you are running this script on the Veeam Backup Server itself." -ForegroundColor Red
|
|
exit 1
|
|
}
|
|
|
|
# Check if service is running
|
|
if ($backupService.Status -ne "Running") {
|
|
Write-Host "ERROR: Veeam Backup Service is not running (Status: $($backupService.Status))." -ForegroundColor Red
|
|
Write-Host "Start the VeeamBackupSvc service and try again." -ForegroundColor Red
|
|
exit 1
|
|
}
|
|
|
|
# Import Veeam PowerShell module
|
|
Write-Host "Importing Veeam PowerShell module..." -ForegroundColor Cyan
|
|
$path = [Environment]::GetEnvironmentVariable('PSModulePath', 'Machine')
|
|
$env:PSModulePath += "$([System.IO.Path]::PathSeparator)$path"
|
|
$veeamPSModule = Get-Module -ListAvailable | Where-Object { $_.Name -match "Veeam.Backup.PowerShell" }
|
|
|
|
if (-not $veeamPSModule) {
|
|
Write-Host "ERROR: Veeam PowerShell module not found. Is Veeam B&R installed correctly?" -ForegroundColor Red
|
|
exit 1
|
|
}
|
|
|
|
try {
|
|
Import-Module $veeamPSModule.Path -DisableNameChecking -ErrorAction Stop
|
|
Write-Host "Veeam PowerShell module imported successfully" -ForegroundColor Green
|
|
}
|
|
catch {
|
|
Write-Host "ERROR: Failed to import Veeam PowerShell module" -ForegroundColor Red
|
|
Write-Host "Error details: $($_.Exception.Message)" -ForegroundColor Red
|
|
exit 1
|
|
}
|
|
|
|
# This function collects current status and prints out a compliance report
|
|
function Get-VBRComplianceReport
|
|
{
|
|
Write-host "Initiating Analyzer and collecting compliance status..." -ForegroundColor Cyan
|
|
|
|
# Trigger S&CA session
|
|
$analyzerJob = Start-VBRSecurityComplianceAnalyzer
|
|
|
|
# Note: Results retrieved via retry loop instead
|
|
# Wait for analyzer job to complete (max 60 seconds) - normally takes about ~10 seconds
|
|
$timeout = 60
|
|
$elapsed = 0
|
|
Write-Host "Waiting for analyzer to complete..." -NoNewline
|
|
|
|
while ($analyzerJob.IsCompleted -eq $false -and $elapsed -lt $timeout) {
|
|
Start-Sleep -Seconds 2
|
|
$elapsed += 2
|
|
Write-Host "." -NoNewline
|
|
|
|
# Re-query the job status
|
|
$analyzerJob = Get-VBRSession | Where-Object { $_.Id -eq $analyzerJob.Id } | Select-Object -First 1
|
|
}
|
|
|
|
if ($analyzerJob.IsCompleted) {
|
|
Write-Host " Done" -ForegroundColor Green
|
|
} else {
|
|
Write-Host ""
|
|
}
|
|
|
|
# Retrieve analyzer results with retry logic (up to 5 attempts with 15-second delays)
|
|
Write-Host "Retrieving compliance results..." -ForegroundColor Cyan
|
|
$AnalyzerResult = Get-VBRSecurityComplianceAnalyzerResults
|
|
$resultCount = ($AnalyzerResult | Measure-Object).Count
|
|
|
|
if ($resultCount -eq 0) {
|
|
for ($retryCount = 1; $retryCount -le 5; $retryCount++) {
|
|
Write-Host " Waiting for results (attempt $retryCount/5)..." -ForegroundColor Cyan
|
|
Start-Sleep -Seconds 15
|
|
|
|
$AnalyzerResult = Get-VBRSecurityComplianceAnalyzerResults
|
|
$resultCount = ($AnalyzerResult | Measure-Object).Count
|
|
|
|
if ($resultCount -gt 0) {
|
|
Write-Host " Results retrieved successfully ($resultCount items)" -ForegroundColor Green
|
|
break
|
|
}
|
|
}
|
|
|
|
if ($resultCount -eq 0) {
|
|
Write-Host "ERROR: Unable to retrieve analyzer results after multiple attempts." -ForegroundColor Red
|
|
Write-Host "Try running the script again or check Veeam Backup service logs." -ForegroundColor Red
|
|
}
|
|
} else {
|
|
Write-Host "Results retrieved successfully ($resultCount items)" -ForegroundColor Green
|
|
}
|
|
|
|
$Recommendations = @(
|
|
[Ordered]@{
|
|
Id = 1
|
|
Name = "Remote Desktop Services (TermService) should be disabled"
|
|
Status = ($AnalyzerResult | Where-Object {$_.Type -eq "RemoteDesktopServiceDisabled"}).Status
|
|
Remediation = "Script"
|
|
}
|
|
[Ordered]@{
|
|
Id = 2
|
|
Name = "Remote Registry service (RemoteRegistry) should be disabled"
|
|
Status = ($AnalyzerResult | Where-Object {$_.Type -eq "RemoteRegistryDisabled"}).Status
|
|
Remediation = "Script"
|
|
}
|
|
[Ordered]@{
|
|
Id = 3
|
|
Name = "Windows Remote Management (WinRM) service should be disabled"
|
|
Status = ($AnalyzerResult | Where-Object {$_.Type -eq "WinRmServiceDisabled"}).Status
|
|
Remediation = "Script"
|
|
}
|
|
[Ordered]@{
|
|
Id = 4
|
|
Name = "Windows Firewall should be enabled"
|
|
Status = ($AnalyzerResult | Where-Object {$_.Type -eq "FirewallEnabled"}).Status
|
|
Remediation = "Script"
|
|
}
|
|
[Ordered]@{
|
|
Id = 5
|
|
Name = "WDigest credentials caching should be disabled"
|
|
Status = ($AnalyzerResult | Where-Object {$_.Type -eq "WDigestNotStorePasswordsInMemory"}).Status
|
|
Remediation = "Script"
|
|
}
|
|
[Ordered]@{
|
|
Id = 6
|
|
Name = "Web Proxy Auto-Discovery service (WinHttpAutoProxySvc) should be disabled"
|
|
Status = ($AnalyzerResult | Where-Object {$_.Type -eq "WebProxyAutoDiscoveryDisabled"}).Status
|
|
Remediation = "Script"
|
|
}
|
|
[Ordered]@{
|
|
Id = 7
|
|
Name = "Deprecated versions of SSL and TLS should be disabled"
|
|
Status = ($AnalyzerResult | Where-Object {$_.Type -eq "OutdatedSslAndTlsDisabled"}).Status
|
|
Remediation = "Script"
|
|
}
|
|
[Ordered]@{
|
|
Id = 8
|
|
Name = "Windows Script Host should be disabled"
|
|
Status = ($AnalyzerResult | Where-Object {$_.Type -eq "WindowsScriptHostDisabled"}).Status
|
|
Remediation = "Script"
|
|
}
|
|
[Ordered]@{
|
|
Id = 9
|
|
Name = "SMBv1 protocol should be disabled"
|
|
Status = ($AnalyzerResult | Where-Object {$_.Type -eq "SMB1ProtocolDisabled"}).Status
|
|
Remediation = "Script"
|
|
}
|
|
[Ordered]@{
|
|
Id = 10
|
|
Name = "Link-Local Multicast Name Resolution (LLMNR) should be disabled"
|
|
Status = ($AnalyzerResult | Where-Object {$_.Type -eq "LLMNRDisabled"}).Status
|
|
Remediation = "Script"
|
|
}
|
|
[Ordered]@{
|
|
Id = 11
|
|
Name = "SMBv3 signing and encryption should be enabled"
|
|
Status = ($AnalyzerResult | Where-Object {$_.Type -eq "CSmbSigningAndEncryptionEnabled"}).Status
|
|
Remediation = "Script"
|
|
}
|
|
[Ordered]@{
|
|
Id = 12
|
|
Name = "MFA for the backup console should be enabled"
|
|
Status = ($AnalyzerResult | Where-Object {$_.Type -eq "MfaEnabledInBackupConsole"}).Status
|
|
Remediation = "Manual"
|
|
}
|
|
[Ordered]@{
|
|
Id = 13
|
|
Name = "Immutable or offline (air gapped) media should be used"
|
|
Status = ($AnalyzerResult | Where-Object {$_.Type -eq "ImmutableOrOfflineMediaPresence"}).Status
|
|
Remediation = "Manual"
|
|
}
|
|
[Ordered]@{
|
|
Id = 14
|
|
Name = "Password loss protection should be enabled"
|
|
Status = ($AnalyzerResult | Where-Object {$_.Type -eq "LossProtectionEnabled"}).Status
|
|
Remediation = "Manual"
|
|
}
|
|
[Ordered]@{
|
|
Id = 15
|
|
Name = "Backup server should not be a part of the production domain"
|
|
Status = ($AnalyzerResult | Where-Object {$_.Type -eq "BackupServerInProductionDomain"}).Status
|
|
Remediation = "Manual"
|
|
}
|
|
[Ordered]@{
|
|
Id = 16
|
|
Name = "Email notifications should be enabled"
|
|
Status = ($AnalyzerResult | Where-Object {$_.Type -eq "EmailNotificationsEnabled"}).Status
|
|
Remediation = "Manual"
|
|
}
|
|
[Ordered]@{
|
|
Id = 17
|
|
Name = "All backups should have at least one copy (the 3-2-1 backup rule)"
|
|
Status = ($AnalyzerResult | Where-Object {$_.Type -eq "ContainBackupCopies"}).Status
|
|
Remediation = "Manual"
|
|
}
|
|
[Ordered]@{
|
|
Id = 18
|
|
Name = "Reverse incremental backup mode is deprecated and should be avoided"
|
|
Status = ($AnalyzerResult | Where-Object {$_.Type -eq "ReverseIncrementalInUse"}).Status
|
|
Remediation = "Manual"
|
|
}
|
|
[Ordered]@{
|
|
Id = 19
|
|
Name = "Unknown Linux servers should not be trusted automatically"
|
|
Status = ($AnalyzerResult | Where-Object {$_.Type -eq "ManualLinuxHostAuthentication"}).Status
|
|
Remediation = "Script"
|
|
}
|
|
[Ordered]@{
|
|
Id = 20
|
|
Name = "The configuration backup must not be stored on the backup server"
|
|
Status = ($AnalyzerResult | Where-Object {$_.Type -eq "ConfigurationBackupRepositoryNotLocal"}).Status
|
|
Remediation = "Manual"
|
|
}
|
|
[Ordered]@{
|
|
Id = 21
|
|
Name = "Host to proxy traffic encryption should be enabled for the Network transport mode"
|
|
Status = ($AnalyzerResult | Where-Object {$_.Type -eq "ViProxyTrafficEncrypted"}).Status
|
|
Remediation = "Script"
|
|
}
|
|
[Ordered]@{
|
|
Id = 22
|
|
Name = "Hardened repositories should not be hosted in virtual machines"
|
|
Status = ($AnalyzerResult | Where-Object {$_.Type -eq "HardenedRepositoryNotVirtual"}).Status
|
|
Remediation = "Manual"
|
|
}
|
|
[Ordered]@{
|
|
Id = 23
|
|
Name = "Network traffic encryption should be enabled in the backup network"
|
|
Status = ($AnalyzerResult | Where-Object {$_.Type -eq "TrafficEncryptionEnabled"}).Status
|
|
Remediation = "Manual"
|
|
}
|
|
[Ordered]@{
|
|
Id = 24
|
|
Name = "Linux servers should have password-based authentication disabled"
|
|
Status = ($AnalyzerResult | Where-Object {$_.Type -eq "LinuxServersUsingSSHKeys"}).Status
|
|
Remediation = "Manual"
|
|
}
|
|
[Ordered]@{
|
|
Id = 25
|
|
Name = "Backup services should be running under the LocalSystem account"
|
|
Status = ($AnalyzerResult | Where-Object {$_.Type -eq "BackupServicesUnderLocalSystem"}).Status
|
|
Remediation = "Manual"
|
|
}
|
|
[Ordered]@{
|
|
Id = 26
|
|
Name = "Configuration backup should be enabled and use encryption"
|
|
Status = ($AnalyzerResult | Where-Object {$_.Type -eq "ConfigurationBackupEnabledAndEncrypted"}).Status
|
|
Remediation = "Manual"
|
|
}
|
|
[Ordered]@{
|
|
Id = 27
|
|
Name = "Credentials and encryption passwords should be rotated at least annually"
|
|
Status = ($AnalyzerResult | Where-Object {$_.Type -eq "PasswordsRotation"}).Status
|
|
Remediation = "Manual"
|
|
}
|
|
[Ordered]@{
|
|
Id = 28
|
|
Name = "Hardened repositories should have the SSH Server disabled"
|
|
Status = ($AnalyzerResult | Where-Object {$_.Type -eq "HardenedRepositorySshDisabled"}).Status
|
|
Remediation = "Manual"
|
|
}
|
|
[Ordered]@{
|
|
Id = 29
|
|
Name = "S3 Object Lock in the Governance mode does not provide true immutability"
|
|
Status = ($AnalyzerResult | Where-Object {$_.Type -eq "OsBucketsInComplianceMode"}).Status
|
|
Remediation = "Manual"
|
|
}
|
|
[Ordered]@{
|
|
Id = 30
|
|
Name = "Backup jobs to cloud repositories should use encryption"
|
|
Status = ($AnalyzerResult | Where-Object {$_.Type -eq "JobsTargetingCloudRepositoriesEncrypted"}).Status
|
|
Remediation = "Manual"
|
|
}
|
|
[Ordered]@{
|
|
Id = 31
|
|
Name = "Latest product updates should be installed"
|
|
Status = ($AnalyzerResult | Where-Object {$_.Type -eq "BackupServerUpToDate"}).Status
|
|
Remediation = "Manual"
|
|
}
|
|
[Ordered]@{
|
|
Id = 32
|
|
Name = "PostgreSQL server should be configured with recommended settings"
|
|
Status = ($AnalyzerResult | Where-Object {$_.Type -eq "PostgreSqlUseRecommendedSettings"}).Status
|
|
Remediation = "Script"
|
|
}
|
|
[Ordered]@{
|
|
Id = 33
|
|
Name = "Hardened repositories should not be used as backup proxy servers"
|
|
Status = ($AnalyzerResult | Where-Object {$_.Type -eq "HardenedRepositoryNotContainsNBDProxies"}).Status
|
|
Remediation = "Manual"
|
|
}
|
|
[Ordered]@{
|
|
Id = 34
|
|
Name = "Local Security Authority Server Service (LSASS) should be set to run as a protected process"
|
|
Status = ($AnalyzerResult | Where-Object {$_.Type -eq "LsassProtectedProcess"}).Status
|
|
Remediation = "Script"
|
|
}
|
|
[Ordered]@{
|
|
Id = 35
|
|
Name = "NetBIOS protocol should be disabled on all network interfaces"
|
|
Status = ($AnalyzerResult | Where-Object {$_.Type -eq "NetBiosDisabled"}).Status
|
|
Remediation = "Script"
|
|
}
|
|
[Ordered]@{
|
|
Id = 36
|
|
Name = "Credential Guard should be enabled"
|
|
Status = ($AnalyzerResult | Where-Object {$_.Type -eq "CredentialsGuardConfigured"}).Status
|
|
Remediation = "Manual"
|
|
}
|
|
[Ordered]@{
|
|
Id = 37
|
|
Name = "Backup encryption passwords should follow length and complexity recommendations"
|
|
Status = ($AnalyzerResult | Where-Object {$_.Type -eq "EncryptionPasswordsComplexityRules"}).Status
|
|
Remediation = "Manual"
|
|
}
|
|
[Ordered]@{
|
|
Id = 38
|
|
Name = "Saved credentials should follow password length and complexity recommendations"
|
|
Status = ($AnalyzerResult | Where-Object {$_.Type -eq "CredentialsPasswordsComplexityRules"}).Status
|
|
Remediation = "Manual"
|
|
}
|
|
|
|
)
|
|
|
|
# Formatting and better structure for future updates
|
|
$Summary = $Recommendations | ForEach-Object {
|
|
if ($_.Id -lt 10) { $CleanID = "0"+$_.Id } else { $CleanID = $_.Id }
|
|
[PSCustomObject]@{
|
|
Id = $CleanID
|
|
Name = $_.Name
|
|
Status = $_.Status
|
|
Remediation = $_.Remediation
|
|
}
|
|
}
|
|
|
|
# Print out current status report
|
|
Clear-Host
|
|
Write-Host "Report:" -ForegroundColor Green
|
|
Write-Host ""
|
|
foreach ($Recommendation in $Summary)
|
|
{
|
|
switch ($Recommendation.Status)
|
|
{
|
|
"UnableToCheck"
|
|
{ Write-Host $Recommendation.Id "-" $Recommendation.Name ": " -NoNewline; Write-Host "Unable to detect" -ForegroundColor Yellow }
|
|
{$Recommendation.Status -eq "Ok"}
|
|
{ Write-Host $Recommendation.Id "-" $Recommendation.Name ": " -NoNewline; Write-Host "Passed" -ForegroundColor Green }
|
|
"Suppressed"
|
|
{ Write-Host $Recommendation.Id "-" $Recommendation.Name ": " -NoNewline; Write-Host "Suppressed" -ForegroundColor DarkGray }
|
|
default
|
|
{ Write-Host $Recommendation.Id "-" $Recommendation.Name ": " -NoNewline; if($Recommendation.Remediation -eq "Script") {Write-Host "Not implemented" -ForegroundColor Red -NoNewline; Write-Host " (Use 'Apply configurations' option to fix)" -ForegroundColor Yellow} else {Write-Host "Not implemented" -ForegroundColor Red;} }
|
|
}
|
|
}
|
|
return $Summary
|
|
}
|
|
|
|
# This function sets defined practice ID configuration on a server into a recommended state
|
|
function Set-VBRComplianceRecommendations($id)
|
|
{
|
|
switch ([int]$id){
|
|
1 {
|
|
Write-host "Disabling Remote Desktop Services (TermService)..." -NoNewline
|
|
Try {
|
|
Set-Service "TermService" -StartupType "Disabled" -ErrorAction SilentlyContinue
|
|
Write-host "OK (Reboot required)" -ForegroundColor Green
|
|
}
|
|
Catch {Write-host "Failed" -ForegroundColor Red}
|
|
}
|
|
2 {
|
|
Write-host "Disabling Remote Registry service (RemoteRegistry)..." -NoNewline
|
|
Try {
|
|
Stop-Service "RemoteRegistry" -Force -ErrorAction SilentlyContinue
|
|
Set-Service "RemoteRegistry" -StartupType "Disabled" -ErrorAction SilentlyContinue
|
|
Write-host "OK" -ForegroundColor Green
|
|
}
|
|
Catch {Write-host "Failed" -ForegroundColor Red}
|
|
}
|
|
3 {
|
|
Write-host "Disabling Windows Remote Management (WinRM) service..." -NoNewline
|
|
Try {
|
|
Set-Service "WinRM" -StartupType "Disabled" -ErrorAction SilentlyContinue
|
|
Write-host "OK (Reboot required)" -ForegroundColor Green
|
|
}
|
|
Catch {Write-host "Failed" -ForegroundColor Red}
|
|
}
|
|
4 {
|
|
Write-host "Enabling Windows Firewall..." -NoNewline
|
|
Try {
|
|
Set-NetFirewallProfile -All -Enabled "True" -ErrorAction SilentlyContinue
|
|
Write-host "OK" -ForegroundColor Green
|
|
}
|
|
Catch {Write-host "Failed" -ForegroundColor Red}
|
|
}
|
|
5 {
|
|
Write-host "Disabling WDigest credentials caching..." -NoNewline
|
|
Try {
|
|
Remove-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Control\SecurityProviders\WDigest" -Name "UseLogonCredential" -ErrorAction Ignore
|
|
Write-host "OK (Reboot required)" -ForegroundColor Green
|
|
}
|
|
Catch {Write-host "Failed" -ForegroundColor Red}
|
|
}
|
|
6 {
|
|
Write-host "Disabling Web Proxy Auto-Discovery service (WinHttpAutoProxySvc)..." -NoNewline
|
|
Try {
|
|
Set-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Services\WinHttpAutoProxySvc" -Name "Start" -Value 4
|
|
|
|
$winhttpPath = "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Internet Settings\WinHttp"
|
|
if (-not (Test-Path $winhttpPath)) {
|
|
New-Item -Path $winhttpPath -Force | Out-Null
|
|
}
|
|
Set-ItemProperty -Path $winhttpPath -Name "DisableWpad" -Value 1 -Type DWord -Force
|
|
|
|
Write-host "OK (Reboot required)" -ForegroundColor Green
|
|
}
|
|
Catch {Write-host "Failed" -ForegroundColor Red}
|
|
}
|
|
7 {
|
|
Write-host "Disabling deprecated versions of SSL and TLS..." -NoNewline
|
|
Try {
|
|
New-Item 'HKLM:\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\SSL 2.0\Server' -Force -ErrorAction SilentlyContinue | Out-Null
|
|
New-ItemProperty -path 'HKLM:\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\SSL 2.0\Server' -name 'Enabled' -value '0' -PropertyType 'DWORD' -Force -ErrorAction SilentlyContinue | Out-Null
|
|
New-ItemProperty -path 'HKLM:\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\SSL 2.0\Server' -name 'DisabledByDefault' -value 1 -PropertyType 'DWORD' -Force -ErrorAction SilentlyContinue | Out-Null
|
|
New-Item 'HKLM:\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\SSL 2.0\Client' -Force | Out-Null
|
|
New-ItemProperty -path 'HKLM:\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\SSL 2.0\Client' -name 'Enabled' -value '0' -PropertyType 'DWORD' -Force -ErrorAction SilentlyContinue | Out-Null
|
|
New-ItemProperty -path 'HKLM:\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\SSL 2.0\Client' -name 'DisabledByDefault' -value 1 -PropertyType 'DWORD' -Force -ErrorAction SilentlyContinue | Out-Null
|
|
|
|
New-Item 'HKLM:\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\SSL 3.0\Server' -Force -ErrorAction SilentlyContinue | Out-Null
|
|
New-ItemProperty -path 'HKLM:\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\SSL 3.0\Server' -name 'Enabled' -value '0' -PropertyType 'DWORD' -Force -ErrorAction SilentlyContinue | Out-Null
|
|
New-ItemProperty -path 'HKLM:\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\SSL 3.0\Server' -name 'DisabledByDefault' -value 1 -PropertyType 'DWORD' -Force -ErrorAction SilentlyContinue| Out-Null
|
|
New-Item 'HKLM:\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\SSL 3.0\Client' -Force -ErrorAction SilentlyContinue | Out-Null
|
|
New-ItemProperty -path 'HKLM:\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\SSL 3.0\Client' -name 'Enabled' -value '0' -PropertyType 'DWORD' -Force -ErrorAction SilentlyContinue | Out-Null
|
|
New-ItemProperty -path 'HKLM:\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\SSL 3.0\Client' -name 'DisabledByDefault' -value 1 -PropertyType 'DWORD' -Force -ErrorAction SilentlyContinue | Out-Null
|
|
|
|
New-Item -Path 'HKLM:\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\TLS 1.0\Server' -Force -ErrorAction SilentlyContinue | Out-Null
|
|
New-Item 'HKLM:\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\TLS 1.0\Server' -Force -ErrorAction SilentlyContinue | Out-Null
|
|
New-ItemProperty -path 'HKLM:\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\TLS 1.0\Server' -name 'Enabled' -value '0' -PropertyType 'DWORD' -Force -ErrorAction SilentlyContinue | Out-Null
|
|
New-ItemProperty -path 'HKLM:\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\TLS 1.0\Server' -name 'DisabledByDefault' -value 1 -PropertyType 'DWORD' -Force -ErrorAction SilentlyContinue | Out-Null
|
|
New-Item 'HKLM:\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\TLS 1.0\Client' -Force -ErrorAction SilentlyContinue | Out-Null
|
|
New-ItemProperty -path 'HKLM:\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\TLS 1.0\Client' -name 'Enabled' -value '0' -PropertyType 'DWORD' -Force -ErrorAction SilentlyContinue | Out-Null
|
|
New-ItemProperty -path 'HKLM:\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\TLS 1.0\Client' -name 'DisabledByDefault' -value 1 -PropertyType 'DWORD' -Force -ErrorAction SilentlyContinue | Out-Null
|
|
|
|
New-Item 'HKLM:\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\TLS 1.1\Server' -Force -ErrorAction SilentlyContinue | Out-Null
|
|
New-ItemProperty -path 'HKLM:\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\TLS 1.1\Server' -name 'Enabled' -value '0' -PropertyType 'DWORD' -Force -ErrorAction SilentlyContinue | Out-Null
|
|
New-ItemProperty -path 'HKLM:\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\TLS 1.1\Server' -name 'DisabledByDefault' -value 1 -PropertyType 'DWORD' -Force -ErrorAction SilentlyContinue | Out-Null
|
|
New-Item 'HKLM:\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\TLS 1.1\Client' -Force -ErrorAction SilentlyContinue | Out-Null
|
|
New-ItemProperty -path 'HKLM:\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\TLS 1.1\Client' -name 'Enabled' -value '0' -PropertyType 'DWORD' -Force -ErrorAction SilentlyContinue | Out-Null
|
|
New-ItemProperty -path 'HKLM:\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\TLS 1.1\Client' -name 'DisabledByDefault' -value 1 -PropertyType 'DWORD' -Force -ErrorAction SilentlyContinue | Out-Null
|
|
|
|
Write-host "OK (Reboot required)" -ForegroundColor Green
|
|
}
|
|
Catch {Write-host "Failed" -ForegroundColor Red}
|
|
}
|
|
8 {
|
|
Write-host "Disabling Windows Script Host..." -NoNewline
|
|
Try {
|
|
New-ItemProperty -Path "HKLM:\SOFTWARE\Microsoft\Windows Script Host\Settings" -Name "Enabled" -PropertyType "DWORD" -Value "0" -Force -ErrorAction SilentlyContinue | Out-Null
|
|
Write-host "OK" -ForegroundColor Green
|
|
}
|
|
Catch {Write-host "Failed" -ForegroundColor Red}
|
|
}
|
|
9 {
|
|
Write-host "Disabling SMBv1 protocol..." -NoNewline
|
|
Try {
|
|
Set-SmbServerConfiguration -EnableSMB1Protocol $false -Force -ErrorAction SilentlyContinue | Out-Null
|
|
Disable-WindowsOptionalFeature -Online -FeatureName "SMB1Protocol" -NoRestart -ErrorAction SilentlyContinue | Out-Null
|
|
Write-host "OK (Reboot required)" -ForegroundColor Green
|
|
}
|
|
Catch {Write-host "Failed" -ForegroundColor Red}
|
|
}
|
|
10 {
|
|
Write-host "Disabling Link-Local Multicast Name Resolution (LLMNR)..." -NoNewline
|
|
Try {
|
|
New-Item "HKLM:\SOFTWARE\Policies\Microsoft\Windows NT" -Name "DNSClient" -Force -ErrorAction SilentlyContinue | Out-Null
|
|
New-ItemProperty "HKLM:\SOFTWARE\Policies\Microsoft\Windows NT\DNSClient" -Name "EnableMultiCast" -Value "0" -PropertyType "DWORD" -Force -ErrorAction SilentlyContinue | Out-Null
|
|
Write-host "OK (Reboot required)" -ForegroundColor Green
|
|
}
|
|
Catch {Write-host "Failed" -ForegroundColor Red}
|
|
}
|
|
11 {
|
|
Write-host "Enabling SMBv3 signing and encryption..." -NoNewline
|
|
Try {
|
|
Set-SmbServerConfiguration -EncryptData $true -Force -ErrorAction SilentlyContinue
|
|
Set-SmbServerConfiguration -EnableSecuritySignature $true -Force -ErrorAction SilentlyContinue
|
|
Set-SmbServerConfiguration -RequireSecuritySignature $true -Force -ErrorAction SilentlyContinue
|
|
Write-host "OK" -ForegroundColor Green
|
|
}
|
|
Catch {Write-host "Failed" -ForegroundColor Red}
|
|
}
|
|
19 {
|
|
Write-host "Setting unknown Linux servers trust settings..." -NoNewline
|
|
Try {
|
|
Set-VBRLinuxTrustedHostPolicy -Type "KnownHosts"
|
|
Write-host "OK" -ForegroundColor Green
|
|
}
|
|
Catch {Write-host "Failed" -ForegroundColor Red}
|
|
}
|
|
21 {
|
|
Write-host "Setting host to proxy traffic encryption in Network transport mode..." -NoNewline
|
|
Try {
|
|
Get-VBRViProxy | Where-Object {$_.UseSSL -ne $True} | Set-VBRViProxy -EnableHostToProxyEncryption -ErrorAction SilentlyContinue
|
|
Write-host "OK" -ForegroundColor Green
|
|
}
|
|
Catch {Write-host "Failed" -ForegroundColor Red}
|
|
}
|
|
32 {
|
|
Write-host "Setting recommended PostgreSQL settings (applies to local instances only)..." -NoNewline
|
|
Try {
|
|
Set-VBRPSQLDatabaseServerLimits -WA 0
|
|
Write-host "OK (Reboot required)" -ForegroundColor Green
|
|
}
|
|
Catch {Write-host "Failed" -ForegroundColor Red}
|
|
}
|
|
34 {
|
|
Write-host "Making LSASS to run as a protected process..." -NoNewline
|
|
Try {
|
|
if ($env:firmware_type -eq "UEFI") { Set-ItemProperty -Path "HKLM:SYSTEM\CurrentControlSet\Control\Lsa" -Name "RunAsPPL" -Value 1 }
|
|
else { Set-ItemProperty -Path "HKLM:SYSTEM\CurrentControlSet\Control\Lsa" -Name "RunAsPPL" -Value 2 }
|
|
Write-host "OK" -ForegroundColor Green
|
|
}
|
|
Catch {Write-host "Failed" -ForegroundColor Red}
|
|
}
|
|
35 {
|
|
Write-host "Disabling NETBIOS on all network interfaces..." -NoNewline
|
|
Try {
|
|
$interfaces = Get-ChildItem "HKLM:SYSTEM\CurrentControlSet\Services\NetBT\Parameters\Interfaces" | Select -ExpandProperty PSChildName
|
|
Foreach($interface in $interfaces) { Set-ItemProperty -Path "HKLM:SYSTEM\CurrentControlSet\Services\NetBT\Parameters\Interfaces\$interface" -Name "NetbiosOptions" -Value 2 }
|
|
Write-host "OK" -ForegroundColor Green
|
|
}
|
|
Catch {Write-host "Failed" -ForegroundColor Red}
|
|
}
|
|
36 {
|
|
Write-host "For Credential Guard, please perform manual changes as per Security & Compliance Analyzer User's Guide." -ForegroundColor Cyan
|
|
Write-host "Reference: https://helpcenter.veeam.com/docs/vbr/userguide/best_practices_analyzer.html?ver=13" -ForegroundColor Cyan
|
|
}
|
|
|
|
default {Write-host "Unknown recommendation ID"}
|
|
}
|
|
}
|
|
|
|
# This function draws main menu
|
|
function Get-VeeamMenu
|
|
{
|
|
Write-host ""
|
|
Write-host "Available actions:" -ForegroundColor Green
|
|
Write-host ""
|
|
Write-host "1 : Refresh compliance report"
|
|
if ($RemediationCount -gt 0) {Write-host "2 : Apply ALL recommended configurations " -NoNewline; Write-host "(total:$RemediationCount)" -ForegroundColor Yellow } else {Write-host "2 : Apply all recommended security & compliance configurations"}
|
|
Write-host "3 : Apply selected configuration only..."
|
|
Write-host "0 : Exit"
|
|
Write-host ""
|
|
}
|
|
|
|
# Trigger execution
|
|
Write-Host "Validating user permissions..."
|
|
try {
|
|
Start-VBRSecurityComplianceAnalyzer
|
|
}
|
|
catch {
|
|
if ($Error[0].Exception.Message -match "MFA-enabled") {
|
|
Write-Host "Unable to connect to the server with MFA-enabled user account. Consider KB4535 (https://www.veeam.com/kb4535)." -ForegroundColor Red
|
|
Exit
|
|
}
|
|
else {
|
|
Write-Host "Failed to start Security & Compliance Analyzer" -ForegroundColor Red
|
|
Exit
|
|
}
|
|
}
|
|
|
|
$Report = Get-VBRComplianceReport
|
|
do
|
|
{
|
|
$RemediationActions = $Report | Where-Object {$_.Remediation -eq "Script" -and $_.Status -eq "Violation"}
|
|
$RemediationCount = ($RemediationActions | Measure-Object).count
|
|
|
|
Get-VeeamMenu
|
|
$choice = Read-host "Select action to perform"
|
|
Write-host ""
|
|
|
|
switch ($choice)
|
|
{
|
|
0 { break }
|
|
1 { $Report = Get-VBRComplianceReport }
|
|
2 { foreach ($Action in $RemediationActions) {Set-VBRComplianceRecommendations $Action.ID} }
|
|
3 {
|
|
$ActionID = Read-Host "Enter recommendation ID"
|
|
if ($Remediationactions.id -contains $ActionID) {
|
|
Set-VBRComplianceRecommendations $ActionID
|
|
} else {
|
|
$matchedReport = $Report | Where-Object { $_.Id -eq $ActionID -or $_.Id -eq ([int]$ActionID).ToString("00") }
|
|
if ($matchedReport -and $matchedReport.Status -eq "UnableToCheck") {
|
|
Write-host "Selected configuration ID does not need to be applied." -ForegroundColor Yellow
|
|
Write-host " This setting may already be applied at a system level by default." -ForegroundColor Cyan
|
|
} elseif ($matchedReport -and $matchedReport.Status -eq "Ok") {
|
|
Write-host "Selected configuration ID is already compliant (Passed)." -ForegroundColor Green
|
|
} else {
|
|
Write-host "Selected configuration ID does not need to be applied or manual only" -ForegroundColor Red
|
|
Write-host "Refer to https://helpcenter.veeam.com/docs/vbr/userguide/best_practices_analyzer.html?ver=13" -ForegroundColor Red
|
|
}
|
|
}
|
|
}
|
|
default { Write-host "Error: select correct action." -ForegroundColor Red}
|
|
}
|
|
} until ($choice -eq 0)
|