Improve UPN export handling
This commit is contained in:
@@ -11,6 +11,7 @@ Fixed:
|
|||||||
### Test-WeakADPasswords.ps1 v1.3.1
|
### Test-WeakADPasswords.ps1 v1.3.1
|
||||||
Fixed:
|
Fixed:
|
||||||
- Domain picker now renders in numeric order from settings for predictable operator workflows.
|
- Domain picker now renders in numeric order from settings for predictable operator workflows.
|
||||||
|
- UPN export now relies on structured weak-password results, so dictionary hit UPN lists are populated reliably.
|
||||||
|
|
||||||
## 2025-10-10
|
## 2025-10-10
|
||||||
|
|
||||||
|
|||||||
@@ -365,40 +365,62 @@ function Test-WeakADPasswords {
|
|||||||
# Report generation with dynamic content and UPNs
|
# Report generation with dynamic content and UPNs
|
||||||
$reportPath = Join-Path -Path $reportPathBase -ChildPath "$($selectedDomain.Name)_WeakPasswordReport_$timestamp.txt"
|
$reportPath = Join-Path -Path $reportPathBase -ChildPath "$($selectedDomain.Name)_WeakPasswordReport_$timestamp.txt"
|
||||||
$upnOnlyReportPath = Join-Path -Path $reportPathBase -ChildPath "$($selectedDomain.Name)_DictionaryPasswordUPNs_$timestamp.txt"
|
$upnOnlyReportPath = Join-Path -Path $reportPathBase -ChildPath "$($selectedDomain.Name)_DictionaryPasswordUPNs_$timestamp.txt"
|
||||||
|
|
||||||
Write-Verbose "Generating report at $reportPath"
|
# Build a lookup of SAM account names to UPNs for dictionary hits by leveraging structured results
|
||||||
$reportContent = @($header, ($testResults | Out-String).Trim(), $footer) -join "`r`n"
|
$dictionaryLogonNames = @()
|
||||||
|
foreach ($result in @($testResults)) {
|
||||||
$lines = $reportContent -split "`r`n"
|
if ($null -ne $result -and $null -ne $result.WeakPassword) {
|
||||||
$newReportContent = @()
|
$dictionaryLogonNames += $result.WeakPassword
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$dictionaryLogonNames = $dictionaryLogonNames | Sort-Object -Unique
|
||||||
|
|
||||||
|
$dictionarySamToUpn = @{}
|
||||||
$upnReportContent = @()
|
$upnReportContent = @()
|
||||||
|
|
||||||
|
foreach ($logonName in $dictionaryLogonNames) {
|
||||||
|
$samAccountName = $logonName -replace '^.*\\', ''
|
||||||
|
if (-not [string]::IsNullOrWhiteSpace($samAccountName) -and -not $dictionarySamToUpn.ContainsKey($samAccountName)) {
|
||||||
|
Write-Verbose "Looking up UPN for $samAccountName (dictionary hit)"
|
||||||
|
$upn = Get-UserUPN -SamAccountName $samAccountName -Domain $selectedDomain.DC -Credential $credential
|
||||||
|
$dictionarySamToUpn[$samAccountName] = $upn
|
||||||
|
if ($upn -ne "UPN not found") {
|
||||||
|
$upnReportContent += $upn
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Write-Verbose "Generating report at $reportPath"
|
||||||
|
$reportContent = @($header, ($testResults | Out-String).Trim(), $footer) -join "`r`n"
|
||||||
|
|
||||||
|
$lines = $reportContent -split "`r`n"
|
||||||
|
$newReportContent = @()
|
||||||
$collectingUPNs = $false
|
$collectingUPNs = $false
|
||||||
|
|
||||||
foreach ($line in $lines) {
|
foreach ($line in $lines) {
|
||||||
$newReportContent += $line
|
$newReportContent += $line
|
||||||
|
|
||||||
# Start collecting UPNs after detecting the relevant section in the report
|
|
||||||
if ($line -match "Passwords of these accounts have been found in the dictionary:") {
|
if ($line -match "Passwords of these accounts have been found in the dictionary:") {
|
||||||
$collectingUPNs = $true
|
$collectingUPNs = $true
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
# Stop collecting UPNs if a new section starts or end of section is detected
|
if ($collectingUPNs) {
|
||||||
if ($collectingUPNs -and $line -match "^\s*$") {
|
if ($line -match '^\s*$') { continue }
|
||||||
$collectingUPNs = $false
|
if ($line -match '^\s*-{2,}') { continue }
|
||||||
}
|
if ($line -match '^\s*(SamAccountName|LogonName)\b') { continue }
|
||||||
|
if ($line -match '^[^\s].*:\s*$' -and $line -notmatch 'dictionary') {
|
||||||
|
$collectingUPNs = $false
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
# Regex to match the SAMAccountName from the report line and collect UPNs if in the target section
|
$firstToken = ($line.Trim() -split '\s+')[0]
|
||||||
if ($collectingUPNs -and $line -match "^\s*(\S+)\s*$") {
|
if (-not [string]::IsNullOrWhiteSpace($firstToken)) {
|
||||||
$samAccountName = $matches[1]
|
$samAccountName = $firstToken -replace '^.*\\', ''
|
||||||
Write-Verbose "Looking up UPN for $samAccountName"
|
if ($dictionarySamToUpn.ContainsKey($samAccountName)) {
|
||||||
$upn = Get-UserUPN -SamAccountName $samAccountName -Domain $selectedDomain.DC -Credential $credential
|
$upnValue = $dictionarySamToUpn[$samAccountName]
|
||||||
$newReportContent += " UPN: $upn"
|
$newReportContent += " UPN: $upnValue"
|
||||||
|
}
|
||||||
# Collect UPNs only for accounts found in the dictionary section
|
|
||||||
if ($upn -ne "UPN not found") {
|
|
||||||
$upnReportContent += $upn
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user