La gestió de la seguretat d'Active Directory (AD) pot ser desafiant, especialment quan s'identifiquen els comptes que comparteixen contrasenyes o s'utilitzen pràctiques d'autenticació febles. , una potent eina PowerShell lleugera que revela ràpidament l'ús de contrasenya compartida i millora la postura de seguretat d'AD de l'organització. LazyAdminFinder Què és LazyAdminFinder? LazyAdminFinder és un script PowerShell que aprofita el mòdul DSInternals per: Detectar i reportar hash de contrasenya compartit NTLM. Arxiu i comparació de dades de hash històrics per identificar la reutilització de contrasenyes. Proporcionar informes exhaustius que identifiquin comportaments de compte arriscats. Dissenyat específicament per als administradors d'Active Directory, LazyAdminFinder proporciona una visió ràpida i factible de la seguretat de contrasenyes. Per què utilitzar LazyAdminFinder? Identify weak or compromised passwords. Security Improvement: Maintain AD integrity for audit and compliance purposes. Compliance: Quickly audit accounts without manually reviewing data. Efficiency: Com funciona LazyAdminFinder? Fitxar i filtrar els comptes d'usuari El script recull els comptes d'usuari d'AD, filtrant els comptes d'usuari desactivat, màquina i servei per centrar-se només en els usuaris actius. Extracció i arxivament de hash de NTLM LazyAdminFinder extreu hash NTLM dels comptes i arxiva de forma segura els seus hash SHA-256 per a la comparació històrica. Recuperació de contrasenyes By comparing the current run to previous archives, the tool detects password reuse, flagging accounts with potential security risks. This helps identify: Permet als usuaris administratius o privilegis sincronitzar contrasenyes entre comptes estàndard i administratiu. Els usuaris, especialment els administradors, repetidament restableixen les seves contrasenyes als valors utilitzats anteriorment. Grups de contrasenya compartida El guió identifica i agrupa els comptes que comparteixen hash de NTLM idèntics, el que pot indicar que s'han compartit contrasenyes intencionals o que diversos usuaris han triat la mateixa contrasenya de forma independent, sovint a causa d'hàbits de contrasenyes febles. Freqüència d'ús recomanada Considereu executar LazyAdminFinder regularment basant-vos en la política de restabliment de contrasenyes de la vostra organització. Per exemple, si la vostra política requereix una restabliment de contrasenyes cada 90 dies, planifiqueu el guió per executar-lo aproximadament cada 100 dies. Aquest temps assegura que captureu instàncies en què els administradors o els usuaris privilegiats puguin restablir les seves contrasenyes a les usades anteriorment. Si la vostra organització no imposa una política de reutilització de contrasenyes, executar LazyAdminFinder periòdicament esdevé encara més crucial per identificar i mitigar possibles riscos de seguretat. Instal·lació de LazyAdminFinder Pas 1: Preparació Assegureu-vos que PowerShell està instal·lat al vostre sistema. Instal·lació del mòdul requerit: Install-Module DSInternals Pas 2: Configurar el guió Personalitzeu aquests paràmetres essencials dins del guió proporcionat: Controlador de domini: $dc = "your-domain-controller.example.com" Nom del context: $nc = "DC=yourdomain,DC=com" Ruta de l'informe de sortida: $outputReport = "C:\Path\To\SharedPasswordsReport.csv" Direcció Arxiu: $archiveDir = "C:\Path\To\HashArchives" Pas 3: Executar el guió Executar el guió com a administrador de domini: powershell.exe -ExecutionPolicy Bypass -File "C:\Path\To\LazyAdminFinder.ps1" Revisió dels resultats Es genera un informe CSV detallat, destacant clarament els comptes que comparteixen contrasenyes o trien de forma independent contrasenyes febles. Els arxius històrics s'emmagatzemen de forma segura per a futures comparacions, garantint una gestió de contrasenyes robusta. Ús de casos per a LazyAdminFinder Auditories de seguretat: identificar i corregir regularment contrasenyes compartides, febles o compromeses. Resposta a incidents: detecta ràpidament els comptes compromesos després d'incidents de seguretat. Comprovacions de conformitat de rutina: Assegureu el compliment continu mitjançant el manteniment de pràctiques de seguretat de comptes sòlides. Gestió de comptes privilegiats: Es dirigeix específicament als administradors o usuaris privilegiats que poden reutilitzar o sincronitzar contrasenyes a través de múltiples comptes. Creació de LazyAdminFinder Pots ajustar el guió segons el teu entorn i les teves necessitats: Modificar la lògica de filtració per incloure/excloure tipus de compte específics. Ajusta els camins d'arxiu i informes per a les teves preferències d'emmagatzematge. Incorporar capacitats d'informació addicionals segons sigui necessari. Avantatges de l'ús de LazyAdminFinder Automates complex AD security checks. Rapid Security Assessments: Clearly identifies potential security risks within AD. Enhanced Visibility: Enables administrators to swiftly address vulnerabilities before exploitation. Proactive Defense: LazyAdminFinder simplifica la tasca crítica de l'auditoria de contrasenyes en Active Directory, permetent als administradors mantenir un entorn de TI segur, compatible i eficient. Descobreix contrasenyes compartides, remedia els riscos de seguretat i reforça la seguretat dels teus anuncis sense esforç amb LazyAdminFinder. #Another /\_[]_/\ # fine |] _||_ [| # ___ \/ || \/ # /___\ || # (|0 0|) || # __/{\U/}\_ ___/vvv # / \ {~} / _|_P| # | /\ ~ /_/ [] # |_| (____) # \_]/______\ Barberion # _\_||_/_ Production # (_,_||_,_) # Import-Module DSInternals # === Parameters === $dc = "your-domain-controller.example.com" $nc = "DC=yourdomain,DC=com" $outputReport = "C:\Path\To\SharedPasswordsReport.csv" $archiveDir = "C:\Path\To\HashArchives" # Ensure archive directory exists if (-not (Test-Path $archiveDir)) { New-Item -ItemType Directory -Path $archiveDir | Out-Null } $timestamp = (Get-Date).ToString("yyyyMMdd_HHmmss") # === 1. Fetch & filter AD user accounts === Write-Host "[+] Fetching AD user accounts (skipping machines, service & disabled)..." $filteredAccounts = Get-ADReplAccount -All -Server $dc -NamingContext $nc | Where-Object { $_.NTHash -and $_.SamAccountName } | Where-Object { $_.SamAccountName -notmatch '\$$' } | Where-Object { $_.SamAccountName -notmatch '^(?i)(svc|service)' } | Where-Object { if ($_.PSObject.Properties.Match('IsDisabled').Count -gt 0) { -not $_.IsDisabled } else { # bit 2 = disabled ( ($_.UserAccountControl -band 2) -eq 0 ) } } if (-not $filteredAccounts) { Write-Host "[-] No matching user accounts found. Exiting." exit } # === 2. Convert NTLM byte array to hex string === $filteredAccounts | ForEach-Object { $hex = [BitConverter]::ToString($_.NTHash) -replace '-', '' $_ | Add-Member -MemberType NoteProperty -Name NTLMHashString -Value $hex -Force } # === 3. Archive SHA-256 of each NTLM hash === Write-Host "[+] Archiving SHA-256 of each NTLM hash..." $sha256 = [System.Security.Cryptography.SHA256]::Create() $currentArchive = $filteredAccounts | ForEach-Object { $shaBytes = $sha256.ComputeHash($_.NTHash) $shaHex = [BitConverter]::ToString($shaBytes) -replace '-', '' [PSCustomObject]@{ SamAccountName = $_.SamAccountName HashSha256 = $shaHex } } $sha256.Dispose() $archiveFile = Join-Path $archiveDir "UserHashArchive_$timestamp.csv" $currentArchive | Export-Csv -Path $archiveFile -NoTypeInformation # === 4. Compare to previous archive === $allArchives = Get-ChildItem -Path $archiveDir -Filter "UserHashArchive_*.csv" | Sort-Object LastWriteTime -Descending if ($allArchives.Count -gt 1) { $previousFile = $allArchives[1].FullName Write-Host "[+] Comparing this run to previous archive: $previousFile" $prevData = Import-Csv $previousFile $reused = Compare-Object ` -ReferenceObject $prevData ` -DifferenceObject $currentArchive ` -Property SamAccountName, HashSha256 ` -IncludeEqual | Where-Object { $_.SideIndicator -eq '==' } | Select-Object SamAccountName, HashSha256 if ($reused) { $reuseReport = Join-Path $archiveDir "PasswordReuse_$timestamp.csv" Write-Host "[!] $($reused.Count) accounts reused their old hash; exporting to $reuseReport" $reused | Export-Csv -Path $reuseReport -NoTypeInformation } else { Write-Host "[+] No password‑reuse detected this run." } } else { Write-Host "[+] Only one archive present; skipping reuse comparison." } # === 5. Shared‑password grouping & report === Write-Host "[+] Grouping accounts by shared NTLM hash..." $sharedGroups = $filteredAccounts | Group-Object -Property NTLMHashString | Where-Object { $_.Count -gt 1 } if (-not $sharedGroups) { Write-Host "[-] No shared hashes found." exit } $reportResults = @() Write-Host "[+] Generating shared‑password report:" foreach ($g in $sharedGroups) { $h = $g.Name $users = $g.Group | ForEach-Object { $_.SamAccountName } $reportResults += [PSCustomObject]@{ SharedHash = $h UserCount = $users.Count Users = $users -join ', ' } Write-Host '----------------------------------------------' Write-Host "Shared Hash: $h" Write-Host "User Count : $($users.Count)" Write-Host "Users : $($users -join ', ')" Write-Host '----------------------------------------------`n' } Write-Host "[+] Saving shared‑password report to $outputReport" $reportResults | Export-Csv -Path $outputReport -NoTypeInformation Write-Host "[Summary] Shared groups: $($reportResults.Count); Total archives: $($allArchives.Count)"