X 번의 로그인 시도 실패에 따른 IP 주소 금지?


47

X 번의 Windows 로그인 실패 시도 후 IP 주소를 차단할 수 있습니까? 내가하는 방법을 알고있는 특정 계정이 아니라 전체 컴퓨터에.

우리는 사용자 이름을 추측하려고하는 무차별 대입 공격에 크게 타격을 받으므로 서버에서 약간의 부하를 얻는 데 실제로 도움이됩니다.


8
* nix에는 fial2ban이 있습니다 ... Windows에 해당하는 포트가 있는지 확실하지 않습니다. fail2ban.org/wiki/index.php/Main_Page
Chris Nava

5
Evan Anderson : serverfault.com/questions/43360/… ... fail2ban의 기능과 동등한 것으로 보이지만 귀하의 질문이 충분히 구체적이지 않기 때문에 IP를 로그인하려고 시도하는 것을 금지하고 있는지 모르겠습니다. 호스팅 된 웹 사이트, 서버 (SSH를 통해) 또는 도메인으로 설명은 먼 길을 갈 것입니다. 또한 방화벽에서 속도를 제한 할 수 있지만 구현에 따라 다릅니다.

4
당신은 한 번 봐 가지고 할 수 있습니다 serverfault.com/questions/216995/... 입니다 IP를 기반으로 금지 자동화 얼마나 유용에 대한 이전 논의를.
pehrs

1
터미널 서비스 / 원격 데스크톱에 대해 이야기하고 있다면 여기를보십시오 : serverfault.com/a/335976/7200
Evan Anderson

3
: 나는 그냥 할 GitHub의에서 Windows 서비스를 만들어 github.com/jjxtra/Windows-IP-Ban-Service
jjxtra

답변:


28

powershell 및 작업 관리자를 사용하여이 작업을 수행 할 수 있습니다. 아마도 완벽한 솔루션은 아니지만 꽤 잘 작동하며 2 개월 안에 약 100 개의 차단 된 IP 주소가 있습니다. EventLog에서 지정한 이벤트 ( "감사 실패")에서 선택하는 스크립트를 작성했습니다. IP 주소에서 로그인이 실패한 경우 지정된 IP 주소로의 트래픽을 차단하는 "BlockAttackers"라는 방화벽 규칙 (수동으로 생성)에 추가됩니다.

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 로그인)로 설정하십시오. 그러나 불필요한 서버로드를 피하기 위해 트리거를 시간당 두 번 실행하도록 설정할 수 있습니다.

스케줄러 트리거

트리거 후 powershell 스크립트를 실행하십시오. 이 스크립트를 실행하려면 더 높은 권한을 설정해야합니다. 그렇지 않으면 보안 예외와 함께 실패합니다.

파워 쉘 스크립트 실행

이 스크립트를 다른 보안 이벤트에 바인딩 할 수도 있습니다.


1
훌륭한 스크립트 @ remunda-감사합니다! FTP에서 많은 4625를 얻었습니다. 보안 로그에는 IP 주소가 없으므로 스크립트를 확장하여 현재의 FTP 로그도 확인하도록했습니다. 자세한 내용은 아래 내 답변을 참조하십시오 : serverfault.com/a/571903/107701
kevinmicke

에서 무료 및 오픈 소스 - 나는 IPBan으로 처리 한 등의 이벤트 로그, IP 주소 로깅과 개는 에지의 많은 경우가 있습니다 github.com/jjxtra/Windows-IP-Ban-Service
jjxtra

7

나는이 질문이 오래되었다는 것을 알고 있지만 실제로 몇 주 전에이 똑같은 일을 시도했을 때 처음으로 우연히 발견 된 포럼 게시물이었습니다. 잘못된 로그인 이벤트 로그 항목에 대해서만 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에 대한 경험이 전혀 없었기 때문에 스크립트를 최적화하는 능력이 많이 필요합니다. 그러나이 사실에도 불구하고 나는 그것을 사용할 수있는 사람과 이것을 공유 할 것이라고 생각했습니다.

초기 아이디어를 알려 주신 Remunda에게 감사드립니다. 포스터는 powershell을 사용하여 이벤트 로그를 검색하는 아이디어로 바뀌 었습니다.


4

