Proibir o endereço IP com base no número X de tentativas malsucedidas de login?


47

É possível banir um endereço IP após um número X de tentativas malsucedidas de logon no Windows Server? Não para uma conta específica, que eu sei fazer, mas para toda a máquina.

Nós somos atingidos com força por ataques de força bruta tentando adivinhar nomes de usuários, então isso realmente ajudaria a obter alguma carga do servidor.


8
* nix tem fial2ban ... não tenho certeza se existe uma porta / equivalente do Windows. fail2ban.org/wiki/index.php/Main_Page
Chris Nava

5
De Evan Anderson: serverfault.com/questions/43360/… ... parece ser um bom equivalente da funcionalidade do fail2ban, mas como sua pergunta não é específica o suficiente, não sei se você está tentando banir IPs que tentam fazer login para um site hospedado, seu servidor (via SSH) ou seu domínio. O esclarecimento percorreu um longo caminho. Além disso, você pode classificar o limite no seu firewall, mas isso depende da implementação.

4
Você pode dar uma olhada em serverfault.com/questions/216995/… para uma discussão anterior sobre a utilidade do banimento automatizado com base no IP.
pehrs 13/02/11

11
Se você está falando sobre Terminal Services / área de trabalho remota, dê uma olhada aqui: serverfault.com/a/335976/7200
Evan Anderson

3
Fiz um serviço do Windows no github para fazer exatamente isso: github.com/jjxtra/Windows-IP-Ban-Service
jjxtra

Respostas:


28

Você pode fazer isso com o PowerShell e o Gerenciador de tarefas. Provavelmente não é uma solução perfeita, mas funciona muito bem e tenho cerca de 100 endereços IP bloqueados em dois meses. Eu escrevi um script que seleciona eventos especificados do EventLog ("falha de auditoria"). Se houver muitos logins com falha de qualquer endereço IP, ele será adicionado à regra de firewall (criada manualmente) chamada "BlockAttackers", que bloqueia qualquer tráfego para os endereços IP especificados.

Script PS1:

$DT = [DateTime]::Now.AddDays(-1) # check only last 24 hours

$l = Get-EventLog -LogName 'Security' -InstanceId 4625 -After $DT | Select-Object @{n='IpAddress';e={$_.ReplacementStrings[-2]} } # select Ip addresses that has audit failure 
$g = $l | group-object -property IpAddress  | where {$_.Count -gt 20} | Select -property Name # get ip adresses, that have more than 20 wrong logins

$fw = New-Object -ComObject hnetcfg.fwpolicy2 # get firewall object

$ar = $fw.rules | where {$_.name -eq 'BlockAttackers'} # get firewall rule named 'BlockAttackers' (must be created manually)

$arRemote = $ar.RemoteAddresses -split(',') #split the existing IPs into an array so we can easily search for existing IPs

$w = $g | where {$_.Name.Length -gt 1 -and  !($arRemote -contains $_.Name + '/255.255.255.255') } # get ip addresses that are not already in firewal rule. Include the subnet mask which is automatically added to the firewall remote IP declaration.

$w| %{$ar.remoteaddresses += ',' + $_.Name} # add IPs to firewall rule

Crie uma tarefa no planejador e defina o gatilho para o evento 4625 (logon no Windows, incluindo serviços de terminal). Mas você pode configurar o acionador para executar, por exemplo, duas vezes por hora para evitar o carregamento desnecessário do servidor.

Disparador do agendador

e após o gatilho, execute o script powershell. Você também deve definir privilégios mais altos para executar este script, caso contrário, ele falhará com exceção de segurança.

script do PowerShell em Execução

Você também pode vincular esse script a outros eventos de segurança.


11
Excelente script @remunda - obrigado! Eu também estava recebendo muitos 4625s do FTP, para os quais o log de segurança não possui endereços IP, então ampliei o seu script para verificar também o log de FTP do dia atual. Por favor, veja a minha resposta abaixo para mais informações: serverfault.com/a/571903/107701
kevinmicke

Existem muitas dicas e casos extremos com os logs de eventos, o registro de endereços IP etc. que eu lidei com o IPBan - de código aberto e gratuito em github.com/jjxtra/Windows-IP-Ban-Service
jjxtra

7

Eu sei que essa pergunta é antiga, mas foi realmente o primeiro post do fórum que eu me deparei quando comecei a tentar fazer exatamente a mesma coisa há algumas semanas. Eu consegui criar um script de trabalho que analise os logs de eventos 24 horas atrás apenas para entradas de log de eventos com logon incorreto, pegue aquelas com mais de 10 logins incorretos e coloque-os em uma lista de filtros ipsec usando o comando netsh. Depois, escrevi um arquivo em lotes com essa linha powershell .\*scriptname.ps1*e criei uma tarefa agendada para executar o arquivo em lotes a cada 24 horas (por algum motivo, ele não seria executado diretamente).

$DATE = [DateTime]::Now.AddDays(-1)

$EVS = Get-EventLog Security -InstanceId 529 -after $DATE

$EVS | select-string -inputobject {$_.message} -pattern "Source Network Address:(.)*\.*\.*\.*"  -allmatches | foreach-object {$_.Matches} | foreach-object {$_.Value} | foreach-object {$_.replace("Source Network Address:", "")} | group-object -property $_ | where-object {$_.count -gt 10} | select-object -property name | format-list | out-file c:\rdpblock.txt 

get-content -path c:\rdpblock.txt | foreach-object {$_.replace("Name :", "")} | out-file c:\rdpblockcleaned.txt 

get-content -path c:\rdpblockcleaned.txt | select-object -unique | out-file c:\rdpblocknospaces.txt

$RDPIP = get-content -path c:\rdpblocknospaces.txt | select-object -skip 1

