Auto blocking attacking IP address

This is to share my PowerShell code online. I original asked this question on MSDN forum (or TechNet?) here:

http://social.technet.microsoft.com/Forums/en-US/winserversecurity/thread/f950686e-e3f8-4cf2-b8ec-2685c1ed7a77

In short, this is trying to find attacking IP address then add it into Firewall block rule. So I suppose:

1, You are running a Windows Server 2008 facing the Internet.

2, You need to have some port open for service, e.g. TCP 21 for FTP; TCP 3389 for Remote Desktop. You can see in my code I’m only dealing with these two since that’s what I opened. You can add further port number if you like, but the way to process might be different with these two.

3, I strongly suggest you use STRONG password and follow all security best practices, this ps1 code is NOT for adding security to your server, but reduce the nuisance from brute force attack, and make sys admin’s life easier: i.e. your FTP log won’t hold megabytes of nonsense, your Windows system log will not roll back and only can tell you what happened last month.

4, You are comfortable with setting up Windows Firewall rules, in my code, my rule has a name of “MY BLACKLIST”, you need to setup a similar one, and set it to BLOCK everything.

5, My rule is dangerous because it has the risk to block myself out as well. I do have a backup plan i.e. the DELL DRAC5 so that if that happens, I still can remote console to my server and reset the firewall.

6, By no means the code is perfect, the coding style, the use of PowerShell skills, the hard coded part, all can be improved, it’s just that it’s good enough for me already. It has been running on my server for more than 7 MONTHS.