이 스크립트는 조금 더 remunda의 대답에 구축하고 간다 https://serverfault.com/a/397637/155102 그것은 어떤 IP를 아직 입력하지 "BlockAttackers"규칙에 대한 계정 (반환에 "*"문자열로). 또한 IP가 규칙에 추가 된시기를 알려주는 주석을 로그 파일에 작성합니다.

좋은 팁은 IP 주소를 차단하지만 처음에는 비활성화하는 "BlockAttackers"규칙을 만드는 것입니다. 그런 다음이 스크립트를 수동으로 한 번 실행하여 "RemoteAddresses"필드를 차단해야하는 실제 IP 주소로 채울 수 있습니다. 해당 IP 주소를 살펴보고 중요한 사항이 추가되지 않았는지 확인한 다음 방화벽 규칙을 활성화하십시오. 설명에 따라이 규칙을 방화벽에 추가하십시오.

이 스크립트의 자식

#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

일반적으로 다른 사람이 방화벽 규칙을 제어하게하는 것은 좋지 않습니다. 그것이 기본적으로 당신이 요구하는 것입니다.


1
+1, 이는 서비스 거부 공격을 설정하는 훌륭한 방법입니다. 그리고 속도 제한을 사용하는 경우 대부분의 자동화 된 무차별 도구는 로그인 시도 간격을 충분히 확보하여 붙 잡히지 않도록합니다.

12
특정 횟수의 로그인 실패 후 IP 자동 차단은 매우 일반적인 관행입니다. FTP 비밀번호를 추측하려고 시도한 후 시간당 호스트가 금지 된 것으로 보입니다. DoS 공격이 될 수있는 유일한 방법은 누군가가 사용자의 IP 스푸핑 (TCP 연결에서는 불가능)을 반복하거나 비밀번호를 반복해서 잘못 입력하는 경우 (이 경우 방화벽 규칙을 제어하는 ​​다른 사람이 아닌 경우)
devicenull

18
죄송하지만 좋은 아이디어인지 묻지 않았습니다.
HeavyWave

1
물론 하나 이상의 특정 IP 주소에 대해 예외를 설정할 수없는 이유는 없으므로 DoS 문제를 거의 제거 할 수 있습니다.
John Gardeniers 2012

2

이것은 오래된 실입니다. 2014-2015 년에 kevinmicke에서 제공 한 스크립트를 사용하고있었습니다. 그런 다음 방금 작동을 멈췄습니다. 그래서 보안 로그에 IP 주소를 남기지 않는 Windows 네트워크 보안 인증을 채택하기 위해 약간 편집해야했습니다. 또한 정기적 인 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 로그에도 IP 주소가없는 것 같습니다. 따라서 실제로 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 : 저는 파워 쉘 전문가가 아니므로 일부 전문가가 내 코드를 수정 / 개선 할 수 있다면 좋을 것입니다.


1

ts_block freeby를 사용 하고 있습니다.

기본적으로 "잘못된 터미널 서비스 로그온에 대한 응답으로 Windows에서 기록한 이벤트를 수신하는 WMI 이벤트 싱크 역할을하는 VBScript 프로그램입니다."

완벽하게 작동하는 것으로 보이며 스크립트를 수정해야 할 경우 스크립트가 간단합니다. 시도를 기록한 다음 허용 된 시도 횟수에 따라 금지하거나 액세스하지 않으려는 로그인 이름을 하드 코딩 할 수 있습니다.

실수로 같은 이름을 두 번 추가하여 잡히면 서비스가 1500ms마다 다시 시작되는 무한 루프로 들어가지만 vbs에 괜찮다면 수정 / 수정하기가 매우 쉽습니다.

현재 설정은 한 번만 다시 시도하면 'admin' 'Admin' 'Administrator' 'guest'등과 같은 로그인이 자동으로 금지되어 2 일 동안 금지됩니다. ip로 변경하는 것이 간단해야합니까?

어느 날 밤에 금지 된 동물을 보러가는 중독성


0

서버 / 도메인에 로그온하거나 서버에서 실행되는 웹 사이트에 로그온하는 것을 의미합니까? 서버 / 도메인에 로그온한다는 의미는 아닙니다. Windows는 IP 주소가 보안 엔티티가 아니기 때문에 실패한 로그온 시도를 기반으로 IP 주소를 차단하는 개념이 없습니다. 이 작업을 수행 할 수있는 타사 도구가있을 수 있지만 본 적이없는 도구는 없습니다.


0