$RDPIP | foreach-object {$_.replace("     ", "")} | foreach-object {netsh ipsec static add filter filterlist=RDP_BLOCK srcaddr=$($_) dstaddr=any}

Sei que esse script é provavelmente ineficiente, mas quando comecei a trabalhar nele não tinha absolutamente nenhuma experiência em PowerShell, portanto, minha capacidade de otimizar scripts deixa muito a desejar. No entanto, apesar desse fato, pensei em compartilhar isso com qualquer pessoa que pudesse usá-lo.

Agradeço a Remunda por me dar a idéia inicial, foi o pôster que me levou à ideia de usar o PowerShell para pesquisar os logs de eventos.


4

Este script baseia-se na resposta do remunda e vai um pouco mais além https://serverfault.com/a/397637/155102 Ele é responsável pela regra "BlockAttackers" que ainda não possui nenhum IP inserido (o que retorna um "*" como uma string). Ele também grava um comentário em um arquivo de log para informar quando o IP foi adicionado à regra.

Uma boa dica é criar a regra "BlockAttackers" que bloqueia os endereços IP, mas torne-os desativados primeiro. Em seguida, execute esse script uma vez manualmente para poder preencher o campo "RemoteAddresses" com endereços IP reais que devem ser bloqueados. Dê uma olhada nesses endereços IP para garantir que nada de crítico tenha sido adicionado e ative a regra do firewall. Adicione esta regra ao seu firewall conforme descrito em remunda.

O git para este script

#Checks for IP addresses that used incorrect password more than 10 times
#within 24 hours and blocks them using a firewall rule 'BlockAttackers'

#Check only last 24 hours
$DT = [DateTime]::Now.AddHours(-24)

#Select Ip addresses that has audit failure
$l = Get-EventLog -LogName 'Security' -InstanceId 4625 -After $DT | Select-Object @{n='IpAddress';e={$_.ReplacementStrings[-2]} }

#Get ip adresses, that have more than 10 wrong logins
$g = $l | group-object -property IpAddress | where {$_.Count -gt 10} | Select -property Name

#Get firewall object
$fw = New-Object -ComObject hnetcfg.fwpolicy2

#Get firewall rule named 'BlockAttackers' (must be created manually)
$ar = $fw.rules | where {$_.name -eq 'BlockAttackers'}

#Split the existing IPs into an array so we can search it for existing IPs
$arRemote = $ar.RemoteAddresses -split(',')

#Only collect IPs that aren't already in the firewall rule
$w = $g | where {$_.Name.Length -gt 1 -and !($arRemote -contains $_.Name + '/255.255.255.255') }

#Add the new IPs to firewall rule
$w| %{
  if ($ar.RemoteAddresses -eq '*') {
    $ar.remoteaddresses = $_.Name
  }else{
    $ar.remoteaddresses += ',' + $_.Name
  }
}

#Write to logfile
if ($w.length -gt 1) {
  $w| %{(Get-Date).ToString() + ' ' + $_.Name >> '.\blocked.txt'}
}


2

Geralmente, não é uma boa ideia deixar outra pessoa controlar suas regras de firewall. É basicamente o que você está pedindo aqui.


11
+1, é uma excelente maneira de se preparar para um ataque de negação de serviço. E se você estiver usando limitação de taxa, a maioria das ferramentas automatizadas de força bruta espaçam suas tentativas de login o suficiente para evitar serem pegos.

12
Banir IPs automaticamente após um certo número de logins com falha é uma prática muito comum. Eu vejo hosts sendo banidos a cada hora depois de tentar adivinhar senhas de FTP. A única maneira isso pode ser um ataque DoS é se alguém conseguiu enganar o seu IP (impossível em conexões TCP), ou se você digitar repetidamente sua senha (caso em que não é alguém controlar regras de firewall, que é você)
devicenull

18
Desculpe, mas não perguntei se era uma boa ideia.
HeavyWave

11
Obviamente, não há razão para que exceções não possam ser definidas para um ou mais endereços IP específicos, o que eliminaria praticamente a preocupação com o DoS.
John Gardeniers

2

