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.