Larangan alamat IP berdasarkan jumlah X upaya percobaan yang gagal?

47

Apakah mungkin untuk mencekal alamat IP setelah X jumlah upaya login yang gagal ke Server Windows? Bukan ke akun tertentu, yang saya tahu bagaimana melakukannya, tetapi untuk seluruh mesin.

Kami tertabrak cukup keras oleh serangan brute force mencoba menebak nama pengguna, jadi ini benar-benar akan membantu mendapatkan beberapa beban dari server.

Gelombang Berat
sumber
8
* nix memiliki fial2ban ... tidak yakin apakah ada Windows / port yang setara. fail2ban.org/wiki/index.php/Main_Page
Chris Nava
5
Dari Evan Anderson: serverfault.com/questions/43360/ ... ... tampaknya setara dengan fungsionalitas fail2ban tetapi karena pertanyaan Anda tidak cukup spesifik, saya tidak tahu apakah Anda ingin melarang IP yang mencoba masuk. ke situs web yang dihosting, server Anda (melalui SSH) atau domain Anda. Klarifikasi akan sangat bermanfaat. Selain itu Anda dapat menilai batas di firewall Anda, tetapi itu tergantung pada implementasi.
4
Anda mungkin ingin melihat serverfault.com/questions/216995/… untuk diskusi sebelumnya tentang seberapa bermanfaat pelarangan otomatis berdasarkan IP.
pehrs
1
Jika Anda berbicara tentang Layanan Terminal / Remote Desktop, lihat di sini: serverfault.com/a/335976/7200
Evan Anderson
3
Saya membuat layanan windows di github untuk melakukan hal itu: github.com/jjxtra/Windows-IP-Ban-Service
jjxtra

Jawaban:

28

Anda dapat melakukan ini dengan PowerShell dan Task Manager. Ini mungkin bukan solusi yang sempurna, tetapi ini bekerja dengan sangat baik dan saya memiliki sekitar 100 alamat IP yang diblokir dalam dua bulan. Saya menulis skrip, yang memilih dari peristiwa yang ditentukan EventLog ("kegagalan audit"). Jika ada banyak login gagal dari alamat IP apa pun, maka itu ditambahkan ke aturan firewall (dibuat secara manual) bernama "BlockAttackers" yang memblokir lalu lintas apa pun ke alamat ip tertentu.

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

Buat tugas dalam penjadwal dan atur pemicu ke acara 4625 (windows login termasuk layanan terminal). Tetapi Anda dapat mengatur pemicu untuk menjalankan mis. Dua kali per jam untuk menghindari pemuatan server yang tidak perlu.

Pemicu penjadwal

dan setelah memicu jalankan skrip PowerShell. Anda juga harus menetapkan hak yang lebih tinggi untuk menjalankan skrip ini, jika tidak maka akan gagal dengan pengecualian keamanan.

menjalankan skrip PowerShell

Anda juga dapat mengikat skrip ini ke acara keamanan lainnya.

Remunda
sumber
1
Skrip luar biasa @remunda - terima kasih! Saya mendapatkan banyak 4625 dari FTP juga, yang log Keamanan tidak memiliki alamat IP untuk, jadi saya memperluas skrip Anda untuk memeriksanya juga log FTP hari ini. Silakan lihat jawaban saya di bawah ini untuk info lebih lanjut: serverfault.com/a/571903/107701
kevinmicke
Ada banyak kasus gotchas dan edge dengan log peristiwa, pencatatan alamat ip, dll. Yang telah saya tangani di IPBan - sumber bebas dan terbuka di github.com/jjxtra/Windows-IP-Ban-Service
jjxtra
7

Saya tahu pertanyaan ini sudah lama tetapi sebenarnya posting forum pertama yang saya temukan ketika saya mulai mencoba melakukan hal yang sama persis beberapa minggu yang lalu. Saya telah berhasil membuat skrip yang berfungsi untuk mengurai log peristiwa 24 jam kembali hanya untuk entri log peristiwa masuk yang buruk, ambil yang memiliki lebih dari 10 login yang buruk, dan kemudian memasukkannya ke daftar filter ipsec menggunakan perintah netsh. Kemudian saya menulis file batch dengan baris ini powershell .\*scriptname.ps1*dan membuat tugas yang dijadwalkan untuk menjalankan file batch setiap 24 jam (untuk beberapa alasan itu tidak akan dijalankan secara langsung).

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