Este é um tópico antigo. Eu estava usando o script fornecido por kevinmicke em 2014-2015. Então parou de funcionar. Portanto, tive que editá-lo um pouco para adotar a autenticação do Windows Network Security que não deixa endereços IP no log de segurança. Além disso, como não tenho FTP em execução, removi essa parte, pois estava causando erros porque não havia pasta de log. A principal mudança está na origem dos eventos RDP.

    $current_date_utc = (Get-Date).ToUniversalTime()

    # Set number of failed login attempts after which an IP address will be blocked
    $int_block_limit = 10

    # Time window during which to check the Security log, which is currently set to check only the last 24 hours
    $dat_time_window = [DateTime]::Now.AddDays(-1)

    $arr_new_bad_ips_all = (get-winevent -filterhashtable @{ logname='Microsoft-Windows-RemoteDesktopServices-RdpCoreTS/Operational'; starttime=$dat_time_window; id=140 }).message |
        % { if ($_ -match "of (.+) failed") { $Matches[1] }} |
        Group-Object |
        Where {$_.Count -ge $int_block_limit} |
        Select -property Name

    # Sort the array, selecting only unique IPs (in case one IP shows up in both the Security and FTP logs)
    $arr_new_bad_ips_all = $arr_new_bad_ips_all | Foreach-Object { [string]$_.Name } | Select-Object -unique

    # Get firewall object
    $firewall = New-Object -comobject hnetcfg.fwpolicy2

    # Get all firewall rules matching "BlockAttackers*"
    $arr_firewall_rules = $firewall.Rules | Where {$_.Name -like 'BlockAttackers*'}

    # If no "BlockAttackers*" firewall rule exists yet, create one and set it to a variable
    if ($arr_firewall_rules -eq $null) {
        $str_new_rule_name = "BlockAttackers (Created " + $current_date_utc.ToString("yyyy-MM-dd HH:mm:ss") + " UTC)"
        netsh advfirewall firewall add rule dir=in action=block name=$str_new_rule_name description="Rule automatically created." enable=yes remoteip="0.0.0.0" | Out-Null
        $arr_firewall_rules = $firewall.Rules | Where {$_.Name -like 'BlockAttackers*'}
    }

    # Split the existing IPs from current "BlockAttackers*" firewall rule(s) into an array so we can easily search them
    $arr_existing_bad_ips = @()
    foreach ($rule in $arr_firewall_rules) {
        $arr_existing_bad_ips += $rule.RemoteAddresses -split(',')
    }

    # Clean subnet masks off of IPs that are currently blocked by the firewall rule(s)
    $arr_existing_bad_ips_without_masks = $arr_existing_bad_ips | ForEach-Object {$_ -replace "/.*", ""}

    # Select IP addresses to add to the firewall, but only ones that...
    $arr_new_bad_ips_for_firewall = $arr_new_bad_ips_all | Where {
        # contain an IP address (i.e. aren't blank or a dash, which the Security log has for systems that failed FTP logins)
        $_.Length -gt 6 -and
        # aren't already in the firewall rule(s)
        !($arr_existing_bad_ips_without_masks -contains $_) -and
        # aren't the local loopback
        !($_.StartsWith('127.0.0.1')) -and
        # aren't part of the local subnet
        !($_.StartsWith('192.168.')) -and
        !($_.StartsWith('0.0.'))
    }

    # If there are IPs to block, do the following...
    if ($arr_new_bad_ips_for_firewall -ne $null) {
        # Write date and time to script-specific log file
        [DateTime]::Now | Out-File -Append -Encoding utf8 C:\Security\blockattackers.txt
        # Write newly-blocked IP addresses to log file
        $arr_new_bad_ips_for_firewall | Out-File -Append -Encoding utf8 C:\Security\blockattackers.txt

        # Boolean to make sure the new IPs are only added on one rule
        $bln_added_to_rule = 0

        # Array to hold bad IPs from each rule one at a time, so we can count to make sure adding the new ones won't exceed 1000 IPs
        $arr_existing_bad_ips_current_rule = @()

        # For each "BlockAttackers*" rule in the firewall, do the following...
        foreach ($rule in $arr_firewall_rules) {
            if ($bln_added_to_rule -ne 1) {
                # Split the existing IPs from the current rule into an array so we can easily count them
                $arr_existing_bad_ips_current_rule = $rule.RemoteAddresses -split(',')

                # If the number of IPs to add is less than 1000 minus the current number of IPs in the rule, add them to this rule
                if ($arr_new_bad_ips_for_firewall.Count -le (1000 - $arr_existing_bad_ips_current_rule.Count)) {
                    # Add new IPs to firewall rule
                    $arr_new_bad_ips_for_firewall | %{$rule.RemoteAddresses += ',' + $_}

                    # Write which rule the IPs were added to to log file
                    echo "New IP addresses above added to Windows Firewall rule:" $rule.Name | Out-File -Append -Encoding utf8 C:\Security\blockattackers.txt

                    # Set boolean so any other rules are skipped when adding IPs
                    $bln_added_to_rule = 1
                }
            }
        }

        # If there wasn't room in any other "BlockAttackers*" firewall rule, create a new one and add the IPs to it
        if ($bln_added_to_rule -ne 1) {
            $str_new_rule_name = "BlockAttackers (Created " + $current_date_utc.ToString("yyyy-MM-dd HH:mm:ss") + " UTC)"
            netsh advfirewall firewall add rule dir=in action=block name=$str_new_rule_name description="Rule automatically created." enable=yes remoteip="0.0.0.0" | Out-Null
            $new_rule = $firewall.rules | Where {$_.Name -eq $str_new_rule_name}

            # Add new IPs to firewall rule
            $arr_new_bad_ips_for_firewall | %{$new_rule.RemoteAddresses += ',' + $_}

            # Write which rule the IPs were added to to log file
            echo "New IP addresses above added to newly created Windows Firewall rule:" $new_rule.Name | Out-File -Append -Encoding utf8 C:\Security\blockattackers.txt
        }
    }

O script acima funcionará no Windows 2012. Se você ainda estiver usando a Área de Trabalho Remota com autenticação no nível de acesso à rede no Windows 2008, poderá executar o seguinte truque. O Windows 2008 também não possui endereços IP no log de segurança e também não os possui no log Microsoft-Windows-RemoteDesktopServices-RdpCoreTS. Então, eu tive que realmente usar 2 logs - corresponder eventos do log de segurança às tentativas de acesso bem-sucedidas à porta 3389 no log do firewall. Este é um trabalho de adivinhação, mas parece estar detectando ataques de senha. Aqui está a parte que coleta IPs violadores:

    $current_date_utc = (Get-Date).ToUniversalTime()

    # Set number of failed login attempts after which an IP address will be blocked
    $int_block_limit = 10

    $dat_time_window = [DateTime]::Now.AddDays(-1)

    $logfn = (netsh advfirewall show allprofiles | Select-String Filename | select-object -unique | % { $_ -replace "%systemroot%",$env:systemroot }).substring(10).trimstart().trimend()

    $badevts = Get-EventLog -LogName 'Security' -InstanceId 4625 -After $dat_time_window | foreach-object { [datetime]$_.TimeWritten } | sort-object

    $fwlog = Select-String -Path $logfn -Pattern "ALLOW TCP" |
        % {
            if ($_ -match "(201.-..-..) (.+) ALLOW TCP (.+) (.+) (.+) 3389") 
            {
                new-object psobject -property @{ 
                  dt = $Matches[1] + ' ' + $Matches[2]
                  ip = $Matches[3]
                }
            }
        }

    $ipa = @()
    $j = 0

    for ($i=0; $i -lt $fwlog.Count; $i++)
    {
        $conn = ([datetime]$fwlog[$i].dt).ticks
        while (($j -lt $badevts.Count) -and (($badevts[$j]).ticks -lt $conn)) { $j++ }
        if ($j -ge $badevts.Count) { break }
        if ((($badevts[$j]).ticks - $conn) -le 30000000) { $ipa += ,($fwlog[$i].ip) }
    }

    $arr_new_bad_ips_all = $ipa |
        Group-Object |
        Where {$_.Count -ge $int_block_limit} |
        Select -property Name