공격중인 웹 서버가있는 경우 동적 IP 제한 확장을 설치할 수 있습니다 . 이것이 서버에 대한 표준 인증을위한 것이라면 도메인 및 서버 격리 를 구현 하여 도메인 가입 컴퓨터에 대한 공격 범위를 제한하고 액세스 권한이 필요한 시스템의 시도 만 허용하도록 설정할 수 있어야합니다. 서버. Windows에서 무차별 대입 공격을 방지하는 것은 계정 잠금 정책을 10 분과 같은 설정으로 설정하고 잘못된 암호 정책을 3 번의 시도로 설정하는 것입니다. 이는 공격을받는 계정이 3 번의 시도 후 10 분 동안 잠김을 의미합니다. Windows에서는 기본적으로 IP 연결을 잠글 수 없습니다. (제쳐두고 나는 또한 시스템에 영향을 미치기 위해 초당 몇 번의 로그온 시도가 필요한지 궁금합니다)


AWS 소형 인스턴스에서 4 초마다 1 회 시도하면 50 % CPU를 소비하기에 충분합니다. 당신이 나에게 묻는다면 꽤 쓰레기 ...
RomanSt

와우, 왜 활용률이 그렇게 높은지 궁금합니다. VM에서 등록을 시도하는 횟수를 확인하려면 몇 가지 테스트를 수행해야합니다.
Jim B

네트워크 수준 인증을 사용하지 않기 때문에 모든 로그인 시도는 원격 데스크톱 세션을 통해 공격자에게 실제로 로그온 UI를 표시합니다. 왜 그렇게 비쌀 지 알 수 있습니다.
RomanSt

0

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

원하는 솔루션이 기본 솔루션 (설치 및 완료) 인 경우 여기에서 무료 도구를 찾을 수 있으며 계속 읽으십시오.

현재 버전 : 1.2 (.NET Framework 4.0 클라이언트 프로파일)-> EvlWatcher 최신 버전 다운로드 (개인 및 상업적 용도로 무료)

1.2의 새로운 기능 (문서에 대한 자세한 정보) :

  • 관리 콘솔
  • WCF 서비스 패턴
  • 블랙리스트
  • 3 회 공격 후 블랙리스트로 자동 이동 (기본값)

이전 서버 (.NET Framework 2.0)

-> EvlWatcher 축소 버전 다운로드 (개인 및 상업용 무료)


0

remunda 의 훌륭한 스크립트를 시작점으로 사용하여 누락 된 중요한 한 가지를 추가 했습니다 . 실패한 FTP 로그인에서 IP 주소 차단 . Windows Server는 누군가 FTP를 통해 로그인하지 못한 경우 IP 주소를 보안 로그에 기록하지 않고 "소스 네트워크 주소"를 대시로 설정합니다. FTP는 무차별 대입 공격에 대한 매우 일반적인 공격 벡터이므로 스크립트에 오늘의 FTP 로그에서 여러 로그인 실패를 검사하고 해당 IP 주소도 차단하는 기능을 추가했습니다.

2014/02/07 업데이트 : 이전 FTP 로그를 모두 처리하기 위해이 작업을 조정했을 때 엄청난 시도 횟수 (50,000+)가 발생했을 때 생성 된 배열이 엄청나고 처리 속도가 엄청나게 느리다는 것을 깨달았습니다. FTP 로그를 처리 할 때 훨씬 효율적으로 만들기 위해 다시 작성했습니다.

또한 하나의 Windows 방화벽 규칙에 몇 개의 IP가있을 수 있는지에 대한 임의의 하드 제한이 1000이라는 것을 알았습니다. 이 제한 때문에 최신 규칙이 채워질 때 새 규칙을 자동으로 작성해야했습니다. 이제이 작업을 수행하고 초기 방화벽 규칙 (생성하지 않은 경우)을 작성하여 이벤트 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
    }
}

참고 : 이전에 시스템에서 powershell 스크립트를 실행하지 않은 경우 먼저 새 powershell을 열고 실행 Set-ExecutionPolicy RemoteSigned해야 로컬 스크립트를 실행할 수 있습니다. 그렇지 않으면 "이 시스템에서 스크립트 실행이 비활성화되어 blockattackers.ps1을로드 할 수 없습니다"라는 오류가 발생합니다.
kevinmicke

0