Saya tahu bahwa skrip ini mungkin tidak efisien tetapi ketika saya mulai mengerjakan ini, saya sama sekali tidak memiliki pengalaman dalam PowerShell, jadi kemampuan saya untuk mengoptimalkan skrip membuat banyak yang diinginkan. Namun, terlepas dari kenyataan ini saya pikir saya akan membagikan ini kepada siapa saja yang dapat menggunakannya.

Saya berterima kasih kepada Remunda karena memberi saya ide awal, poster itulah yang membuat saya beralih ke ide menggunakan PowerShell untuk mencari log peristiwa.

Keegan
sumber
4

Skrip ini dibangun berdasarkan jawaban remunda dan sedikit lebih jauh https://serverfault.com/a/397637/155102 Ini menyumbang aturan "BlockAttackers" belum ada IP yang dimasukkan (yang mengembalikan "*" sebagai string). Itu juga menulis komentar ke file log untuk memberi tahu Anda ketika IP ditambahkan ke aturan.

Kiat yang bagus adalah membuat aturan "BlockAttackers" yang memblokir alamat IP, tetapi pada awalnya dinonaktifkan. Kemudian, jalankan skrip ini satu kali secara manual sehingga dapat mengisi bidang "RemoteAddresses" dengan alamat IP aktual yang harus diblokir. Lihatlah alamat IP tersebut untuk memastikan tidak ada hal penting yang ditambahkan dan kemudian aktifkan aturan firewall. Tambahkan aturan ini ke firewall Anda seperti yang dijelaskan remunda.

Git untuk skrip ini

#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'}
}
Michael Khalili
sumber
2

Biasanya bukan ide yang baik untuk membiarkan orang lain mengendalikan aturan firewall Anda. Pada dasarnya itulah yang Anda minta di sini.

Thorsten
sumber
1
+1, ini adalah cara terbaik untuk mengatur diri Anda untuk penolakan serangan layanan. Dan jika Anda menggunakan pembatasan kecepatan, sebagian besar alat brute force otomatis membatasi upaya login mereka cukup jauh untuk menghindari ketahuan.
12
Larangan IP secara otomatis setelah sejumlah login gagal adalah praktik yang sangat umum. Saya melihat host dilarang setiap jam setelah mencoba menebak kata sandi FTP. Satu-satunya cara ini bisa menjadi serangan DoS adalah jika seseorang berhasil menipu IP Anda (tidak mungkin pada koneksi TCP), atau jika Anda berulang kali salah ketik kata sandi Anda (dalam hal ini bukan orang lain yang mengendalikan aturan firewall, itu Anda)
devicenull
18
Maaf, tapi saya tidak bertanya apakah itu ide yang bagus.
HeavyWave
1
Tentu saja tidak ada alasan pengecualian tidak dapat ditetapkan untuk satu atau lebih alamat IP tertentu, yang akan menghilangkan kekhawatiran DoS.
John Gardeniers
2

Ini adalah utas lama. Saya menggunakan skrip yang disediakan oleh kevinmicke pada 2014-2015. Kemudian berhenti bekerja. Jadi saya harus mengeditnya sedikit untuk mengadopsi otentikasi Windows Network Security yang tidak meninggalkan alamat IP di log keamanan. Juga, karena saya tidak memiliki FTP reguler yang berjalan saya menghapus bagian itu karena menyebabkan kesalahan karena tidak ada folder log. Perubahan utama adalah di sumber acara 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
        }
    }