NOTA: Não esqueça de ativar os logs do firewall. NOTA 2: Eu não sou um especialista em PowerShell, então seria bom se alguns gurus pudessem corrigir / melhorar meu código.


1

Estou usando o ts_block freeby.

Basicamente, é um "programa VBScript que atua como um coletor de eventos WMI para receber eventos registrados pelo Windows em resposta a logons inválidos dos Serviços de Terminal".

Parece funcionar perfeitamente, e o script é direto se você precisar modificá-lo. Você pode permitir que ele registre tentativas e depois banir com base no número de tentativas permitidas, e / ou pode codificar os nomes de login aos quais não deseja dar acesso.

Eu fui pego adicionando acidentalmente o mesmo nome duas vezes e o serviço entra em um loop sem fim reiniciando a cada 1500ms, mas muito fácil de corrigir / mod se você estiver de acordo com o vbs.

Minhas configurações atuais são apenas uma nova tentativa e você é banido por 2 dias, com logins como 'admin' 'Admin' 'Administrator' 'guest' 'etc automaticamente banidos. Deve ser simples mudar para ip?

Meio viciante entrar e ver quais criaturas foram banidas da noite para o dia ...


0

Você quer dizer logon no servidor / domínio ou logon em um site em execução no servidor? Se você quer fazer logon no servidor / domínio, a resposta é não. O Windows não tem o conceito de bloquear endereços IP com base em tentativas falhas de logon, pois os endereços IP não são entidades de segurança. Pode haver ferramentas de terceiros que podem fazer isso, mas não conheço nenhuma, pois nunca a examinei.


0

Se houver um servidor da Web que está sendo atacado, você pode instalar a extensão de restrições de IP dinâmico . Se for para autenticação padrão no servidor, você poderá implementar o isolamento de domínio e servidor, o que limitaria o escopo dos ataques a computadores ingressados ​​no domínio e poderia ser configurado para permitir apenas tentativas dos sistemas aos quais você precisa ter acesso. o servidor. No Windows, a prevenção de ataques de força bruta é definir a política de bloqueio de conta para uma configuração de 10 minutos e uma política de senha incorreta para 3 tentativas - isso significa que a conta sendo atacada será bloqueada por 10 minutos após 3 tentativas. As conexões IP não são bloqueáveis ​​por padrão no Windows. (Além disso, também estou curioso para saber quantas tentativas de logon são necessárias por segundo para impactar o sistema)


Na minha pequena instância da AWS, uma tentativa a cada 4 segundos é suficiente para consumir 50% da CPU. Porcaria muito se você me perguntar ...
RomanSt

Uau, eu me pergunto por que a utilização é tão alta. Vou ter que fazer alguns testes para ver quantas tentativas são necessárias nas minhas VMs para registrar.
Jim B

Eu acho que é porque eu não estou usando a autenticação no nível da rede; portanto, cada tentativa de login gera uma interface de usuário de logon para realmente apresentar ao invasor por meio de uma sessão de área de trabalho remota. Eu posso ver por que isso pode ser caro.
RomanSt

0

http://nerderies.blogspot.co.at/2012/12/automatically-banning-ips-with-windows.html

Se o que você deseja é uma solução pronta para uso (Instalação e execução), você pode encontrar uma ferramenta gratuita aqui e provavelmente deve continuar lendo isso:

Versão atual: 1.2 (Perfil do Cliente .NET Framework 4.0) -> Faça o download da versão atual do EvlWatcher (gratuita para uso pessoal e comercial)

Novo no 1.2 (mais informações na documentação):

  • Console de Gerenciamento
  • Padrão de Serviço WCF
  • Lista negra
  • Movendo-se automaticamente para a lista negra após três advertências (por padrão)

Para servidores mais antigos (.NET Framework 2.0)

-> Baixe a versão reduzida do EvlWatcher (gratuita para uso pessoal e comercial)


0

Usando o ótimo script do remunda como ponto de partida, adicionei a principal coisa que estava faltando: bloquear endereços IP de logins FTP com falha . O Windows Server não registra o endereço IP no log de segurança quando alguém falha no logon via FTP, mas define o "Endereço de rede de origem" como um traço. O FTP é um vetor de ataque muito comum para ataques de força bruta, então eu adicionei ao seu script a capacidade de verificar os logs de FTP do dia atual em busca de várias falhas de logon e bloquear esses endereços IP também.

Atualização 2014/02/07: Quando fiz alguns ajustes para processar todos os meus logs antigos de FTP, percebi que eles tinham um número imenso de tentativas (mais de 50.000), as matrizes criadas eram enormes e tornavam o processamento incrivelmente lento. Desde então, eu o reescrevi para torná-lo muito mais eficiente ao processar logs de FTP.