7, Current code still has problem, I didn’t solve it yet, further on this point after the code. :)


 

 #Dong Xie, March 2012
 #my simple code to monitor attack and deal with it
 #Windows Server 2008 Logon Type
 #8: NetworkCleartext, i.e. FTP
 #10: RemoteInteractive, i.e. RDP
 
 $tick = 0;
 "Start to run at: " + (get-date);
 
 $regex1 = [regex] "192\.168\.100\.(?:101|102):3389\s+(\d+\.\d+\.\d+\.\d+)";
 $regex2 = [regex] "Source Network Address:\t(\d+\.\d+\.\d+\.\d+)";
 
 while($True) {
  $blacklist = @();
 
  "Running... (tick:" + $tick + ")"; $tick+=1;
 
 #Port 3389
 $a = @()
 netstat -no | Select-String ":3389" | ? { $m = $regex1.Match($_); `
   $ip = $m.Groups[1].Value; if ($m.Success -and $ip -ne "10.0.0.1") {$a = $a + $ip;} }

 if ($a.count -gt 0) {
   $ips = get-eventlog Security -Newest 1000 | Where-Object {$_.EventID -eq 4625 -and $_.Message -match "Logon Type:\s+10"} | foreach { `
     $m = $regex2.Match($_.Message); $ip = $m.Groups[1].Value; $ip; } | Sort-Object | Tee-Object -Variable list | Get-Unique

   foreach ($ip in $a) { if ($ips -contains $ip) {
     if (-not ($blacklist -contains $ip)) {
       $attack_count = ($list | Select-String $ip -SimpleMatch | Measure-Object).count;
       "Found attacking IP on 3389: " + $ip + ", with count: " + $attack_count;
       if ($attack_count -ge 20) {$blacklist = $blacklist + $ip;}
     } 
    }
   }
 }
 
 
 #FTP
 $now = (Get-Date).AddMinutes(-5); #check only last 5 mins.
    #Get-EventLog has built-in switch for EventID, Message, Time, etc. but using any of these it will be VERY slow.
 $count = (Get-EventLog Security -Newest 1000 | Where-Object {$_.EventID -eq 4625 -and $_.Message -match "Logon Type:\s+8" -and `
             $_.TimeGenerated.CompareTo($now) -gt 0} | Measure-Object).count;
 if ($count -gt 50) #threshold
 {
    $ips = @();
    $ips1 = dir "C:\inetpub\logs\LogFiles\FPTSVC2" | Sort-Object -Property LastWriteTime -Descending `
      | select -First 1 | gc | select -Last 200 | where {$_ -match "An\+error\+occured\+during\+the\+authentication\+process."} `
       | Select-String -Pattern "(\d+\.\d+\.\d+\.\d+)" | select -ExpandProperty Matches | select -ExpandProperty value | Group-Object `
       | where {$_.Count -ge 10} | select -ExpandProperty Name;
 
    $ips2 = dir "C:\inetpub\logs\LogFiles\FTPSVC3" | Sort-Object -Property LastWriteTime -Descending `
      | select -First 1 | gc | select -Last 200 | where {$_ -match "An\+error\+occured\+during\+the\+authentication\+process."} `
       | Select-String -Pattern "(\d+\.\d+\.\d+\.\d+)" | select -ExpandProperty Matches | select -ExpandProperty value | Group-Object `
       | where {$_.Count -ge 10} | select -ExpandProperty Name;
    $ips += $ips1; $ips += $ips2; $ips = $ips | where {$_ -ne "10.0.0.1"} | Sort-Object | Get-Unique;
   
    foreach ($ip in $ips) {
      if (-not ($blacklist -contains $ip)) {
       "Found attacking IP on FTP: " + $ip;
       $blacklist = $blacklist + $ip;
      }
    }
 }
 
 
 
 #Firewall change

<# $current = (netsh advfirewall firewall show rule name="MY BLACKLIST" | where {$_ -match "RemoteIP"}).replace("RemoteIP:", "").replace(" ","").replace("/255.255.255.255",""); #inside $current there is no \r or \n need remove. foreach ($ip in $blacklist) { if (-not ($current -match $ip) -and -not ($ip -like "10.0.0.*")) {"Adding this IP into firewall blocklist: " + $ip; $c= 'netsh advfirewall firewall set rule name="MY BLACKLIST" new RemoteIP="{0},{1}"' -f $ip, $current; Invoke-Expression $c; } } #>
 
 foreach ($ip in $blacklist) {

   $fw=New-object –comObject HNetCfg.FwPolicy2; # http://blogs.technet.com/b/jamesone/archive/2009/02/18/how-to-manage-the-windows-firewall-settings-with-powershell.aspx
   $myrule = $fw.Rules | where {$_.Name -eq "MY BLACKLIST"} | select -First 1; # Potential bug here?

   if (-not ($myrule.RemoteAddresses -match $ip) -and -not ($ip -like "10.0.0.*"))
     {"Adding this IP into firewall blocklist: " + $ip; 
       $myrule.RemoteAddresses+=(","+$ip);
     }
 }
 
 Wait-Event -Timeout 30 #pause 30 secs
 
 } # end of top while loop.

 


Further points:

1, I suppose the server is listening on port 3389 on server IP: 192.168.100.101 and 192.168.100.102, you need to replace that with your real IP.

2, I suppose you are Remote Desktop to this server from a workstation with IP: 10.0.0.1. Please replace as well.

3, The threshold for 3389 attack is 20, you don’t want to block yourself just because you typed your password wrong 3 times, you can change this threshold by your own reasoning.

4, FTP is checking the log for attack only to the last 5 mins, you can change that as well.

5, I suppose the server is serving FTP on both IP address and their LOG path are C:\inetpub\logs\LogFiles\FPTSVC2 and C:\inetpub\logs\LogFiles\FPTSVC3. Change accordingly.

6, FTP checking code is only asking for the last 200 lines of log, and the threshold is 10, change as you wish.

7, the code runs in a loop, you can set the loop time at the last line.


To run this code, copy and paste to your editor, finish all the editing, get it to your server, and open an CMD window, then type powershell.exe –file your_powershell_file_name.ps1, it will start running, you can Ctrl-C to break it.

This is what you see when it’s running:

image

This is when it detected attack and adding the firewall rule:

image


Regarding the design of the code:

1, There are many ways you can detect the attack, but to add an IP into a block rule is no small thing, you need to think hard before doing it, reason for that may include: You don’t want block yourself; and not blocking your customer/user, i.e. the good guy.

2, Thus for each service/port, I double check. For 3389, first it needs to show in netstat.exe, then the Event log; for FTP, first check the Event log, then the FTP log files.

3, At three places I need to make sure I’m not adding myself into the block rule. –ne with single IP, –like with subnet.

 

Now the final bit:

1, The code will stop working after a while (depends on how busy you are attacked, could be weeks, months, or days?!) It will throw Red error message in CMD, don’t Panic, it does no harm, but it also no longer blocking new attack. THE REASON is not confirmed with MS people: the COM object to manage firewall, you can only give it a list of IP addresses to the length of around 32KB I think, once it reaches the limit, you get the error message.

2, This is in fact my second solution to use the COM object, the first solution is still in the comment block for your reference, which is using netsh, that fails because being run from CMD, you can only throw it a list of IP to 8KB.

3, I haven’t worked the workaround yet, some ideas include: wrap that RemoteAddresses setting line with error checking and once it reaches the limit, use the newly detected IP to be the list, not appending to it. This basically reset your block rule to ground zero and lose the previous bad IPs. This does no harm as it sounds, because given a certain period has passed, any these bad IPs still not repent and continue the attack to you, it only got 30 seconds or 20 guesses of your password before you block it again. And there is the benefit that the bad IP may turn back to the good hands again, and you are not blocking a potential customer or your CEO’s home pc because once upon a time, it’s a zombie. Thus the ZEN of blocking: never block any IP for too long.

4, But if you insist to block the ugly forever, my other ideas include: You call MS support, ask them how can we set an arbitrary length of IP addresses in a rule; at least from my experiences at the Forum, they don’t know and they don’t care, because they think the dynamic blocking should be done by some expensive hardware. Or, from programming perspective, you can create a new rule once the old is full, then you’ll have MY BLACKLIST1, MY  BLACKLIST2, MY BLACKLIST3, … etc. Once in a while you can compile them together and start a business to sell your blacklist on the market!

Enjoy the code!

p.s. (PowerShell is REALLY REALLY GREAT!)

Published 06 March 2012 15:59 by dong

Comments

# re: Auto blocking attacking IP address

Awesome script!  This simply does exactly what my very expensive (and well known brand) of firewall/IPS/IDS cannot do for me at the perimiter.  I modified the script to telnet to our fw and 'shun' the ip address instead of using Windows Firewall.  Also some text file logging...

Question:  Is it possible to use event sinks to look for the audit fail logs?  So the script wouldn't necessarily run on a timer?  I'm new to powershell (late adopter from VB script/admin).  Thanks again!

13 April 2012 14:21 by gbx

# re: Auto blocking attacking IP address

@gbx,

Thanks! That's a very good suggestion. I'll look at Wait-Event to try that. Maybe with another post.

Given we can change from polling to block and wait, the FTP part still need to go to the LogFiles and netstat to double confirm the attacking IP, because in event 4625 for Logon Type 8, there is no IP address inside. (Why?)

Best,

dong

24 April 2012 14:16 by dong

# re: Auto blocking attacking IP address

Be careful if you copy and paste this into a file, you might have an extra space added after all the backtick symbol (`), this will generate many nonsense errors.

Now you can download above code as a file here:

sqlblogcasts.com/.../entry16228.aspx

Best,

dong

06 June 2012 17:59 by dong

# re: Auto blocking attacking IP address

Fantastic script.Thanks!

13 November 2012 12:13 by beny.pl

# lost+found: Trojanerknacker, Brute-Force-Blockade und Bollywood | Edv-Sicherheitskonzepte.de &#8211; News Blog aus vielen Bereichen

Pingback from  lost+found: Trojanerknacker, Brute-Force-Blockade und Bollywood | Edv-Sicherheitskonzepte.de &#8211; News Blog aus vielen Bereichen

# IT Secure Site &raquo; Blog Archive &raquo; Lost+Found: A Trojan cracker, a brute force blockade and Bollywood

Pingback from  IT Secure Site  &raquo; Blog Archive   &raquo; Lost+Found: A Trojan cracker, a brute force blockade and Bollywood

# Lost+Found: A Trojan cracker, a brute force blockade and Bollywood - PHP web application, Joomla, ecommerce website development - PHP OOPS &#8211; PHP Development

Pingback from  Lost+Found: A Trojan cracker, a brute force blockade and Bollywood - PHP web application, Joomla, ecommerce website development - PHP OOPS  &#8211; PHP Development

# re: Auto blocking attacking IP address

Very nice code!  

similar to gbx, I too hide my servers behind a dedicated firewall (in my case IPCOP) although ya won't be a telneting into that box anytime soon. ;o)

A couple ideas for thought.

I've been asked to lock down several unmanaged boxes over the years.  Sort of like a 3 am emergency call, omg can ya help us?  

There are several things I learned from this activity.

Scripting the grepping of the logs for the top 100 bad ip's (which get BANNED if not WHITELISTED), then sorting that data and when 5 or more IP's have the same netblock I kick the rule up, to a CIDR NETBLOCK  (I get this from doing a cidr -a xxx.xxx.xxx.xxx and reading the  cidr line  . This game for me started out with the famous "R-fx Networks apf firewall", and eventually morphed (for me at least) into a more direct custom ban script based off of JoeCat (if you can even find that now.)

The neat thing is such a script can run at the same time as apf.  But... you have to create the CUSTOMINPUT CUSTOMOUTPUT CUSTOMFORWARD and like you ya have to put banned IP/net's in it three times sadly which makes the list bigger. I digress if all your doing is blocking a spammer on your email server all you really need is the CUSTOMINPUT rule.

Why would I bother telling you about locking down linux boxes like this?

Cause you can also use the SAME script like Mr gbx (above post) however I wouldn't use telnet personally for anything but say synchronet+fidonet bbs these days. I digress, you can port knock, or SPA access, or SSH over a LIST which then get's processed via iptables.

One such list is what I call my 256 list (certainly someone's done this before but I'll be damned if the only one on the net I can find it published was me)

0.0.0.0/8

1.0.0.0/8

2.0.0.0/8

...  continue with pattern

254.0.0.0/8

255.0.0.0/8

the point here being in 256 lines you can BLOCK ALL PACKETS (and make that little glowing red light go out)  

modifications would be to allow for DNS resolve, Admin Access IP address, updates for the operating system itself.  and that's about it. Clearly you need to make an exception for your OWN IP if you roll this out on something remote, so you do not get locked out.  (if that matters to ya)

I should mention another thing.  it just seems SAFER to me to have all servers sitting behind ipcop.  Even if I was going to face a http server to the web directly, any SQL server would NOT be facing the web.

If I were smarter I would use NETBSD instead of IPCOP but, frankly I've reached the end of what my security capabilities are both financially and intellectually.  And full disclosure, NO I DON'T DO IPV6.

Peace my friends, hope this helps someone.

08 January 2013 05:06 by pengwyn

# Block IP address with Windows Firewall 2008 : The Digital Jedi&#039;s Blog

Pingback from  Block IP address with Windows Firewall 2008 : The Digital Jedi&#039;s Blog

# Block IP address with Windows Firewall 2008 : The Digital Jedi&#039;s Blog

Pingback from  Block IP address with Windows Firewall 2008 : The Digital Jedi&#039;s Blog