VBScript: Stop Dictionary FTP Attacks in IIS using VBScript

Spencer Ruport of netortech.com modified my FTP ban script into one that stops dictionary attacks. And he chooses not to ban via the problematic IIS way but instead creating a bad route for the offending IP address. Pretty darn ingenius.

ftpdprotection.vbs

Set objFTPSVC = GetObject("IIS://localhost/MSFTPSVC")
    Set objFSO = CreateObject("Scripting.FileSystemObject")
    Set objLog = CreateObject("MSWC.IISLog")
    Set objDictionary = CreateObject("Scripting.Dictionary")

    Dim Attempts(), IP(), LastAttempt(), IPs
    Dim AlreadyBanned, InProcess, Session
    Dim CutOff, x, i
    IPs = 0

    'Iterate through each FTP site.
      For Each objSITE in objFTPSVC
        If lcase(objSITE.class) = "iisftpserver" Then
          ftpLogFilePath =  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
            Do While NOT objLog.AtEndOfLog
              objLog.ReadLogRecord
              If instr(ucase(objLog.Method), "USER") Then
  'Someone is attempting to authenticate with the FTP server
InProcess = False
AlreadyBanned = False
For x = 0 to IPs - 1
'Check to see if this IP address has already attempted to log in.
If objLog.ClientIP = IP(x) Then
'To be nice this code will give the user
'another attempt every minute.
'This is to avoid banning a person who
'attempts to log in multiple times
'in a day but keeps forgetting their password.
Attempts(x) = Attempts(x) + datediff("n", objLog.DateTime, lastattempt(x))
LastAttempt(x) = objLog.DateTime
InProcess = True
End If
Next
If Not InProcess Then
'If we aren't keeping track of this IP
'it's possible the IP has already been
'added to the ban list.
AlreadyBanned = objDictionary.Exists(objLog.ClientIP)
End If
If Not InProcess And Not AlreadyBanned Then
'First authentication attempt by this IP
IPs = IPs + 1
Redim Preserve IP(IPs)
Redim Preserve Attempts(IPs)
Redim Preserve LastAttempt(IPs)
IP(IPs - 1) = objLog.ClientIP
Attempts(IPs - 1) = 1
LastAttempt(IPs - 1) = objLog.DateTime
End If
      ElseIf instr(ucase(objLog.Method), "PASS") Then
'The server is responding to an authentication
'attempt.
For x = 0 to IPs - 1
'See if we're keeping track of this IP
    If IP(x) = objLog.ClientIP Then
'Increment the authentication attempts
Attempts(x) = Attempts(x) + 1
If Attempts(x) = 10 Then
'Ban if necessary
WScript.Echo "Banning " & objLog.ClientIP & "..."
objDictionary.Add objLog.ClientIP, "255.255.255.255"
AddDeadRoute objLog.ClientIP
    For i = x to (IPs - 2)
IP(i) = IP(i + 1)
Attempts(i) = Attempts(i + 1)
Next
IPs = IPs - 1
Redim Preserve IP(IPs)
Redim Preserve Attempts(IPs)
End If
End If
Next
              End If
            Loop
          objLog.CloseLogFiles 1
        End If
      Next

    Set objDictionary = Nothing
    Set objLog = Nothing
    Set objFSO = Nothing
    Set objFTPSVC = Nothing

    Function addDeadRoute(IP)
dim adoDBConn, sConnStr, objFSO, objBanBatch, cmdShell, WshShell
Dim fakeGateway
'I've been told that IPSec could be used to block certain IPs
'but 1) I'm not sure WMI can interface with it and 2) I don't
'know how to begin with. Someone gave me a much easier solution
'Simply add a route to the routing table pointing to a gateway
'that doesn't exist.

'Ensure that this IP is on the same subnet as the server
fakeGateway = "192.168.1.101"

Set WshShell = WScript.CreateObject("WScript.Shell")
Set objFSO = CreateObject("Scripting.FileSystemObject")
Set objBanBatch = objFSO.CreateTextFile("W:\config files\blocks\addRoute.bat", True)
objBanBatch.WriteLine "ROUTE ADD " & IP & " MASK 255.255.255.255 " & fakeGateWay
objBanBatch.Close
WshShell.Run """W:\config files\blocks\addRoute.bat""", 1, True
Set objFSO = Nothing
    End Function