Também descobri que há um limite rígido arbitrário de 1000 para quantos IPs podem estar em uma regra do Firewall do Windows. Por causa desse limite, eu precisava que ela criasse automaticamente uma nova regra quando a mais recente fosse preenchida. Agora ele faz isso e também cria a regra inicial do firewall (se você não criar sua própria), de modo que a única configuração a ser feita é adicioná-la ao Agendador para execução quando houver um evento 4625.

Aqui está o código, que foi testado no Windows Server 2008 R2 e no Windows 7:

# This Windows Powershell script will automatically block IP addresses that attempt to login to the system
# and fail the number of times set below with the $int_block_limit variable or more. Is scans both the Security
# log, which covers Remote Desktop and other attempts, as well as the current day's FTP log. If the $int_block_limit
# limit is hit on either of those logs (separately, not combined), then the IP address will be added to the
# firewall rule.
#
# The script will automatically create a firewall rule named "BlockAttackers (Created yyyy-MM-dd HH:mm:ss UTC)" using
# the current time if one with a name that includes "BlockAttackers" doesn't already exist. Because there's a hard
# limit of 1000 entries (IP addresses) you can block per rule, it will also create similarly-named rules once that
# limit is reached for the latest one.
#
# I recommend setting the script to run as a scheduled task triggered by event 4625 login audit failures from the
# Security log, or alternatively you could set it to run after some amount of time (i.e. every 10 minutes).
#
# Authors:
# Majority of script written by serverfault.com user kevinmicke
# Windows Security Log portion written by serverfault.com user remunda, which provided the starting point for kevinmicke
#
# Details: https://serverfault.com/questions/233222/ban-ip-address-based-on-x-number-of-unsuccessful-login-attempts


# Set number of failed login attempts after which an IP address will be blocked
$int_block_limit = 10

# Time window during which to check the Security log, which is currently set to check only the last 24 hours
$dat_time_window = [DateTime]::Now.AddDays(-1)

# Select from the Security log all IP addresses that have more than $int_block_limit audit failures (event 4625) within $dat_time_window
$arr_new_bad_ips_security_log = @()
$arr_new_bad_ips_security_log = Get-EventLog -LogName 'Security' -InstanceId 4625 -After $dat_time_window |
    Select-Object @{n='IpAddress';e={$_.ReplacementStrings[-2]}} |
    Group-Object -property IpAddress |
    Where {$_.Count -ge $int_block_limit} |
    Select -property Name

# Get current time UTC to figure out filename for current FTP log
$current_date_utc = (Get-Date).ToUniversalTime()

# Set path to today's FTP log file
$str_log_file_name = "C:\inetpub\logs\LogFiles\FTPSVC2\u_ex" + $current_date_utc.ToString("yyMMdd") + ".log"

# Search today's FTP log file for "530 1326" to find lines that contain IPs of systems that failed to log in,
# get just the IP from each line, group the IPs by IP to count the attempts from each one, and select only the
# IPs that have $int_block_limit or more bad logins today
$arr_new_bad_ips_ftp = @()
$arr_new_bad_ips_ftp = Select-String $str_log_file_name -pattern "530 1326" |
    ForEach-Object {$_.Line.Substring(20,15) -replace " .*", ""} |
    Group |
    Where {$_.Count -ge $int_block_limit} |
    Select -property Name

# Concatenate the two arrays of IPs (one from Security log, one from FTP log)
$arr_new_bad_ips_all = @()
# $arr_new_bad_ips_all = @($arr_new_bad_ips_security_log) + @($arr_new_bad_ips_ftp_over_limit)
$arr_new_bad_ips_all = @($arr_new_bad_ips_security_log) + @($arr_new_bad_ips_ftp)

# Sort the array, selecting only unique IPs (in case one IP shows up in both the Security and FTP logs)
$arr_new_bad_ips_all_sorted = @()
$arr_new_bad_ips_all_sorted = $arr_new_bad_ips_all |
    Foreach-Object { [string]$_.Name } |
    Select-Object -unique

# Get firewall object
$firewall = New-Object -comobject hnetcfg.fwpolicy2

# Get all firewall rules matching "BlockAttackers*"
$arr_firewall_rules = $firewall.Rules | Where {$_.Name -like 'BlockAttackers*'}

# If no "BlockAttackers*" firewall rule exists yet, create one and set it to a variable
if ($arr_firewall_rules -eq $null) {
    $str_new_rule_name = "BlockAttackers (Created " + $current_date_utc.ToString("yyyy-MM-dd HH:mm:ss") + " UTC)"
    netsh advfirewall firewall add rule dir=in action=block name=$str_new_rule_name description="Rule automatically created by BlockAttackers Powershell script written by Kevin Micke." enable=yes remoteip="0.0.0.0" | Out-Null
    $arr_firewall_rules = $firewall.Rules | Where {$_.Name -like 'BlockAttackers*'}
}

# Split the existing IPs from current "BlockAttackers*" firewall rule(s) into an array so we can easily search them
$arr_existing_bad_ips = @()
foreach ($rule in $arr_firewall_rules) {
    $arr_existing_bad_ips += $rule.RemoteAddresses -split(',')
}

# Clean subnet masks off of IPs that are currently blocked by the firewall rule(s)
$arr_existing_bad_ips_without_masks = @()
$arr_existing_bad_ips_without_masks = $arr_existing_bad_ips | ForEach-Object {$_ -replace "/.*", ""}

# Select IP addresses to add to the firewall, but only ones that...
$arr_new_bad_ips_for_firewall = @()
$arr_new_bad_ips_for_firewall = $arr_new_bad_ips_all_sorted | Where {
    # contain an IP address (i.e. aren't blank or a dash, which the Security log has for systems that failed FTP logins)
    $_.Length -gt 6 -and
    # aren't already in the firewall rule(s)
    !($arr_existing_bad_ips_without_masks -contains $_) -and
    # aren't the local loopback
    !($_.StartsWith('127.0.0.1')) -and
    # aren't part of the local subnet
    !($_.StartsWith('192.168.')) -and
    !($_.StartsWith('10.0.'))
}

