Embora as ameaças cibernéticas certamente estejam em constante evolução, o fato é que a maioria das invasões ainda depende de técnicas básicas e comprovadas. Quem precisa queimar um dia zero se adivinhar senhas comumente usadas ou explorar senhas usadas em várias contas pode lhe dar acesso fácil?
Os ataques de força bruta continuam sendo uma ameaça incrivelmente comum que as organizações enfrentam. Detectar e bloquear essas tentativas o mais rápido possível é fundamental, pois elas costumam ser o prenúncio de atividades mais prejudiciais e tentativas de acesso mal-intencionado que estão por vir. Como cada minuto conta nessas situações, a configuração de políticas de bloqueio de contas e alertas em tempo real para tentativas de login fracassadas é uma medida extremamente importante de dissuasão e alerta antecipado.
Mas e quanto à detecção de ataques de força bruta remotamente e em escala em uma rede corporativa inteira?
Como isso pode ser um desafio, fornecemos o seguinte script que os administradores podem usar para automatizar o processo, monitorando as tentativas de login com falha e acionando alertas com base em limites personalizáveis.
Script de detecção e prevenção de ataques de força bruta
#Requires -Version 5.1
<#
.SYNOPSIS
Condition for helping detect brute force login attempts.
.DESCRIPTION
Condition for helping detect brute force login attempts.
.EXAMPLE
-Hours 10
Number of hours back in time to look through in the event log.
Default is 1 hour.
.EXAMPLE
-Attempts 100
Number of login attempts to trigger at or above this number.
Default is 8 attempts.
.OUTPUTS
PSCustomObject[]
.NOTES
Minimum OS Architecture Supported: Windows 10, Windows Server 2016
Release Notes:
Initial Release
By using this script, you indicate your acceptance of the following legal terms as well as our Terms of Use at https://www.ninjaone.com/terms-of-use.
Ownership Rights: NinjaOne owns and will continue to own all right, title, and interest in and to the script (including the copyright). NinjaOne is giving you a limited license to use the script in accordance with these legal terms.
Use Limitation: You may only use the script for your legitimate personal or internal business purposes, and you may not share the script with another party.
Republication Prohibition: Under no circumstances are you permitted to re-publish the script in any script library or website belonging to or under the control of any other software provider.
Warranty Disclaimer: The script is provided “as is” and “as available”, without warranty of any kind. NinjaOne makes no promise or guarantee that the script will be free from defects or that it will meet your specific needs or expectations.
Assumption of Risk: Your use of the script is at your own risk. You acknowledge that there are certain inherent risks in using the script, and you understand and assume each of those risks.
Waiver and Release: You will not hold NinjaOne responsible for any adverse or unintended consequences resulting from your use of the script, and you waive any legal or equitable rights or remedies you may have against NinjaOne relating to your use of the script.
EULA: If you are a NinjaOne customer, your use of the script is subject to the End User License Agreement applicable to you (EULA).
#>
[CmdletBinding()]
param (
[Parameter()]
[int]
$Hours = 1,
[Parameter()]
[int]
$Attempts = 8
)
begin {
function Test-IsElevated {
$id = [System.Security.Principal.WindowsIdentity]::GetCurrent()
$p = New-Object System.Security.Principal.WindowsPrincipal($id)
$p.IsInRole([System.Security.Principal.WindowsBuiltInRole]::Administrator)
}
function Test-StringEmpty {
param([string]$Text)
# Returns true if string is empty, null, or whitespace
process { [string]::IsNullOrEmpty($Text) -or [string]::IsNullOrWhiteSpace($Text) }
}
if (-not $(Test-StringEmpty -Text $env:Hours)) {
$Hours = $env:Hours
}
if (-not $(Test-StringEmpty -Text $env:Attempts)) {
$Attempts = $env:Attempts
}
}
process {
if (-not (Test-IsElevated)) {
Write-Error -Message "Access Denied. Please run with Administrator privileges."
exit 1
}
if ($(auditpol.exe /get /category:* | Where-Object { $_ -like "*Logon*Success and Failure" })) {
Write-Information "Audit Policy for Logon is set to: Success and Failure"
}
else {
Write-Error "Audit Policy for Logon is NOT set to: Success and Failure"
exit 1
# Write-Host "Setting Logon to: Success and Failure"
# auditpol.exe /set /subcategory:"Logon" /success:enable /failure:enable
# Write-Host "Future failed login attempts will be captured."
}
$StartTime = (Get-Date).AddHours(0 - $Hours)
$EventId = 4625
# Get failed login attempts
try {
$Events = Get-WinEvent -FilterHashtable @{LogName = "Security"; ID = $EventId; StartTime = $StartTime } -ErrorAction Stop | ForEach-Object {
$Message = $_.Message -split [System.Environment]::NewLine
$Account = $($Message | Where-Object { $_ -Like "*Account Name:*" }) -split 's+' | Select-Object -Last 1
[int]$LogonType = $($Message | Where-Object { $_ -Like "Logon Type:*" }) -split 's+' | Select-Object -Last 1
$SourceNetworkAddress = $($Message | Where-Object { $_ -Like "*Source Network Address:*" }) -split 's+' | Select-Object -Last 1
[PSCustomObject]@{
Account = $Account
LogonType = $LogonType
SourceNetworkAddress = $SourceNetworkAddress
}
} | Where-Object { $_.LogonType -in @(2, 7, 10) }
}
catch {
if ($_.Exception.Message -like "No events were found that match the specified selection criteria.") {
Write-Host "No failed logins found in the past $Hours hour(s)."
exit 0
}
else {
Write-Error $_
exit 1
}
}
# Build a list of accounts
$UsersAccounts = [System.Collections.Generic.List[String]]::new()
try {
$ErrorActionPreference = "Stop"
Get-LocalUser | Select-Object -ExpandProperty Name | ForEach-Object { $UsersAccounts.Add($_) }
$ErrorActionPreference = "Continue"
}
catch {
$NetUser = net.exe user
$(
$NetUser | Select-Object -Skip 4 | Select-Object -SkipLast 2
# Join each line with a ","
# Replace and spaces with a ","
# Split everything by ","
) -join ',' -replace 's+', ',' -split ',' |
# Sort and remove any duplicates
Sort-Object -Descending -Unique |
# Filter out empty strings
Where-Object { -not [string]::IsNullOrEmpty($_) -and -not [string]::IsNullOrWhiteSpace($_) } |
ForEach-Object {
$UsersAccounts.Add($_)
}
}
$Events | Select-Object -ExpandProperty Account | ForEach-Object { $UsersAccounts.Add($_) }
$Results = $UsersAccounts | Select-Object -Unique | ForEach-Object {
$Account = $_
$AccountEvents = $Events | Where-Object { $_.Account -like $Account }
$AttemptCount = $AccountEvents.Count
$SourceNetworkAddress = $AccountEvents | Select-Object -ExpandProperty SourceNetworkAddress -Unique
if ($AttemptCount -gt 0) {
[PSCustomObject]@{
Account = $Account
Attempts = $AttemptCount
SourceNetworkAddress = $SourceNetworkAddress
}
}
}
# Get only the accounts with fail login attempts at or over $Attempts
$BruteForceAttempts = $Results | Where-Object { $_.Attempts -ge $Attempts }
if ($BruteForceAttempts) {
$BruteForceAttempts | Out-String | Write-Host
exit 1
}
$Results | Out-String | Write-Host
exit 0
}
end {
$ScriptVariables = @(
[PSCustomObject]@{
name = "Hours"
calculatedName = "hours" # Must be lowercase and no spaces
required = $false
defaultValue = [PSCustomObject]@{ # If not default value, then remove
type = "TEXT"
value = "1"
}
valueType = "TEXT"
valueList = $null
description = "Number of hours back in time to look through in the event log."
}
[PSCustomObject]@{
name = "Attempts"
calculatedName = "attempts" # Must be lowercase and no spaces
required = $false
defaultValue = [PSCustomObject]@{ # If not default value, then remove
type = "TEXT"
value = "8"
}
valueType = "TEXT"
valueList = $null
description = "Number of login attempts to trigger at or above this number."
}
)
}
Acesse mais de 300 scripts no NinjaOne Dojo
Entendendo e usando o script
Nosso script se baseia em dois parâmetros principais: `Hours` e `-Attempts`. O parâmetro `-Hours` determina o período a ser revisado no registro de eventos (padrão: 1 hora). O parâmetro `-Attempts` define o limite de tentativas de login antes de acionar um alerta (padrão definido como 8 tentativas).
Para instalar e executar o script, siga estas etapas:
- Abra o PowerShell com privilégios de administrador.
- Copie o script em seu ambiente do PowerShell.
- Personalize os parâmetros `-Hours` e `-Attempts` conforme necessário.
- Execute o script.
Em seguida, o script avaliará os registros de eventos com base nos parâmetros fornecidos. Se o número de tentativas de login com falha ultrapassar o limite dentro do período de tempo especificado, ele o alertará sobre um possível ataque de força bruta.
Considere um exemplo em que você deseja monitorar as tentativas de login nas últimas três horas e deseja receber um alerta se houver mais de 15 tentativas com falha. Com o NinjaOne, você tem a flexibilidade de personalizar sua abordagem de segurança executando o script com parâmetros personalizados, como -Hours 3 -Attempts 15. Esse recurso permite que você se adapte às necessidades de segurança e aos perfis de risco exclusivos da sua organização.
Medidas de segurança adicionais
A detecção de ataques de força bruta é apenas um componente de uma estratégia holística de segurança cibernética. Outras medidas cruciais incluem:
- Senhas fortes: Incentive os usuários a criar senhas robustas e exclusivas – de preferência, uma combinação de letras, números e símbolos. Os gerenciadores de senhas podem facilitar o gerenciamento de senhas complexas.
- Autenticação multifatorial (MFA): A MFA fornece uma camada adicional de segurança, exigindo que os usuários verifiquem sua identidade usando dois ou mais mecanismos (por exemplo, algo que eles sabem, algo que eles têm ou algo que eles são).
- Atualizações de software: A atualização regular do software é fundamental. As atualizações geralmente incluem correções para vulnerabilidades de segurança que, se não forem corrigidas, podem ser uma porta aberta para ataques cibernéticos.
- Treinamento de funcionários: O estabelecimento de um programa de treinamento de conscientização sobre segurança ajuda a educar os funcionários sobre as ameaças cibernéticas e o papel que eles desempenham na manutenção da segurança. O fator humano é geralmente o elo mais fraco da segurança cibernética, e funcionários bem informados podem reforçar significativamente suas defesas.
Considerações finais
A detecção eficaz de força bruta é crucial no atual cenário digital, e nosso script do PowerShell oferece uma solução potente e personalizável. No entanto, é essencial lembrar que ele faz parte de uma estratégia mais ampla de segurança cibernética. Ao combinar a detecção em tempo real com senhas fortes, MFA, atualizações de software e treinamento de funcionários, é possível criar um protocolo de segurança abrangente para proteger seus ativos digitais.
O NinjaOne é uma ferramenta abrangente que reforça significativamente sua capacidade de detectar e neutralizar ataques de força bruta. Com controle total sobre a segurança do endpoint, você pode gerenciar aplicativos, editar registros remotamente e implementar scripts para aumentar a segurança. Os controles de acesso baseados em funções garantem que seus técnicos tenham apenas os níveis de acesso necessários, reduzindo os possíveis pontos de violação. A plataforma também oferece ferramentas de gerenciamento de criptografia de unidades e a capacidade de instalar e gerenciar automaticamente a proteção de endpoints, proporcionando controle granular sobre as operações de antivírus.
Além disso, o recurso de troca de credenciais do NinjaOne protege as credenciais, uma linha crítica de defesa contra ataques de força bruta. Ele também permite a identificação e a remoção de endpoints desonestos, acrescentando uma camada extra de proteção. Não espere que ocorra uma violação. Comece sua jornada para aumentar a segurança hoje mesmo com o NinjaOne.