Files
phi-scanner/scripts/win_scan_targeted.ps1
2026-05-08 17:44:26 -05:00

67 lines
3.4 KiB
PowerShell

# GreySec PHI Scanner - Targeted WinServer Scan
$ErrorActionPreference = 'SilentlyContinue'
$results = @{
hostname = $env:COMPUTERNAME
timestamp = (Get-Date).ToString("o")
total_files_scanned = 0
findings = @()
}
$searchPaths = @('C:\phi_test')
$exts = @('*.txt','*.csv','*.log','*.json','*.xml','*.sql','*.cfg','*.ini','*.dat')
$ssnRx = [regex]'\b\d{3}[-\s]\d{2}[-\s]\d{4}\b'
$mrnRx = [regex]'\b(MRN|Medical Record|EHR|Patient ID)[:\s#]*\d{6,10}\b', [regex]'\b\d{6,10}\b'
$phoneRx = [regex]'\b(\+?1[-.\s]?)?\(?\d{3}\)?[-.\s]?\d{3}[-.\s]?\d{4}\b'
$emailRx = [regex]'\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}\b'
$dobRx = [regex]'\b(0[1-9]|1[0-2])[/.-](0[1-9]|[12]\d|3[01])[/.-](19|20)\d{2}\b'
$zip4Rx = [regex]'\b\d{5}[-\s]\d{4}\b'
$ipRx = [regex]'\b\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\b'
$maxSize = 52428800
$count = 0
foreach ($sp in $searchPaths) {
if (Test-Path $sp) {
Get-ChildItem -Path $sp -File -Recurse | Where-Object { $_.Length -le $maxSize } | ForEach-Object {
$content = $_ | Get-Content -Raw -Encoding UTF8
if ($null -eq $content) { return }
$fn = $_.FullName
$count++
# SSN
$ssnRx.Matches($content) | ForEach-Object {
$val = $_.Value
$ctx = $content.Substring([Math]::Max(0,$_.Index-$30),[Math]::Min(80,$content.Length-$_.Index+$_.Length+30)).Replace("`n"," ").Replace("`r","")
$results.findings += @{type='SSN';value=$val;file=$fn;context=$ctx}
}
# MRN
$mrnRx | ForEach-Object {
$_.Matches($content) | Where-Object { $_.Value -notmatch '^\d{10}$' } | ForEach-Object {
$val = $_.Value
$ctx = $content.Substring([Math]::Max(0,$_.Index-$30),[Math]::Min(80,$content.Length-$_.Index+$_.Length+30)).Replace("`n"," ").Replace("`r","")
$results.findings += @{type='MRN';value=$val;file=$fn;context=$ctx}
}
}
# Phone
$phoneRx.Matches($content) | Where-Object { $_.Value.Length -ge 10 } | ForEach-Object {
$val = $_.Value
$ctx = $content.Substring([Math]::Max(0,$_.Index-$30),[Math]::Min(80,$content.Length-$_.Index+$_.Length+30)).Replace("`n"," ").Replace("`r","")
$results.findings += @{type='Phone';value=$val;file=$fn;context=$ctx}
}
# Email
$emailRx.Matches($content) | ForEach-Object {
$val = $_.Value
$ctx = $content.Substring([Math]::Max(0,$_.Index-$30),[Math]::Min(80,$content.Length-$_.Index+$_.Length+30)).Replace("`n"," ").Replace("`r","")
$results.findings += @{type='Email';value=$val;file=$fn;context=$ctx}
}
# DOB
$dobRx.Matches($content) | ForEach-Object {
$val = $_.Value
$ctx = $content.Substring([Math]::Max(0,$_.Index-$30),[Math]::Min(80,$content.Length-$_.Index+$_.Length+30)).Replace("`n"," ").Replace("`r","")
$results.findings += @{type='DOB';value=$val;file=$fn;context=$ctx}
}
}
}
}
$results.total_files_scanned = $count
$json = $results | ConvertTo-Json -Depth 6
$json | Set-Content -Path 'C:\phi_test\phi_scan_results.json' -Encoding UTF8
$ssnCount = ($results.findings | Where-Object {$_.type -eq 'SSN'}).Count
"FINISHED:$count`:$ssnCount"