Script di atas akan berfungsi pada Windows 2012. Jika Anda masih menggunakan Remote Desktop dengan otentikasi tingkat akses jaringan pada Windows 2008 maka Anda mungkin perlu melakukan trik berikut. Windows 2008 tidak memiliki alamat IP di log keamanan dan tampaknya tidak memilikinya dalam log Microsoft-Windows-RemoteDesktopServices-RdpCoreTS. Jadi saya harus benar-benar menggunakan 2 log - mencocokkan peristiwa dari log keamanan untuk upaya akses yang sukses ke port 3389 di log firewall. Ini dugaan, tetapi tampaknya mendeteksi serangan kata sandi. Inilah bagian yang mengumpulkan melanggar 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

CATATAN: Jangan lupa untuk mengaktifkan log firewall. CATATAN 2: Saya bukan ahli PowerShell jadi alangkah baiknya jika beberapa guru dapat memperbaiki / meningkatkan kode saya.

Tenang
sumber
1

Saya menggunakan ts_block freeby.

Pada dasarnya ini adalah "program VBScript yang bertindak sebagai peristiwa WMI untuk menerima peristiwa yang dicatat oleh Windows sebagai tanggapan terhadap log masuk Layanan Terminal yang tidak valid."

Tampaknya bekerja dengan sempurna, dan skripnya mudah jika Anda perlu mengubahnya. Anda bisa membiarkannya mencatat upaya dan kemudian mencekal berdasarkan jumlah upaya yang diizinkan, dan / atau Anda bisa memasukkan kode nama login yang tidak ingin Anda beri akses.

Saya ketahuan dengan tidak sengaja menambahkan nama yang sama dua kali dan layanan ini berjalan tanpa henti memulai kembali setiap 1500ms, tetapi sangat mudah untuk memperbaiki / mod jika Anda setuju dengan vbs.

Pengaturan saya saat ini hanya satu coba lagi dan Anda diblokir selama 2 hari, dengan login seperti 'admin' 'Admin' 'Administrator' 'guest' dll secara otomatis dilarang. Harus langsung berubah ke ip?

Agak membuat ketagihan untuk masuk dan melihat makhluk yang telah dilarang semalam ...

chipbug
sumber
0

Apakah maksud Anda masuk ke server / domain atau masuk ke situs web yang berjalan di server? Jika Anda bermaksud masuk ke server / domain maka jawabannya adalah tidak. Windows tidak memiliki konsep memblokir alamat ip berdasarkan upaya masuk yang gagal karena alamat ip bukan entitas keamanan. Mungkin ada alat pihak ketiga yang bisa melakukan ini, tapi saya tidak tahu apa-apa karena saya belum pernah melihatnya.

joeqwerty
sumber
0

Jika ada server web yang sedang diserang Anda dapat menginstal ekstensi pembatasan IP dinamis . Jika ini untuk otentikasi standar ke server, maka Anda harus dapat menerapkan isolasi domain dan server yang akan membatasi cakupan serangan ke komputer yang bergabung dengan domain, dan dapat diatur agar hanya memungkinkan upaya dari sistem yang harus Anda akses. server. Di windows pencegahan serangan brute force adalah mengatur kebijakan penguncian akun ke pengaturan seperti 10 menit dan kebijakan kata sandi yang buruk menjadi 3 upaya - ini berarti bahwa akun yang diserang akan mengunci selama 10 menit setelah 3 upaya. Koneksi IP tidak dapat dikunci secara default di windows. (Selain itu saya juga ingin tahu berapa banyak upaya masuk yang diperlukan per detik untuk mempengaruhi sistem)

Jim B
sumber
Pada contoh kecil AWS saya, 1 upaya setiap 4 detik sudah cukup untuk mengkonsumsi 50% CPU.
Omong
Wow, saya bertanya-tanya mengapa pemanfaatannya sangat tinggi. Saya harus melakukan beberapa pengujian untuk melihat berapa banyak upaya yang diperlukan pada VM saya untuk mendaftar.
Jim B
Saya pikir itu karena saya tidak menggunakan Otentikasi Tingkat Jaringan, jadi setiap upaya masuk memutar UI masuk untuk benar-benar hadir kepada penyerang melalui sesi desktop jarak jauh. Saya bisa melihat mengapa itu mahal.
RomanSt
0

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

Jika yang Anda inginkan adalah solusi di luar kotak (Instal & selesai), Anda dapat menemukan alat gratis di sini, dan mungkin harus terus membaca ini:

Versi Saat Ini: 1.2 (Profil Klien .NET Framework 4.0) -> Unduh versi EvlWatcher saat ini (gratis untuk penggunaan pribadi dan komersial)

Baru dalam 1.2 (info lebih lanjut dalam dokumentasi):

  • Konsol Manajemen
  • Pola Layanan WCF
  • Daftar hitam
  • Pindah otomatis ke daftar hitam setelah 3 kali mogok (per default)

Untuk server yang lebih lama (.NET Framework 2.0)

-> Unduh EvlWatcher versi berkurang (gratis untuk penggunaan pribadi dan komersial)

Mastro
sumber
0

Menggunakan skrip remunda yang bagus sebagai titik awal, saya menambahkan satu hal utama yang hilang: memblokir alamat IP dari login FTP yang gagal . Windows Server tidak mencatat alamat IP ke log Keamanan ketika seseorang gagal masuk melalui FTP, tetapi sebaliknya menetapkan "Alamat Jaringan Sumber" ke tanda hubung. FTP adalah vektor serangan yang sangat umum untuk serangan brute force, jadi saya menambahkan pada skripnya kemampuan untuk memindai log FTP hari ini untuk beberapa kegagalan login dan memblokir alamat IP tersebut juga.

Pembaruan 2014/02/07: Ketika saya membuat beberapa tweak untuk memproses semua log FTP lama saya, saya menyadari ketika mereka memiliki sejumlah besar upaya (50.000+), array yang dibuatnya akan sangat besar dan membuat pemrosesan menjadi sangat lambat. Sejak itu saya menulis ulang untuk membuatnya jauh lebih efisien ketika memproses log FTP.

Saya juga menemukan bahwa ada batas keras sewenang-wenang 1000 untuk berapa banyak IP dapat dalam satu aturan Windows Firewall. Karena batas itu, saya memerlukannya untuk secara otomatis membuat aturan baru ketika yang terbaru terisi. Sekarang melakukan hal itu, dan juga membuat aturan firewall awal (jika Anda tidak membuat sendiri) sehingga satu-satunya pengaturan yang harus dilakukan adalah menambahkannya ke Penjadwal untuk dijalankan ketika ada peristiwa 4625.

Berikut kode, yang telah diuji pada Windows Server 2008 R2 dan 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
    }
}
kevinmicke
sumber
FYI: Bagi yang belum menjalankan skrip PowerShell pada sistem sebelumnya, Anda harus membuka PowerShell baru dan menjalankannya Set-ExecutionPolicy RemoteSignedsehingga Anda dapat menjalankan skrip lokal. Kalau tidak, Anda akan mendapatkan kesalahan: "blockattackers.ps1 tidak dapat dimuat karena eksekusi skrip dinonaktifkan pada sistem ini."
kevinmicke
0

Skrip remuda , diedit oleh kevinmicke (7 Februari pukul 21:59) tidak memeriksa saluran kontrol FTP, yang memiliki folder sendiri di sistem saya (Windows Server 2008 R2). Juga - 530 11001acara belum dikenali, yang tampaknya muncul ketika hacker hanya mencoba mengakses ke saluran kontrol. Jadi saya menambahkan beberapa baris dalam skrip untuk memeriksa folder FTP-log kedua:

# Skrip Windows Powershell ini akan secara otomatis memblokir alamat IP yang mencoba masuk ke sistem
# dan gagal berapa kali ditetapkan di bawah ini dengan variabel $ int_block_limit atau lebih. Apakah memindai Keamanan
# log, yang mencakup Remote Desktop dan upaya lain, serta log FTP hari ini. Jika $ int_block_limit
batas # adalah hit pada salah satu log tersebut (secara terpisah, tidak digabungkan), maka alamat IP akan ditambahkan ke
# aturan firewall.
#
# Script akan secara otomatis membuat aturan firewall bernama "BlockAttackers (Dibuat yyyy-MM-dd HH: mm: ss UTC)" menggunakan
# waktu saat ini jika seseorang dengan nama yang menyertakan "BlockAttackers" belum ada. Karena ada yang sulit
# Batas 1000 entri (alamat IP) yang dapat Anda blokir per aturan, itu juga akan membuat aturan yang bernama sama sekali itu
# Batas tercapai untuk yang terakhir.
#
# Saya sarankan untuk mengatur skrip agar dijalankan sebagai tugas terjadwal yang dipicu oleh peristiwa 4625 kegagalan audit masuk dari
# Log keamanan, atau Anda dapat mengatur agar dijalankan setelah beberapa waktu (yaitu setiap 10 menit).
#
# Penulis:
# Mayoritas skrip ditulis oleh pengguna serverfault.com kevinmicke
# Bagian Keamanan Windows Log ditulis oleh userfunda.com user remunda, yang menyediakan titik awal untuk kevinmicke
# Memeriksa saluran kontrol FTP yang ditambahkan oleh pengguna serverfault.com Uwe Martens
#
# Perincian: https://serverfault.com/questions/233222/ban-ip-address-based-on-x-number-of-unsuccessful-login-attempts


# Tetapkan jumlah upaya login yang gagal setelah alamat IP akan diblokir
$ int_block_limit = 3

# Jendela waktu untuk memeriksa log Keamanan, yang saat ini ditetapkan untuk memeriksa hanya 24 jam terakhir
$ dat_time_window = [DateTime] :: Now.AddDays (-1)

# Pilih dari Security log semua alamat IP yang memiliki lebih dari $ kegagalan audit int_block_limit (peristiwa 4625) dalam $ dat_time_window
$ arr_new_bad_ips_security_log = @ ()
$ arr_new_bad_ips_security_log = Dapatkan-EventLog -LogName 'Security' -InstanceId 4625 -Setelah $ dat_time_window |
    Select-Object @ {n = 'IpAddress'; e = {$ _. ReplacementStrings [-2]}} |
    Group-Object -property IpAddress |
    Di mana {$ _. Hitung-tambah $ int_block_limit} |
    Pilih -Nama Properti

# Dapatkan waktu UTC saat ini untuk mengetahui nama file untuk log FTP saat ini
$ current_date_utc = (Get-Date) .ToUniversalTime ()

# Tetapkan jalur ke file log Saluran Kontrol FTP hari ini
$ str_log_file_name_control_channel = "C: \ inetpub \ logs \ LogFiles \ FTPSVC \ u_ex" + $ current_date_utc.ToString ("yyMMdd") + ".log"

# Cari file log Saluran Kontrol FTP hari ini untuk "530 1" untuk menemukan baris yang berisi IP sistem yang gagal masuk,
# dapatkan hanya IP dari setiap baris, kelompokkan IP dengan IP untuk menghitung upaya dari masing-masing, dan pilih hanya
# IP yang memiliki $ int_block_limit atau lebih banyak login buruk hari ini
$ arr_new_bad_ips_ftp_control_channel = @ ()
$ arr_new_bad_ips_ftp_control_channel = Pilih-String $ str_log_file_name_control_channel -pattern "530 1" |
    ForEach-Object {$ _. Line.Substring (20,15)-ganti ". *", ""} |
    Grup |
    Di mana {$ _. Hitung-tambah $ int_block_limit} |
    Pilih -Nama Properti

# Tetapkan path ke file log FTP hari ini
$ str_log_file_name = "C: \ inetpub \ logs \ LogFiles \ FTPSVC * \ u_ex" + $ current_date_utc.ToString ("yyMMdd") + ".log"

# Cari file log FTP hari ini untuk "530 1" untuk menemukan baris yang berisi IP sistem yang gagal masuk,
# dapatkan hanya IP dari setiap baris, kelompokkan IP dengan IP untuk menghitung upaya dari masing-masing, dan pilih hanya
# IP yang memiliki $ int_block_limit atau lebih banyak login buruk hari ini
# Dalam FTPSVC * harus ditambahkan ID dari FTP-server daripada *, atau hanya mengambil folder-log yang tepat
$ arr_new_bad_ips_ftp = @ ()
$ arr_new_bad_ips_ftp = Pilih-String $ str_log_file_name -pattern "530 1" |
    ForEach-Object {$ _. Line.Substring (20,15)-ganti ". *", ""} |
    Grup |
    Di mana {$ _. Hitung-tambah $ int_block_limit} |
    Pilih -Nama Properti