# If there are IPs to block, do the following...
if ($arr_new_bad_ips_for_firewall -ne $null) {
    # Write date and time to script-specific log file
    [DateTime]::Now | Out-File -Append -Encoding utf8 C:\blockattackers.txt
    # Write newly-blocked IP addresses to log file
    $arr_new_bad_ips_for_firewall | Out-File -Append -Encoding utf8 C:\blockattackers.txt

    # Boolean to make sure the new IPs are only added on one rule
    $bln_added_to_rule = 0

    # Array to hold bad IPs from each rule one at a time, so we can count to make sure adding the new ones won't exceed 1000 IPs
    $arr_existing_bad_ips_current_rule = @()

    # For each "BlockAttackers*" rule in the firewall, do the following...
    foreach ($rule in $arr_firewall_rules) {
        if ($bln_added_to_rule -ne 1) {
            # Split the existing IPs from the current rule into an array so we can easily count them
            $arr_existing_bad_ips_current_rule = $rule.RemoteAddresses -split(',')

            # If the number of IPs to add is less than 1000 minus the current number of IPs in the rule, add them to this rule
            if ($arr_new_bad_ips_for_firewall.Count -le (1000 - $arr_existing_bad_ips_current_rule.Count)) {
                # Add new IPs to firewall rule
                $arr_new_bad_ips_for_firewall | %{$rule.RemoteAddresses += ',' + $_}

                # Write which rule the IPs were added to to log file
                echo "New IP addresses above added to Windows Firewall rule:" $rule.Name | Out-File -Append -Encoding utf8 C:\blockattackers.txt

                # Set boolean so any other rules are skipped when adding IPs
                $bln_added_to_rule = 1
            }
        }
    }

    # If there wasn't room in any other "BlockAttackers*" firewall rule, create a new one and add the IPs to it
    if ($bln_added_to_rule -ne 1) {
        $str_new_rule_name = "BlockAttackers (Created " + $current_date_utc.ToString("yyyy-MM-dd HH:mm:ss") + " UTC)"
        netsh advfirewall firewall add rule dir=in action=block name=$str_new_rule_name description="Rule automatically created by BlockAttackers Powershell script written by Kevin Micke." enable=yes remoteip="0.0.0.0" | Out-Null
        $new_rule = $firewall.rules | Where {$_.Name -eq $str_new_rule_name}

        # Add new IPs to firewall rule
        $arr_new_bad_ips_for_firewall | %{$new_rule.RemoteAddresses += ',' + $_}

        # Write which rule the IPs were added to to log file
        echo "New IP addresses above added to newly created Windows Firewall rule:" $new_rule.Name | Out-File -Append -Encoding utf8 C:\blockattackers.txt
    }
}

Para sua informação: Para aqueles que não executaram um script do PowerShell em um sistema antes, será necessário primeiro abrir um novo PowerShell e executar Set-ExecutionPolicy RemoteSignedpara poder executar scripts locais. Caso contrário, você receberá um erro: "o blockattackers.ps1 não pode ser carregado porque a execução dos scripts está desativada neste sistema".
Kevickei

0

O script do remuda , editado por kevinmicke (7 de fevereiro às 21:59), não verificou o canal de controle do FTP, que possui uma pasta própria no meu sistema (Windows Server 2008 R2). Os 530 11001eventos também não foram reconhecidos, o que parece aparecer quando o hacker tenta apenas acessar o canal de controle. Então, acrescentei algumas linhas no script para verificar uma segunda pasta de log de FTP:

# Esse script do Windows Powershell bloqueará automaticamente os endereços IP que tentam fazer login no sistema
# e falha o número de vezes definido abaixo com a variável $ int_block_limit ou mais. É varre tanto a Segurança
# log, que abrange a Área de trabalho remota e outras tentativas, bem como o log FTP do dia atual. Se o $ int_block_limit
# limit for atingido em um desses logs (separadamente, não combinados), o endereço IP será adicionado ao
# regra de firewall.
#
# O script criará automaticamente uma regra de firewall chamada "BlockAttackers (criado aaaa-MM-dd HH: mm: ss UTC)" usando
# a hora atual se um com um nome que inclui "BlockAttackers" ainda não existe. Porque há uma difícil
# limite de 1000 entradas (endereços IP) que você pode bloquear por regra, ele também criará regras com nomes semelhantes assim que
# limite é atingido para o mais recente.
#
# Eu recomendo definir o script para ser executado como uma tarefa agendada acionada por falhas de auditoria de logon do evento 4625 do diretório
# Log de segurança ou, alternativamente, você pode configurá-lo para executar após um certo período de tempo (ou seja, a cada 10 minutos).
#
# Autores:
# Maioria do script escrito pelo usuário serverfault.com kevinmicke
# Parte do Log de Segurança do Windows escrita pelo usuário do serverfault.com remunda, que forneceu o ponto de partida para o kevinmicke
# Verificação do canal de controle do FTP adicionado pelo usuário serverfault.com Uwe Martens
#
# Detalhes: https://serverfault.com/questions/233222/ban-ip-address-based-on-x-number-of-unsuccessful-login-attempts


# Defina o número de tentativas falhas de login, após as quais um endereço IP será bloqueado
$ int_block_limit = 3

# Janela de tempo durante a qual verificar o log de segurança, atualmente definido para verificar apenas as últimas 24 horas
$ dat_time_window = [DateTime] :: Now.AddDays (-1)

