Detection rules › Kusto

Spearphishing Attachment: ISO Images (Microsoft Sentinel)

Author
Cyb3rMonk
Source
github.com/Cyb3r-Monk/Threat-Hunting-and-Detection

ISO images are often meant to be used offline and they are often used by IT Admins and/or used on Servers.
Installation from an iso file don't require network connection most of the time. Activities deviating from these situations can be considered as highly suspicious. Below queries detects opening a mounted image, process creation under a mounted image, and network connection from a process created under a mounted image.
All detections can be used seperately or combined together to generate a higher fidelity alert. WARNING: Check your Sysmon parsing functions and verify you have the logs. Using "Rendered Description" field for parsing causes parsing issues for registry events. Detect opening of a mounted image:

MITRE ATT&CK coverage

TacticTechniques
Initial AccessNo specific technique

Telemetry coverage

Rule body

// Author: Cyb3rMonk(https://twitter.com/Cyb3rMonk, https://mergene.medium.com)
// Link to original post:
// Part-1: https://mergene.medium.com/detecting-initial-access-html-smuggling-and-iso-images-part-1-c4f953edd13f?source=friends_link&sk=e685d7d44928edd142972a4041463f10
// Part-2: https://mergene.medium.com/detecting-initial-access-html-smuggling-and-iso-images-part-2-f8dd600430e2?source=friends_link&sk=38b7cd310a4929c25d3eefc545683d5f
//
//
let parse_sysmon_events = (T:(TimeGenerated:datetime,EventID:int, Source:string, EventData:string))
{
T 
| where Source == "Microsoft-Windows-Sysmon"
| extend EventData = parse_xml(EventData).DataItem.EventData.Data
| mv-expand bagexpansion=array EventData
| evaluate bag_unpack(EventData)
| extend Key=tostring(['@Name']), Value=['#text']
| evaluate pivot(Key, any(Value), TimeGenerated, Source, EventLog, Computer, EventLevel, EventLevelName, EventID, UserName, RenderedDescription, MG, ManagementGroupName, Type, _ResourceId)
};
// Query Parameters
let lookback = 2h;
Event
| where TimeGenerated > ago(lookback)
| where EventID == 11
| invoke parse_sysmon_events()
| where tostring(TargetFilename) endswith ".iso.lnk" or tostring(TargetFilename) endswith ".img.lnk"
// Exclude servers and workstation used by IT admins if needed.

// Author: Cyb3rMonk(https://twitter.com/Cyb3rMonk, https://mergene.medium.com)
// Link to original post:
// Part-1: https://mergene.medium.com/detecting-initial-access-html-smuggling-and-iso-images-part-1-c4f953edd13f?source=friends_link&sk=e685d7d44928edd142972a4041463f10
// Part-2: https://mergene.medium.com/detecting-initial-access-html-smuggling-and-iso-images-part-2-f8dd600430e2?source=friends_link&sk=38b7cd310a4929c25d3eefc545683d5f
//
//
let parse_sysmon_events = (T:(TimeGenerated:datetime,EventID:int, Source:string, EventData:string))
{
T 
| where Source == "Microsoft-Windows-Sysmon"
| extend EventData = parse_xml(EventData).DataItem.EventData.Data
| mv-expand bagexpansion=array EventData
| evaluate bag_unpack(EventData)
| extend Key=tostring(['@Name']), Value=['#text']
| evaluate pivot(Key, any(Value), TimeGenerated, Source, EventLog, Computer, EventLevel, EventLevelName, EventID, UserName, RenderedDescription, MG, ManagementGroupName, Type, _ResourceId)
};
// Query Parameters
let lookback = 2h;
Event
| where TimeGenerated > ago(lookback)
| where EventID == 13
| invoke parse_sysmon_events()
| where TargetObject startswith @"HKLM\SYSTEM\MountedDevices\\DosDevices"
| extend Folder = replace(@'.*\\([A-Z]:)',@'\1\\',tostring(TargetObject))
| join kind = inner 
    (
    Event
    | where TimeGenerated > ago(lookback)
    | where EventID == 1
    | invoke parse_sysmon_events()
    | extend Folder = tostring(CurrentDirectory)
    ) on Computer, Folder
// If needed, exclude servers from the results.

