Public/New-LS2Dashboard.ps1
|
function New-LS2Dashboard { <# .SYNOPSIS Generates an interactive HTML dashboard for Locksmith2 scan results. .DESCRIPTION Creates a comprehensive HTML dashboard with left navigation menu showing: - All issues with expanded principals - Issues filtered by type (Template, CA, Object) - Risky principals analysis Supports light/dark mode toggle and interactive filtering/sorting. Requires PSWriteHTML module (Install-Module PSWriteHTML). .PARAMETER FilePath Path where the HTML dashboard will be saved. Default: $env:TEMP\Locksmith2-Dashboard.html .PARAMETER Show Opens the dashboard in default browser after generation. .PARAMETER ExpandGroups Expands group principals into individual member issues. .PARAMETER Online Uses online CDN resources instead of embedding CSS/JS. Results in smaller file size but requires internet connection to view. .INPUTS None. This function does not accept pipeline input. .OUTPUTS None. Generates an HTML file at the specified path. .EXAMPLE Invoke-Locksmith2 New-LS2Dashboard -FilePath C:\Reports\locksmith-dashboard.html -Show Runs a scan and generates an interactive dashboard. .EXAMPLE New-LS2Dashboard -ExpandGroups -Show Generates dashboard with group memberships expanded to individual principals. .EXAMPLE New-LS2Dashboard -FilePath C:\Reports\report.html -Online Generates a smaller dashboard file using online CDN resources. .NOTES Author: Jake Hildreth (@jakehildreth) Requires: PSWriteHTML module (https://github.com/EvotecIT/PSWriteHTML) Requires: PowerShell 5.1 or later The dashboard reads from the current IssueStore. Run Invoke-Locksmith2 or Find-LS2Vulnerable* functions first to populate the store with scan data. .LINK Invoke-Locksmith2 .LINK Find-LS2RiskyPrincipal .LINK Get-FlattenedIssues #> [CmdletBinding()] param( [Parameter()] [string]$FilePath = "$env:TEMP\Locksmith2-Dashboard.html", [Parameter()] [switch]$Show, [Parameter()] [switch]$ExpandGroups, [Parameter()] [switch]$Online ) #requires -Version 5.1 # Check for PSWriteHTML module if (-not (Get-Module -ListAvailable -Name PSWriteHTML)) { Write-Error "PSWriteHTML module is required. Install with: Install-Module PSWriteHTML" return } Import-Module PSWriteHTML -ErrorAction Stop # Check if IssueStore is populated if (-not $script:IssueStore -or $script:IssueStore.Count -eq 0) { Write-Warning "IssueStore is empty. Run Invoke-Locksmith2 or Find-LS2Vulnerable* functions first." Write-Warning "Generating empty dashboard..." } # Get all issues from IssueStore $allIssues = Get-FlattenedIssues # Expand groups if requested if ($ExpandGroups) { Write-Verbose "Expanding group memberships for dashboard..." $allIssues = $allIssues | ForEach-Object { Expand-IssueByGroup $_ } } # Filter issues by category $templateTechniques = @('ESC1', 'ESC2', 'ESC3c1', 'ESC3c2', 'ESC4a', 'ESC4o', 'ESC9') $caTechniques = @('ESC6', 'ESC7a', 'ESC7m', 'ESC11', 'ESC16') $objectTechniques = @('ESC5a', 'ESC5o') $templateIssues = $allIssues | Where-Object { $_.Technique -in $templateTechniques } $caIssues = $allIssues | Where-Object { $_.Technique -in $caTechniques } $objectIssues = $allIssues | Where-Object { $_.Technique -in $objectTechniques } # Get risky principals Write-Verbose "Calculating principal risk scores..." $riskyPrincipals = Find-LS2RiskyPrincipal # Prepare data for tables - select key properties for display $allIssuesTable = $allIssues | Select-Object ` Technique, Forest, Name, IdentityReference, ActiveDirectoryRights, @{N='Enabled';E={if($null -ne $_.Enabled){$_.Enabled}else{'-'}}}, @{N='CAFullName';E={if($_.CAFullName){$_.CAFullName}else{'-'}}}, @{N='Owner';E={if($_.Owner){$_.Owner}else{'-'}}}, @{N='Members';E={if($_.MemberCount){$_.MemberCount}else{'-'}}} $templateIssuesTable = $templateIssues | Select-Object ` Technique, Name, IdentityReference, ActiveDirectoryRights, Enabled, MemberCount $caIssuesTable = $caIssues | Select-Object ` Technique, Name, CAFullName, IdentityReference, ActiveDirectoryRights, MemberCount $objectIssuesTable = $objectIssues | Select-Object ` Technique, Name, Owner, IdentityReference, ActiveDirectoryRights, MemberCount $principalsTable = $riskyPrincipals | Select-Object ` Principal, IssueCount, @{N='Techniques';E={$_.Techniques -join ', '}}, @{N='VulnerableObjects';E={$_.VulnerableObjects.Count}} $forestName = if ($script:Forest) { $script:Forest } else { 'Unknown Forest' } # Generate HTML Dashboard New-HTML -TitleText "Locksmith2 Security Dashboard - $forestName" -Online:$Online -FilePath $FilePath -Show:$Show { # Use tabs for single-page navigation with content switching New-HTMLTabStyle -SlimTabs -Transition -SelectorColor Magenta New-HTMLTab -Name 'All Issues' -IconSolid exclamation-triangle -IconColor Red { New-HTMLSection -Invisible { New-HTMLPanel -Width 10% { New-HTMLText -Text "All Issues - Expanded Principals ($($allIssues.Count) total)" -FontSize 20 -FontWeight bold New-HTMLText -Text @" This view shows all discovered AD CS vulnerabilities with group memberships expanded to individual principals. Issues are marked with the ESC technique and show which principals can exploit each configuration. "@ -Color '#888' -FontSize 14 } New-HTMLPanel { New-HTMLTable -DataTable $allIssuesTable ` -Filtering ` -PagingLength 25 ` -Buttons @('copyHtml5', 'excelHtml5', 'csvHtml5', 'pdfHtml5', 'searchBuilder', 'searchPanes') ` -Title 'All AD CS Security Issues' { New-TableButtonSearchBuilder -ButtonName 'Search Builder' New-HTMLTableCondition -Name 'Technique' -ComparisonType string -Operator like -Value 'ESC1*' -BackgroundColor '#ffebee' -Color Black New-HTMLTableCondition -Name 'Technique' -ComparisonType string -Operator like -Value 'ESC7*' -BackgroundColor '#fff3e0' -Color Black New-HTMLTableCondition -Name 'Members' -ComparisonType string -Operator ne -Value '-' -BackgroundColor '#e8f5e9' -Color Black } } } } New-HTMLTab -Name 'Templates' -IconSolid file-contract -IconColor Orange { New-HTMLSection -Invisible { New-HTMLPanel -Width 10% { New-HTMLText -Text "Certificate Template Issues ($($templateIssues.Count) issues)" -FontSize 20 -FontWeight bold New-HTMLText -Text @" Certificate templates are the most common source of AD CS vulnerabilities. These issues allow principals to request certificates with dangerous permissions, subject alternative names, or enrollment agent capabilities. "@ -Color '#888' -FontSize 14 } New-HTMLPanel { New-HTMLTable -DataTable $templateIssuesTable ` -Filtering ` -PagingLength 25 ` -Buttons @('copyHtml5', 'excelHtml5', 'csvHtml5') ` -Title 'Template Vulnerabilities' { New-HTMLTableCondition -Name 'Technique' -Value 'ESC1' -BackgroundColor '#ffcdd2' -Color Black New-HTMLTableCondition -Name 'Enabled' -Value $true -BackgroundColor '#fff9c4' -Color Black } } } } New-HTMLTab -Name 'CAs' -IconSolid certificate -IconColor Yellow { New-HTMLSection -Invisible { New-HTMLPanel -Width 10% { New-HTMLText -Text "Certification Authority Issues ($($caIssues.Count) issues)" -FontSize 20 -FontWeight bold New-HTMLText -Text @" CA-level issues involve dangerous role assignments (ESC7) or insecure CA configurations (ESC6, ESC11, ESC16). These vulnerabilities grant principals excessive control over certificate issuance. "@ -Color '#888' -FontSize 14 } New-HTMLPanel { New-HTMLTable -DataTable $caIssuesTable ` -Filtering ` -PagingLength 25 ` -Buttons @('copyHtml5', 'excelHtml5', 'csvHtml5') ` -Title 'CA Configuration Issues' { New-HTMLTableCondition -Name 'Technique' -Value 'ESC7a' -BackgroundColor '#ffccbc' -Color Black New-HTMLTableCondition -Name 'Technique' -Value 'ESC7m' -BackgroundColor '#ffe0b2' -Color Black } } } } New-HTMLTab -Name 'Objects' -IconSolid folder -IconColor Blue { New-HTMLSection -Invisible { New-HTMLPanel -Width 10% { New-HTMLText -Text "PKI Object Issues ($($objectIssues.Count) issues)" -FontSize 20 -FontWeight bold New-HTMLText -Text @" ESC5 vulnerabilities involve dangerous ownership or write permissions on PKI infrastructure objects. These allow principals to modify templates, CAs, or other critical AD CS components. "@ -Color '#888' -FontSize 14 } New-HTMLPanel { New-HTMLTable -DataTable $objectIssuesTable ` -Filtering ` -PagingLength 25 ` -Buttons @('copyHtml5', 'excelHtml5', 'csvHtml5') ` -Title 'Infrastructure Object Issues' { New-HTMLTableCondition -Name 'Technique' -Value 'ESC5a' -BackgroundColor '#c5e1a5' -Color Black New-HTMLTableCondition -Name 'Technique' -Value 'ESC5o' -BackgroundColor '#fff59d' -Color Black } } } } New-HTMLTab -Name 'Risky Principals' -IconSolid user-shield -IconColor Purple { New-HTMLSection -Invisible { New-HTMLPanel -Width 10% { New-HTMLText -Text "Principal Risk Analysis ($($principalsTable.Count) principals)" -FontSize 20 -FontWeight bold New-HTMLText -Text @" This analysis shows which principals have access to the most AD CS vulnerabilities. Principals with high issue counts represent concentrated risk and should be prioritized for remediation or monitoring. "@ -Color '#888' -FontSize 14 } New-HTMLPanel { New-HTMLTable -DataTable $principalsTable ` -Filtering ` -PagingLength 25 ` -Buttons @('copyHtml5', 'excelHtml5', 'csvHtml5', 'pdfHtml5') ` -Title 'Principals by Risk Score' ` -DefaultSortColumn 'IssueCount' ` -DefaultSortOrder Descending { New-HTMLTableCondition -Name 'IssueCount' -ComparisonType number -Operator gt -Value 10 -BackgroundColor '#ef5350' -Color White New-HTMLTableCondition -Name 'IssueCount' -ComparisonType number -Operator ge -Value 5 -BackgroundColor '#ff9800' -Color White New-HTMLTableCondition -Name 'IssueCount' -ComparisonType number -Operator ge -Value 1 -BackgroundColor '#fdd835' -Color Black } } } } } Write-Verbose "Dashboard generated: $FilePath" if (-not $Show) { Write-Host "Dashboard saved to: $FilePath" } } |