IIS: Instantly Ban IPs Attempting to Login to MS-FTP as Administrator

Filed under: IIS, Quick Code, Security, VBScript — Written by Chrissy on Sunday, July 2nd, 2006 @ 5:49 pm

UPDATE 12/18/06: The startup script has been modified slightly (cscript.exe was changed to wscript.exe). Now, console users will no longer encounter a blank black box upon login.
UPDATE 11/21/06: Now that banning at the IP level has been added to the script, offending users are completely banned before they can even attempt a second login on Windows 2003 machines. Windows 2000 machines still have a slight delay.
UPDATE 1/18/07: I updated the code so that it does not throw out an "unknown" error on line 48 for Win2k users. Thanks to the commenters for figuring that out. Also, check the comments for some really great script modification and ideas posted by blog visitors. Thanks to everyone who has posted!

Recently while reviewing my Windows Events, I noticed over 2800 failed login attempts to my Microsoft FTP server. Apparently, a bot was trying to brute force the Administrator password. Thankfully, I soon determined that there were only two IPs I needed to ban. The FTP server needs to be accessed by my employer's clients so I couldn't just change the port (as I did when I found 30,000+ SSH login attempts to my Linux box). Thus, I decided to instantly ban any IPs attempting to login as Administrator. I did this using a VBScript file (saved as: C:\Scripts\Startup\banftpips.vbs) that is set to execute upon boot-up. This can be done like so.

banftpips.vbs

