The Graylog Blog

Back to Basics: Enhance Windows Security with Sysmon and Graylog

Previously we discussed how you can use Graylog Collector Sidecar to configure Filebeat and work with Logfiles. Now we’ll show you how to use the winlogbeat to get the Windows Event Log over to your Graylog Installation. This will be useful if you are running Windows Servers in your environment or have a fleet of workstations that you are responsible for and want to have the additional information added to your already present central logfile system.

The Microsoft System Monitor (sysmon) that provides you information about your Windows also writes messages to the Windows Event Log. After installation and configuration, you can configure your already running winlogbeat to get the sysmon messages into Graylog. For added protection, you can also install our threat intelligence plugin. The plugin adds processing pipeline functions to enrich log messages with threat intelligence data. Note, the threat intelligence plugin is still in testing mode.

We will walkthrough the steps below and once implemented, you will be able to easily monitor your data and react to any unusual requests.

Collector Sidecar and Winlogbeat

The documentation provides a step-by-step guide to install the collector sidecar. This will already include winlogbeat so you only need to install and configure one package. When installing the collector sidecar, leave the tag windows so you will be able to configure everything from the Graylog web interface.

Since we only want the Windows Event Logfile, simply disable the filebeat backend in the collector sidecar configuration file.

Back to the Graylog Web interface! We assume you have a beats input already running as global input on Port 5044 with no TLS.

Follow the step-by-step guide to create a configuration and choose WinlLogBeat for the type of configuration.

The important step is to now replace the Event name with [{'name':'Microsoft-Windows-Sysmon/Operational'}] so that you will only receive the sysmon messages in Graylog.

With this setup, each windows host that runs sysmon and has the collector sidecar configured with the tag windows will send over messages.

Enhance sysmon messages with pipelines

Sysmon should be installed as an administrator with the following command line so that it will survive reboots, collect network connection information, record MD5 hashes for all created processes, and record loading of modules:

.\Sysmon.exe –i –accepteula –h md5 –n -l

Create the following pipeline rules in System > Pipelines > Manage rules as new rules.

// This rule is cleaning up the message
// -- It addresses an issue with older filebeat versions, which can have trouble with the 'source' field 
// -- The rule will not cause any trouble with filebeat versions that do not have that issue
rule "sysmon cleanup (gl2_source_fix)"
    set_field("gl2_source_collector", to_string($message.winlogbeat_fields_gl2_source_collector));
// Sysmon Installation
// -- Sysmon has to be installed on Windows, and be run with: sysmon –i –accepteula –h md5 –n -l 
// -- Transport should be a winlogbeat
// -- Consider using the Graylog Sidecar to manage winlogbeat remotely
rule "sysmon cleanup"
    // Only run for Sysmon messages
    has_field("winlogbeat_source_name") AND contains(to_string($message.winlogbeat_source_name), "Microsoft-Windows-Sysmon")

    // Rename some fields to clean up
    rename_field("winlogbeat_computer_name", "sysmon_computer_name");
    rename_field("winlogbeat_event_data_Image", "sysmon_data_process");
    rename_field("winlogbeat_event_data_UtcTime", "sysmon_data_utc_time");
    rename_field("winlogbeat_event_id", "sysmon_event_id");
    rename_field("winlogbeat_level", "sysmon_data_level");
    rename_field("winlogbeat_task", "sysmon_task");
    rename_field("winlogbeat_event_data_User", "sysmon_data_user");
    rename_field("winlogbeat_event_data_TargetFilename", "sysmon_data_file_created");
    rename_field("winlogbeat_event_data_CreationUtcTime", "sysmon_data_file_created_time");
    rename_field("winlogbeat_event_data_PreviousCreationUtcTime", "sysmon_data_file_created_time_previous");
    rename_field("winlogbeat_user_name", "sysmon_data_user_name");
    rename_field("winlogbeat_thread_id", "sysmon_thread_id"); 
    rename_field("winlogbeat_user_domain", "sysmon_user_domain");
    rename_field("winlogbeat_user_identifier", "sysmon_user_identifier");
    rename_field("winlogbeat_user_type", "sysmon_user_type");
    rename_field("winlogbeat_event_data_DestinationHostname", "sysmon_dns_lookup");
    rename_field("winlogbeat_event_data_DestinationIp", "sysmon_dns_lookup_ip");
    rename_field("winlogbeat_event_data_DestinationPort", "sysmon_dest_port");
    rename_field("winlogbeat_event_data_DestinationPortName", "sysmon_dest_port_name");
    rename_field("winlogbeat_event_data_Initiated", "sysmon_con_initiated");
    rename_field("winlogbeat_event_data_Protocol", "sysmon_con_proto");
    rename_field("winlogbeat_event_data_SourceHostname", "sysmon_src_name");
    rename_field("winlogbeat_event_data_SourceIp", "sysmon_src_ip");
    rename_field("winlogbeat_event_data_SourcePort", "sysmon_src_port");
    rename_field("winlogbeat_event_data_SourcePortName", "sysmon_src_port_name");
    rename_field("winlogbeat_event_data_CommandLine", "sysmon_cmd_event");
    rename_field("winlogbeat_event_data_CurrentDirectory", "sysmon_cmd_location");
    rename_field("winlogbeat_event_data_Hashes", "sysmon_cmd_hash");
    rename_field("winlogbeat_event_data_IntegrityLevel", "sysmon_cmd_integrity");
    rename_field("winlogbeat_event_data_LogonId", "sysmon_cmd_logon_id");
    rename_field("winlogbeat_event_data_ParentCommandLine", "sysmon_cmd_parent_cmd");
    rename_field("winlogbeat_event_data_ParentImage", "sysmon_cmd_parent_file");
    rename_field("winlogbeat_event_data_ParentProcessId", "sysmon_cmd_parent_pid");
    rename_field("winlogbeat_event_data_TerminalSessionId", "sysmon_cmd_terminal_pid");
    rename_field("winlogbeat_event_data_LogonGuid", "sysmon_cmd_logon_guid");
    rename_field("winlogbeat_event_data_ParentProcessGuid", "sysmon_cmd_parent_guid");

    // Remove clutter.
    let fix = regex("^\\{(\\S+)\\}$", to_string($message.winlogbeat_event_data_ProcessGuid));
    set_field("sysmon_data_process_guid", to_string(fix["0"]));

    let fix = regex("^\\{(\\S+)\\}$", to_string($message.winlogbeat_provider_guid));
    set_field("sysmon_data_provider_gui", to_string(fix["0"]));

    // Remove unwanted fields

    // Remove winlogbeats fields we don't need