의 스크립트 remuda 에 의해 편집, kevinmicke (21시 59분에서 월 7) 내 시스템 (윈도우 서버 2008 R2) 상에 자신의 폴더가있는 FTP의 제어 채널을 확인하지 않았다. 또한- 530 11001이벤트가 인식되지 않아 해커가 제어 채널에만 액세스하려고 할 때 나타납니다. 그래서 두 번째 FTP 로그 폴더를 확인하기 위해 스크립트에 몇 줄을 추가했습니다.

#이 Windows Powershell 스크립트는 시스템에 로그인을 시도하는 IP 주소를 자동으로 차단합니다
# 및 $ int_block_limit 변수 이상으로 아래에 설정된 횟수만큼 실패합니다. 보안을 모두 검사합니다
# log-현재 데스크탑의 FTP 로그뿐만 아니라 원격 데스크톱 및 기타 시도를 포함합니다. $ int_block_limit 인 경우
# 해당 로그 중 하나에 제한이 설정되고 (별도로 결합되지 않은) IP 주소가
# 방화벽 규칙.
#
# 스크립트는 "BlockAttackers (작성된 yyyy-MM-dd HH : mm : ss UTC)"라는 방화벽 규칙을 자동으로 생성합니다.
# "BlockAttackers"를 포함하는 이름을 가진 이름이 존재하지 않는 경우 현재 시간. 힘들 기 때문에
# 규칙 당 차단할 수있는 1000 개 항목 (IP 주소) 제한, 비슷한 이름의 규칙도 한 번 생성합니다.
최근 한도에 도달했습니다.
#
# 이벤트 4625 로그인 감사 실패로 인해 스크립트가 예약 된 작업으로 실행되도록 설정하는 것이 좋습니다.
# 보안 로그, 또는 일정 시간이 지나면 (즉, 10 분마다) 실행되도록 설정할 수 있습니다.
#
# 저자 :
# serverfault.com 사용자 kevinmicke에 의해 작성된 대부분의 스크립트
serverfault.com 사용자 remunda가 작성한 Windows 보안 로그 부분.
# serverfault.com 사용자가 추가 한 FTP 제어 채널 확인 Uwe Martens
#
# 세부 정보 : https://serverfault.com/questions/233222/ban-ip-address-based-on-x-number-of-unsuccessful-login-attempts


# IP 주소가 차단 된 후 실패한 로그인 시도 횟수 설정
$ int_block_limit = 3

# 최근 24 시간 만 확인하도록 설정된 보안 로그를 확인하는 시간 창
$ dat_time_window = [날짜 시간] :: Now.AddDays (-1)

# $ dat_time_window 내에서 $ int_block_limit 감사 실패 (이벤트 4625)를 초과하는 모든 IP 주소를 보안 로그에서 선택하십시오.
$ 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]}} |
    그룹 개체 속성 IpAddress |
    여기서 {$ _. Count -ge $ int_block_limit} |
    -속성 이름 선택

# 현재 FTP 로그의 파일 이름을 알아 내기 위해 현재 시간 UTC를 가져옵니다.
$ current_date_utc = (Get-Date) .ToUniversalTime ()

# 오늘의 FTP 제어 채널 로그 파일 경로 설정
$ str_log_file_name_control_channel = "C : \ inetpub \ logs \ LogFiles \ FTPSVC \ u_ex"+ $ current_date_utc.ToString ( "yyMMdd") + ".log"

# 오늘 FTP 제어 채널 로그 파일에서 "530 1"을 검색하여 로그인에 실패한 시스템의 IP를 포함하는 라인을 찾으십시오.
# 각 줄에서 IP 만 가져오고 IP별로 IP를 그룹화하여 각 시도를 계산하고
오늘 $ int_block_limit 이상의 잘못된 로그인이있는 IP
$ arr_new_bad_ips_ftp_control_channel = @ ()
$ arr_new_bad_ips_ftp_control_channel = 선택 문자열 $ str_log_file_name_control_channel-패턴 "530 1"|
    ForEach-Object {$ _. Line.Substring (20,15)- ". *", ""} 바꾸기 |
    그룹 |
    여기서 {$ _. Count -ge $ int_block_limit} |
    -속성 이름 선택

# 오늘의 FTP 로그 파일 경로 설정
$ str_log_file_name = "C : \ inetpub \ logs \ LogFiles \ FTPSVC * \ u_ex"+ $ current_date_utc.ToString ( "yyMMdd") + ".log"

