Skip to content

Instantly share code, notes, and snippets.

@wqweto
Created December 10, 2013 09:36
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save wqweto/7888059 to your computer and use it in GitHub Desktop.
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.
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