Como monitorizar alterações de permissões NTFS em PowerShell: passo a passo
Este tutorial mostra como monitorizar alterações de permissões NTFS em PowerShell para detetar quando as ACLs (Access Control Lists) de ficheiros ou pastas são alteradas. É útil para auditoria, segurança e para manter o controlo sobre quem tem acesso a dados sensíveis.
Pré-requisitos
- Windows 10/11 ou Windows Server com PowerShell 5.1 ou PowerShell 7+
- Permissões de leitura nas pastas a monitorizar
- Preferível executar o PowerShell com privilégios elevados para aceder a todas as ACLs
- Editor de texto (ex.: Visual Studio Code) para guardar o script
Passo 1: Porque monitorizar ACLs e a abordagem
Alterações a permissões NTFS nem sempre criam um evento claro no sistema. A abordagem aqui é ler periodicamente as ACLs de uma pasta/ficheiro, gerar um hash representativo e comparar com o snapshot anterior. Quando o hash muda, regista-se a diferença e envia-se uma notificação simples.
Passo 2: Função para obter um 'fingerprint' da ACL
Vamos criar uma função que lê a ACL de uma pasta e cria um fingerprint consistente. Isto permite comparar versões de forma rápida.
function Get-AclFingerprint {
param(
[Parameter(Mandatory)] [string] $Path
)
# Obtém a ACL e cria uma string ordenada para hashing
$acl = Get-Acl -Path $Path
$entries = $acl.Access | ForEach-Object {
"{0}|{1}|{2}|{3}|{4}" -f $_.IdentityReference, $_.FileSystemRights, $_.AccessControlType, $_.InheritanceFlags, $_.PropagationFlags
}
$entries = $entries | Sort-Object
$joined = $entries -join ";"
# MD5 é suficiente para fingerprint (não para segurança criptográfica)
$md5 = [System.Security.Cryptography.MD5]::Create()
$bytes = [System.Text.Encoding]::UTF8.GetBytes($joined)
$hash = $md5.ComputeHash($bytes)
return ([System.BitConverter]::ToString($hash)).Replace("-","")
}
Passo 3: Capturar snapshot inicial e guardar em ficheiro
Guarde o fingerprint inicial num ficheiro JSON para comparações futuras. Pode monitorizar várias pastas guardando um objecto por caminho.
$paths = @('C:\Dados\Projeto', 'C:\Logs')
$snapshot = @{}
foreach ($p in $paths) {
if (Test-Path $p) {
$snapshot[$p] = Get-AclFingerprint -Path $p
}
}
$snapshot | ConvertTo-Json | Out-File -FilePath 'C:\MonitorACL\acl_snapshot.json' -Encoding UTF8
Passo 4: Script de monitorização e deteção de mudanças
Script que carrega o snapshot, recalcula fingerprints e, ao detectar mudança, escreve para um log e grava o novo snapshot. Também mostra como obter a diferença nas entradas ACL para contextualizar a alteração.
# Requer a função Get-AclFingerprint definida acima
$snapshotPath = 'C:\MonitorACL\acl_snapshot.json'
$logPath = 'C:\MonitorACL\acl_changes.log'
$paths = @('C:\Dados\Projeto', 'C:\Logs')
# Carrega snapshot existente
if (Test-Path $snapshotPath) {
$oldSnapshot = Get-Content $snapshotPath -Raw | ConvertFrom-Json | ConvertTo-Hashtable
} else {
$oldSnapshot = @{}
}
foreach ($p in $paths) {
if (-not (Test-Path $p)) { continue }
$newHash = Get-AclFingerprint -Path $p
$oldHash = $oldSnapshot[$p]
if ($oldHash -ne $null -and $newHash -ne $oldHash) {
$time = (Get-Date).ToString('s')
$msg = "[$time] ACL altered for $p (old:$oldHash new:$newHash)"
$msg | Out-File -FilePath $logPath -Append -Encoding UTF8
# Opcional: obter e registar entradas ACL actuais para análise
$acl = Get-Acl -Path $p
$entries = $acl.Access | ForEach-Object { "{0} {1} {2}" -f $_.IdentityReference, $_.FileSystemRights, $_.AccessControlType }
($time + ' - Entries:') | Out-File -FilePath $logPath -Append -Encoding UTF8
$entries | Out-File -FilePath $logPath -Append -Encoding UTF8
}
# Actualiza snapshot em memória
$oldSnapshot[$p] = $newHash
}
# Grava snapshot actualizado
$oldSnapshot | ConvertTo-Json | Out-File -FilePath $snapshotPath -Encoding UTF8
Passo 5: Agendar execução periódica (exemplo rápido)
Para monitorização contínua, pode executar o script num loop com atraso ou usar o Task Scheduler. Exemplo de loop simples que corre a cada 5 minutos (útil para testes).
while ($true) {
& 'C:\MonitorACL\Check-AclChanges.ps1'
Start-Sleep -Seconds 300
}
Verificar o resultado
Abra o ficheiro de log definido (ex.: C:\MonitorACL\acl_changes.log) para ver entradas com timestamps quando ocorreram alterações. Verifique também acl_snapshot.json para confirmar que os hashes foram actualizados. Se não surgir nenhum registo apesar de alterações, confirme permissões, caminhos e se o script tem acesso a Get-Acl para esses itens.
Conclusão
Com este método simples consegue monitorizar alterações de permissões NTFS usando PowerShell, registar eventos e guardar snapshots para auditoria. Próximos passos: integrar com envio de e-mail ou Teams quando ocorrer uma alteração, e usar Event Forwarding para centralizar logs. Dica: teste primeiro em pastas não críticas para validar falsos positivos e ajustar a frequência de verificação.