# Selecione no log de segurança todos os endereços IP com mais de $ int_block_limit falhas de auditoria (evento 4625) em $ dat_time_window
$ arr_new_bad_ips_security_log = @ ()
$ arr_new_bad_ips_security_log = Get-EventLog -LogName 'Security' -InstanceId 4625 -Depois de $ dat_time_window |
    Objeto Select @ {n = 'IpAddress'; e = {$ _. ReplacementStrings [-2]}} |
    IpAddress de propriedade de objeto de grupo |
    Onde {$ _. Count -ge $ int_block_limit} |
    Selecione o nome da propriedade

# Obter o horário atual do UTC para descobrir o nome do arquivo do log FTP atual
$ current_date_utc = (Get-Date) .ToUniversalTime ()

# Defina o caminho para o arquivo de log do canal de controle FTP de hoje
$ str_log_file_name_control_channel = "C: \ inetpub \ logs \ LogFiles \ FTPSVC \ u_ex" + $ current_date_utc.ToString ("yyMMdd") + ".log"

# Pesquise o arquivo de log do canal de controle FTP de hoje por "530 1" para encontrar linhas que contêm IPs de sistemas que não logaram,
# obtenha apenas o IP de cada linha, agrupe os IPs por IP para contar as tentativas de cada uma e selecione apenas o
# IPs que possuem $ int_block_limit ou mais logins inválidos hoje
$ arr_new_bad_ips_ftp_control_channel = @ ()
$ arr_new_bad_ips_ftp_control_channel = Cadeia de seleção $ str_log_file_name_control_channel - padrão "530 1" |
    ForEach-Object {$ _. Line.Substring (20,15) - substitua ". *", ""} |
    Grupo |
    Onde {$ _. Count -ge $ int_block_limit} |
    Selecione o nome da propriedade

# Definir caminho para o arquivo de log FTP de hoje
$ str_log_file_name = "C: \ inetpub \ logs \ LogFiles \ FTPSVC * \ u_ex" + $ current_date_utc.ToString ("yyMMdd") + ".log"

# Pesquise o arquivo de log FTP de hoje por "530 1" para encontrar linhas que contêm IPs de sistemas que não logaram,
# obtenha apenas o IP de cada linha, agrupe os IPs por IP para contar as tentativas de cada uma e selecione apenas o
# IPs que possuem $ int_block_limit ou mais logins inválidos hoje
# No FTPSVC * deve ser adicionado o ID do servidor FTP em vez de *, ou apenas pegue a pasta de log correta
$ arr_new_bad_ips_ftp = @ ()
$ arr_new_bad_ips_ftp = Selecionar cadeia de caracteres $ str_log_file_name - padrão "530 1" |
    ForEach-Object {$ _. Line.Substring (20,15) - substitua ". *", ""} |
    Grupo |
    Onde {$ _. Count -ge $ int_block_limit} |
    Selecione o nome da propriedade

# Concatene as duas matrizes de IPs (uma do log de segurança e outra do log de FTP)
$ arr_new_bad_ips_all = @ ()
# $ arr_new_bad_ips_all = @ ($ arr_new_bad_ips_security_log) + @ ($ arr_new_bad_ips_ftp_over_limit)
$ arr_new_bad_ips_all = @ ($ arr_new_bad_ips_security_log) + @ ($ arr_new_bad_ips_ftp_control_channel) + @ ($ arr_new_bad_ips_ftp)

# Classifique a matriz, selecionando apenas IPs exclusivos (caso um IP apareça nos logs de segurança e FTP)
$ arr_new_bad_ips_all_sorted = @ ()
$ arr_new_bad_ips_all_sorted = $ arr_new_bad_ips_all |
    Objeto Foreach {[string] $ _. Nome} |
    Select-Object -unique

# Obter objeto de firewall
$ firewall = New-Object -comobject hnetcfg.fwpolicy2

# Obtenha todas as regras de firewall correspondentes a "BlockAttackers *"
$ arr_firewall_rules = $ firewall.Rules | Onde {$ _. Name-like 'BlockAttackers *'}

# Se ainda não existir uma regra de firewall "BlockAttackers *", crie uma e defina-a como uma variável
if ($ arr_firewall_rules -eq $ null) {
    $ str_new_rule_name = "BlockAttackers (criado" + $ current_date_utc.ToString ("aaaa-MM-dd HH: mm: ss") + "UTC)"
    netsh advfirewall firewall adicionar regra dir = em ação = nome do bloco = $ str_new_rule_name description = "Regra criada automaticamente." enable = yes remoteip = "0.0.0.0" | Out-Null
    $ arr_firewall_rules = $ firewall.Rules | Onde {$ _. Name-like 'BlockAttackers *'}
}

# Divida os IPs existentes das atuais regras de firewall "BlockAttackers *" em um array para que possamos pesquisá-los facilmente
$ arr_existing_bad_ips = @ ()
foreach (regra de $ em $ arr_firewall_rules) {
    $ arr_existing_bad_ips + = $ rule.RemoteAddresses -split (',')
}

# Limpe as máscaras de sub-rede dos IPs atualmente bloqueados pelas regras de firewall
$ arr_existing_bad_ips_without_masks = @ ()
$ arr_existing_bad_ips_without_masks = $ arr_existing_bad_ips | ForEach-Object {$ _ -replace "/.*", ""}

# Digite o IP do seu servidor (IPv4 e IPv6) nas linhas 115 e 116.
# Selecione os endereços IP a serem adicionados ao firewall, mas apenas os que ...
$ arr_new_bad_ips_for_firewall = @ ()
$ arr_new_bad_ips_for_firewall = $ arr_new_bad_ips_all_sorted | Onde {
    # contém um endereço IP (ou seja, não está em branco ou é um traço, que o log de segurança possui para sistemas com falha no logon FTP)
    $ _. Length -gt 6 - e
    # ainda não estão nas regras do firewall
    ! ($ arr_existing_bad_ips_without_masks -contains $ _) -e
    # não são o loopback local
    ! ($ _. Inicia com ('127.0.0.1')) - e
    # não fazem parte da sub-rede local
    ! ($ _. Inicia com ('192.168.')) - e
    ! ($ _. Inicia com ('0.0.')) - e
    ! ($ _. Inicia com ('10 .0. ')) - e
    ! ($ _. Inicia com ('*. *. *. *')) - e
    ! ($ _. StartsWith ('*: *: *: *: *: *'))
}

