Detecção e prevenção de ataques de força bruta com o PowerShell

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

Obter acesso

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:

  1. Abra o PowerShell com privilégios de administrador.
  2. Copie o script em seu ambiente do PowerShell.
  3. Personalize os parâmetros `-Hours` e `-Attempts` conforme necessário.
  4. 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.

Próximas etapas

Montar uma equipe de TI eficaz requer uma solução centralizada que seja a principal ferramenta de entrega de serviços. Com NinjaOne, a TI monitora, gerencia, protege e oferece suporte a todos os dispositivos, onde quer que estejam, dispensando infraestrutura complexa no local.

Saiba mais sobre a solução NinjaOne Remote Script Deployment, agende uma demonstração, ou inicie sua avaliação gratuita da plataforma NinjaOne.

Categorias:

Recomendados para você

Aprimoramento da comunicação de TI: Domínio das mensagens pop-up do PowerShell

Simplifique a configuração de sua VPN: Configurar uma VPN com o PowerShell

Automatização da criação de atalhos para a área de trabalho remota usando o PowerShell

Como criar uma nova conta de usuário local com o PowerShell

Dominando o gerenciamento de energia do Windows: Um guia do PowerShell para profissionais de TI e MSPs

Como renomear máquinas Windows com o PowerShell

Termos e condições NinjaOne

Ao clicar no botão “Aceito” abaixo, você indica sua aceitação dos seguintes termos legais, bem como dos nossos Termos de Uso:

  • Direitos de propriedade: A NinjaOne é proprietária e continuará a ser proprietária de todos os direitos, títulos e interesses relativos ao script (incluindo os direitos autorais). A NinjaOne está concedendo a você uma licença limitada para usar o script de acordo com os presentes termos legais.
  • Limitação de uso: Você só poderá usar o script para fins comerciais internos ou pessoais legítimos, sendo vedado compartilhar o script com terceiros.
  • Proibição de republicação: Em nenhuma circunstância você tem permissão para republicar o script em qualquer biblioteca de scripts pertencente ou sob o controle de qualquer outro fornecedor de software.
  • Isenção de responsabilidade da garantia: O script é fornecido “no estado em que se encontra” e “conforme disponível”, sem qualquer tipo de garantia. A NinjaOne não promete ou garante que o script estará livre de defeitos ou que atenderá às suas necessidades ou expectativas específicas.
  • Assunção de riscos: O uso do script é por sua própria conta e risco. Você reconhece que há certos riscos inerentes ao uso do script, e você compreende e assume cada um desses riscos.
  • Renúncia e isenção de responsabilidade: Você não responsabilizará a NinjaOne por consequências adversas ou não intencionais resultantes do seu uso do script e renunciará a quaisquer direitos ou tutelas legais que possa ter contra a NinjaOne em relação ao seu uso do script.
  • EULA: Se você for cliente da NinjaOne, o uso do script está sujeito ao Contrato de Licença de Usuário Final aplicável a você (EULA).