From 09d62b6275143e63c7506de84c2c58b436662bd9 Mon Sep 17 00:00:00 2001 From: Evan Anderson Date: Tue, 29 Nov 2011 15:34:56 -0500 Subject: First code checkin --- LICENSE | 198 +++++++++++++++++++++++++++++++++ ts_block.adm | 42 +++++++ ts_block.vbs | 357 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 597 insertions(+) create mode 100644 LICENSE create mode 100644 ts_block.adm create mode 100644 ts_block.vbs diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..7332f58 --- /dev/null +++ b/LICENSE @@ -0,0 +1,198 @@ +Artistic License 2.0 + +Copyright (c) 2000-2006, The Perl Foundation. + +Everyone is permitted to copy and distribute verbatim copies of this +license document, but changing it is not allowed. + +Preamble +******** + +This license establishes the terms under which a given free software +Package may be copied, modified, distributed, and/or redistributed. The +intent is that the Copyright Holder maintains some artistic control over +the development of that Package while still keeping the Package +available as open source and free software. + +You are always permitted to make arrangements wholly outside of this +license directly with the Copyright Holder of a given Package. If the +terms of this license do not permit the full use that you propose to +make of the Package, you should contact the Copyright Holder and seek a +different licensing arrangement. + +Definitions +*********** + +"Copyright Holder" means the individual(s) or organization(s) named in +the copyright notice for the entire Package. + +"Contributor" means any party that has contributed code or other +material to the Package, in accordance with the Copyright Holder's +procedures. + +"You" and "your" means any person who would like to copy, distribute, or +modify the Package. + +"Package" means the collection of files distributed by the Copyright +Holder, and derivatives of that collection and/or of those files. A +given Package may consist of either the Standard Version, or a Modified +Version. + +"Distribute" means providing a copy of the Package or making it +accessible to anyone else, or in the case of a company or organization, +to others outside of your company or organization. + +"Distributor Fee" means any fee that you charge for Distributing this +Package or providing support for this Package to another party. It does +not mean licensing fees. + +"Standard Version" refers to the Package if it has not been modified, or +has been modified only in ways explicitly requested by the Copyright +Holder. + +"Modified Version" means the Package, if it has been changed, and such +changes were not explicitly requested by the Copyright Holder. + +"Original License" means this Artistic License as Distributed with the +Standard Version of the Package, in its current version or as it may be +modified by The Perl Foundation in the future. + +"Source" form means the source code, documentation source, and +configuration files for the Package. + +"Compiled" form means the compiled bytecode, object code, binary, or any +other form resulting from mechanical transformation or translation of +the Source form. + +Permission for Use and Modification Without Distribution +******************************************************** + +(1) You are permitted to use the Standard Version and create and use +Modified Versions for any purpose without restriction, provided that you +do not Distribute the Modified Version. + +Permissions for Redistribution of the Standard Version +****************************************************** + +(2) You may Distribute verbatim copies of the Source form of the +Standard Version of this Package in any medium without restriction, +either gratis or for a Distributor Fee, provided that you duplicate all +of the original copyright notices and associated disclaimers. At your +discretion, such verbatim copies may or may not include a Compiled form +of the Package. + +(3) You may apply any bug fixes, portability changes, and other +modifications made available from the Copyright Holder. The resulting +Package will still be considered the Standard Version, and as such will +be subject to the Original License. + +Distribution of Modified Versions of the Package as Source +********************************************************** + +(4) You may Distribute your Modified Version as Source (either gratis or +for a Distributor Fee, and with or without a Compiled form of the +Modified Version) provided that you clearly document how it differs from +the Standard Version, including, but not limited to, documenting any +non-standard features, executables, or modules, and provided that you do +at least ONE of the following: + +(a) make the Modified Version available to the Copyright Holder of the +Standard Version, under the Original License, so that the Copyright +Holder may include your modifications in the Standard Version. + +(b) ensure that installation of your Modified Version does not prevent +the user installing or running the Standard Version. In addition, the +Modified Version must bear a name that is different from the name of the +Standard Version. + +(c) allow anyone who receives a copy of the Modified Version to make the +Source form of the Modified Version available to others under + +(i) the Original License or + +(ii) a license that permits the licensee to freely copy, modify and +redistribute the Modified Version using the same licensing terms that +apply to the copy that the licensee received, and requires that the +Source form of the Modified Version, and of any works derived from it, +be made freely available in that license fees are prohibited but +Distributor Fees are allowed. + +Distribution of Compiled Forms of the Standard Version or Modified +****************************************************************** +Versions without the Source +*************************** + +(5) You may Distribute Compiled forms of the Standard Version without +the Source, provided that you include complete instructions on how to +get the Source of the Standard Version. Such instructions must be valid +at the time of your distribution. If these instructions, at any time +while you are carrying out such distribution, become invalid, you must +provide new instructions on demand or cease further distribution. If +you provide valid instructions or cease distribution within thirty days +after you become aware that the instructions are invalid, then you do +not forfeit any of your rights under this license. + +(6) You may Distribute a Modified Version in Compiled form without the +Source, provided that you comply with Section 4 with respect to the +Source of the Modified Version. + +Aggregating or Linking the Package +********************************** + +(7) You may aggregate the Package (either the Standard Version or +Modified Version) with other packages and Distribute the resulting +aggregation provided that you do not charge a licensing fee for the +Package. Distributor Fees are permitted, and licensing fees for other +components in the aggregation are permitted. The terms of this license +apply to the use and Distribution of the Standard or Modified Versions +as included in the aggregation. + +(8) You are permitted to link Modified and Standard Versions with other +works, to embed the Package in a larger work of your own, or to build +stand-alone binary or bytecode versions of applications that include the +Package, and Distribute the result without restriction, provided the +result does not expose a direct interface to the Package. + +Items That are Not Considered Part of a Modified Version +******************************************************** + +(9) Works (including, but not limited to, modules and scripts) that +merely extend or make use of the Package, do not, by themselves, cause +the Package to be a Modified Version. In addition, such works are not +considered parts of the Package itself, and are not subject to the terms +of this license. + +General Provisions +****************** + +(10) Any use, modification, and distribution of the Standard or Modified +Versions is governed by this Artistic License. By using, modifying or +distributing the Package, you accept this license. Do not use, modify, +or distribute the Package, if you do not accept this license. + +(11) If your Modified Version has been derived from a Modified Version +made by someone other than you, you are nevertheless required to ensure +that your Modified Version complies with the requirements of this +license. + +(12) This license does not grant you the right to use any trademark, +service mark, tradename, or logo of the Copyright Holder. + +(13) This license includes the non-exclusive, worldwide, free-of-charge +patent license to make, have made, use, offer to sell, sell, import and +otherwise transfer the Package with respect to any patent claims +licensable by the Copyright Holder that are necessarily infringed by the +Package. If you institute patent litigation (including a cross-claim or +counterclaim) against any party alleging that the Package constitutes +direct or contributory patent infringement, then this Artistic License +to you shall terminate on the date that such litigation is filed. + +(14) Disclaimer of Warranty: THE PACKAGE IS PROVIDED BY THE COPYRIGHT +HOLDER AND CONTRIBUTORS "AS IS' AND WITHOUT ANY EXPRESS OR IMPLIED +WARRANTIES. THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +PARTICULAR PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED TO THE EXTENT +PERMITTED BY YOUR LOCAL LAW. UNLESS REQUIRED BY LAW, NO COPYRIGHT +HOLDER OR CONTRIBUTOR WILL BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING IN ANY WAY OUT OF THE USE +OF THE PACKAGE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + diff --git a/ts_block.adm b/ts_block.adm new file mode 100644 index 0000000..eb582f9 --- /dev/null +++ b/ts_block.adm @@ -0,0 +1,42 @@ +CLASS MACHINE + +CATEGORY "Wellbury LLC" + CATEGORY "ts_block" + KEYNAME "Software\Policies\Wellbury LLC\ts_block" + + POLICY "Block attempts" + PART "Block attempts threshold" NUMERIC REQUIRED SPIN 1 + VALUENAME "BlockAttempts" + DEFAULT 5 + MIN 2 + END PART ; "Block attempts threshold" + EXPLAIN "The number of sequential failed logon attempts (with accounts that are not considered 'block immediately' accounts) that will trigger a block." + END POLICY + + POLICY "Block duration" + PART "Block duration (seconds)" NUMERIC REQUIRED SPIN 1 + VALUENAME "BlockDuration" + DEFAULT 300 + MIN 1 + END PART ; "Block duration" + EXPLAIN "The duration, in seconds, of a block (either because of reaching the BlockAttempts threshhold or because of a 'block immediately')." + END POLICY + + POLICY "Block timeout" + PART "Block timeout (seconds)" NUMERIC REQUIRED SPIN 1 + VALUENAME "BlockTimeout" + DEFAULT 120 + MIN 1 + END PART ; "Block timeout" + EXPLAIN "The duration, in seconds, that must elapse between failed logon attempts to reset the count of failed logon attempts for a given IP address." + END POLICY + + POLICY "Black-hole IP address" + PART "Black-hole IP address" EDITTEXT REQUIRED + VALUENAME "BlackholeIP" + END PART ; "Block timeout" + EXPLAIN "The IP address used for the black-hole route (for Windows Server 2003). If not specified the default algorithm of selecting the IP address of a network interface with no default gateway specified will be used. This setting is not used in Windows Server 2008 and later versions of Windows." + END POLICY + + END CATEGORY ; "ts_block" +END CATEGORY ; "Wellbury LLC" diff --git a/ts_block.vbs b/ts_block.vbs new file mode 100644 index 0000000..2a772ba --- /dev/null +++ b/ts_block.vbs @@ -0,0 +1,357 @@ +Option Explicit + +' ts_block.vbs - Blocks IP addresses generating invalid Terminal Services logons. +' Copyright 2011 Wellbury LLC - See LICENSE for license information +' +' Release 20110831 - Adapted from sshd_block release 20100120 + +' External executables required to be accessible from PATH: +' +' ROUTE.EXE For black-hole routing blocked IP addresses in Windows 2003 +' NETSH.EXE For black-hole firewall rule creation on Windows Vista / 2008 / 7 / 2008 R2 +' EVENTCREATE.EXE For writing to the event log (if enabled) +' +' For support, please contact Evan Anderson at Wellbury LLC: +' EAnderson@wellbury.com, (866) 569-9799, ext 801 + +' Main +Dim objShell, objWMIService, objEventSink, blackHoleIPAddress, regexpSanitizeEventLog, regexpSanitizeIP +Dim dictIPLastSeenTime, dictIPBadLogons, dictUnblockTime, dictBlockImmediatelyUsers +Dim colOperatingSystem, intOSBuild, intBlackholeStyle +Dim intBlockDuration, intBlockAttempts, intBlockTimeout + +' =====================( Configuration )===================== + +' Set to 0 to disable debugging output +Const DEBUGGING = 0 + +' Set to 0 to disable event log reporting of blocks / unblocks +Const USE_EVENTLOG = 1 +Const EVENTLOG_SOURCE = "ts_block" +Const EVENTLOG_TYPE_INFORMATION = "INFORMATION" +Const EVENTLOG_TYPE_ERROR = "ERROR" +Const EVENTLOG_ID_STARTED = 1 +Const EVENTLOG_ID_ERROR_NO_BLACKHOLE_IP = 2 +Const EVENTLOG_ID_ERROR_WIN_XP = 3 +Const EVENTLOG_ID_BLOCK = 256 +Const EVENTLOG_ID_UNBLOCK = 257 + +' Registry path for configuration +Const REG_CONFIG_PATH = "HKLM\Software\Policies\Wellbury LLC\ts_block\" + +' Number of failed logons in time window before IP will be blocked +Const DEFAULT_BLOCK_ATTEMPTS = 5 ' Attempts +Const REG_BLOCK_ATTEMPTS = "BlockAttempts" + +' Expiration (in seconds) for IPs to be blocked +Const DEFAULT_BLOCK_DURATION = 300 +Const REG_BLOCK_DURATION = "BlockDuration" + +' Timeout for attempts before a new attempt is considered attempt #1 +Const DEFAULT_BLOCK_TIMEOUT = 120 ' in X seconds +Const REG_BLOCK_TIMEOUT = "BlockTimeout" + +' Black hole IP address (if hard-specified) +Const REG_BLACKHOLE_IP = "BlackholeIP" + +' Usernames that attempted logons for result in immediate blocking +Set dictBlockImmediatelyUsers = CreateObject("Scripting.Dictionary") +dictBlockImmediatelyUsers.Add "administrator", 1 +dictBlockImmediatelyUsers.Add "root", 1 +dictBlockImmediatelyUsers.Add "guest", 1 + +' ===================( End Configuration )=================== + +Const TS_BLOCK_VERSION = "20110831" +Const BLACKHOLE_ROUTE = 1 ' Blackhole packets via routing table +Const BLACKHOLE_FIREWALL = 2 ' Blackhole packets via firewall + +' =====================( Stress Testing )==================== + +' Set to 1 to perform stress testing +Const TESTING = 0 + +' Number of "bogus" blocks to load +Const TESTING_IP_ADDRESSES = 10000 + +' Minimum and maximum milliseconds between adding "bogus" IPs to the block list during testing +Const TESTING_IP_MIN_LATENCY = 10 +Const TESTING_IP_MAX_LATENCY = 50 + +If TESTING Then + Dim testLatency, cumulativeLatency, testLoop, maxBlocked, blockedAddresses + Randomize +End If + +' ===================( End Stress Testing )================== + +Set dictIPLastSeenTime = CreateObject("Scripting.Dictionary") +Set dictIPBadLogons = CreateObject("Scripting.Dictionary") +Set dictUnblockTime = CreateObject("Scripting.Dictionary") +Set objShell = CreateObject("WScript.Shell") + +Set regexpSanitizeEventLog = new Regexp +regexpSanitizeEventLog.Global = True +regexpSanitizeEventLog.Pattern = "[^0-9a-zA-Z._ /:\-]" + +Set regexpSanitizeIP = new Regexp +regexpSanitizeIP.Global = True +regexpSanitizeIP.Pattern = "[^0-9.]" + +' Get OS build number +Set objWMIService = GetObject("winmgmts:{(security)}!root/cimv2") +Set colOperatingSystem = objWMIService.ExecQuery("SELECT BuildNumber FROM Win32_OperatingSystem") + +For Each intOSBuild in colOperatingSystem + ' Windows OS versions with the "Advanced Firewall" functionality have build numbers greater than 4000 + If intOSBuild.BuildNumber < 4000 Then intBlackholeStyle = BLACKHOLE_ROUTE Else intBlackholeStyle = BLACKHOLE_FIREWALL + + If intOSBuild.BuildNumber = 2600 Then + LogEvent EVENTLOG_ID_ERROR_WIN_XP, EVENTLOG_TYPE_ERROR, "Fatal Error - Windows XP does not provide an IP address to black-hole in failure audit event log entries." + WScript.Quit EVENTLOG_ID_ERROR_WIN_XP + End If + + If DEBUGGING Then WScript.Echo "intBlackHoleStyle = " & intBlackHoleStyle +Next ' intOSBuild + +' Read configuration from the registry, if present, in a really simplsitic way +On Error Resume Next ' Noooo!!! +intBlockDuration = DEFAULT_BLOCK_DURATION +If CInt(objShell.RegRead(REG_CONFIG_PATH & REG_BLOCK_DURATION)) > 0 Then intBlockDuration = CInt(objShell.RegRead(REG_CONFIG_PATH & REG_BLOCK_DURATION)) + +intBlockAttempts = DEFAULT_BLOCK_ATTEMPTS +If CInt(objShell.RegRead(REG_CONFIG_PATH & REG_BLOCK_ATTEMPTS)) > 0 Then intBlockAttempts = CInt(objShell.RegRead(REG_CONFIG_PATH & REG_BLOCK_ATTEMPTS)) + +intBlockTimeout = DEFAULT_BLOCK_TIMEOUT +If CInt(objShell.RegRead(REG_CONFIG_PATH & REG_BLOCK_TIMEOUT)) > 0 Then intBlockTimeout = CInt(objShell.RegRead(REG_CONFIG_PATH & REG_BLOCK_TIMEOUT)) + +If objShell.RegRead(REG_CONFIG_PATH & REG_BLACKHOLE_IP) <> "" Then + blackHoleIPAddress = regexpSanitizeIP.Replace(objShell.RegRead(REG_CONFIG_PATH & REG_BLACKHOLE_IP), "") +Else + blackHoleIPAddress = "" +End If + +On Error Goto 0 + +' Only obtain a blackhole adapter address on versions of Windows where it is required +If (intBlackholeStyle = BLACKHOLE_ROUTE) and (blackHoleIPAddress = "") Then + blackHoleIPAddress = GetBlackholeIP() + If IsNull(blackHoleIPAddress) Then + LogEvent EVENTLOG_ID_ERROR_NO_BLACKHOLE_IP, EVENTLOG_TYPE_ERROR, "Fatal Error - Could not obtain an IP address for an interface with no default gateway specified." + WScript.Quit EVENTLOG_ID_ERROR_NO_BLACKHOLE_IP + End If +End If + +If DEBUGGING Then LogEvent EVENTLOG_ID_STARTED, EVENTLOG_TYPE_INFORMATION, "Block Duration: " & intBlockDuration +If DEBUGGING Then LogEvent EVENTLOG_ID_STARTED, EVENTLOG_TYPE_INFORMATION, "Block Attempts: " & intBlockAttempts +If DEBUGGING Then LogEvent EVENTLOG_ID_STARTED, EVENTLOG_TYPE_INFORMATION, "Block Timeout: " & intBlockTimeout +If DEBUGGING Then LogEvent EVENTLOG_ID_STARTED, EVENTLOG_TYPE_INFORMATION, "Blackhole IP: " & blackHoleIPAddress + +' Create event sink to catch security events +Set objEventSink = WScript.CreateObject("WbemScripting.SWbemSink", "eventSink_") +objWMIService.ExecNotificationQueryAsync objEventSink, "SELECT * FROM __InstanceCreationEvent WHERE TargetInstance ISA 'Win32_NTLogEvent' AND TargetInstance.Logfile = 'Security' AND TargetInstance.EventType = 5 AND (TargetInstance.EventIdentifier = 529 OR TargetInstance.EventIdentifier = 4625) AND (TargetInstance.SourceName = 'Security' OR TargetInstance.SourceName = 'Microsoft-Windows-Security-Auditing')" + +LogEvent EVENTLOG_ID_STARTED, EVENTLOG_TYPE_INFORMATION, EVENTLOG_SOURCE & " (version " & TS_BLOCK_VERSION & ") started." + +If TESTING Then + If DEBUGGING Then WScript.Echo "Stress test loop" + + For testLoop = 1 to TESTING_IP_ADDRESSES + testLatency = Int(Rnd() * (TESTING_IP_MAX_LATENCY - TESTING_IP_MIN_LATENCY)) + TESTING_IP_MIN_LATENCY + + WScript.Sleep(testLatency) + Block(CStr(Int(Rnd * 256)) & "." & CStr(Int(Rnd * 256)) & "." & CStr(Int(Rnd * 256)) & "." & CStr(Int(Rnd * 256))) + blockedAddresses = blockedAddresses + 1 + + ' Try to ExpireBlocks no more often than once every 1000ms + cumulativeLatency = cumulativeLatency + testLatency + If cumulativeLatency >= 250 Then + if blockedAddresses > maxBlocked Then maxBlocked = blockedAddresses + cumulativeLatency = 0 + ExpireBlocks + End If + Next ' testLoop + + ' Drain the queue + While dictUnblockTime.Count > 0 + WScript.Sleep(250) + ExpireBlocks + Wend + + WScript.Echo "Stress test completed. " & TESTING_IP_ADDRESSES & " tested with a maximum of " & maxBlocked & " addresses blocked at once." + + ' Loop until killed + While (True) + WScript.Sleep(250) + Wend + +Else + + If DEBUGGING Then WScript.Echo "Entering normal operation busy-wait loop." + + ' Loop sleeping for 250ms, expiring blocks + While (True) + WScript.Sleep(250) + ExpireBlocks + Wend + +End If + + +Sub Block(IP) + ' Block an IP address and set the time for the block expiration + Dim strRunCommand + Dim intRemoveBlockTime + + ' Block an IP address (either by black-hole routing it or adding a firewall rule) + If (TESTING <> 1) Then + If intBlackholeStyle = BLACKHOLE_ROUTE Then strRunCommand = "route add " & IP & " mask 255.255.255.255 " & blackHoleIPAddress + If intBlackholeStyle = BLACKHOLE_FIREWALL Then strRunCommand = "netsh advfirewall firewall add rule name=""Blackhole " & IP & """ dir=in protocol=any action=block remoteip=" & IP + + If DEBUGGING Then WScript.Echo "Executing " & strRunCommand + objShell.Run strRunCommand + End If + + ' Calculate time to remove block and add to dictUnblockTime + intRemoveBlockTime = (Date + Time) + (intBlockDuration / (24 * 60 * 60)) + + If NOT dictUnblockTime.Exists(intRemoveBlockTime) Then + Set dictUnblockTime.Item(intRemoveBlockTime) = CreateObject("Scripting.Dictionary") + End If + If NOT dictUnblockTime.Item(intRemoveBlockTime).Exists(IP) Then dictUnblockTime.Item(intRemoveBlockTime).Add IP, 1 + + LogEvent EVENTLOG_ID_BLOCK, EVENTLOG_TYPE_INFORMATION, "Blocked " & IP & " until " & intRemoveBlockTime +End Sub + +Sub Unblock(IP) + ' Unblock an IP address + Dim strRunCommand + + If (TESTING <> 1) Then + If intBlackholeStyle = BLACKHOLE_ROUTE Then strRunCommand = "route delete " & IP & " mask 255.255.255.255 " & blackHoleIPAddress + If intBlackholeStyle = BLACKHOLE_FIREWALL Then strRunCommand = "netsh advfirewall firewall delete rule name=""Blackhole " & IP & """" + + If DEBUGGING Then WScript.Echo "Executing " & strRunCommand + objShell.Run strRunCommand + End If + + LogEvent EVENTLOG_ID_UNBLOCK, EVENTLOG_TYPE_INFORMATION, "Unblocked " & IP +End Sub + +Sub LogFailedLogonAttempt(IP) + ' Log failed logon attempts and, if necessary, block the IP address + + ' Have we already seen this IP address before? + If dictIPLastSeenTime.Exists(IP) Then + + ' Be sure that prior attempts, if they are older than intBlockTimeout, don't count it against the IP + If (dictIPLastSeenTime.Item(IP) + (intBlockTimeout / (24 * 60 * 60))) <= (Date + Time) Then + If dictIPBadLogons.Exists(IP) Then dictIPBadLogons.Remove(IP) + End If + + dictIPLastSeenTime.Item(IP) = (Date + Time) + Else + dictIPLastSeenTime.Add IP, (Date + Time) + End If + + ' Does this IP address already have a history of bad logons? + If dictIPBadLogons.Exists(IP) Then + dictIPBadLogons.Item(IP) = dictIPBadLogons.Item(IP) + 1 + Else + dictIPBadLogons.Add IP, 1 + End If + + If DEBUGGING Then WScript.Echo "Logging bad attempt from " & IP & ", attempt # " & dictIPBadLogons.Item(IP) + + ' Should we block this IP address? + If dictIPBadLogons.Item(IP) = intBlockAttempts Then Block(IP) +End Sub + +Sub ExpireBlocks() + Dim unblockTime, ipAddress + + For Each unblockTime in dictUnblockTime.Keys + + If unblockTime <= (Date + Time) Then + For Each ipAddress in dictUnblockTime.Item(unblockTime) + Unblock(ipAddress) + If TESTING Then blockedAddresses = blockedAddresses - 1 + Next ' ipAddress + + dictUnblockTime.Remove unblockTime + End If + Next 'ipAddress +End Sub + +' Should an invalid logon from specified user result in an immediate block? +Function BlockImmediate(user) + Dim userToBlock + + For Each userToBlock in dictBlockImmediatelyUsers.Keys + If UCase(user) = UCase(userToBlock) Then + BlockImmediate = True + Exit Function + End If + Next 'userToBlock + + BlockImmediate = False +End Function + +' Fires each time new security events are generated +Sub eventSink_OnObjectReady(objEvent, objWbemAsyncContext) + Dim arrEventMessage, arrInvalidLogonText + Dim IP, user + + ' Differentiate W2K3 and W2K8+ + If objEvent.TargetInstance.SourceName = "Microsoft-Windows-Security-Auditing" Then + user = objEvent.TargetInstance.InsertionStrings(5) + IP = objEvent.TargetInstance.InsertionStrings(19) + Else + ' Assume W2K3 + user = objEvent.TargetInstance.InsertionStrings(0) + IP = objEvent.TargetInstance.InsertionStrings(11) + End If + + ' Make sure only characters allowed in IP addresses are passed to external commands + IP = regexpSanitizeIP.Replace(IP, "") + + ' If the event didn't generate both a username and IP address then do nothing + If (IP <> "") AND (user <> "") Then + If BlockImmediate(user) Then Block(IP) Else LogFailedLogonAttempt(IP) + End If +End Sub + +Function GetBlackholeIP() + ' Sift through the NICs on the machine to locate a NIC's IP to use to blackhole offending hosts. + ' Look for a NIC with no default gateway set and an IP address assigned. Return NULL if we can't + ' find one. + + Dim objNICs, objNICConfig + Set objNICs = GetObject("winmgmts:\\.\root\cimv2").ExecQuery("SELECT * FROM Win32_NetworkAdapterConfiguration WHERE IPEnabled = TRUE") + + ' Scan for a NIC with no default gateway set and IP not 0.0.0.0 + For Each objNICConfig in objNICs + If IsNull(objNICConfig.DefaultIPGateway) and (objNICConfig.IPAddress(0) <> "0.0.0.0") Then + If DEBUGGING Then WScript.Echo "Decided on black-hole IP address " & objNICConfig.IPAddress(0) & ", interface " & objNICConfig.Description + GetBlackholeIP = objNICConfig.IPAddress(0) + Exit Function + End If + Next + + ' Couldn't find anything, return NULL to let caller know we failed + GetBlackHoleIP = NULL +End Function + +Sub LogEvent(ID, EventType, Message) + ' Log an event to the Windows event log + + ' Sanitize input string + Message = regexpSanitizeEventLog.Replace(Message, "") + + If DEBUGGING Then WScript.Echo "Event Log - Event ID: " & ID & ", Type: " & EventType & " - " & Message + + ' Don't hit the event log during testing + If TESTING Then Exit Sub + + If USE_EVENTLOG Then objShell.Exec "EVENTCREATE /L APPLICATION /SO " & EVENTLOG_SOURCE & " /ID " & ID & " /T " & EventType & " /D """ & Message & """" +End Sub -- cgit v1.2.3