# Menggabungkan dua array IP (satu dari log Keamanan, satu dari log 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)

# Urutkan array, pilih hanya IP unik (seandainya satu IP muncul di Keamanan dan log FTP)
$ arr_new_bad_ips_all_sorted = @ ()
$ arr_new_bad_ips_all_sorted = $ arr_new_bad_ips_all |
    Foreach-Object {[string] $ _. Name} |
    Pilih-Objek -unik

# Dapatkan objek firewall
$ firewall = New-Object -comobject hnetcfg.fwpolicy2

# Dapatkan semua aturan firewall yang cocok dengan "BlockAttackers *"
$ arr_firewall_rules = $ firewall.Rules | Di mana {$ _. Nama-like 'BlockAttackers *'}

# Jika belum ada aturan firewall "BlockAttackers *", buat satu dan tetapkan ke variabel
if ($ arr_firewall_rules -eq $ null) {
    $ str_new_rule_name = "BlockAttackers (Dibuat" + $ current_date_utc.ToString ("yyyy-MM-dd HH: mm: ss") + "UTC)"
    firewall netsh advfirewall add aturan dir = dalam aksi = blok nama = $ str_new_rule_name description = "Aturan dibuat secara otomatis." aktifkan = yes remoteip = "0.0.0.0" | Out-Null
    $ arr_firewall_rules = $ firewall.Rules | Di mana {$ _. Nama-like 'BlockAttackers *'}
}

# Pisahkan IP yang ada dari aturan firewall "BlockAttackers *" saat ini menjadi array sehingga kami dapat dengan mudah mencari mereka
$ arr_existing_bad_ips = @ ()
foreach ($ rule dalam $ arr_firewall_rules) {
    $ arr_existing_bad_ips + = $ rule.RemoteAddresses -split (',')
}

# Bersihkan subnet mask dari IP yang saat ini diblokir oleh aturan firewall
$ arr_existing_bad_ips_without_masks = @ ()
$ arr_existing_bad_ips_without_masks = $ arr_existing_bad_ips | ForEach-Object {$ _ -replace "/.*", ""}

# Masukkan IP server Anda (IPv4 dan IPv6) di baris 115 dan 116.
# Pilih alamat IP yang akan ditambahkan ke firewall, tetapi hanya yang ...
$ arr_new_bad_ips_for_firewall = @ ()
$ arr_new_bad_ips_for_firewall = $ arr_new_bad_ips_all_sorted | Dimana {
    # berisi alamat IP (mis. tidak kosong atau tanda hubung, yang dimiliki log Keamanan untuk sistem yang gagal login FTP)
    $ _. Panjang -gt 6 -dan
    # belum ada dalam aturan firewall
    ! ($ arr_existing_bad_ips_without_masks -contains $ _) -dan
    # bukan loopback lokal
    ! ($ _. Mulai dengan ('127.0.0.1')) -dan
    # bukan bagian dari subnet lokal
    ! ($ _. Mulai dengan ('192.168.')) -Dan
    ! ($ _. Mulai dengan ('0.0.')) -Dan
    ! ($ _. Mulai dengan ('10 .0. ')) -Dan
    ! ($ _. Mulai dengan ('*. *. *. *')) -Dan
    ! ($ _. Mulai Dengan ('*: *: *: *: *: *'))
}

