Skip to main content

Analyze Sysmon for Linux logs using Kusto Query Language

Recently I have come across a situation where I need to install Sysmon on a Linux virtual machine in Azure subscription and analyze those logs in Log analytics workspace. This post is a quick guide to help installing Sysmon and analyzing logs using Kusto query language. 

Prerequisites to install Sysmon for Linux 

  • Ensure the Linux virtual machine is on boarded to Log analytics workspace. 
  • Collect Syslog events with Azure Monitor Agent. Install using this

Installing Sysmon on Linux 

For complete installation process on various .nix operating systems, follow Sysmon installation instructions here  

Ubuntu 20.04 & 22.04

  •  Register Microsoft key and feed
    • wget -q https://packages.microsoft.com/config/ubuntu/$(lsb_release -rs)/packages-microsoft-prod.deb -O packages-microsoft-prod.deb
    • sudo dpkg -i packages-microsoft-prod.deb
  •  Install SysmonForLinux
    • sudo apt-get update
    • sudo apt-get install sysmonforlinux

The Kusto query to parse the Sysmon logs on a Linux can be found here. 

let Eventlogs = materialize (Syslog
| where SyslogMessage has "Linux-Sysmon"
| extend Data =parse_xml(SyslogMessage)
| extend System = Data.Event.System, EventDetail=Data.Event.EventData.Data
| extend Provider = tostring(System.Provider.["@Name"]), EventID = toint(System.EventID)
| extend Operation = case(
EventID == 1,
"ProcessCreate. Log all newly created processes",
EventID == 3,
"NetworkConnect Detected. Log all network connections",
EventID == 5,
"ProcessTerminate. Log all processes terminated",
EventID == 9,
"RawAccessRead. Log all raw access read",
EventID == 10,
"ProcessAccess. Log all open process operations",
EventID == 11,
"FileCreate. Log every file creation",
EventID == 23,
"FileDelete. Log all files being deleted",
""
)
| project-away Data, System);
let Linux_SYSMON_CREATE_PROCESS_1=() {
let ProcessCreate = Eventlogs
| where EventID == 1
| extend
RuleName = EventDetail.[0].["#text"],
UtcTime = EventDetail.[1].["#text"],
ProcessGuid = EventDetail.[2].["#text"],
ProcessId = EventDetail.[3].["#text"],
Image = EventDetail.[4].["#text"],
FileVersion = EventDetail.[5].["#text"],
Description = EventDetail.[6].["#text"],
Product = EventDetail.[7].["#text"],
Company = EventDetail.[8].["#text"],
OriginalFileName = EventDetail.[9].["#text"],
CommandLine = EventDetail.[10].["#text"],
CurrentDirectory = EventDetail.[11].["#text"],
User = EventDetail.[12].["#text"],
LogonGuid = EventDetail.[13].["#text"],
LogonId = EventDetail.[14].["#text"],
TerminalSessionId = EventDetail.[15].["#text"],
IntegrityLevel = EventDetail.[16].["#text"],
Hashes = EventDetail.[17].["#text"],
ParentProcessGuid = EventDetail.[18].["#text"],
ParentProcessId = EventDetail.[19].["#text"],
ParentImage = EventDetail.[20].["#text"],
ParentCommandLine = EventDetail.[21].["#text"],
ParentUser=EventDetail.[22].["#text"]
| extend Hashes = extract_all(@"(?P<key>\w+)=(?P<value>[a-zA-Z0-9]+)", dynamic(["key", "value"]), tostring(Hashes))
| mv-apply Hashes on (
summarize ParsedHashes = make_bag(pack(tostring(Hashes[0]), tostring(Hashes[1])))
)
| project-away EventDetail, SyslogMessage;
ProcessCreate;
};
let Linux_SYSMON_NETWORK_CONNECT_3=() {
let processEvents = Eventlogs
| where EventID == 3
| extend
RuleName = EventDetail.[0].["#text"],
UtcTime = EventDetail.[1].["#text"],
ProcessGuid = EventDetail.[2].["#text"],
ProcessId = EventDetail.[3].["#text"],
Image = EventDetail.[4].["#text"],
User = EventDetail.[5].["#text"],
Protocol = EventDetail.[6].["#text"],
Initiated = EventDetail.[7].["#text"],
SourceIsIpv6 = EventDetail.[8].["#text"],
SourceIp = EventDetail.[9].["#text"],
SourceHostname = EventDetail.[10].["#text"],
SourcePort = EventDetail.[11].["#text"],
SourcePortName = EventDetail.[12].["#text"],
DestinationIsIpv6 = EventDetail.[13].["#text"],
DestinationIp = EventDetail.[14].["#text"],
DestinationHostname = EventDetail.[15].["#text"],
DestinationPort = EventDetail.[16].["#text"],
DestinationPortName = EventDetail.[17].["#text"]
| project-away EventDetail, SyslogMessage;
processEvents;
};
let Linux_SYSMON_PROCESS_TERMINATE_5=() {
let processEvents = Eventlogs
| where EventID == 5
| extend
RuleName = EventDetail.[0].["#text"],
UtcTime = EventDetail.[1].["#text"],
ProcessGuid = EventDetail.[2].["#text"],
ProcessId = EventDetail.[3].["#text"],
Image = EventDetail.[4].["#text"]
| project-away EventDetail, SyslogMessage;
processEvents;
};
let Linux_SYSMON_RAWACCESS_READ_9=() {
let processEvents = Eventlogs
| where EventID == 9
| extend
RuleName = EventDetail.[0].["#text"],
UtcTime = EventDetail.[1].["#text"],
ProcessGuid = EventDetail.[2].["#text"],
ProcessId = EventDetail.[3].["#text"],
Image = EventDetail.[4].["#text"],
Device = EventDetail.[5].["#text"]
| project-away EventDetail, SyslogMessage;
processEvents;
};
let linunx_SYSMON_ACCESS_PROCESS_10=() {
let processEvents = Eventlogs
| where EventID == 10
| extend
RuleName = EventDetail.[0].["#text"],
UtcTime = EventDetail.[1].["#text"],
SourceProcessGUID = EventDetail.[2].["#text"],
SourceProcessId = EventDetail.[3].["#text"],
SourceThreadId = EventDetail.[4].["#text"],
SourceImage = EventDetail.[5].["#text"],
TargetProcessGUID = EventDetail.[6].["#text"],
TargetProcessId = EventDetail.[7].["#text"],
TargetImage = EventDetail.[8].["#text"],
GrantedAccess = EventDetail.[9].["#text"],
CallTrace = EventDetail.[10].["#text"]
| project-away EventDetail, SyslogMessage;
processEvents;
};
let linux_SYSMON_FILE_CREATE_11=() {
let processEvents = Eventlogs
| where EventID == 11
| extend
RuleName = EventDetail.[0].["#text"],
UtcTime = EventDetail.[1].["#text"],
ProcessGuid = EventDetail.[2].["#text"],
ProcessId = EventDetail.[3].["#text"],
Image = EventDetail.[4].["#text"],
TargetFilename = EventDetail.[5].["#text"],
CreationUtcTime = EventDetail.[6].["#text"]
| project-away EventDetail, SyslogMessage;
processEvents;
};
let Linux_SYSMON_FILE_DELETE_23=() {
let processEvents = Eventlogs
| where EventID == 23
| extend
RuleName = EventDetail.[0].["#text"],
UtcTime = EventDetail.[1].["#text"],
ProcessGuid = EventDetail.[2].["#text"],
ProcessId = EventDetail.[3].["#text"],
User = EventDetail.[4].["#text"],
Image = EventDetail.[5].["#text"],
TargetFilename = EventDetail.[6].["#text"],
Hashes = EventDetail.[7].["#text"],
IsExecutable = EventDetail.[8].["#text"],
Archived = EventDetail.[9].["#text"]
| extend Hashes = extract_all(@"(?P<key>\w+)=(?P<value>[a-zA-Z0-9]+)", dynamic(["key", "value"]), tostring(Hashes))
| mv-apply Hashes on (
summarize ParsedHashes = make_bag(pack(tostring(Hashes[0]), tostring(Hashes[1])))
)
| project-away EventDetail, SyslogMessage;
processEvents;
};
(union isfuzzy=true
Linux_SYSMON_CREATE_PROCESS_1,
Linux_SYSMON_NETWORK_CONNECT_3,
Linux_SYSMON_PROCESS_TERMINATE_5,
Linux_SYSMON_RAWACCESS_READ_9,
linunx_SYSMON_ACCESS_PROCESS_10,
linux_SYSMON_FILE_CREATE_11,
Linux_SYSMON_FILE_DELETE_23)
| extend
Details = column_ifexists("Details", ""),
RuleName = column_ifexists("RuleName", ""),
PreviousCreationUtcTime=column_ifexists("PreviousCreationUtcTime", ""),
Hashes = column_ifexists("Hashes", "")
| project
EventID,
UtcTime,
Description,
RuleName,
ProcessGuid,
ProcessId,
Image,
FileVersion,
Product,
Company,
OriginalFileName,
CommandLine,
CurrentDirectory,
User,
LogonGuid,
LogonId,
TerminalSessionId,
IntegrityLevel,
Hashes,
ParsedHashes,
ParentProcessGuid,
ParentProcessId,
ParentImage,
ParentCommandLine,
TargetFilename,
CreationUtcTime,
PreviousCreationUtcTime,
Protocol,
Initiated,
SourceIsIpv6,
SourceIp,
SourceHostname,
SourcePort,
SourcePortName,
DestinationIsIpv6,
DestinationIp,
DestinationHostname,
DestinationPort,
DestinationPortName,
SourceProcessId,
SourceImage,
TargetProcessId,
TargetImage,
Device,
SourceProcessGUID,
SourceThreadId,
TargetProcessGUID,
GrantedAccess,
CallTrace,
Details,
Operation,
Type,
IsExecutable,
Archived