Posted in IIS, VBScript
13 comments on “VBScript: Stop Dictionary FTP Attacks in IIS using VBScript
  1. Dennis Pinckard says:

    Is this a modification of your script? I don’t see the event sink code in it. It would be nice if Spencer had provided a bit more info on usage. That said, I’m looking forward to putting it in place as we just started getting hit with an FTP attack.

    Thanks

  2. M Mucklo says:

    Is this scripts free to use (no copyright restrictions?)

  3. M Mucklo says:

    Also do these routes stick after server reboot?

  4. InTech says:

    Has anyone gotten this to work? With no sink, am I just running this as a scheduled task to check connections?

    I NEED THIS! MY FTP SERVER IS CONSTANTLY BEING ATTACKED!

  5. Tim says:

    Ok… well

    I’ve been playing with this script (and chrissy’s orignal) for quite a while now. After a LOT of experimenting, I decided I really don’t need the IP’s added to the ftp directory security table…. what’s the point? If the IP’s are added as a bad route… that handles it all.

    I’ve also re-thought the code a few times.

    I’ve deleted the generic ftp file path finder… you can add it back in if you need it. I just hard coded a path to the one ftp file on my server. It’s less flexible but MUCH simpler.

    I added in the code to delete older log files.

    I changed the ROUTE ADD statement to make it a persistent route.

    Finally, I changed the way the dictionary objects were being used, to let them keep count of the login attempts in the log file.

    Here’s where I’m at…. it’s working 100% for me….

    ‘ 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)

    Set objDictionary = CreateObject(“Scripting.Dictionary”)
    Set objFSO = CreateObject(“Scripting.FileSystemObject”)
    Set objLog = CreateObject(“MSWC.IISLog”)
    Set WshShell = WScript.CreateObject(“WScript.Shell”)

    serverIP = “65.23.156.121″
    xMax = 3 ‘Max number of invalid login attempts
    xLogFiles = 10 ‘Max number of log files to keep in the folder before deleting them

    Set objFolder = objFSO.GetFolder(“C:\WINDOWS\system32\LogFiles\MSFTPSVC1\”)
    Set objFiles = objFolder.Files
    For Each fileName In objFiles
    lastFile = fileName
    Set f = objFSO.GetFile(fileName)
    If f.DateCreated

  6. Tim says:

    Not sure why my post was cut short. Here’s the rest of it… with a little overlap.

    For Each fileName In objFiles
    lastFile = fileName
    Set f = objFSO.GetFile(fileName)
    If f.DateCreated

  7. Tim says:

    Chrissy… what must I do to post my code????

    Tim

  8. Tim says:

    OK… let’s try this once more using the quickcode tags….

    ‘ 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)

    Set objDictionary = CreateObject(“Scripting.Dictionary”)
    Set objFSO = CreateObject(“Scripting.FileSystemObject”)
    Set objLog = CreateObject(“MSWC.IISLog”)
    Set WshShell = WScript.CreateObject(“WScript.Shell”)

    serverIP = “65.23.156.121″
    xMax = 3 ‘Max number of invalid login attempts
    xLogFiles = 10 ‘Max number of log files to keep in the folder before deleting them

    Set objFolder = objFSO.GetFolder(“C:\WINDOWS\system32\LogFiles\MSFTPSVC1\”)
    Set objFiles = objFolder.Files
    For Each fileName In objFiles
    lastFile = fileName
    Set f = objFSO.GetFile(fileName)
    If f.DateCreated

  9. Tim says:

    I give up. It seems your page won’t accept the less than character that immediately follows the DateCreated in the last line above. Visit my website (vizimetrics.com) for the code.

  10. Joost says:

    Thanks Tim, I took the script from your site and it works flawlessly :)

  11. jessica_love says:

    i have a problem…can u help me pls….can someone ban a site with a vbs file….someone send me a vbs file and y just double click`it …nothing is happend….but now i cannot access a site….the site is http://www.silkroadonline.net i can access anything…but this site no…when i enter this site it say`s something like…"the page cannot be displayed…or …Network failure" … if u know something please help me….send me a e-mail….thanks!!!

  12. John Marston says:

    What’s the addroute.bat file on drive w: ?

  13. Hello Chrissy,
    I used part of your code to create an OpenSource software called WinFail2Ban (detect IP from failed logins and ban IP).

    The project page is: http://winfail2ban.sourceforge.net

    Regards and thanks !!!

    Vittorio

1 Pings/Trackbacks for "VBScript: Stop Dictionary FTP Attacks in IIS using VBScript"
  1. [...] is an enhancement to scripts I originally found at NetNerds.net and VisiMetrics.com, which provided the base code to create the dead route. I’ve added the [...]

Leave a Reply

Your email address will not be published. Required fields are marked *

*

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code class="" title="" data-url=""> <del datetime=""> <em> <i> <q cite=""> <strike> <strong> <pre class="" title="" data-url=""> <span class="" title="" data-url="">