# Jika ada IP yang akan diblokir, lakukan yang berikut ...
if ($ arr_new_bad_ips_for_firewall -ne $ null) {
    # Tulis tanggal dan waktu untuk file log khusus skrip
    [DateTime] :: Sekarang | Keluar-File -Tambahkan -Encoding utf8 C: \ inetpub \ logs \ LogFiles \ blockattackers.txt
    # Tulis alamat IP yang baru diblokir untuk mencatat file
    $ arr_new_bad_ips_for_firewall | Keluar-File -Tambahkan -Encoding utf8 C: \ inetpub \ logs \ LogFiles \ blockattackers.txt

    # Boolean untuk memastikan IP baru hanya ditambahkan pada satu aturan
    $ bln_added_to_rule = 0

    # Array untuk menyimpan IP buruk dari setiap aturan satu per satu, sehingga kami dapat menghitung untuk memastikan bahwa menambahkan yang baru tidak akan melebihi 1000 IP
    $ arr_existing_bad_ips_current_rule = @ ()

    # Untuk setiap aturan "BlockAttackers *" di firewall, lakukan hal berikut ...
    foreach ($ rule dalam $ arr_firewall_rules) {
        if ($ bln_added_to_rule -ne 1) {
            # Pisahkan IP yang ada dari aturan saat ini menjadi array sehingga kami dapat dengan mudah menghitungnya
            $ arr_existing_bad_ips_current_rule = $ rule.RemoteAddresses -split (',')

            # Jika jumlah IP yang ditambahkan kurang dari 1000 dikurangi jumlah IP saat ini dalam aturan, tambahkan mereka ke aturan ini
            if ($ arr_new_bad_ips_for_firewall.Count -le (1000 - $ arr_existing_bad_ips_current_rule.Count)) {
                # Tambahkan IP baru ke aturan firewall
                $ arr_new_bad_ips_for_firewall | % {$ rule.RemoteAddresses + = ',' + $ _}

                # Tulis aturan IP mana yang ditambahkan ke file log
                echo "Alamat IP baru di atas ditambahkan ke aturan Windows Firewall:" $ rule.Name | Keluar-File -Tambahkan -Encoding utf8 C: \ inetpub \ logs \ LogFiles \ blockattackers.txt

                # Atur boolean sehingga aturan lain dilewati saat menambahkan IP
                $ bln_added_to_rule = 1
            }
        }
    }

    # Jika tidak ada ruang dalam aturan firewall "BlockAttackers *" lainnya, buat yang baru dan tambahkan IP ke dalamnya
    if ($ bln_added_to_rule -ne 1) {
        $ str_new_rule_name = "BlockAttackers (Dibuat" + $ current_date_utc.ToString ("yyyy-MM-dd HH: mm: ss") + "UTC)"
        firewall netsh advfirewall add aturan dir = dalam aksi = blok nama = $ str_new_rule_name description = "Aturan dibuat secara otomatis." aktifkan = yes remoteip = "0.0.0.0" | Out-Null
        $ new_rule = $ firewall.rules | Di mana {$ _. Nama -eq $ str_new_rule_name}

        # Tambahkan IP baru ke aturan firewall
        $ arr_new_bad_ips_for_firewall | % {$ new_rule.RemoteAddresses + = ',' + $ _}

        # Tulis aturan IP mana yang ditambahkan ke file log
        echo "Alamat IP baru di atas ditambahkan ke aturan Windows Firewall yang baru dibuat:" $ new_rule.Name | Keluar-File -Tambahkan -Encoding utf8 C: \ inetpub \ logs \ LogFiles \ blockattackers.txt
    }
}

Nama folder log FTP FTPSVC*pada baris 54 harus dilengkapi penyebabnya. Dalam baris 115 dan 116 harus dimasukkan IP server Anda (IPv4 dan IPv6), jika tidak, IP server sendiri mungkin ditambahkan ke aturan firewall ratusan kali. Variabel yang $int_block_limitsaya atur ke 1 di server saya, jadi skripnya memblokir serangan peretas yang menyebabkan 4625 peristiwa dalam dua detik. Saya masih berpikir untuk menjalankan skrip tambahan untuk terjadi 4625 peristiwa dalam periode waktu beberapa menit. Sebabnya, mungkin juga, untuk memisahkan skrip dan membiarkan satu skrip memeriksa 4625-event yang dipicu oleh 4625-event dan satu lagi log-folder FTP memeriksa secara berkala setiap 5 atau 10 menit, bahkan dengan aturan firewall yang terpisah dan file log.

Uwe Martens
sumber
-1

Saya telah menambahkan milik saya untuk 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 $_;
    }

Maka Anda harus menambahkan array ke 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)
Vince Vinci
sumber