'****************************************************************************
' This script created by Chrissy LeMaire (clemaire@gmail.com)
' Website: http://netnerds.net/
'
' NO WARRANTIES, etc.
'
' This script instantly bans IP addresses trying to login to FTP
' using the NT account "Administrator"
'
' Run this script on the FTP server. It sits in the back and waits for an
' event viewer "push" that lets it know someone failed FTP authentication.
'
' This script has only been tested on Windows Server 2003. It assumes, as it
' should, that there are no legitimate Administrator account FTP logins.
'
' "What it does"
' 1. Sets an Async Event Sink to notify the script when someone fails MS-FTP auth
' 2. When alerted, the script parses the last day's FTP logs for all FTP sites (this
'    is because the Event Viewer doesn't tell you which FTP site, if you have more than
'    one, is the one getting hit)
' 3. Compiles the list of IPs to be banned and then bans them using IIS /and/
'    IP level banning (thanks Spencer @ netortech.com for the idea)
'*****************************************************************************
 
' Push Event Viewer Alert
    Set objWMIService = GetObject("winmgmts:{(security)}!root/cimv2")
    Set eventSink = wscript.CreateObject("WbemScripting.SWbemSink", "EVSINK_")
    strWQL = "Select * from __InstanceCreationEvent where TargetInstance isa  'Win32_NTLogEvent' and TargetInstance.SourceName = 'MSFTPSVC' and TargetInstance.EventCode = 100"
    objWMIService.ExecNotificationQueryAsync eventSink,strWQL
 
' Keep it going forever
While (True)
    Wscript.Sleep(1000)
Wend
 
Sub EVSINK_OnObjectReady(objObject, objAsyncContext)
  If InStr(LCase(objObject.TargetInstance.Message),"administrator") > 0 Then
    Set objFTPSVC = GetObject("IIS://localhost/MSFTPSVC")
    Set WshShell = CreateObject("WScript.Shell")
    Set objFSO = CreateObject("Scripting.FileSystemObject")
    Set objLog = CreateObject("MSWC.IISLog")
    Set objDictionary = CreateObject("Scripting.Dictionary")
    Set objFTPIPSec = objFTPSVC.IPSecurity
    
    'Get IP address of server so we can use it later to give the offending IP a bad route
    Set IPConfigSet = GetObject("winmgmts:\\.\root\cimv2").ExecQuery("SELECT * FROM Win32_NetworkAdapterConfiguration WHERE IPEnabled=TRUE")
    for each IPConfig in IPConfigSet
      if Not IsNull(IPConfig.DefaultIPGateway) then serverIP =  IPConfig.IPAddress(0)
    Next
    Set IPConfigSet = Nothing
 
    'Iterate through each FTP site. See #2 up above.
      For Each objSITE in objFTPSVC
        If lcase(objSITE.class) = "iisftpserver" Then
          ftpLogFilePath =  WshShell.ExpandEnvironmentStrings(objSITE.LogFileDirectory) & "\msftpsvc" & objSITE.Name
      
          Set objFolder = objFSO.GetFolder(ftpLogFilePath)
            Set objFiles = objFolder.Files
              For Each fileName In objFiles
                lastFile = fileName
              Next
            strLogFile = lastFile
            Set file = Nothing
          Set objFolder = Nothing
          
          'Use the IIS log file parser provided by MSFT
          objLog.OpenLogFile strLogFile, 1, "MSFTPSVC", 1, 0
            '(FileName,IOMode,ServiceName,ServiceInstance,OutputLogFileFormat)
            ' 0 = NotApplicable, 1 = ForReading  
            While NOT objLog.AtEndOfLog
              objLog.ReadLogRecord
              If LCase(objLog.URIStem) = "administrator" Then
                ClientIP = objLog.ClientIP
                  If objDictionary.Exists(ClientIP) = False Then
                      'Kill the route to the machine then add it to the array of banned IPs.
                      Set WshShell = WScript.CreateObject("WScript.Shell")
                    WshShell.Run "ROUTE ADD " & clientIP & " MASK 255.255.255.255 " & serverIP, 1, True
                    Set WshShell = Nothing
                    objDictionary.Add ClientIP, "255.255.255.255" '255 is just there for padding.
                  End If
              End If
            Wend  
          objLog.CloseLogFiles 1
        End If
      Next
    
      'Append the newly banned IPs to the currently banned IPs  
      If objDictionary.Count > 0 And objFTPIPSec.GrantByDefault = True Then
        bannedIPArray = objFTPIPSec.IPDeny
          For i = 0 to ubound(bannedIPArray)
          clientIP = Left(bannedIPArray(i),InStr(bannedIPArray(i),",")-1)
            If objDictionary.Exists(ClientIP) = False Then
              objDictionary.Add bannedIPArray(i), "255.255.255.255"
            End If
          Next
          
        objFTPIPSec.IPDeny = objDictionary.Keys
        objFTPSVC.IPSecurity = objFTPIPSec
        objFTPSVC.SetInfo
      End If
      
    Set objFTPIPSec = Nothing
    Set objDictionary = Nothing
    Set objLog = Nothing
    Set objFSO = Nothing
    Set objFTPSVC = Nothing
  End If
  End Sub

Once the IP has been added to the ban list, the user will no longer be able to connect to the machine via TCP/IP as it has been given a bad route. If the server reboots, it will lose the route but the IP will still be banned in IIS. The offending user will then see the following message:

Connected to ftpserver
530 Connection refused, unknown IP address.
421 Service not available, closing control connection.
Connection closed by remote host.

Note that this bans the IPs on a global FTP level. You will find the banned IPs listed under Windows 2003 @ IIS -> FTP -> Properties and under Windows 2000 @ IIS -> Hostname -> Properties -> FTP Service -> Edit -> Directory Security. This means you will not find it on the properties of the Default FTP Site. This pro-actively bans the IPs from hitting other FTP sites in an IIS setup with multiple FTP sites. In addition, with the new ban at the IP level, the machine can't even contact your server until your Windows server has been rebooted and the manual routes have thus been reset.

133 Comments   -
  • Comment by Vittorio Pavesi | July 6, 2006 @ 2:01 pm

    Really useful !!!
    Thanks

    Vittorio

  • Comment by Chrissy | July 6, 2006 @ 5:07 pm

    Hey Vittorio,
    Make sure you don't put this script into the GPO startup. Since it's a monitoring script that doesn't end until you kill the process, the machine hangs at "Running startup scripts..." Not too sure what the default time-out is for GPO scripts but it was too long for me. I'm going to update the blog to let others know.

  • Comment by Spencer Ruport | July 11, 2006 @ 6:31 pm

    Thanks for this.

    Your code helped me write my own script which I now use to curb dictionary attacks.

  • Comment by Rick | July 23, 2006 @ 3:49 pm

    Hey Chrissy,
    This snippet rocks. Thank you again for sharing.
    I would like to ask you about an ASP solution that is similar in concept...adding an IP to a specific site where the IIsIPSecuritySetting DenyByDefault is used instead of GrantByDefault. I have a IIS Web Site that is configured to use an Admin account in which NTLM auth is disabled, and an ASP login form where the user/pass is validated against a SQL record (MySQL5) -- no NTLM involved period. If the user is validated, I would like the ASP script to add the IP addy dynamicaly to a couple of other web sites hosted on the same server. My WSH/WMI skills are pretty weak to say the least and was hoping maybe if you have time one day you could maybe point me in the right direction....oh hell, who am I kidding...I need code girl, plain and simple, lol. I am not beyond begging, so let me know if there is anything that maybe I could do for you. The only part I have no clue on is the WSH/WMI interaction with IIS to accomplish this specific task.
    Shouts from the Mississippi Delta!

  • Comment by Jeri Morris | July 24, 2006 @ 4:19 pm

    Looks like an excellent script--thank you for posting it!

    I'd like to get this running on my Windows 2000 server. I'm not familiar with Group Policy objects or startup scripts (other than reading the Windows 2000 help, which isn't too helpful). Can you suggest how to install the script on a Windows 2000 server so that the script runs asynchronously and doesn't hang the system on reboot?

    Thanks again,

    Jeri

  • Comment by Steven De See | July 27, 2006 @ 2:21 pm

    You are a lifesaver. After logging upwards of 10K attempts at administrator logins from ~12 different IP's we needed something to combat the inherent stupidity of being locked out of logging into the server as administrator because some other clown(s) was banging away illictly at that server!

    Two questions, one dumb & the other hopefully not so:
    >how do I tell that it's actually working?
    >how can I add this BANIPFTP functionality to a couple other usual suspects ("admin", "guest")? Duplicate the section of code starting with 'Sub EVSINK_OnObjectReady(objObject...' and sub the desired name? Of couse it's not a big deal because these logins don't exist and/or are securely disabled, but would still like to ban the uninvited.

    Many thanks,
    Steve

  • Comment by Steven De See | July 27, 2006 @ 2:39 pm

    p.s. I asked the dumb "how do I know..." question because after a dry spell of no attempts there was a recent dictionary attempt by someone and the first few hundred logins attempted was with "administrator" (then 'admin', 'guest', etc.) - I was suprised that this attempt was able to continue after first trying with 'administrator'

  • Comment by Chrissy | July 27, 2006 @ 6:16 pm

    Hey Jeri,
    You can add it to the startup registry. http://blog.netnerds.net/code/startup.txt lists how to do it though I don't know if Win2k supports "reg add" if not, just add it using regedit.

  • Comment by Chrissy | July 27, 2006 @ 6:18 pm

    Hey Rick,
    That's completely doable. I'll think about it and get back to you.

    Chrissy

  • Comment by Chrissy | July 27, 2006 @ 6:41 pm

    Hey Steven,
    first, to add other users, just add to the following line

    If InStr(LCase(objObject.TargetInstance.Message),"administrator") > 0 Then

    So in your case, that line would say

    If InStr(LCase(objObject.TargetInstance.Message),"admin") > 0 or InStr(LCase(objObject.TargetInstance.Message),"guest") > 0 Then

    Also, make a similar change on the objLog.URIStem line...

    Since the "instr" doesn't look for exact matches, "admin" would work for both admin and administrator.

    To see if its running, go to Task Manager and order by name. Look for Wscript.exe ..if you see that running, it may be this script.

    To see if it's working, go to IIS -> FTP -> Properties -> Directory Security.

    For the record, on ONE of my machines.. there was a delay in IIS enforcing the policy. It took about 4 hours and then hasn't had a problem since. Weird!

    EDIT: I took a snapshot of the wrong location. It should be under Windows 2003 @ IIS -> FTP -> Properties and under Windows 2000 @ IIS -> Hostname -> Properties -> FTP Service -> Edit -> Directory Security. This means you will not find it on the properties of the Default FTP Site.

  • Comment by Rick | August 6, 2006 @ 6:32 pm

    Hey Chrissy, I am experiencing an anomaly I have been unable to solve with the startup method of your script on a server I manage remotely...it works fine on my VMWare instance that I initialy tested the script on, but I logon to it local.

    I used the "reg add" method you posted, double-checked the paths and NTFS perms, but on the remote server the script does not appear to be running until I login via RDP, and then terminates when I logoff of the remote server...at least it appears to be so...I mean, I tried to login to FTP as Administrator and it never banned my IP addy and I waited for a day as I see in your comment above that sometimes it might take a while for it to appear under Directory Security.

    The remote server is not part of a domain (workgroup only), and is running 2003SE+all current patches.

    Penny for your thoughts?

    Thanks,
    Rick

  • Comment by Rick | August 8, 2006 @ 11:32 am

    Ok Chrissy, I can be a little scatter brained sometimes...I was lloking at the Default FTP Site properties instead of the FTP Sites Master Properties...there I found the Denied IP addys I have been testing with.
    Thanks again for this wonderful script!
    Best Regards,
    Rick

  • Comment by MK | August 14, 2006 @ 2:28 am

    Hello Chrissy,

    I had tried the script, but I had encounter some problem after run the seript. So I don't have any idea what is the error.

    It show :

    Script: c:\baniisadm.vbs
    Line: 28
    Char: 5
    Error: Access denied

    Code: 80041003
    Source: SWbemServices

    Thanks in advance,
    MK

  • Comment by MK | August 14, 2006 @ 2:30 am

    Sorry, I had missing some information, I had test it in the Server2000 /wSP4 and under a Domain (Server2003 Std)

  • Comment by chris | August 21, 2006 @ 6:22 am

    Hello.
    I copied the sctript to notepad as saved as vbs then ran it on server 2003 sp1 and i get a error.
    (96,1) Microsoft VBScript compilaiton error: Exspected 'End'
    Any Ideas?

  • Comment by chris | August 21, 2006 @ 6:43 am

    Added...At the end of the script I needed to add 'End Sub' on a new last line, line 96. All works GREAT now and initialized as soon as I ran it with a CMD window. As you guessed, this script can manually be run with a command promt minimized (suggested for testing to minimize the restart times). Now the big test will be if these idiot attackers have thier bots set to realize their IP's are blocked and the attacks stops there.

  • Comment by vern | August 23, 2006 @ 9:23 am

    Chrisy: I got hit hard the other day and none of the offending addresses were banned.

    I made some additions to the words to check similar to what you showed Stevan above, but nothing was checked.
    Here's what I changed;
    If InStr(LCase(objObject.TargetInstance.Message),"admin") > 0 or InStr(LCase(objObject.TargetInstance.Message),"user") > 0 or InStr(LCase(objObject.TargetInstance.Message),"tomy") > 0 or InStr(LCase(objObject.TargetInstance.Message),"guest") > 0 or InStr(LCase(objObject.TargetInstance.Message),"Www") > 0 Then

    Does that look ok?

  • Comment by vern | August 23, 2006 @ 9:27 am

    Is there anyway to have a whitelist of acceptable userames and everything else gets banned?

  • Comment by vern | August 28, 2006 @ 1:06 pm

    Something else I was thinking about that could (I think) use part of this code; add those same IPs to the www service ban list, and, perhaps even more importantly, the SMTP Virtual Server Connection Control Deny list(s).

    Or just add it to the Global Settings Message Delivery Connection Filtering Deny list...

    Whatcha think?

  • Comment by Andy | September 21, 2006 @ 6:25 am

    Cool script - thanks. It's added an internal ip to the ban list after logging in from the lan (to test) but I can still connect to the ftp server and get a login prompt which I wasn't sure should happen.
    I'm going to try a bit more debugging to see whats going on.

  • Comment by Sean | September 22, 2006 @ 7:56 am

    I am getting the same access enied error, any thoughts on why?

  • Comment by sam | September 24, 2006 @ 7:40 am

    Hi Chrissy.

    This script is just what I need - thx! Having a problem with it, tho. It seems to be runing (I see the script process), but it doesn't ban my test IP- even after waiting the "four hours" you observed.

    Few questions: what format does the log file need to be in? Mine is set for daily using W3C Extended. Also, does it matter if I have added a few 'deny' IP's manualy?

    I'm running Windows Small Business Server2003 Standard.

    Thank for any help...

  • Comment by Phi | September 26, 2006 @ 10:30 pm

    Hello Chrissy,

    Thanks for sharing with us your very nice script. :)
    I'm just wondering if the script is to handle multiple login accounts, e.g. admin and guest, shouldn't this line be changed too?

    If LCase(objLog.URIStem) = "administrator" Then

    Btw, if the script can be modified to block IP only if that particular IP has entered the wrong password for, say 6 times withing 10 minutes, that will be awesome. :)
    Cheers,
    Phi

  • Comment by Chrissy | September 27, 2006 @ 2:47 pm

    Whoa, lots of responses! Sorry I haven't been on the ball, guys.. I've been slammed at work and schoool.

    Right off the top of my head..not sure what the access denied error is about. As for the lag in enforcing the IP ban, someone said rebooting IIS fixed their prob. That's not a solution, of course..but it may mean I'm missing one finalizing line from my code. I'll check around it when I can. That was the mysterious "four hours" i spoke of..I probably restarted the service at some point.

    And Phi, you are totally right. I'll update my comment to reflect that. Thanks!

  • Comment by john andrews | October 4, 2006 @ 8:15 am

    Very nice script Chrissy, thank you for posting this. Just installed on win2k3 SE SP I with much sucess. Kudos is also due to those who listed the multi username catch mods.

    Quick question... is there an easy way to supress the cscript.exe window from loading? Everytime I RDS into the server a blank cscript window pops up.

    Thanks Again,
    John Andrews

  • Comment by Mike | October 6, 2006 @ 10:06 am

    If LCase(objLog.URIStem) = “administrator” Then

    Can someone please post the modified version of this line to include multiple login names? I made a few attempts and can't seem to NOT screw it up.

  • Comment by G | October 7, 2006 @ 4:40 pm

    Access denied error (80041003): I got this error on a Windows XP machine. The problem was that the Win32_NTLogEvent class needed the wbemPrivilegeSecurity (SeSecurityPrivilege) privilege to be enabled. Change the moniker string:

    Set objWMIService = GetObject("winmgmts:{(security)}!root/cimv2")

    Unfortunately, Chrissy's script doesn't work on Windows XP. It contains IIS 5.1, which doesn't support denying IP addresses (as far, as I know).

  • Comment by Sean | October 11, 2006 @ 9:56 am

    G ... That worked perfectly.

    Now I get the same behaviour as others have reported which is that the newly banned ips do not take effect immidiately. I verified that they are on the list and when I restart the FTP service they take affect .

    I just added a script to restart the FTP service every night which seems to work.

  • Comment by Jim | October 13, 2006 @ 6:35 am

    Well this would be great but my FTP runs on a Win 2K Server. Im not sure this works on 2K.

    I cant seem to see the process running, and IPs dont seem to be being banned even after the restart of the service.

    Shame.

    Jim

  • Comment by Phi | October 15, 2006 @ 11:45 pm

    Mike, here's my modified version to include multiple login names:

    If InStr(LCase(objLog.URIStem),"admin") > 0 or InStr(LCase(objLog.URIStem),"guest") > 0 or InStr(LCase(objLog.URIStem),"root") > 0 or InStr(LCase(objLog.URIStem),"test") > 0 or InStr(LCase(objLog.URIStem),"user") > 0 Then

    Does anyone know how to use a script to auto restart the FTP service when there is no active connection?

  • Comment by Tomas Krug | October 19, 2006 @ 5:06 am

    objDictionary.Add ClientIP, "255.255.255.255" '255 is just there for padding.

    This line dosnt add the IP to the blocked list... anyone have any idea what can cause this? I am running this on an w2k3 EE SP1 Server with lots of s/w installed.

    The variable ClientIP contains the correct IP.

    Thanks,
    Tomas Krug
    Stockholm, Sweden

  • Comment by Chrissy | October 26, 2006 @ 2:48 pm

    They Thomas,
    You are right, that line doesnt add the IP to the blocked list. It just adds it to the dictionary when then adds the IP to the blocked list.

    objFTPIPSec.IPDeny = objDictionary.Keys is the line that actually does the work.

  • Comment by Chrissy | October 26, 2006 @ 2:49 pm

    Phi,
    I swear I'll find the way to add those IPs for good w/o restarting.. I just havent had a chance to look. Worst case, I'll ask the Scripting Guys.

  • Comment by Randy | October 27, 2006 @ 3:36 am

    I love the ftp anti-hack script...but let's take this to the next level. The script currently doesn't stop them from hammering and generating huge logs, or from trying to hack anything else on the server. How would you modify the script to ban them from even connecting to the server in the first place? I am guessing that the script would need to be changed to add the offending IP address to the denied list in the Routing & Remote Access?

    Thanks for the great script. :)

  • Comment by Clayten | October 28, 2006 @ 5:58 pm

    Great script! Running it as a service using srvany.exe utility so I don't have to leave the server logged in. The IP's aren't banned unless I restart my FTP server so I put this at the end of the script.

    strComputer = "."
    Set objWMIService = GetObject _
    ("winmgmts:{authenticationLevel=pktPrivacy}\\" _
    & strComputer & "\root\microsoftiisv2")

    Set colItems = objWMIService.ExecQuery _
    ("Select * From IIsFtpServer Where Name LIKE " & _
    "'%MSFTPSVC/%'")

    For Each objItem in colItems
    objItem.Stop
    objItem.Start
    Next

  • Comment by Phi | October 30, 2006 @ 9:37 pm

    Thanks Chrissy. I admire your persistence and will be looking forward to your solution.

    Meanwhile, have fun! :)

  • Comment by sam | November 16, 2006 @ 6:17 am

    Clayten, where exactly in th script did you add your "restarting" code?

  • Comment by Dan | November 16, 2006 @ 12:39 pm

    Hey everyone! I used this idea plus a lot of modification to create a windows service which does this and a little more. Let me know what you think!

    http://www.insight-onsite.us/ftpsecurity

  • Comment by Clayten | November 17, 2006 @ 1:34 pm

    sam,

    Add it between the:

    End If

    Set objFTPIPSec = Nothing
    Set objDictionary = Nothing

    in Chrissy's code.

  • Comment by Todd | November 18, 2006 @ 2:36 pm

    Wouldn't your stop and start code eject any users that were currently connected to the FTP service?

  • Comment by sam | November 19, 2006 @ 10:11 am

    Thx Clayten. That works, but there seems to be a delay in the time it takes the service to restart, sometimes 1-2 minutes. Of course in that time, the newly-detected IP is not banned, and dozens more attempts are allowed.

    Any idea what may cause the delay??

  • Comment by Andie | November 19, 2006 @ 1:52 pm

    Anyone get this working with windows 2000?

    Andie

  • Comment by Clayten | November 21, 2006 @ 1:39 pm

    sam,

    I happens to me as well. Attackers normally get about a dozen or two tries before they are locked out.

    If I had to take a guess, that 1 or 2 minutes is the time it takes for the Event to get logged to trigger the script (if you do a lot auditing it has to wait in line), processing your entire log file for the day (which could be big), then restarting the ftp servers.

    If Chrissy can find out how to ban IPs instantly that will solve the delay.

  • Comment by Chrissy | November 21, 2006 @ 1:59 pm

    Ahhh! You know.. Clayten .. I think I may have just figured out a solution.

    First, you got me thinking.. IIS Log files take a little bit to write from memory to disk...perhaps that is where the delay comes in? But I wonder if the MSWC.IISLog object can read "unwritten" data.

    If it does, what I can do is combine Spencer Rupert's script with mine to temporarily create a bad route to the offending IP address which will stay in effect (I'm guessing until the next reboot) at least until the FTP server catches up.

    I tried newsgroups for a way to solve that delay but received 0 responses. Perhaps I should get around to writing to David Wang. Till then, I'll rewrite the script and add that in then email you guys with the new script.

  • Comment by Chrissy | November 21, 2006 @ 3:55 pm

    Hey Guys,
    Okay, the script has been retooled and it now stops attackers before they can even login a second time.

    The modifications I made was to figure out the server's IP address (so that Spencer's fakeGateway variable wouldnt have to be manually set) then use that to add a route to the IP routing table that instantly kills off the attacker's packets. While Spencer's script writes all the IPs to a batch file for permanent banning, I decided to just take my chances and do a "temporary" ban. How temporary? Depends on how often you reboot. So if you go for a year without rebooting, then the bad route will last for a year.

    So for the record MSWC.IISLog reads data that is still unwritten to disk. This script now works so quickly, that again, I couldn't even get a second login attempt in when testing.

    When implementing the new script at work, I also randomly ran into the access denied error that another commenter encountered. Thankfully "G" solved that by suggesting that the the WMI object string change slightly. That worked wonderfully and I've modified the original script to reflect the change.

    I didn't add the IIS restarter script that Clayten so graciously posted because I didn't want to chance kicking off legit users. Hopefully the IP level ban will take care of that time delay.

    Now to figure out the slickest way to get this going each time the computer boots up. The run key works but my coworkers who login to the console always see a black box. Not cool.

  • Comment by Clayten | November 22, 2006 @ 4:42 pm

    Chrissy,

    I figured you'd find a better way and render my restart part moot. :-) Thanks again for the script! Note: Running the script as a service eliminates the black box.

  • Comment by Mike | November 27, 2006 @ 7:31 am

    Chrissy,

    Thanks so much for posting this script. We have been getting pounded by login attempts and this has really helped.

    Your excellent solution is greatly appreciated.

    Thanks again, Mike

  • Comment by Gaelan | December 5, 2006 @ 10:46 am

    I am a total nube to this so excuse my nube issue but I get Microsoft VBScript runtime error: Object required: 'WshShell'
    when running the script. The machine is running server 2003 SE. Can anyone shed some light here

  • Comment by DIV | December 7, 2006 @ 7:24 am

    This looks like a kickin script to get running... been looking for a solution like this ... does anyone have the source for the new script crissy was talking about I would like to take a look.. also has anyone tried to script in some variables so that you could possibly set a attempt limit instead off banning them if they get it wrong the first time ... typos can really suck in that case and sometimes half asleep at the keyboard it does happen ;)

  • Comment by Gaelan | December 8, 2006 @ 6:55 am

    OK ignore my question. It works, I was broken. Chrissy YOU ARE MY PERSONAL HERO!!!!!
    I cannot express in words how unbelievably awesome this script is. YOU ROCK!

  • Comment by Charles | December 14, 2006 @ 12:13 pm

    Takes a lot to impress me.. I'm impressed..

  • Comment by Dave Savage | December 19, 2006 @ 10:11 am

    Thanks for this script! I was getting hit everyday with so many unauthorized login attempts that it was avg. 4 attempts every SECOND!!! Not anymore!! Saweeeeeeeeeeeeeeeeet!

  • Comment by Jim | December 28, 2006 @ 12:16 pm

    One problem I had with this script is that if you don't have a folder called "MSFTPSVC1" in "%WinDir%\System32\LogFiles" you will receive the Object required: ‘WshShell’ error that Gaelan received just above. If you create a dummy folder with that name the script will run without error.

    If I had to guess, I would say this is because the script assumes that the log file location hasn't changed for the Default FTP site. If it has, it errors out before even getting to the second FTP site. (But I'm no scripting expert.)

    If anyone is wondering; If you are testing this script and it does lock your IP address out, you can simply run "route delete " in a command prompt and you will be allowed again for further testing.

  • Comment by Jim | December 28, 2006 @ 12:19 pm

    To add to my previous post, you have to type "route delete xxx.xxx.xxx.xxx"

    Also, if your running a Windows 2000 server and the command-line tool "reg" isn't available, you can copy and past the following into a text file, rename it to a .reg extension, and run the file:

    Windows Registry Editor Version 5.00

    [HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Run]
    "banftpip"="C:\\WINDOWS\\system32\\wscript.exe C:\\WINNT\\SYSVOL\\sysvol\\biomedix.local\\scripts\\banftpips.vbs"

  • Comment by Jim | December 28, 2006 @ 12:21 pm

    Sorry, I forgot to tell you to rename the path in the last part of that .reg file.

  • Comment by Chrissy | January 2, 2007 @ 6:37 pm

    Thanks Jim.

    Clayten, I'm getting a delay on my Windows 2000 machine.. I was all confused thinking the delay was at the IIS end. It is indeed on the Event service end. I don't really think there's a way to get around that other than "tailing" the log file forever and that seems to be way more overhead. Perhaps Vista and Longhorn will have some better solutions!

  • Comment by Rogue | January 3, 2007 @ 9:00 pm

    I installed the above script on 21/12/06 so I assume this is the latest evolution. (script "retooled" 21/11/06)....unless the above is not the "retooled" version of the script.

    If it is....
    I have it working fine in winK2 and between 21/12/06 and 02/01/07 it banned some 15 IP's. The problem remains, however, that the attacks can last up 20+ minutes and all of the "premier attack period" is still reflected in the log ...some times as many as 2 per second. The attacker may only get one shot but the "shot" is still lasting quite awhile.

    If the above isn't the "retooled" version of the script and the new version really stops the attacker from a second log on (not just a second attack) where can a copy be obtained? mucho thanx

  • Comment by Chrissy | January 4, 2007 @ 10:12 pm

    Hey Rogue, I tested it on Windows 2003 and the ban is instant but that doesn't seem to be the case on the Windows 2000 machine I tested on. Not sure at this point how to speed things up.

  • Comment by niTz | January 9, 2007 @ 9:19 am

    hi
    i just tried this script and when i attempt a logon with adminstrator from another computer. my server pops out an error about the vbs script

    Line: 57
    Char: 11
    Error: Path not found
    Code: 800A004C
    Source: Microsoft VBScript runtime error

    im pretty nub on scripting any help would be great
    thx

  • Comment by Chrissy | January 9, 2007 @ 11:00 am

    Hey Nitz,
    You changed the default path for the FTP logs.. line 57 is this

    ftpLogFilePath = WshShell.ExpandEnvironmentStrings(objSITE.LogFileDirectory) & "\msftpsvc" & objSITE.Name

    just change that to whatever the path of your FTP logs are.. ie

    ftpLogFilePath = "D:\Logfiles\FTPSite"

  • Comment by Chrissy | January 9, 2007 @ 4:20 pm

    Btw. this script WILL ban IPs on XP. As it turns out, IP banning works in XP programatically -- just not in the GUI. Awes!

  • Comment by niTz | January 10, 2007 @ 8:34 pm

    thank you so much Chrissy that worked =)

  • Comment by Anthony | January 15, 2007 @ 10:14 am

    Chrissy, first of all great work on this very handy script. thank you. I am wondering if you can figure out why normal 'user' users logging in over terminal services get this error pop up:

    C:/scripts/startup/banftips.vbs
    line 27
    char 5
    Access denied
    source swbemservicesex

    & how to correct it? Thank you! :)

  • Comment by Josh | January 19, 2007 @ 12:56 pm

    Has anyone tested the script with a FTP site that logs to a SQL DB? We currently log the site to a DB for better reporting. It gets huge from the attacks but that is how the powers that be want to log. This is the perfect script to help me but will it still work with a DB?

  • Comment by Theo | February 3, 2007 @ 2:37 am

    Thanks for this great script Chrissy! It works like a charm. I've got it running on WinXP-SP2 IIS 5.1...flawlessly. It blocks IPs as if the door is slammed! I've been looking for a tool like this for ages. Thanks again!

  • Comment by Louay Farag | February 12, 2007 @ 7:09 pm

    Why not just rename the default administrative account "Administrator" to another name??

  • Comment by Chrissy | February 12, 2007 @ 7:21 pm

    Louay, for a number of reasons. No administrator account should have a password easy enough for any of this bots to crack. Thus, I'm not concerned about a cracked password. I'm concerned about intense resource usage by thousands of attempted logins per minute as well as the Event Viewer getting so filled up.

  • Comment by David | February 13, 2007 @ 4:15 pm

    Thanks for the code!

    I am having some problems with it though. I adapted it to ban any IP that used any unknown username (I have a security group that has valid usernames). It works for the first ban, then doesn't catch events from the even log anymore until I restart it the script.

    I have been running the script as a scheduled task to run at system startup, but the behavior is exhibited if I run it directly from the shell or from the task scheduler.

    Has anyone seen this behavior?

  • Comment by David | February 14, 2007 @ 2:16 pm

    I guess my post above this one is a bit off. Eventually, the event's get processed but there is quite a large delay in when they get processed.

    Has anyone seen this?

  • Comment by Patrick | February 14, 2007 @ 10:21 pm

    Awesome, thank you so much, this works perfectly right out of the ... uhh... "box". It stopped 2 attackers within 5 seconds of being launched.

  • Comment by Mat | February 21, 2007 @ 9:14 pm

    Nice script!

    I too am having the speed issue... Im running on Windows 2000. It eventually does catch the offending IP address, but not before the attacker has been allowed hundreds or thousands of administrator login attempts. Has anyone resolved the speed issue on W2K?

  • Comment by David | February 26, 2007 @ 5:21 am

    I forgot to mention, I am running Windows 2003 Standard SP1.

    Still have the delay. Sometimes it's as short as 5 seconds, sometimes it's 5 minutes. It has something to do with the timing of that event being generated that triggers the meat of the script.

    I wonder how we can control that?

  • Comment by Bob Marley | March 5, 2007 @ 8:52 pm

    Thanks a TON for this. I've been routinely going through our logs and manually banning IP addresses as they show up. As someone mentioned above, I've combined this script with srvany.exe. Just make sure you use CScript.exe to execute it, otherwise you'll get an error when you try to start the service.

    Thanks again, this works great. I actually saw one of the bots get banned as I was messing around with it. :)

  • Comment by Frijoles | March 5, 2007 @ 9:20 pm

    (This is the Bob Marley guy above :) )

    I posted an article on your script on my own blog, mainly how to turn it in to a service (I send them here to get the script and read about it):

    http://blogs.mscorlib.com/Home/tabid/111/EntryID/42/Default.aspx

    This is a step-by-step instruction guide on how to make it run as a service. Thanks again!

  • Comment by insidejazz | March 11, 2007 @ 7:30 pm

    First , thanks Chrissy for the usefull script.
    I've a questiom :) we work with plesk and we have multiple ftp sites also log directories.like ;

    ..\7438\logs\MSFTPSVC7438\
    ..\7435\logs\MSFTPSVC7435\

    How can i set or is it possible to set multiple log directories ?
    thanks again...

  • Comment by afterburn | March 14, 2007 @ 1:29 pm

    The event is fired from NON-root FTP site. The result is that it gets the directory for the logs from the wrong site Id.

  • Comment by MrFurious | March 14, 2007 @ 7:54 pm

    Uh oh...

    I got this successfully working on my IIS 5.0 Windows 2000 Professional Box (Sp4). It blocks IPs wonderfully, but I can't seem to remove them. Unfortunately, even after a reboot I cannot remove entries from the denied list. I've manually tried removing it from the routing table at the command prompt with:
    route delete

    It has removed it from the table, but even then it still appears under directory security tab as denied. Unfortunately, in 2000 Professional the Directory Security table is all grayed out, so I cannot click on the entry and select remove! I'm stock with an IP I don't want to block.

    Like an idiot, I tested this out with my home box and now can't get into my FTP site. :x Any suggestions?

  • Comment by afterburn | March 15, 2007 @ 9:27 pm

    no you can use

    route -f

    this is the incorrect method to do this.

    http://www.codeproject.com/csharp/iiswmi.asp

    it is the correct method. I am sorry but i would rather have it added to IIS where it is easy to manage, rather than using routing. It would have been nice to use IPSec instead for this peice of code. but i created it to go to the MSFTPSVC node in the metabase it works well.

  • Comment by Chrissy | March 15, 2007 @ 10:08 pm

    afterburn, thanks for the pointer about it firing from a non-root site. When I get a chance, I'll adjust the script to handle situations with multiple FTP sites or sites with non-standard ftp logging directories.

    As for the routing, if you don't want it, you can remove it. The script bans at the IIS level in addition to the routing level. Route banning was added to this script because people were experiencing delays with pure IIS banning. And while IPSec would be nice, it's also a pain to work with. If you've got easy code, please feel free to post.

    As for Mr. Furious, anyone with win2k workstation or xp pro that experience similar problems can do one of two things
    1. Backup the metabase before trying the script, and replace it if necessary (which is what he ended up doing)
    2. Use scripting to add/remove ips as can be seen here.

  • Comment by afterburn | March 16, 2007 @ 12:52 pm

    Const c_strDomainControllerName = "DomainServer"
    Const c_strServerName = "WebServer"

    Dim objDsIpSec
    Set objDsIpSec = CreateObject("ExIpSec.ExIpSecurity")

    objDsIpSec.BindToSmtpVsi c_strServerName , "1", c_strDomainControllerName

    objDsIpSec.GetIpSecurityList
    objDsIpSec.GrantByDefault=false
    redim Preserve objDsIpSec.IpGrant(UBound(objDsIpSec.IpGrant)+1)

    listGrant(UBound(objDsIpSec.IpGrant)) = "1.2.3.4"
    objDsIpSec.WriteList

    objDsIpSec.ReleaseBinding

    set objDsIpSec = Nothing

  • Comment by Chrissy | March 16, 2007 @ 3:56 pm

    Hey afterburn,
    Thanks for posting the code. I thought you were referring to IPSec at the network level. This looks like IP Security at the IIS level, specifically SMTP. I'm not sure how it relates to banning at the FTP level.. In my script, I used objFTPSVC.IPSecurity to accomplish that.

  • Comment by Rewesh | March 21, 2007 @ 2:56 pm

    Thanks for the script however i have some questions
    1-is the new script the one that is published at the top of this blog. if not where is it?
    2- i have tried to unban an IP with the script the you listed but it is not working.
    3-While there is a banned IP , and has been removed form the security directory of the default site, this ip still can not connect and your script does not list this ip before or after the manual removal.
    4- What about the specific times of logging instead of the second time.
    The script is running on w2k sp4 with IIS 5.0.

    Thanks for the great script again...you are doing an awesome job

  • Comment by Chrissy | March 21, 2007 @ 3:09 pm

    Hey Rewesh:
    1. Yes
    2. Not sure why.. but I've only tested this on win2k3.
    3. It bans the IP both at the IIS level and the network level. To remove from the network level, run cmd then type route DELETE ip.add.res.s
    4. Not sure what you mean by that

    As for running it in win2k, I don't think the script works as well under win2k.. the events are slower to register.

  • Comment by Don | April 2, 2007 @ 5:11 pm

    Can someone explain what makes the route added in the code a "Bad Route"?

  • Comment by Tim | April 3, 2007 @ 11:07 pm

    Hi Chrissy (and all)....

    I've installed your script as a service (as detailed above). The network level IP block works GREAT. Instantaneous.

    It's been HOURS now since my tests, and still no sign of any IPs in the FTP blocked IP listing. I've looked at the Global level and the Default website level and... nada.

    Can you give me a clue what I might do to troubleshoot this?

    PS.... you're hot! Your script is hot! If I can get this working right, you're my HERO forever!!! And you're my hero right now just for the part that IS working!!!!!

  • Comment by CrimsonSmear | April 5, 2007 @ 10:08 am

    Chrissy, thank you for the awesome script!
    Frijoles, thank you for showing how to add as a service.

    I'd never tried vbs before yesterday, very cool stuff.

    Thought I might share the script I whipped up for unbanning. It'll show you the banned IPs and let you unban single IPs, as I haven't figured out how to make it 'purge' the list... yet.

    banftpview.vbs
    -----------------
    strComputer = "localhost"

    'Set Objects
    Set objFTPSVC = GetObject("IIS://" & strComputer & "/MSFTPSVC")
    Set WshShell = CreateObject("WScript.Shell")
    Set objIPRestrict = objFTPSVC.IPSecurity

    arrDeny = objFTPSVC.Get("IPSecurity").IPDeny
    For i = 0 to Ubound(arrDeny)
    strBannedIPs = strBannedIPs & arrDeny(i) & vbCrlf
    Next

    If len(strBannedIPs) > 0 Then
    strUnbanIP = InputBox("IP, Subnet: " & vbCrLF & strBannedIPs ,"Banned FTP IP List","Enter IP To Unban")
    arrIPAddresses = objIPRestrict.IPDeny
    For i = 0 to ubound(arrIPAddresses)
    strClientIP = Left(arrIPAddresses(i),InStr(arrIPAddresses(i),",")-1)
    If strClientIP strUnbanIP Then
    If Len(strStillBanned) = 0 Then
    strStillBanned = strClientIP
    Else
    strStillBanned = strStillBanned & "," & strClientIP
    End If
    End If
    Next

    WshShell.Run "ROUTE DELETE " & strUnbanIP
    arrStillBannedIPs = split(strStillBanned,",")
    objIPRestrict.IPDeny = arrStillBannedIPs
    objFTPSVC.IPSecurity = objIPRestrict
    objFTPSVC.SetInfo
    Else
    msgbox "No IPs have been banned.",,"Banned FTP IP List"
    End if

    'Kill Objects
    Set objIPRestrict = Nothing
    Set WshShell = Nothing
    Set objFTPSVC = Nothing

  • Comment by Chrissy | April 5, 2007 @ 10:28 am

    Hey Crimson,
    You're totally welcome! I remember the first time I made a .vbs file and ran it, I was freakin pumped. I knew ASP but never understood how to run VBScript on a workstation as opposed to an IIS Server.

    Thanks a ton for pasting your code too. Very useful!

    http://blog.netnerds.net/2007/01/vbscript-windows-xpiis-51-does-support-denying-access-by-ip-addresses/

    That has a purge script that may help you.

  • Comment by Chrissy | April 5, 2007 @ 11:20 am

    Tim,
    You're hot too!

    I really don't know why it works instantly sometimes, within X minutes other times, then X hours other times. Thats one of the reasons I added the ban at the network level.

    Yeah... I'll update the blog if I ever find out ;)

  • Comment by CrimsonSmear | April 5, 2007 @ 12:12 pm

    Tim,
    I have a feeling that you're looking in the wrong spot for the bans.
    Don't look at the Default FTP Site-Properties-Directory Security, instead look in the FTP Sites "Folder"-Properties-Directory Security for your banned IPs.
    My .vbs script (above) will unban single test IPs from FTP Directory Security and the Route List, giving instant access again.

  • Comment by Tim | April 6, 2007 @ 8:43 am

    Crimson... Nope: I don't think I'm looking in the wrong spot. I've checked the top level FTP Sites FOLDER properties-Directory Security tab too. No banned IPs ever show up.

    Chrissy: It's been DAYS, and no IPs have shown up. I can only assume there is something wrong with my install. I've done ftp tests numerous times from several different machines. I DO get banned instantaneously. But I never get ANY IPs in the banned IP list.

    Any ideas what else it might be?

  • Comment by Chrissy | April 6, 2007 @ 8:51 am

    Ok..... Let's see.

    1. Make sure there's no on error resume next in there so that if an error comes up, you'll be notified
    2. Run this script and see if anything shows up

    strComputer = "localhost"

    'Set Objects
    Set objWebSite = GetObject("IIS://" & strComputer & "/MSFTPSVC")
    Set objIPRestrict = objWebSite.IPSecurity

    arrDeny = objWebSite.Get("IPSecurity").IPDeny
    For i = 0 to Ubound(arrDeny)
    strBannedIPs = strBannedIPs & arrDeny(i) & vbCrlf
    Next

    If len(strBannedIPs) > 0 Then
    msgbox "IP, Subnet: " & vbCrLF & strBannedIPs
    Else
    msgbox "No IPs have been banned."
    End if

    'Kill Objects
    Set objIPRestrict = Nothing
    Set objWebSite = Nothing

    3. If that doesn't work.. I have no idea :|

  • Comment by Tim | April 6, 2007 @ 7:59 pm

    Thanks Chrissy...

    Your script showed NO banned IPs. But there WERE banned IPs for the network because I couldn't connect from two test machines at all until rebooting.

    Interestingly... I started taking apart your original script and found that if I remove the network ban code, then the FTP banned IPs show up just fine. But, if I add in the network ban code, the FTP banned IPs do NOT show up. So, there must be something going wrong right there... at least for my machine.

    Anyway... The FTP banned IP list works instantly for me, so I've removed the network ban. This gives me the ability to "manage" the list better than for the network bans.

    Finally... I've added a couple of lines to auto-delete ftp logs older than X days.

    So.. for now, for what I need, it's all working like a charm. I'm eternally in your debt. Feel free to call on me anytime for anything.

    Warm regards...

    Tim

  • Comment by Chrissy | April 6, 2007 @ 8:05 pm

    Hey Tim,
    That's really interesting. Can you do me a favor and add the network banning back /after/ the IIS ban? Let me know if that works?

    Hopefully this will all be easier with IIS 7...

  • Comment by Tim | April 7, 2007 @ 6:56 pm

    Hi again Chrissy...

    Putting the network ban AFTER the FTP ban works for me.

    But I did something else at the same time, so I'm not certain which change did the trick....

    I noticed that in the first few lines of the EVSINK sub, you create all the objects, one of which is the line...

    Set WshShell = WScript.CreateObject("WScript.Shell")

    You use this object to get the FTP log file path.

    Later you recreate the same WshShell for the network IP ban.

    Could the re-creation of the object perhaps be the problem. You don't destroy the previous WshShell object anywhere in your code before this.

    I removed the 2nd WshShell creation code, and also moved the Set WshShell line to the bottom of the code where you destroy all the other objects.

    And now... it all seems to be working in harmony!

    Tim

    PS... can you possibly give me some guidance for how I would add this IP to existing IPSec settings?

    I've added a list of banned IPs to the IPSec "Security Settings on Local Computer" under a folder I created called "FireWall". I would MUCH rather add the Banned IPs to this list rather than do the network ban to the route table.

    Any suggestions?

  • Comment by Don | April 10, 2007 @ 7:33 am

    Can someone explain what makes the route added in the code a "Bad Route"?

    On my server, the script adds the banned IP, but doesn't stop the network connection.

    Any ideas?

  • Comment by Don | April 11, 2007 @ 10:46 am

    I added the following code to email me when an FTP attack occurs. Put it right after the " WshShell.Run "ROUTE ADD " & clientIP & " MASK 255.255.255.255 " & serverIP, 1, True" statement.

    ' ------ SCRIPT CONFIGURATION ------
    strFrom = "xxx@xxx.edu"
    strTo = "xxx@xxx.edu;yyy@xxx.edu"
    strSub = "FTP Attack on FILESERV"
    strBody = "FTP attack on Fileserv by IP " & clientIP
    strSMTP = "10.9.9.9"
    ' ------ END CONFIGURATION ---------
    set objEmail = CreateObject("CDO.Message")
    objEmail.From = strFrom
    objEmail.To = strTo
    objEmail.Subject = strSub
    objEmail.Textbody = strBody
    objEmail.Configuration.Fields.Item("http://schemas.microsoft.com/cdo/configuration/sendusing") = 2
    objEmail.Configuration.Fields.Item("http://schemas.microsoft.com/cdo/configuration/smtpserver") = strSMTP
    objEmail.Configuration.Fields.Update
    objEmail.Send

  • Comment by Bob | April 14, 2007 @ 5:36 am

    I have been using the script for a few weeks now and can finally breathe a sigh of relief as I feel that I am back in control of my equipment.
    Now when I receive an e-mail that I am under attack, I just smile….
    I thank Chrissy and the other supporters here for that.

    Since the script helped me so much, I feel like I should give something back.

    I made a few changes to the script to suit my situation that I would like to share with the group.
    I will call it 2 enhancements and 1 bug fix.

    1. Added email report when attacker is blocked
    2. Made routing changes persistent across reboots
    3. Moved dictionary code out of subroutine so it would be persistent

    First; I am running on Windows 2000 and I not only do I have the “cached” IIS log file delay that others have mentioned in this blog.
    Apparently Windows 2003 flushes the IIS logs much quicker than W2k although I have not tested this myself.

    The script is designed to initially stop attacks at the IP route level and permanently ban the offender by adding the IP to the IIS FTP “Denied” list.
    I was not interested in banning at the IIS level.
    My testing with Windows 2000 Server (I did not make the same tests with Windows 2003.) revealed that although the offender’s IP was added to the blocked list, the offender was still able to make login attempts against the FTP server. When the correct password was “finally” used, the server denied the user access, but with a different error message than the user received when they guessed with the wrong password.
    For that reason, the IIS ban was of no value to me, but the bad IP route seemed like the solution for me.
    Note: Although I kept the IIS ban code in place it never added any IPs to the list as others have also confirmed.

    1. Added email report when attacker is blocked
    I wanted to be notified when an attacker was blocked so I added some email code after the following line:
    objDictionary.Add ClientIP, "255.255.255.255" '255 is just there for padding.
    To my surprise, I started getting “tons” of duplicate emails when I expected to get only one per ban.
    My friend helped me diagnose the fact that the dictionary gets initialized every time the subrouting got called.
    I believe this is unintentional and is a bug. (forgive me if I am wrong)
    See item 3 below for fix.

    2. Made routing changes persistent across reboots
    I waned to make the bad routes survive reboots so I modified the ROUTE ADD line to:
    WshShell.Run "ROUTE -p ADD " & clientIP & " MASK 255.255.255.255 " & serverIP & " METRIC 10", 1, True
    I added the METRIC 10 so I could spot the changes to the routing table easier when I did a “route print”
    The persistent routes are printed below the table as well, sorted in the order they were banned. ;-)
    3. Moved dictionary code out of subroutine so it would be persistent
    After adding the email code, I noticed that I received an email for every new Event 100 in the Event log even though it was the same IP in the FTP logs.
    This means that the dictionary was unaware the current IP address was in fact the same as the previous 20 that
    So if there were 30 new Event 100 entries from the same IP, I would get 30 emails (plus any previous offenses from the same day)
    I moved the line:
    Set objDictionary = CreateObject("Scripting.Dictionary")
    From inside the subroutine to the “' Push Event Viewer Alert” section of code at the top. Anywhere above the “While (True)” line should be fine.

    Thanks so much for your help…

  • Comment by Don | April 16, 2007 @ 6:50 am

    Bob - Thanks for the heads-up on the email bug. Because the "bad route" step doesn't seem to work for me, I was greeted by 30,000 emails this morning!

  • Comment by Preston | April 17, 2007 @ 12:02 pm

    Chrissy,

    You are awesome!! Thank you so much for script. It worked like a charm.

  • Comment by MJ | April 18, 2007 @ 6:40 pm

    Stellar! Trying it out now.

  • Comment by michelle | May 6, 2007 @ 9:48 am

    I just installed this and it's not banning (2003 sp2). I'm getting the Object required: 'WshShell' error. I saw that someone suggested creating a MSFTPSVC1 directory to fix the error, but I already have that directory. Are there any permissions I might be missing?

    Tim's solution looked interesting, but I didn't quite understand what his final file looked like - Tim, if you're there - can you post?

    Thanks,
    Michelle

  • Comment by JKPCHEWY | May 24, 2007 @ 10:21 am

    Chrissy,

    The script is great but I have run into a problem where not all of my FTP sites follow the msftpsvc naming. I could create a script for each FTP site that is in a sub directory of logfiles but that would be to hard on the system. Will there be an update that will loop through the logfiles directory pulling logs for each subdirectory? Hope this question makes sense.

    Thanks,
    Chewy

  • Comment by Eric Greer | May 28, 2007 @ 4:14 am

    Thanks tons for writing this, and thanks tons for answering my emails so helpfully!

    I created a psexec installer package for this that runs with a batch file. Basically that means you can deploy this to lots of remote computers on your network easily with one swoop. Check it out here on my blog: http://blog.integrii.net/?p=18

    Tons of thanks to Chrissy!

  • Comment by Tim | May 28, 2007 @ 4:21 am

    I've posted my current solution on our website (I can't seem to get this site to accept my code without cutting it short).

    See it at www.vizimetrics.com (Ban FTP Logins).

    Tim

  • [...] the .vbs script’s author Chrissy ( http://blog.netnerds.net/2006/07/ban-administrator-ftp-login-attemps/ ) and to frijoles at his post here: [...]

  • Comment by Ralph | June 1, 2007 @ 5:13 am

    Sorry - I'm trying to understand this code and ... why, exactly, does the code to add the client's ip to the routing table (as the destination) with the server's ip as the gateway result in the client being unable to connect to the server via TCP?
    I thought you could use the routing table to block access TO a destination, not FROM a client. And, is the serverIP supposed to be an unused address in the local network, or my actual server IP (which wouldn't seem to work).
    Thanks a million, and thanks for posting this code in the first place.

  • Comment by James | June 28, 2007 @ 12:55 am

    Strange this is one of the few websites I could find on the internet that addresses this problem at all and Ive done all kinds of searches.

    Thanks to the ideas on this site, I got the idea to block the ips on our cisco firewall.

    if anyone is interested in persueing this method, I downloaded sock.dll from
    http://tech.dimac.net/FreeDownloads/dlstart.asp?ProductID=2

    and another file, winsck.ocx from here
    http://www.gurgensvbstuff.com/index.php?ID=27

    so I could vbscript a telnet session.

    Instead of creating an event alert, I used a scheduled tasked to check the last log every couple of minutes. The alert does stop the hacker faster though.

    I used a 2nd script to clear the blocked ips once a day since our hackers seem to use a different ip everyday. The nice thing about blocking at the firewall is it completely stlops the IP from doing anything, including FTP. Cisco firewalls have a shun command that does this, and I would think most other firewalls have a similar command.

    The full script is below.

    Const NotApplicable = 0
    Const ForReading = 1
    Const ForWriting = 2
    Const ForAppending = 8
    Const AllOpenFiles = 32

    strScriptLogFile = "\\server01\schedule\shunIPs\shunips.log"
    strIPS = "\\server01\schedule\shunIPs\bannedips.txt"
    strFtpLogFilePath = "\\server01\c$\windows\system32\LogFiles\MSFTPSVC392258225"

    'Get the last log file
    Set objFSO = CreateObject("Scripting.FileSystemObject")
    Set objFolder = objFSO.GetFolder(strFtpLogFilePath)
    Set objFiles = objFolder.Files
    For Each fileName In objFiles
    lastFile = fileName
    Next

    strLogFile = lastFile
    'strLogFile = "\\server01\schedule\shunips\test.log"
    'wscript.echo strLogFile

    Set objFiles = Nothing
    Set objFolder = Nothing

    'read in a list of IPs that are already banned so we dont keep banning the same IPs
    set bannedips = objfso.OpenTextFile(strIPs, ForReading, True)

    Set objDictionary = CreateObject("Scripting.Dictionary")
    Do While not bannedips.atendofstream
    strIP = bannedips.readline
    if NOT(strIP = "clear") AND NOT(strIP="") then
    objDictionary.add strIP, "bannedIP"
    end if
    Loop

    bannedips.close

    're-open the bannedips list so we can possibly add to it.
    set bannedips = objfso.OpenTextFile(strIPs, ForAppending, True)

    'open the log file and see if anyone is hacking us, test to see if someone is logging in as administrator, test, or root.
    set scriptLog = objfso.OpenTextFile(strScriptLogFile, ForAppending, True)

    Set objLog = CreateObject("MSWC.IISLog")
    'Use the IIS log file parser provided by MSFT
    objLog.OpenLogFile strLogFile, ForReading, "MSFTPSVC", 1, NotApplicable
    '(FileName,IOMode,ServiceName,ServiceInstance,OutputLogFileFormat)
    ' 0 = NotApplicable, 1 = ForReading

    While NOT objLog.AtEndOfLog
    objLog.ReadLogRecord
    If InStr(LCase(objLog.URIStem),"admin") > 0 or InStr(LCase(objLog.URIStem),"root") > 0 or InStr(LCase(objLog.URIStem),"test") > 0 Then
    ClientIP = objLog.ClientIP
    If objDictionary.Exists(ClientIP) = False and objDictionary.Count "
    objw3sock.SendLine "enable"
    objw3sock.WaitFor "Password:"
    objw3sock.SendLine "SwitchM3"
    objw3sock.WaitFor "ZERO#"
    objw3sock.SendLine "shun " & IP
    objw3sock.WaitFor "ZERO#"
    objw3sock.SendLine "exit"
    objw3sock.Close
    set objW3Sock = NOTHING
    wscript.sleep 1000
    end sub

  • Comment by James | June 28, 2007 @ 1:02 am

    looks like i might have exceeded the line limit, heres how the script is suppose to end

    While NOT objLog.AtEndOfLog
    objLog.ReadLogRecord
    If InStr(LCase(objLog.URIStem),"admin") > 0 or InStr(LCas