Monitoring Remote Desktop Gateway Authentication in Splunk

The current image has no alternative text. The file name is: SplunkSiemRDGateway-scaled.webp

Some time ago, I needed to monitor Remote Desktop Gateway (RDG) authentication and authorization using Windows Event Logs and Splunk. I initially expected this task to be straightforward – similar to monitoring VPN activity on a firewall. Unfortunately, that wasn’t the case.

The main challenge I faced was correlating different logs related to connections, authentication, and authorization.

Starting Point: Event ID 312

Let’s begin at the start. I found very useful information in the Microsoft-Windows-TerminalServices-Gateway/Operational log, specifically Event ID 312:

The user “username@DOMAINNAME”, on client computer “12.12.12.12:2827”, has initiated an outbound connection. This connection may not be authenticated yet.

This tells us that a connection was initialized and provides both the username and the client’s source IP address.

The Authentication Challenge

The next step is authentication. This is where the problems began.

If the domain name (DOMAINNAME) is valid, authentication is forwarded to a Domain Controller, and logs must be correlated accordingly. You could use Event ID 4768, where:

  • Result Code: 0x0 indicates success.
  • Any other code indicates failure.

However, correlating Event ID 4768 with Event ID 312 would require matching on the username, client IP address, and timestamp – a complex task, especially when dealing with logs from both RD Gateway and Domain Controllers.

To complicate things further, if the domain or username is invalid (e.g., due to a brute-force or dictionary attack), the authentication attempt does not reach the Domain Controller. Instead, it’s logged in the RD Gateway logs using Event ID 4625.

Simplifying the Process with Event ID 302

After analyzing the complexities, I decided to take a simpler and more effective approach – by incorporating Event ID 302 into the query:

The user “DOMAINNAME\username”, on client computer “12.12.12.12”, connected to resource “-SERVER-RDSHOST”. Connection protocol used: “HTTP”.

This log entry confirms that both authentication and authorization were successful, and it shows where the connection was forwarded – providing sufficient information to record the result.

Logical Flow

The log flow is as follows:

  1. Connection Initiated – Logged by Event ID 312.
  2. Two possible outcomes:
    • SUCCESS – If Event ID 312 is followed by Event ID 302 for the same username and IP address within a 1-second window.
    • FAILURE – If Event ID 302 does not follow within that window.

Building the Splunk Search Query

Here’s how I approached the Splunk query, solving several key problems along the way.

1. Filter Relevant Events

2. Normalize Username Format

Event ID 312 logs the username as username@DOMAINNAME, while Event ID 302 uses DOMAINNAME\username. To correlate these, we normalize the username:

3. Normalize IP Address

Event ID 312 includes the port (e.g., 12.12.12.12:2827), so we remove it:

4. Handle Timestamps and Time Zones

The next problem was with time. By default, event logs record timestamps with 1-second accuracy, which unfortunately wasn’t sufficient for the query.

I decided to use SystemTime, but that introduced another issue, as it operates in the UTC time zone. In my case, this resulted in a one-hour discrepancy.

I addressed both problems in the query below. It was quite challenging – especially accounting for time zone adjustments and daylight saving time.

5. Group Logs Within 1-Second Window

Using streamstats, we group logs by time, username, and IP address:

6. Remove Duplicate Groups

When status is SUCCESS: multiple 312 logs may fall into the same time window. We deduplicate them:

7. Determine Connection Status

Based on the count of correlated events:

8. Format Time for Readability

Another necessary step was converting epoch time to a human readable format.

9. Display the Final Table

And finally, displaying the results in a table format, sorted by time.


Complete Query

Sample Output

Acknowledgments

Special thanks to @malix_la_harpe from the Splunk community for helping me discover the streamstats approach, which proved to be an elegant solution to a complex correlation problem.

Share Us

Leave a Reply

Your email address will not be published. Required fields are marked *