// Author: Cyb3rMonk(https://twitter.com/Cyb3rMonk, https://mergene.medium.com)
// Link to original post:
// Part-1: https://mergene.medium.com/detecting-initial-access-html-smuggling-and-iso-images-part-1-c4f953edd13f?source=friends_link&sk=e685d7d44928edd142972a4041463f10
// Part-2: https://mergene.medium.com/detecting-initial-access-html-smuggling-and-iso-images-part-2-f8dd600430e2?source=friends_link&sk=38b7cd310a4929c25d3eefc545683d5f
//
//
let parse_sysmon_events = (T:(TimeGenerated:datetime,EventID:int, Source:string, EventData:string))
{
T 
| where Source == "Microsoft-Windows-Sysmon"
| extend EventData = parse_xml(EventData).DataItem.EventData.Data
| mv-expand bagexpansion=array EventData
| evaluate bag_unpack(EventData)
| extend Key=tostring(['@Name']), Value=['#text']
| evaluate pivot(Key, any(Value), TimeGenerated, Source, EventLog, Computer, EventLevel, EventLevelName, EventID, UserName, RenderedDescription, MG, ManagementGroupName, Type, _ResourceId)
};
// Query Parameters
let lookback = 30h;
Event
| where TimeGenerated > ago(lookback)
| where EventID == 13
| invoke parse_sysmon_events()
| where TargetObject startswith @"HKLM\SYSTEM\MountedDevices\\DosDevices"
| extend Folder = replace(@'.*\\([A-Z]:)',@'\1\\',tostring(TargetObject))
| join kind = inner 
    (
    Event
    | where TimeGenerated > ago(lookback)
    | where EventID == 3
    | invoke parse_sysmon_events()
    | extend Folder = replace(@'^([A-Z]:\\).*',@'\1',tostring(Image))
    ) on Computer, Folder
// If needed, exclude the legitimate activity and servers

Stages and Predicates

Parameters

let lookback = 2h;

Let binding: parse_sysmon_events

let parse_sysmon_events = (T:(TimeGenerated:datetime,EventID:int, Source:string, EventData:string))
{
T 
| where Source == "Microsoft-Windows-Sysmon"
| extend EventData = parse_xml(EventData).DataItem.EventData.Data
| mv-expand bagexpansion=array EventData
| evaluate bag_unpack(EventData)
| extend Key=tostring(['@Name']), Value=['#text']
| evaluate pivot(Key, any(Value), TimeGenerated, Source, EventLog, Computer, EventLevel, EventLevelName, EventID, UserName, RenderedDescription, MG, ManagementGroupName, Type, _ResourceId)
};

Stage 1: source

Event

Stage 2: where

where TimeGenerated > ago(7200s)

Stage 3: where

where EventID == 11

Stage 4: where

where Source =~ "Microsoft-Windows-Sysmon"

Stage 5: extend

extend EventData

Stage 6: mv-expand

mv-expand EventData

Stage 7: evaluate

evaluate

Stage 8: extend

extend Key, Value

Stage 9: evaluate

evaluate

Stage 10: where

where (TargetFilename endswith ".img.lnk" or TargetFilename endswith ".iso.lnk")

Stage 11: source

Event

Stage 12: where

where TimeGenerated > ago(7200s)

Stage 13: where

where EventID == 13

Stage 14: where

where Source =~ "Microsoft-Windows-Sysmon"

Stage 15: extend

extend EventData

Stage 16: mv-expand

mv-expand EventData

Stage 17: evaluate

evaluate

Stage 18: extend

extend Key, Value

Stage 19: evaluate

evaluate

Stage 20: where

where TargetObject startswith @"HKLM\SYSTEM\MountedDevices\\DosDevices"

Stage 21: extend

extend Folder

Stage 22: join

join kind=inner (Event) on Computer, Folder

Stage 23: source

Event

Stage 24: where

where TimeGenerated > ago(108000s)

Stage 25: where

where EventID == 13

Stage 26: where

where Source =~ "Microsoft-Windows-Sysmon"

Stage 27: extend

extend EventData

Stage 28: mv-expand

mv-expand EventData

Stage 29: evaluate

evaluate

Stage 30: extend

extend Key, Value

Stage 31: evaluate

evaluate

Stage 32: where

where TargetObject startswith @"HKLM\SYSTEM\MountedDevices\\DosDevices"

Stage 33: extend

extend Folder

Stage 34: join

join kind=inner (Event) on Computer, Folder

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
EventIDeq
  • 1 corpus 241 (splunk 225, kusto 15, elastic 1)
  • 11 corpus 26 (splunk 24, kusto 2)
  • 13 corpus 23 (splunk 18, kusto 5)
  • 3 corpus 24 (splunk 14, kusto 8, chronicle 2)
field:"EventID" kind:eq
TargetFilenameends_with
  • .img.lnk transforms: tostring corpus 2 (sigma 1, kusto 1)
  • .iso.lnk transforms: tostring corpus 2 (sigma 1, kusto 1)
field:"TargetFilename" kind:ends_with
TargetObjectstarts_with
  • HKLM\SYSTEM\MountedDevices\\DosDevices
field:"TargetObject" kind:starts_with value:"HKLM\SYSTEM\MountedDevices\\DosDevices"

Output fields

These fields are emitted when the rule matches.

FieldSource
EventDataextend
Keyextend
Valueextend