Запретить IP-адрес на основе X количества неудачных попыток входа в систему?

Облачные вычисления могли возвратить мейнфрейм? Риторический, но тот, который спрашивают в большом количестве мест. Вы могли настроить пакет большого VMs там.

Честно, если бы я выполнил гигантский отдел ИТ, то я искренне рассмотрел бы железо IBM, вероятно, на арендном договоре. С виртуализацией и меньшим штатом (хотя более дорогой) это могло иметь БОЛЬШОЙ смысл.

Я уполномочил бы приложения КОБОЛа на нем? Нет. Но конечно DB2, Java, XML и другие приложения Linux.

Как история, я сейчас отвечаю на RFP для очень новых приложений Java на System z.

47
задан 10 February 2014 в 20:20
13 ответов

Я не могу приписать себе этот ответ, но https://serverfault.com/users/7200/evan-anderson упомянул его http://opensource.wellbury.com/projects/windows_sshd_block/newest-release/ проекта

3
ответ дан 28 November 2019 в 19:39

Это обычно - не хорошая идея позволить кому-то еще управлять Вашими правилами брандмауэра. Это в основном, что Вы просите здесь.

2
ответ дан 28 November 2019 в 19:39

Вы означаете входить в систему сервера/домена или входить в систему веб-сайта, работающего на сервере? Если Вы означаете входить в систему сервера/домена затем, ответ нет. Windows не имеет никакого понятия блокирующихся IP-адресов на основе неудавшихся попыток входа в систему, поскольку IP-адреса не являются объектами безопасности. Могут быть сторонние инструменты, которые могут сделать это, но я не знаю ни о ком, поскольку я никогда не заглядывал к нему.

0
ответ дан 28 November 2019 в 19:39

Если существует веб-сервер, который подвергается нападению, можно установить динамическое расширение ограничений IP. Если бы это для стандартной аутентификации к серверу затем, необходимо смочь реализовать домен и изоляцию сервера, которая ограничила бы объем нападений к домену, присоединился к компьютерам и мог быть установлен только позволить попытки от систем, у Вас должен быть доступ к серверу. В окнах предотвращение атак перебором должно установить политику локаута учетной записи на установку как 10 минут и политику неверного пароля к 3 попыткам - это означает, что нападение учетной записи заблокировало бы в течение 10 минут после 3 попыток. IP-соединения не блокируемы по умолчанию в окнах. (Как в стороне мне также любопытно относительно того, сколько попыток входа в систему требуется в секунду для влияния на систему),

0
ответ дан 28 November 2019 в 19:39

Это можно сделать с помощью PowerShell и диспетчера задач. Возможно, это не идеальное решение, но оно работает достаточно хорошо, и за два месяца у меня было заблокировано около 100 IP-адресов. Я написал скрипт, который выбирает из EventLog указанные события («отказ аудита»). Если существует много неудачных попыток входа с любого IP-адреса, это добавляется в правило брандмауэра (созданное вручную) под названием «BlockAttackers», которое блокирует любой трафик на указанные IP-адреса.

Скрипт 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

Создать задачу в планировщике и установить триггер до события 4625 (вход в Windows, включая службы терминала). Но вы можете настроить триггер на запуск, например, два раза в час, чтобы избежать ненужной загрузки сервера.

Scheduler trigger

и после триггера запускать скрипт powershell. Вы также должны установить более высокие привилегии для запуска этого сценария, иначе он завершится ошибкой с исключением безопасности.

28
ответ дан 28 November 2019 в 19:39

Я знаю, что это старый вопрос, но на самом деле это было первое сообщение на форуме, на которое я наткнулся, когда начал пытаться сделать то же самое пару недель назад. Мне удалось придумать рабочий скрипт, который будет анализировать журналы событий 24 часа назад только на предмет неправильных записей журнала событий входа в систему, захватывать те, у которых более 10 неверных входов, а затем помещать их в список фильтров ipsec с помощью команда netsh. Затем я написал командный файл с этой строкой powershell. \ * Scriptname.ps1 * и создал запланированную задачу для запуска командного файла каждые 24 часа (по какой-то причине он не выполнялся напрямую).

$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}

Я знаю, что этот сценарий, вероятно, неэффективен, но когда я начал работать над ним, у меня не было абсолютно никакого опыта работы с PowerShell, поэтому моя способность оптимизировать скрипты оставляла желать лучшего. Однако,

7
ответ дан 28 November 2019 в 19:39

Этот сценарий основан на ответе remunda и идет немного дальше https://serverfault.com/a/397637/155102 Он учитывает правило «BlockAttackers», которого нет любые введенные IP-адреса (который возвращает "*" в виде строки). Он также записывает комментарий в файл журнала, чтобы вы знали, когда IP был добавлен к правилу.

Хороший совет - создать правило «BlockAttackers», которое блокирует IP-адреса, НО сначала отключит его. Затем запустите этот сценарий один раз вручную, чтобы он мог заполнить поле «RemoteAddresses» фактическими IP-адресами, которые следует заблокировать. Посмотрите на эти IP-адреса, чтобы убедиться, что ничего критического не добавлено, а затем включите правило брандмауэра. Добавьте это правило в свой брандмауэр, как описано в remunda.

Git для этого скрипта

#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'}
}
4
ответ дан 28 November 2019 в 19:39

Вы, вероятно, думаете о настройке "stat" в apc. Он находится в /etc/php.d/apc.ini или /etc/php/conf.d/apc.ini в зависимости от вашего дистрибутива.

Вы хотите, чтобы apc.stat = 1 проверьте наличие изменений в файлах, поскольку вы сказали, что это приведет к значительной потере производительности, поэтому вы должны отключить его в производственной среде.

См. http://www.php.net/manual/en/apc .configuration.php # ini.apc.stat для получения дополнительной информации.


Для более новых версий PHP, использующих OPcache, параметр, который вы хотите включить, - это validate_timestamps в вашем opcache.ini. Затем вам также необходимо установить revalidate_freq, как часто вы хотите, чтобы он проверял наличие изменений. Значение 0 заставит его проверять каждый запрос.

Итак, -> Загрузить текущую версию EvlWatcher (бесплатно для личного и коммерческого использования)

Новое в версии 1.2 (дополнительная информация в документации):

  • Консоль управления
  • Шаблон службы WCF
  • Внесение в черный список
  • Автоматический переход в черный список после 3 предупреждений (по умолчанию)

Для старых серверов (.NET Framework 2.0)

-> Загрузите сокращенную версию EvlWatcher (бесплатно для личного и коммерческого использования)

0
ответ дан 28 November 2019 в 19:39

Используя отличный скрипт remunda в качестве отправной точки, я добавил одну важную вещь, которой не хватало: блокирование IP-адресов от неудачных попыток входа на FTP . Windows Server не регистрирует IP-адрес в журнале безопасности, когда кто-то не может войти через FTP, а вместо этого устанавливает «Исходный сетевой адрес» на тире. FTP - очень распространенный вектор атаки для атак методом грубой силы, поэтому я добавил в его сценарий возможность сканировать журналы FTP текущего дня на предмет множественных сбоев входа в систему и также блокировать эти IP-адреса.

Обновление 2014/02/07: Когда я сделал некоторые настройки для обработки всех моих старых журналов FTP, я понял, что когда у них было огромное количество попыток (50 000+), создаваемые им массивы были бы огромными, что сделало бы обработку невероятно медленной. Я' Я переписал его, чтобы сделать его более эффективным при обработке журналов FTP.

Я также обнаружил, что существует произвольный жесткий предел в 1000 для того, сколько IP-адресов может быть в одном правиле Windows Firewall. Из-за этого ограничения мне нужно было, чтобы оно автоматически создавало новое правило, когда заполняется последнее. Теперь он делает это, а также создает исходное правило брандмауэра (если вы не создаете свое собственное), так что единственная настройка, которую нужно сделать, - это добавить его в планировщик для запуска при событии 4625.

Вот код, который был протестирован как на Windows Server 2008 R2, так и на 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
    }
}
0
ответ дан 28 November 2019 в 19:39

I'm using ts_block freeby.

Basically it's a "VBScript program that acts as a WMI event sink to receive events logged by Windows in response to invalid Terminal Services logons."

Seems to work perfectly, and the script is straightforward if you need to mod it. You can either let it log attempts and then ban based on your number of allowed attempts, and/or you can hard-code login names you don't want to give access to.

I got caught out by accidentally adding the same name twice and the service just goes into an endless loop restarting every 1500ms, but very easy to fix/mod if you're ok with vbs.

My current settings are just one retry and you're banned for 2 days, with logins like 'admin' 'Admin' 'Administrator' 'guest' etc automatically banned. Should be straightforward to change to ip?

Kinda addictive to go in and see which critters have been banned overnight...

1
ответ дан 28 November 2019 в 19:39

Сценарий remuda , отредактированный kevinmicke (7 февраля в 21:59), не проверял канал управления FTP, у которого есть собственная папка в моей системе (Windows Server 2008 R2). Также не были распознаны 530 11001 -события, которые появляются, когда хакер пытается получить доступ только к каналу управления. Поэтому я добавил несколько строк в сценарий, чтобы проверить вторую папку журнала FTP:

# 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
# Checking of the FTP's control channel added by serverfault.com user Uwe Martens
#
# 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 = 3

# 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 Control Channel log file
$str_log_file_name_control_channel = "C:\inetpub\logs\LogFiles\FTPSVC\u_ex" + $current_date_utc.ToString("yyMMdd") + ".log"

# Search today's FTP Control Channel log file for "530 1" 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_control_channel = @()
$arr_new_bad_ips_ftp_control_channel = Select-String $str_log_file_name_control_channel -pattern "530 1" |
    ForEach-Object {$_.Line.Substring(20,15) -replace " .*", ""} |
    Group |
    Where {$_.Count -ge $int_block_limit} |
    Select -property Name

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

# Search today's FTP log file for "530 1" 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
# In FTPSVC* has to be added the ID of the FTP-server instead of *, or just take the right log-folder
$arr_new_bad_ips_ftp = @()
$arr_new_bad_ips_ftp = Select-String $str_log_file_name -pattern "530 1" |
    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_control_channel) + @($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." 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 "/.*", ""}

# Enter your server's IP (IPv4 and IPv6) in line 115 and 116.
# 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('0.0.')) -and
    !($_.StartsWith('10.0.')) -and
    !($_.StartsWith('*.*.*.*')) -and
    !($_.StartsWith('*:*:*:*:*:*'))
}

# 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:\inetpub\logs\LogFiles\blockattackers.txt
    # Write newly-blocked IP addresses to log file
    $arr_new_bad_ips_for_firewall | Out-File -Append -Encoding utf8 C:\inetpub\logs\LogFiles\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:\inetpub\logs\LogFiles\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:\inetpub\logs\LogFiles\blockattackers.txt
    }
}

Имя папки журнала FTP FTPSVC * в строке 54 должно быть заполнено по причине. В строках 115 и 116 необходимо ввести IP-адрес вашего сервера (IPv4 и IPv6), иначе IP-адрес собственного сервера может быть добавлен в правило брандмауэра сотни раз. Переменная $ int_block_limit я устанавливаю на 1 на моем сервере, поэтому сценарий блокирует атаку хакеров, вызывающую событие 4625 в течение двух секунд. Я все еще думаю о том, чтобы запустить сценарий дополнительно к возникновению событий 4625 за период времени в несколько минут. Конечно, также можно было бы разделить сценарии и позволить одному сценарию проверять события 4625, инициированным событием 4625, а другому - папки журналов FTP, периодически проверяющие каждые 5 или 10 минут, даже с отдельным правилом брандмауэра. и лог-файл.

0
ответ дан 28 November 2019 в 19:39

Я добавил свой для 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 $_;
    }

. Тогда вам придется добавить массив в 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)
-1
ответ дан 28 November 2019 в 19:39

Это старый поток. Я использовал сценарий, предоставленный kevinmicke в 2014-2015 годах. Потом просто перестало работать. Поэтому мне пришлось немного отредактировать его, чтобы приспособить к проверке подлинности Windows Network Security, которая не оставляет IP-адреса в журнале безопасности. Кроме того, поскольку у меня нет обычного FTP, я удалил эту часть, так как она вызывала ошибки, потому что не было папки журнала. Основное изменение заключается в источнике событий 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
        }
    }

Приведенный выше сценарий будет работать в Windows 2012. Если вы все еще используете удаленный рабочий стол с аутентификацией уровня доступа к сети в Windows 2008, вам может потребоваться выполнить следующий трюк. Windows 2008 не имеет IP-адресов в журнале безопасности и, похоже, не имеет их в журнале Microsoft-Windows-RemoteDesktopServices-RdpCoreTS. Поэтому мне пришлось фактически использовать 2 журнала - сопоставить события из журнала безопасности с успешными попытками доступа к порту 3389 в журнале брандмауэра. Это предположение, но похоже, что это обнаруживает парольные атаки. Вот часть, которая собирает нарушающие IP-адреса:

    $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

ПРИМЕЧАНИЕ. Не забудьте включить журналы брандмауэра. ПРИМЕЧАНИЕ 2: Я не эксперт по PowerShell, поэтому было бы неплохо, если бы некоторые гуру могли исправить / улучшить мой код.

2
ответ дан 28 November 2019 в 19:39

Теги

Похожие вопросы