In server 2008, it’s quite easy to attach a task to an event. In EventViewer, simply right-click on the event and choose Attach Task to This Event. This is fine and dandy but sometimes, we want a little more granular control over when to actually fire the task; e.g., I typically want to only notify myself via email of failed RDP logons, not ALL failed logons.
It’s a little more complicated to get only the events you want based on some details inside the actual event – the Event Data.
Note: In Server 2008 the EventID for a Successful Logon is 4624 and for a Failed Logon is 4625. There are multiple Logon Types and you can reference them at this link from MSDN and adapt this guide to your liking. Look at the Logon Type section specifically.
These are the two XPath filters I’ll be working with and I will show you how to create 2 tasks based on 2 separate events:
1. Failed RDP Logon
2. Successful RDP Logon
XML for Failed RDP Logon
Note: After doing some testing, it seems that LogonType 10 isn’t working for notification but LogonType 3 is. I’m still looking at why this is the case since this is RDP logon I’m testing.
<QueryList> <Query Id="0" Path="Security"> <Select Path="Security">*[System[(EventID=4625)]] and *[EventData[Data[@Name='LogonType'] and (Data=10)]]</Select> </Query> </QueryList>
XML for Successful RDP Logon
<QueryList> <Query Id="0" Path="Security"> <Select Path="Security">*[System[(EventID=4624)]] and *[EventData[Data[@Name='LogonType'] and (Data=10)]]</Select> </Query> </QueryList>
1. Failed RDP Logon Task Setup
Launch Event Viewer (Start -> eventvwr.msc [ENTER])
2. Successful RDP Logon
Repeat all the steps from 1. Failed RDP Logon, simply replacing the XML EventID with 4624.
Manage Event Viewer Tasks
You can see all your Event Viewer Tasks by launching Task Scheduler (Start -> taskschd.msc [ENTER]) and choosing the Event Viewer Tasks folder.
Hopefully this helps anyone out there that has been wondering how to do this. Got any more tips? Let me know. I’d be interested to know if you can specify variables in the email output – like other XPath variables that could be set or something. Maybe even a specific event tag so that instead of directly emailing, you could write a short script that runs and will get the full details (Event Data) of the event and then embed it in an email.
I have found (Oh, glorious Google: Ref 1, Ref 2) how to reference Event Data in the emails. This makes me excited and now I’m cooking up commands also for dynamically adding IPs to RDP firewall for this case.
So, to be able to reference a variable from the Event Data, you need to add a ValueQueries element (MSDN link) to your Task. The easiest way to do this is to export your task as XML and open it with notepad to edit it. First, let’s look at some of the data options available to use as variables. To get these, I like to find an event in the event viewer and look at the XML and look at the Data elements.
Let’s go back to what I was wanting to do originally – notify via email when a failed RDP logon occurs. Now, I not only want to just send myself an email but I want to include some extra information. In this case, I want to include the IpAddress as well as the TargetUserName. This will tell me which IP address the logon came from as well as what user name the remote system tried to use. Awesome!
So, fire up task scheduler (Start -> taskschd.msc [ENTER]) and navigate to the event viewer tasks item in the left pane. Then, right-click the task we created earlier (Failed RDP Logon) and choose Export.
Save it somewhere convenient and then right-click and choose Edit (or open with notepad).
We need to add a ValueQueries element in the EventTrigger element.
You will want to add the ValueQueries element in the EventTrigger element. Of course if you aren’t following what I’m doing, change them to something you’d rather see from your own available event data values.
<ValueQueries> <Value name="IpAddress">Event/EventData/Data[@Name="IpAddress"]</Value> <Value name="TargetUserName">Event/EventData/Data[@Name="TargetUserName"]</Value> </ValueQueries>
Now that we have setup the variables, let’s add them to our email message. This can be done from in this exported task easily. Scroll to the bottom and look for the following block of code:
<Actions context="Author">
In that, modify your Body element to reflect your variables. Note: Variables are CAsE-SenSiTive!
In Conclusion
So in conclusion there are some really cool “tricks” we can do here to help monitor our systems. Another cool thing would be to, instead of email notification, simply take the $(IpAddress) and pass it to a command such as, say,:
netsh advfirewall firewall add rule name="Block $(IpAddress) - Bad Dude" dir=in protocol=any action=block remoteip=$(IpAddress)
Now, how cool would that be? =)
Firstly thanks for this awesome little script, it works a treat however I would like to let you know of 1 small typo in your script below.
Event/EventData/Data[@Name=”IpAddress”] <— Small V
Event/EventData/Data[@Name=”TargetUserName”]
Please amend the Lower Case V in your script, it would appear that Microsoft is sometimes a little pedantic about case. (I thought that was only a Linux thing)
The correct code is below for anyone else in the meantime:
Event/EventData/Data[@Name=”IpAddress”]
Event/EventData/Data[@Name=”TargetUserName”]
Thanks for pointing this out but sorry I can’t see any <— Small V":
I would like to let you know of 1 small typo in your script below.
Event/EventData/Data[@Name="IpAddress"] <— Small V
Event/EventData/Data[@Name="TargetUserName"]
The correct code is below for anyone else in the meantime:
Event/EventData/Data[@Name="IpAddress"]
Event/EventData/Data[@Name="TargetUserName"]
I really don't see any difference !
Ohh it would appear that it removed the syntax from my comment the small V is on the IpAddress line in the ending Value tag.
One nice feature that I would like would be the ability to have it only send an email once every 2 minutes instead of every event, I just had 30 emails come in, in just 2 minutes. Any ideas on that one?
Content updated, thanks for that catch.
Now, regarding the burst of emails…
Once every 2 minutes of all the collected login failures?
I believe that would be possible. There are a number of ways that I’m thinking this could be _possibly_ done.
The only problem is that the nature of this task is created from an event so I think there would have to be some logic in there to identify if this task has run already within X minutes, and if so, has it been Y minutes long to generate the new Action (e.g., send another email). I’d have to think about this and do some research.
One other idea is to go the route of not triggering on every event, but rather, run a task on a scheduled time to collect failed login events from event log. That may be a more viable option but it is not real-time. So you could collect past 5 minutes failed logins every 5 minutes and email it to yourself. Just a few of my thoughts on that last comment.
Hi Rich,
I’ve come up with a fairly rudimentary way of doing it.
I’ve basically setup everything just like you suggested but added an extra ACTION to the scheduled task, which is setup to “Start a Program” then I created a batch file that just says “ping -n 100 127.0.0.1” and saved it as “wait.bat” which I used as the program for the second action.
So basically what happens now is someone tries to guess the password, it logs a logon failure event. The task scheduler job executes and it sends an email and then starts the 100 Second ping.
If the person attempts to hack again then the scheduled job won’t run because the first job is still running. And by default a scheduled task has the option set to “Do Not Start a New Instance” on the Settings Page.
If you find a better way let me know but for now this seems to be working great. I will see how many hackers I can trap and foil their plans. We will most likely be implementing this on all our Cloud Servers.
Brett
Ah, nice workaround. I’ll tinker and see if I can come up with another way built-in to scheduler and let you know this week. Thanks for the follow-up and nice idea. =)
I’m not using the native SMTP server, so I’m having problems sending the email because of the SMTP authentication. I solved by using SMTPMailSender (http://www.snapfiles.com/get/smtpmailsender.html).
There is still a problem. This mail sender generates a login error creating an infinite loop. So I wrote a batch file that solves this problem and adds a new firewall rule:
——————————————————-
IF %2==alberto@xxxxx.it GOTO FINE
IF %1==11.222.33.44 GOTO FINE
c:smtpsendersmtpmailsender.exe -t alberto@xxxxxx.it -f postmaster@xxxxxx.it -s “intrusion detected” -b “Intrusion from %1 with username %2” -username alberto@xxxxx.it -password mypassword -send
netsh advfirewall firewall add rule name=”Block %1 – bad dude” dir=in protocol=any action=block remoteip=%1
:FINE
——————————————————-
the batch file is called with parameter 1 $(IpAddress) and parameter 2 $(TargetUserName).
The second IF has been added to exclude my IP address from being blocked.
Hope this helps.
Ciao
Alberto
Nice tip Alberto, thanks. I remember using a simple SMTP server as well. In my environment, I allow relay from this specific host on the SMTP server I’m sending through. Alleviates having to setup another SMTP workaround but this is nice instructions for doing so. Thanks again!
Great script.
Anyone know what the ValueQueries element would be to retrive the computer name of the computer trying to logon?
@Michael
Should be WorkstationName as seen in screenshot on this page captioned Friendly view of an event showing the data types
The Network Information fields indicate where a remote logon request originated. Workstation name is not always available and may be left blank in some cases.
Hi,
I am trying to get the IpAddress and the TargetUserName , but All i get is
From IP $(IpAddress) By User $(TargetUserName)
Any pointers please ?
Which server are you using this on and did you make sure to use IpAddress and TargetUserName with CaseSenSitiVity?
Hi Rich,
Please can you explain how to auto-add to an already existing firewall rule the failed logon attempts.
You said to use the:
(netsh advfirewall firewall add rule name=Block $(IpAddress) – Bad Dude dir=in protocol=any action=block remoteip=$(IpAddress))
But I presume this creates a new rule for each IP, or am I wrong? a better way is to add the IP’s into the same rule.
Anyway how to put it in the xml file? where exactly to copy paste it.
Please explain,
Thank You so much for this useful post.
Yes, this does create a new rule for each IP Address.
You could look at the “set” verb instead of “add”. See here for more information on this verb: http://technet.microsoft.com/en-us/library/dd734783(v=ws.10).aspx#BKMK_3_set
1. Use “add” to create a generic container called “Bad Dudes”
2. Use “set” to add to the “Bad Dudes” container
netsh advfirewall firewall add rule name=”Bad Dudes” dir=in protocol=any action=block remoteip=FirstIP
Then, for the actual trigger portion of this you would use “set” to add a remote IP to the “Bad Dudes” rule by substituting “add” with “set” in the above line.
I guess you could add another “action” to the task scheduler for this. I’m not sure exactly how to do it in the XML but I think this could be easily searched for.