Prevent brute force attacks in Microsoft FTP Server (IIS6/7)
8,803
See this post from the IIS newsgroup for some code to resolve the issue
Also below is Chrissy Lemaire's script
'****************************************************************************
' This script created by Chrissy LeMaire ([email protected])
' 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
Related videos on Youtube
Author by
Kjensen
Updated on September 17, 2022Comments
-
Kjensen over 1 year
Looking over my ftp-server logfiles, I find a lot of brute force attacks, where the same IP-address tries 100s of username/password combinations.
Is there something I can do to make life harder on these brute force attackers? Something like an IP is locked out for x time if it has y failed login-attempts?
Server is Microsoft Windows Server 2008.
-
Kjensen almost 15 yearsAny publicly available ftp-server will eventually get hammered from all kinds of different ip's, so blocking the ip after will not have much effect.
-
Ryan Ferretti almost 15 yearsYou can blog the subnets which the IPs are coming from. Unless it's a distributed attack they will always be coming from the same IPs. You can also block the IPs from certain countries which are known for less strict policies (China, Iran, Russia) that you probably don't need to allow access to and block them.
-
Dave Forgac almost 15 yearsThat one attacker will always come from the same IP but just about any server that listens on port 21 will be connected to by automated scanners and brute-force attackers.
-
Spence almost 15 yearsThat's almost an upvote because I very nearly wrote a script to do that (and DID write a script to do that with OpenSSH) a couple of years ago. The problems with this script are (a) I don't trust my IIS metabase to the potentially thousands of different IPs that a distributed scanning attack will hit the box with, (b) it appears at first glance that it would create performance problems on really busy FTP servers, and (c) it only handles "Administrator". It's not the fault of the script's author, IMO, because Microsoft provides such poor failure reporting from MSFTPSVC to the event log.
-
Kilo almost 15 yearswell, I up-voted, even though I agree, in part, with Evan's comments. I guess it depends on your situation like, how busy is the box, running the script as Administrator can be mitigated by changing the administrator's account name (we use things like $administrator).
-
raja almost 15 yearsIt's not perfect for sure, I'm not worried about the metabase. Its not as big a peformance hit as you might think unless you are in the middle of a ddos attack, then you will wish you had a real IDS. Even if you have done the basics like change he admin account you'd probably still be happy banning anyone trying it.