# Se houver IPs para bloquear, faça o seguinte ...
if ($ arr_new_bad_ips_for_firewall -ne $ null) {
    # Grava data e hora no arquivo de log específico do script
    [DateTime] :: Agora | Arquivo de saída - Anexar - Codificação utf8 C: \ inetpub \ logs \ LogFiles \ blockattackers.txt
    # Grava endereços IP recém-bloqueados no arquivo de log
    $ arr_new_bad_ips_for_firewall | Arquivo de saída - Anexo - Codificação utf8 C: \ inetpub \ logs \ LogFiles \ blockattackers.txt

    # Booleano para garantir que os novos IPs sejam adicionados apenas a uma regra
    $ bln_added_to_rule = 0

    # Matriz para manter IPs inválidos de cada regra, um de cada vez, para que possamos contar para garantir que a adição de novos não exceda 1000 IPs
    $ arr_existing_bad_ips_current_rule = @ ()

    # Para cada regra "BlockAttackers *" no firewall, faça o seguinte ...
    foreach (regra de $ em $ arr_firewall_rules) {
        if ($ bln_added_to_rule -ne 1) {
            # Divida os IPs existentes da regra atual em uma matriz para que possamos contá-los facilmente
            $ arr_existing_bad_ips_current_rule = $ rule.RemoteAddresses -split (',')

            # Se o número de IPs a serem adicionados for menor que 1000 menos o número atual de IPs na regra, adicione-os a esta regra
            if ($ arr_new_bad_ips_for_firewall.Count -le (1000 - $ arr_existing_bad_ips_current_rule.Count)) {
                # Adicione novos IPs à regra do firewall
                $ arr_new_bad_ips_for_firewall | % {$ rule.RemoteAddresses + = ',' + $ _}

                # Escreva a qual regra os IPs foram adicionados ao arquivo de log
                echo "Novos endereços IP acima adicionados à regra do Firewall do Windows:" $ rule.Name | Arquivo de saída - Anexar - Codificação utf8 C: \ inetpub \ logs \ LogFiles \ blockattackers.txt

                # Defina booleano para que outras regras sejam ignoradas ao adicionar IPs
                $ bln_added_to_rule = 1
            }
        }
    }

    # Se não houver espaço em nenhuma outra regra de firewall "BlockAttackers *", crie uma nova e adicione os IPs a ela
    if ($ bln_added_to_rule -ne 1) {
        $ str_new_rule_name = "BlockAttackers (criado" + $ current_date_utc.ToString ("aaaa-MM-dd HH: mm: ss") + "UTC)"
        netsh advfirewall firewall adicionar regra dir = em ação = nome do bloco = $ str_new_rule_name description = "Regra criada automaticamente." enable = yes remoteip = "0.0.0.0" | Out-Null
        $ new_rule = $ firewall.rules | Onde {$ _. Name -eq $ str_new_rule_name}

        # Adicione novos IPs à regra do firewall
        $ arr_new_bad_ips_for_firewall | % {$ new_rule.RemoteAddresses + = ',' + $ _}

        # Escreva a qual regra os IPs foram adicionados ao arquivo de log
        echo "Novos endereços IP acima adicionados à regra do Firewall do Windows recém-criada:" $ new_rule.Name | Arquivo de saída - Anexar - Codificação utf8 C: \ inetpub \ logs \ LogFiles \ blockattackers.txt
    }
}

O nome da pasta de log do FTP FTPSVC*na linha 54 deve ser preenchido por causa. Nas linhas 115 e 116, é necessário inserir o IP do servidor (IPv4 e IPv6), caso contrário, o próprio IP do servidor poderá ser adicionado à regra do firewall centenas de vezes. A variável $int_block_limitque estou definindo como 1 no meu servidor, portanto, o script está bloqueando um ataque de hackers, causando um evento 4625 em dois segundos. Ainda estou pensando em executar o script adicionalmente para ocorrer 4625 eventos em um período de alguns minutos. Por uma causa, também seria possível separar os scripts e deixar um script verificar os eventos 4625 disparados pelo evento 4625 e outro as pastas de log do FTP verificando periodicamente a cada 5 ou 10 minutos, mesmo com regras de firewall separadas e arquivo de log.


-1

Eu adicionei o meu para SQL

# Select from the Application log (SQL) all IP addresss that have more than $int_block_limit logon failure within $dat_time_window
$arr_new_bad_ips_SQL_log = @()
$arr_new_bad_ips_SQL_log = Get-EventLog -LogName 'Application' -After $dat_time_window |
    Where-Object{$_.EventID -eq 18456} |
    Select-Object @{n='CLIENT';e={$_.ReplacementStrings[-1]}} |
    Group-Object -property CLIENT |
    Where {$_.Count -ge $int_block_limit} |
    Select -property Name |
    {
        $_.Name = $_.Name.Replace(" [CLIENT: ", "");
        $_.Name = $_.Name.Replace("]", "");
        return $_;
    }

Então você terá que adicionar a matriz em ips_all

$arr_new_bad_ips_all = @($arr_new_bad_ips_SQL_log) + @($arr_new_bad_ips_security_log) + @($arr_new_bad_ips_ftp_control_channel) + @($arr_new_bad_ips_ftp)
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.