# 오늘 FTP 로그 파일에서 "530 1"을 검색하여 로그인에 실패한 시스템의 IP를 포함하는 행을 찾으십시오.
# 각 줄에서 IP 만 가져오고 IP별로 IP를 그룹화하여 각 시도를 계산하고
오늘 $ int_block_limit 이상의 잘못된 로그인이있는 IP
# FTPSVC *에서 * 대신 FTP 서버의 ID를 추가하거나 올바른 로그 폴더를 가져와야합니다.
$ arr_new_bad_ips_ftp = @ ()
$ arr_new_bad_ips_ftp = 선택 문자열 $ str_log_file_name-패턴 "530 1"|
    ForEach-Object {$ _. Line.Substring (20,15)- ". *", ""} 바꾸기 |
    그룹 |
    여기서 {$ _. Count -ge $ int_block_limit} |
    -속성 이름 선택

# 두 개의 IP 배열을 연결합니다 (하나는 보안 로그, 하나는 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)

# 고유 한 IP 만 선택하여 어레이를 정렬합니다 (보안 및 FTP 로그에 하나의 IP가 표시되는 경우)
$ arr_new_bad_ips_all_sorted = @ ()
$ arr_new_bad_ips_all_sorted = $ arr_new_bad_ips_all |
    Foreach-Object {[문자열] $ _. 이름} |
    객체 선택-고유

# 방화벽 객체를 얻는다
$ firewall = 새 개체 -comobject hnetcfg.fwpolicy2

# "BlockAttackers *"와 일치하는 모든 방화벽 규칙을 가져옵니다.
$ arr_firewall_rules = $ firewall.Rules | {$ _. 이름과 같은 'BlockAttackers *'}

# "BlockAttackers *"방화벽 규칙이 아직 존재하지 않는 경우 하나를 만들어 변수로 설정하십시오.
if ($ arr_firewall_rules -eq $ null) {
    $ str_new_rule_name = "블록 어택커 (생성 된"+ $ current_date_utc.ToString ( "yyyy-MM-dd HH : mm : ss") + "UTC)"
    netsh advfirewall 방화벽 추가 규칙 dir = in action = block name = $ str_new_rule_name description = "규칙이 자동으로 생성되었습니다." enable = yes remoteip = "0.0.0.0"| 외부 널
    $ arr_firewall_rules = $ firewall.Rules | {$ _. 이름과 같은 'BlockAttackers *'}
}

# 기존의 IP를 현재 "BlockAttackers *"방화벽 규칙에서 배열로 분할하여 쉽게 검색 할 수 있습니다.
$ arr_existing_bad_ips = @ ()
foreach ($ arr_firewall_rules의 $ rule) {
    $ arr_existing_bad_ips + = $ rule.RemoteAddresses -split ( ',')
}

# 방화벽 규칙에 의해 현재 차단 된 IP에서 서브넷 마스크 정리
$ arr_existing_bad_ips_without_masks = @ ()
$ arr_existing_bad_ips_without_masks = $ arr_existing_bad_ips | ForEach-Object {$ _-대체 "/.*", ""}

# 115, 116 행에 서버의 IP (IPv4 및 IPv6)를 입력하십시오.
# 방화벽에 추가 할 IP 주소를 선택하십시오.
$ arr_new_bad_ips_for_firewall = @ ()
$ arr_new_bad_ips_for_firewall = $ arr_new_bad_ips_all_sorted | 어디 {
    # IP 주소를 포함합니다 (즉, FTP 로그인에 실패한 시스템의 보안 로그에있는 공백 또는 대시가 아님)
    $ _. Length -gt 6-및
    #은 (는) 아직 방화벽 규칙에 없습니다
    ! ($ arr_existing_bad_ips_without_masks-$ _ 포함)-및
    #는 로컬 루프백이 아닙니다
    ! ($ _. StartsWith ( '127.0.0.1'))-및
    #은 로컬 서브넷의 일부가 아닙니다
    ! ($ _. StartsWith ( '192.168.'))-및
    ! ($ _. StartsWith ( '0.0.')) 및
    ! ($ _. StartsWith ('10 .0. '))-및
    ! ($ _. StartsWith ( '*. *. *. *'))-및
    ! ($ _. StartsWith ( '* : * : * : * : * : *'))
}

