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

Note (2025): This post targets legacy IIS FTP on Windows 2000/2003 (IIS 5/6). Those platforms are long out of support and the approach below is preserved for historical reference. For modern Windows Server and IIS FTP, prefer built-in controls such as IP and Domain Restrictions, Windows Defender Firewall rules, and account lockout policies. Also avoid allowing the built-in Administrator account to authenticate via FTP, and use FTPS/SFTP where possible. See: Microsoft IIS IP security (https://learn.microsoft.com/iis/configuration/system.webserver/security/ipsecurity/) and Windows Account lockout policy (https://learn.microsoft.com/windows/security/threat-protection/security-policy-settings/account-lockout-policy).

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 (IIS FTP service). 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 by configuring a Windows 2000/2003 Scheduled Task to run wscript.exe C:\\Scripts\\Startup\\banftpips.vbs at system startup.

  1'*************************************************************************
  2' This script created by Chrissy LeMaire ([email protected])
  3' Website: https://netnerds.net/
  4'
  5' NO WARRANTIES, etc.
  6'
  7' This script instantly bans IP addresses trying to login to FTP
  8' using the NT account "Administrator"
  9'
 10' Run this script on the FTP server. It sits in the back and waits for an
 11' event viewer "push" that lets it know someone failed FTP authentication.
 12'
 13' This script has only been tested on Windows Server 2003. It assumes, as it
 14' should, that there are no legitimate Administrator account FTP logins.
 15'
 16' "What it does"
 17' 1. Sets an Async Event Sink to notify the script when someone fails MS-FTP auth
 18' 2. When alerted, the script parses the last day's FTP logs for all FTP sites (this
 19'    is because the Event Viewer doesn't tell you which FTP site, if you have more than
 20'    one, is the one getting hit)
 21' 3. Compiles the list of IPs to be banned and then bans them using IIS /and/
 22'    IP level banning (thanks Spencer @ netortech.com for the idea)
 23'*************************************************************************
 24
 25' Push Event Viewer Alert
 26Set objWMIService = GetObject("winmgmts:{(security)}!root/cimv2")
 27Set eventSink = wscript.CreateObject("WbemScripting.SWbemSink", "EVSINK_")
 28strWQL = "Select * from __InstanceCreationEvent where TargetInstance isa 'Win32_NTLogEvent' and TargetInstance.SourceName = 'MSFTPSVC' and TargetInstance.EventCode = 100"
 29objWMIService.ExecNotificationQueryAsync eventSink, strWQL
 30
 31' Keep it going forever
 32While (True)
 33    Wscript.Sleep(1000)
 34Wend
 35
 36Sub EVSINK_OnObjectReady(objObject, objAsyncContext)
 37    If InStr(LCase(objObject.TargetInstance.Message),"administrator") > 0 Then
 38        Set objFTPSVC = GetObject("IIS://localhost/MSFTPSVC")
 39        Set WshShell = CreateObject("WScript.Shell")
 40        Set objFSO = CreateObject("Scripting.FileSystemObject")
 41        Set objLog = CreateObject("MSWC.IISLog")
 42        Set objDictionary = CreateObject("Scripting.Dictionary")
 43        Set objFTPIPSec = objFTPSVC.IPSecurity
 44
 45        'Get IP address of server so we can use it later to give the offending IP a bad route
 46        Set IPConfigSet = GetObject("winmgmts:\\.\root\cimv2").ExecQuery("SELECT * FROM Win32_NetworkAdapterConfiguration WHERE IPEnabled=TRUE")
 47        For Each IPConfig In IPConfigSet
 48            If Not IsNull(IPConfig.DefaultIPGateway) Then
 49                serverIP = IPConfig.IPAddress(0)
 50            End If
 51        Next
 52        Set IPConfigSet = Nothing
 53
 54        'Iterate through each FTP site. See #2 up above.
 55        For Each objSITE In objFTPSVC
 56            If LCase(objSITE.class) = "iisftpserver" Then
 57                ftpLogFilePath = WshShell.ExpandEnvironmentStrings(objSITE.LogFileDirectory) & "\msftpsvc" & objSITE.Name
 58
 59                Set objFolder = objFSO.GetFolder(ftpLogFilePath)
 60                Set objFiles = objFolder.Files
 61                For Each fileName In objFiles
 62                    lastFile = fileName
 63                Next
 64                strLogFile = lastFile
 65                Set file = Nothing
 66                Set objFolder = Nothing
 67
 68                'Use the IIS log file parser provided by MSFT
 69                objLog.OpenLogFile strLogFile, 1, "MSFTPSVC", 1, 0
 70                '(FileName,IOMode,ServiceName,ServiceInstance,OutputLogFileFormat)
 71                ' 0 = NotApplicable, 1 = ForReading
 72                While NOT objLog.AtEndOfLog
 73                    objLog.ReadLogRecord
 74                    If LCase(objLog.URIStem) = "administrator" Then
 75                        ClientIP = objLog.ClientIP
 76                        If objDictionary.Exists(ClientIP) = False Then
 77                            'Kill the route to the machine then add it to the array of banned IPs.
 78                            Set WshShell = WScript.CreateObject("WScript.Shell")
 79                            WshShell.Run "ROUTE ADD " & clientIP & " MASK 255.255.255.255 " & serverIP, 1, True
 80                            Set WshShell = Nothing
 81                            objDictionary.Add ClientIP, "255.255.255.255" '255 is just there for padding.
 82                        End If
 83                    End If
 84                Wend
 85                objLog.CloseLogFiles 1
 86            End If
 87        Next
 88
 89        'Append the newly banned IPs to the currently banned IPs
 90        If objDictionary.Count > 0 And objFTPIPSec.GrantByDefault = True Then
 91            bannedIPArray = objFTPIPSec.IPDeny
 92            For i = 0 To UBound(bannedIPArray)
 93                clientIP = Left(bannedIPArray(i), InStr(bannedIPArray(i), ",") - 1)
 94                If objDictionary.Exists(ClientIP) = False Then
 95                    objDictionary.Add bannedIPArray(i), "255.255.255.255"
 96                End If
 97            Next
 98
 99            objFTPIPSec.IPDeny = objDictionary.Keys
100            objFTPSVC.IPSecurity = objFTPIPSec
101            objFTPSVC.SetInfo
102        End If
103
104        Set objFTPIPSec = Nothing
105        Set objDictionary = Nothing
106        Set objLog = Nothing
107        Set objFSO = Nothing
108        Set objFTPSVC = Nothing
109    End If
110End Sub
111``` 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:
112
113> Connected to ftpserver 530 Connection refused, unknown IP address. 421 Service not available, closing control connection. Connection closed by remote host.
114
115Note 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.