// Threat Intelligence enrichment
// --- Needs installed Graylog Threat Intel plugin :
rule "sysmon threatintel"
   // To save CPU cycles, only run if there is something to look up
   has_field("sysmon_dns_lookup") OR has_field("sysmon_dns_lookup_ip") OR has_field("sysmon_src_ip")

    // look up the requested DNS captured by sysmon
    // this will be the most fired rule
    let sysmon_dns_lookup_intel = threat_intel_lookup_domain(to_string($message.query_domain), "sysmon_dns_lookup");

    // look up the ip from the DNS answer
    // if we do not monitor the dns, then this might be nice to have
    let sysmon_lookup_ip_answer_intel = threat_intel_lookup_ip(to_string($message.query_answer), "sysmon_dns_lookup_ip");

    // look up the requesting IP 
    // this is useful if dealing with non internal IPs 
    // so you know if your IP is seen as a problem
    let sysmon_src_ip_answer_intel = threat_intel_lookup_ip(to_string($message.query_answer), "sysmon_src_ip");

    // WHOIS lookup. This is disabled by default. Enable and carefully watch latency and performance.
    //let sysmon_dns_lookup_ip_whois = whois_lookup_ip(to_string($message.query_answer), "sysmon_dns_lookup_ip");
rule "sysmon threatintel inflate"
    // run only if one of the fields is true
    to_bool($message.sysmon_dns_lookup_ip_threat_indicated) OR to_bool($message.sysmon_dns_lookup_threat_indicated) OR to_bool($message.sysmon_src_ip_threat_indicated)

    // This is to make Graylog searches easy
    // -- Enables searches like threat_indicated:true
    set_field("threat_indicated", true);

The rules will now need to be added to a new Pipeline. We will name it Windows-Sysmon. In this Pipeline, we will have the following Stages containing rules:

  1. Stage -1
    • sysmon cleanup (gl2sourcefix)
    • sysmon cleanup
  2. Stage 0
    • sysmon threatintel
  3. Stage 1
    • sysmon threatintel inflate

Please note, due to the amount of messages produced by sysmon, you should enable the delivery to Graylog in batches so that you are able to scale and size the environment.

To use the last two Stages, you will need to install the Graylog threat intelligence plugin on all your Graylog Nodes. Without the plugin, it would not be possible to save the rules because of the missing functions.

To process, connect the Pipeline to a Stream of messages.

Your messages will now look like the following:

Create Dashboard

To easily view and work with the data, you can create your own dashboard or download the dashboard below,

Legal aspects

Note that you should first check with your local and workplace guidelines to make sure that you are not invading any privacy laws.

Next Steps

With the verbose information from sysmon, you will be able to create user profiles and discover which programs run on Windows system. The benefit of having this data in a central environment is that you can see correlations, work with the data from all machines you are responsible for, as well as run a certain task once, and not on multiple systems. This should also be viewed as a starting point for your journey as we've only covered the basic lookups in our Dashboard. You can also use the search _exists_:sysmon_cmd_hash to quickly look for the process hashes that were created on the Windows Systems.

comments powered by Disqus