# 차단할 IP가 있으면 다음을 수행하십시오.
if ($ arr_new_bad_ips_for_firewall -ne $ null) {
    # 스크립트 별 로그 파일에 날짜 및 시간 쓰기
    [날짜 시간] :: 지금 | Out-File -Append -Encoding utf8 C : \ inetpub \ logs \ LogFiles \ blockattackers.txt
    # 새로 차단 된 IP 주소를 로그 파일에 기록
    $ arr_new_bad_ips_for_firewall | Out-File -Append -Encoding utf8 C : \ inetpub \ logs \ LogFiles \ blockattackers.txt

    # 새 규칙이 하나의 규칙에만 추가되도록 부울
    $ bln_added_to_rule = 0

    # 각 규칙에서 잘못된 IP를 한 번에 하나씩 보유하는 배열이므로 새 IP를 추가하면 1000 개의 IP를 초과하지 않도록 계산할 수 있습니다.
    $ arr_existing_bad_ips_current_rule = @ ()

    # 방화벽의 각 "BlockAttackers *"규칙에 대해 다음을 수행하십시오.
    foreach ($ arr_firewall_rules의 $ rule) {
        if ($ bln_added_to_rule -ne 1) {
            # 기존 규칙을 현재 규칙에서 배열로 분할하여 쉽게 계산할 수 있습니다.
            $ arr_existing_bad_ips_current_rule = $ rule.RemoteAddresses -split ( ',')

            # 추가 할 IP 수가 1000 미만에서 규칙의 현재 IP 수를 뺀 경우이 규칙에 추가하십시오.
            if ($ arr_new_bad_ips_for_firewall.Count -le (1000-$ arr_existing_bad_ips_current_rule.Count)) {
                # 방화벽 규칙에 새 IP 추가
                $ arr_new_bad_ips_for_firewall | % {$ rule.RemoteAddresses + = ','+ $ _}

                # 로그 파일에 IP가 추가 된 규칙 작성
                echo "위의 새로운 IP 주소가 Windows 방화벽 규칙에 추가되었습니다 :"$ rule.Name | Out-File -Append -Encoding utf8 C : \ inetpub \ logs \ LogFiles \ blockattackers.txt

                # IP를 추가 할 때 다른 규칙을 건너 뛰도록 부울을 설정하십시오.
                $ bln_added_to_rule = 1
            }
        }
    }

    # 다른 "BlockAttackers *"방화벽 규칙에 공간이 없으면 새 것을 만들고 IP를 추가하십시오.
    if ($ bln_added_to_rule -ne 1) {
        $ str_new_rule_name = "블록 어택커 (생성 된"+ $ current_date_utc.ToString ( "yyyy-MM-dd HH : mm : ss") + "UTC)"
        netsh advfirewall 방화벽 추가 규칙 dir = in action = block name = $ str_new_rule_name description = "규칙이 자동으로 생성되었습니다." enable = yes remoteip = "0.0.0.0"| 외부 널
        $ new_rule = $ firewall.rules | 여기서 {$ _. Name -eq $ str_new_rule_name}

        # 방화벽 규칙에 새 IP 추가
        $ arr_new_bad_ips_for_firewall | % {$ new_rule.RemoteAddresses + = ','+ $ _}

        # 로그 파일에 IP가 추가 된 규칙 작성
        echo "위의 새 IP 주소가 새로 작성된 Windows 방화벽 규칙에 추가되었습니다."$ new_rule.Name | Out-File -Append -Encoding utf8 C : \ inetpub \ logs \ LogFiles \ blockattackers.txt
    }
}

FTPSVC*54 행 의 FTP 로그 폴더 이름 은 원인이 있어야합니다. 115 번과 116 번 줄에 서버의 IP (IPv4와 IPv6)를 입력해야합니다. 그렇지 않으면 자신의 서버 IP가 방화벽 규칙에 100 번 추가 될 수 있습니다. $int_block_limit서버에서 변수 를 1로 설정했기 때문에 스크립트가 2 초 내에 4625 이벤트를 발생시키는 해커 공격을 차단하고 있습니다. 나는 아직도 몇 분 동안 4625 이벤트가 발생할 때 스크립트를 추가로 실행하려고합니다. 원인은 스크립트를 분리하고 하나의 스크립트가 4625 이벤트에 의해 트리거 된 4625 이벤트를 검사하고 다른 스크립트가 별도의 방화벽 규칙을 사용하더라도 5 분 또는 10 분마다 주기적으로 검사하는 FTP 로그 폴더를 검사하게 할 수도 있습니다. 및 로그 파일.


-1

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)
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.