References

Comments

Popular posts from this blog

Memory Analysis of WannaCry Ransomware

Introduction  This post explains the memory dump analysis of WannaCry infected system using volatility (An open source memory forensics framework) and other open source tools. It doesn't cover the analysis of initial infection vector, propagation and recovery of infected system. The objective is to leverage memory forensic analysis to uncover and extract Indicators of Compromise (IoC)  WannaCry  WannaCry (or WannaCrypt, WanaCrypt0r 2.0, Wanna Decryptor) is a ransomware program targeting the Microsoft Windows operating system. On Friday, 12 May 2017, a large cyber-attack using it was launched, infecting more than 230,000 computers in 150 countries, demanding ransom payments in the cryptocurrency bitcoin in 28 languages.The attack has been described by Europol as unprecedented in scale. https://en.wikipedia.org/wiki/WannaCry_ransomware_attack Discalimer You are dealing with real malware samples Don’t expose them to internal networks or internet Analyze them in a...
Dionaea – A Malware collection honeypot Introduction  This post outlines the necessary requirements, configurations and step by step installation procedure for honeypot Dionaea. It also briefs the logging of various attacks from external entities and produces the results to a dashboard interface feature for ease of understanding. Dionaea Dionaea is one of the modern malware collection honeypots that’s aimed to trap malware exploiting vulnerabilities exposed by services offered over a network to obtain a copy of malware. Dionaea emulates protocols by embedding python as its scripting language and also detects shellcodes using LibEmu. It also supports IPv6 and TLS. Dionaea traps malware from below mentioned protocols. • SMB (Server Message Block):  • HTTP (Hyper Text Transfer Protocol) • FTP (File Transfer Protocol) • TFTP (Trivial File Transfer Protocol)  • MSSQL (Microsoft SQL Server)  • VoIP (Voice over IP)  Requirements...