# Author: Wes Lambert
#
# Last Update: 09/19/2018
#
# This conf file is based on accepting logs from OSSEC

filter {
  # OSSEC Alerts
  if [type] == "ossec" {
        
	# Sysmon/Autoruns logs transported by OSSEC
        if [message] =~ "Microsoft-Windows-Sysmon" {
            mutate {
                replace => { "type" => "sysmon" }
                add_tag => [ "ossec" ]
            }
        }
        if [message] =~ "AR-LOG" {
            mutate {
                replace => { "type" => "autoruns" }
                add_tag => [ "ossec" ]
            }
        }
		
	# If message looks like json, try to parse it as such. Otherwise, grok.
        if [message] =~ /^{.*}$/ {
                json {
                        source => "message"
                }
		mutate {
			rename => { "rule" => "wazuh-rule" }
			rename => { "[wazuh-rule][level]" => "alert_level" }
			rename => { "[wazuh-rule][description]" => "description" }
			rename => { "[data][srcuser]" => "username" }
			rename => { "[data][dstuser]" => "escalated_user" }
			rename => { "[data][command]" => "command" }
			rename => { "[predecoder][program_name]" => "process" }
			
                }
                # Wazuh 3.8.2
                if [data][EventChannel] {
        		mutate {
				rename => { "[data][EventChannel][EventData][User]" => "username" }
        			rename => { "[data][EventChannel][System][EventID]" => "event_id" }
        			rename => { "[data][EventChannel][EventData][DestinationPort]" => "destination_port" }
        			rename => { "[data][EventChannel][EventData][DestinationIp]" => "destination_ip" }
        			rename => { "[data][EventChannel][EventData][SourcePort]" => "source_port" }
        			rename => { "[data][EventChannel][EventData][SourceIp]" => "source_ip" }
        			rename => { "[data][EventChannel][EventData][SourceHostname]" => "source_hostname" }
        			rename => { "[data][EventChannel][EventData][DestinationHostname]" => "destination_hostname" }
			}
		}
                # Wazuh 3.9.2
		if [data][win] {
                        mutate {
				rename => { "[data][win][eventdata][user]" => "username" }
                        	rename => { "[data][win][system][eventID]" => "event_id" }
                        	rename => { "[data][win][eventdata][destinationPort]" => "destination_port" }
                        	rename => { "[data][win][eventdata][destinationIp]" => "destination_ip" }
                        	rename => { "[data][win][eventdata][sourcePort]" => "source_port" }
                        	rename => { "[data][win][eventdata][sourceIp]" => "source_ip" }
                        	rename => { "[data][win][eventdata][sourceHostname]" => "source_hostname" }
                        	rename => { "[data][win][eventdata][destinationHostname]" => "destination_hostname" } 
                        }
		}
	} else {
		grok {
			match => ["message", "Alert Level: %{NONNEGINT;alert_level}; Rule: %{NONNEGINT:rule} - %{DATA:description}; Location: %{DATA:location}; user: +%{DATA:username}; %{SYSLOGTIMESTAMP} %{DATA:host} %{DATA:process}\[%{INT:pid}]: %{GREEDYDATA:details}", 
				"message", "Alert Level: %{NONNEGINT:alert_level}; Rule: %{NONNEGINT:rule} - %{DATA:description}; Location: %{DATA:location}; %{SYSLOGTIMESTAMP:timestamp} %{DATA:host} %{DATA:process}\[%{NONNEGINT:pid}]: %{GREEDYDATA:details}",
				"message", "Alert Level: %{NONNEGINT:alert_level}; Rule: %{NONNEGINT:rule} - %{DATA:description}; Location: %{DATA:location}; %{SYSLOGTIMESTAMP} %{DATA:host} %{DATA:process}\[%{NONNEGINT:pid}]: %{GREEDYDATA:details}", 
				"message", "Alert Level: %{NONNEGINT:alert_level}; Rule: %{NONNEGINT:rule} - %{DATA:description}; Location: %{DATA:location}; %{SYSLOGTIMESTAMP:timestamp} %{DATA:host} %{DATA:program}: +%{DATA:username} : TTY=%{DATA:tty} ; PWD=%{DATA:dir} ; USER=%{DATA:escalated_user} ; COMMAND=%{GREEDYDATA:command}", 
				"message", "Alert Level: %{NONNEGINT:alert_level}; Rule: %{NONNEGINT:rule} - %{DATA:description}; Location: %{DATA:location}; %{SYSLOGTIMESTAMP:timestamp} %{DATA:host} %{DATA:program}: %{GREEDYDATA:details}", 
				"message", "Alert Level: %{NONNEGINT:alert_level}; Rule: %{NONNEGINT:rule} - %{DATA:description}; Location: %{DATA:location}; %{SYSLOGTIMESTAMP:timestamp} %{DATA:host} %{DATA:program}: +%{DATA:username} : %{GREEDYDATA:details}",  
				"message", "Alert Level: %{NONNEGINT:alert_level}; Rule: %{NONNEGINT:rule} - %{DATA:description}; Location: %{DATA:location}; srcip: %{IP:source_ip};%{GREEDYDATA:details}", 
				"message", "Alert Level: %{NONNEGINT:alert_level}; Rule: %{NONNEGINT:rule} - %{DATA:description}; Location: %{DATA:location}; %{DATA:username}: %{DATA}: \'%{DATA}': %{DATA:interface}: %{INT:num_packets}",
				"message", "Alert Level: %{NONNEGINT:alert_level}; Rule: %{NONNEGINT:rule} - %{DATA:description}; Location: %{DATA:location}; %{DATA:username}: %{GREEDYDATA:details}.",
				"message", "Alert Level: %{NONNEGINT:alert_Level}; Rule: %{NONNEGINT:Rule} - %{DATA:Description}; Location: %{DATA:location}; user: +%{DATA:username};",
				"message", "Alert Level: %{NONNEGINT:alert_level}; Rule: %{NONNEGINT:rule} - %{DATA:description}; Location: %{DATA:location}; %{DATA}: %{DATA}: \'%{DATA}': %{DATA:interface}: %{NONNEGINT:num_packets}",
				"message", "Alert Level: %{NONNEGINT:alert_level}; Rule: %{NONNEGINT:rule} - %{DATA:description}; Location: %{DATA:location}; %{GREEDYDATA:details}"]
		}
	}
	
	# Add tag for OSSEC alerts
	if [alert_level] {
            mutate {
		add_tag => [ "alert" ]
	    }
        }

	translate {
		field => "alert_level"

		destination => "classification"

		dictionary => [
               	    "1", "None",
		    "2", "System low priority notification",
		    "3", "Successful/authorized event",
		    "4", "System low priority error",
		    "5", "User generated error",
		    "6", "Low relevance attack",
		    "7", '"Bad word" matching',
		    "8", "First time seen",
		    "9", "Error from invalid source",
		    "10", "Multiple user generated errors",
		    "11", "Integrity checking warning",
		    "12", "High importance event",
		    "13", "Unusal error (high importance)",
		    "14", "High importance security event",
		    "15", "Severe attack"
               	]
	}
  }

  # OSSEC Archive Logs
  if [type] == "ossec_archive" {
        
	# Sysmon/Autoruns logs transported by OSSEC
	if [message] =~ "Microsoft-Windows-Sysmon" {
            mutate { 
                replace => { "type" => "sysmon" } 
                add_tag => [ "ossec" ] 
	    }
        }
	if [message] =~ "AR-LOG" {
            mutate { 
                replace => { "type" => "autoruns" } 
                add_tag => [ "ossec" ]
            }
        }

	# If message looks like json, try to parse it as such. Otherwise, grok.
        if [message] =~ /^{.*}$/ {
                json {
                        source => "message"
                }
		mutate {
                        rename => [ "rule", "wazuh-rule" ]
                        rename => [ "[wazuh-rule][level]", "alert_level" ]
                        rename => [ "[wazuh-rule][description]", "description" ]
                        rename => [ "[data][srcuser]", "username" ]
                        rename => [ "[data][dstuser]", "escalated_user" ]
                        rename => [ "[data][command]", "command" ]
                        rename => [ "[predecoder][program_name]", "process" ]
                }
	} else {
		grok {
			match => ["message",'%{YEAR:year} %{SYSLOGTIMESTAMP:timestamp} %{DATA:location} %{IP:source_ip} - %{DATA:username} \[%{DATA:request_timestamp}] "%{DATA:method} %{DATA:requested_resource} %{DATA:protocol}\/%{DATA:protocol_version}" %{NONNEGINT:status_code} %{NONNEGINT:object_size} "%{DATA:referrer}" "%{DATA:user_agent}"',
				"message","%{YEAR:year} %{SYSLOGTIMESTAMP:timestamp} %{DATA:location} %{SYSLOGTIMESTAMP:ossec_timestamp} %{DATA:host} %{DATA:process}\[%{NONNEGINT:pid}]: \(%{DATA:username}\) CMD \(%{DATA:command}\)",
				"message", "%{YEAR:year} %{SYSLOGTIMESTAMP:timestamp} %{DATA:location} %{GREEDYDATA:details}","message","%{YEAR:year} %{SYSLOGTIMESTAMP:timestamp} %{DATA:location} %{SYSLOGTIMESTAMP:ossec_timestamp} %{DATA:ossec_host} %{DATA:process}\[%{NONNEGINT:pid}]: %{GREEDYDATA:details}",
				"message","%{DATA:age} %{DATA:program} %{DATA} '%{DATA:checksum}'",
				"message", "%{DATA:username} : TTY=%{DATA:tty} ; PWD=%{DATA:dir} ; USER=%{DATA:escalated_user} ; COMMAND=%{GREEDYDATA:command}"]
			remove_field => [ "ossec_timestamp" ]
		}
		mutate {
			convert => [ "status_code", "integer" ]
		}
	}
  }
}
