Created
December 10, 2013 09:36
-
-
Save wqweto/7888059 to your computer and use it in GitHub Desktop.
This script transfers failed logon attempts from Terminal Servers to /var/log/rdp/audit.log on the gateway server. From this point the log file is processed by fail2ban rules.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Const SSH_SERVER_LOG = "/var/log/rdp/audit.log" | |
Const LOCAL_RDP_GROUP = "Remote Desktop Users" | |
Const CACHE_AGE_IN_MINUTES = 5 | |
Const DENY_USERS = "Administrator|Administrador|Admin|Admin1|POS|User|UsUser1|system|sys|aspnet|root|sql|post|post1|bank|operator|oper|oper1|test|test1" | |
Const NOLOG_USERS = "VDC02" | |
If Not WScript.Arguments.Named.Exists("s") Then | |
WScript.echo "usage: " & WScript.ScriptName & " /s:server /l:user /i:key_file" | |
WScript.Quit 1 | |
End if | |
'--- init args | |
m_sSshServer = WScript.Arguments.Named("s") | |
m_sSshPort = WScript.Arguments.Named("p") | |
m_sSshUser = WScript.Arguments.Named("l") | |
m_sSshKeyfile = WScript.Arguments.Named("i") | |
m_sSshPass = WScript.Arguments.Named("pw") | |
'--- init member vars | |
Set m_oWMI = GetObject("winmgmts:{impersonationLevel=impersonate}!\\.\root\cimv2") | |
Set m_oShell = WScript.CreateObject("WScript.Shell") | |
Set m_oFSO = WScript.CreateObject("Scripting.FileSystemObject") | |
m_sProcessName = WScript.ScriptName | |
m_lProcessId = GetCurrentProcessId() | |
With WScript.CreateObject("WScript.Network") | |
m_sComputerName = .ComputerName | |
m_sDomainName = .UserDomain | |
End With | |
'--- init regexp | |
Set m_oSanitizeIP = new RegExp | |
m_oSanitizeIP.Global = True | |
m_oSanitizeIP.Pattern = "[^0-9.]" | |
'--- init known rdp users | |
Set m_oRdpUsers = GetRdpUsers() | |
m_dRdpUsersTimestamp = Now | |
'--- init event sink | |
sQuery = "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')" | |
m_oWMI.ExecNotificationQueryAsync WScript.CreateObject("WbemScripting.SWbemSink", "EventSink_"), sQuery | |
'--- main loop | |
Do | |
WScript.Sleep 100 | |
Loop | |
'= event sinks ================================================================================== | |
Sub EventSink_OnObjectReady(oEvent, oWbemAsyncContext) | |
If oEvent.TargetInstance.SourceName = "Microsoft-Windows-Security-Auditing" Then | |
sUserName = oEvent.TargetInstance.InsertionStrings(5) | |
sClientIp = oEvent.TargetInstance.InsertionStrings(19) | |
Else '--- Win2k3 | |
sUserName = oEvent.TargetInstance.InsertionStrings(0) | |
sClientIp = oEvent.TargetInstance.InsertionStrings(11) | |
End If | |
sClientIp = m_oSanitizeIP.Replace(sClientIp, vbNullString) | |
If LenB(sUserName) <> 0 And LenB(sClientIp) <> 0 Then | |
If InStr(1, "|" & NOLOG_USERS & "|", "|" & sUserName & "|", vbTextCompare) > 0 Then | |
'--- do nothing | |
ElseIf InStr(1, "|" & DENY_USERS & "|", "|" & sUserName & "|", vbTextCompare) > 0 Then | |
LogEvent "Denied user name " & sUserName & " from " & sClientIp | |
ElseIf CheckLoginExist(sUserName) Then | |
LogEvent "Login failed for " & sUserName & " from " & sClientIp | |
Else | |
If m_dRdpUsersTimestamp < DateAdd("n", -CACHE_AGE_IN_MINUTES, Now()) Then | |
On Error Resume Next | |
Set oUsers = GetRdpUsers() | |
On Error GoTo 0 | |
If IsObject(oUsers) Then | |
Set m_oRdpUsers = oUsers | |
m_dRdpUsersTimestamp = Now | |
If CheckLoginExist(sUserName) Then | |
LogEvent "Login failed for " & sUserName & " from " & sClientIp | |
Exit Sub | |
End If | |
End If | |
End If | |
LogEvent "Unknown user name " & sUserName & " from " & sClientIp | |
End If | |
End If | |
End Sub | |
'= functions ==================================================================================== | |
Function CheckLoginExist(sUserName) | |
If m_oRdpUsers.Exists(m_sDomainName & "\" & sUserName) Then | |
CheckLoginExist = True | |
ElseIf m_oRdpUsers.Exists(m_sComputerName & "\" & sUserName) Then | |
CheckLoginExist = True | |
Else | |
CheckLoginExist = (InStr(1, sUserName, "_") > 0) | |
End If | |
End Function | |
Sub LogEvent(sMsg) | |
sLog = FormatLogDate(Now) & " " & m_sComputerName & " " & m_sProcessName & "[" & CStr(m_lProcessId) & "]: " & sMsg | |
WScript.echo sLog | |
sCmd = "plink.exe " & Quote(m_sSshUser & "@" & m_sSshServer) & _ | |
IIf(LenB(m_sSshPort) <> 0, " -P " & Quote(m_sSshPort), vbNullString) & _ | |
IIf(LenB(m_sSshKeyfile) <> 0, " -i " & Quote(m_sSshKeyfile), vbNullString) & _ | |
IIf(LenB(m_sSshPass) <> 0, " -pw " & Quote(m_sSshPass), vbNullString) | |
m_oShell.Exec sCmd & " echo -e " & Quote(Replace(sLog, "\", "\\")) & " >> " & SSH_SERVER_LOG | |
End Sub | |
Function FormatLogDate(d) | |
FormatLogDate = Split("N/A Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec")(Month(d)) & " " & Right(" " & Day(d), 2) & " " & _ | |
Right("0" & Hour(d), 2) & ":" & Right("0" & Minute(d), 2) & ":" & Right("0" & Second(d), 2) | |
End Function | |
Function IIf(Cond, TruePart, FalsePart) | |
If Cond Then IIf = TruePart: Else IIf = FalsePart | |
End Function | |
Function Quote(sText) | |
Quote = """" & Replace(sText, """", "\""") & """" | |
End Function | |
Function GetCurrentProcessId() | |
Const TemporaryFolder = 2 | |
Const ForWriting = 2 | |
With m_oFSO | |
sTempFile = .BuildPath(.GetSpecialFolder(TemporaryFolder), "$~sleep.vbs") | |
.OpenTextFile(sTempFile, ForWriting, True).Write "WScript.Sleep 1000" | |
End With | |
With m_oShell.Exec("WScript " & sTempFile) | |
sQuery = "SELECT * FROM Win32_Process WHERE ProcessId=" & .ProcessID | |
End With | |
For Each oPrc In m_oWMI.ExecQuery(sQuery) | |
GetCurrentProcessId = oPrc.ParentProcessId | |
Exit For | |
Next | |
End Function | |
Function GetRdpUsers() | |
'--- init local group | |
Set GetRdpUsers = CreateObject("Scripting.Dictionary") | |
GetRdpUsers.CompareMode = 1 | |
GetGroupMembers m_sComputerName, LOCAL_RDP_GROUP, GetRdpUsers | |
'--- loop groups | |
lIdx = 0 | |
vKeys = GetRdpUsers.Keys | |
Do While lIdx < GetRdpUsers.Count | |
If lIdx > UBound(vKeys) Then | |
vKeys = GetRdpUsers.Keys | |
End If | |
vItem = GetRdpUsers.Item(vKeys(lIdx)) | |
GetGroupMembers vItem(0), vItem(1), GetRdpUsers | |
lIdx = lIdx + 1 | |
Loop | |
LogEvent "Cached " & GetRdpUsers.Count & " users and groups from " & LOCAL_RDP_GROUP | |
End Function | |
Function GetGroupMembers(sDomain, sGroup, oResult) | |
sQuery = "SELECT * FROM Win32_GroupUser WHERE GroupComponent = ""Win32_Group.Domain='" & sDomain & "',Name='" & sGroup & "'""" | |
For Each vPath In m_oWMI.ExecQuery(sQuery) | |
vSplit = Split(vPath.PartComponent, """") | |
If Not oResult.Exists(vSplit(1) & "\" & vSplit(3)) Then | |
oResult.Add vSplit(1) & "\" & vSplit(3), Array(vSplit(1), vSplit(3)) | |
End If | |
Next | |
End Function |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment