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
Share:
8,803

Related videos on Youtube

Kjensen
Author by

Kjensen

Updated on September 17, 2022

Comments

  • Kjensen
    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
    Kjensen almost 15 years
    Any 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
    Ryan Ferretti almost 15 years
    You 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
    Dave Forgac almost 15 years
    That 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
    Spence almost 15 years
    That'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
    Kilo almost 15 years
    well, 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
    raja almost 15 years
    It'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.