Detection rules › Kusto
Potential Fodhelper UAC Bypass
This detection looks for the steps required to conduct a UAC bypass using Fodhelper.exe. By default this detection looks for the setting of the required registry keys and the invoking of the process within 1 hour - this can be tweaked as required.
MITRE ATT&CK coverage
| Tactic | Techniques |
|---|---|
| Privilege Escalation |
Telemetry coverage
Rule body
id: 56f3f35c-3aca-4437-a1fb-b7a84dc4af00
name: Potential Fodhelper UAC Bypass
description: |
'This detection looks for the steps required to conduct a UAC bypass using Fodhelper.exe. By default this detection looks for the setting of the required registry keys and the invoking of the process within 1 hour - this can be tweaked as required.'
severity: Medium
requiredDataConnectors:
- connectorId: SecurityEvents
dataTypes:
- SecurityEvent
- connectorId: WindowsSecurityEvents
dataTypes:
- SecurityEvent
queryFrequency: 2h
queryPeriod: 2h
triggerOperator: gt
triggerThreshold: 0
status: Available
tactics:
- PrivilegeEscalation
relevantTechniques:
- T1548.002
query: |
SecurityEvent
| where EventID == 4657
| parse ObjectName with "\\REGISTRY\\" KeyPrefix "\\" RegistryKey
| project-reorder RegistryKey
| where RegistryKey has "Software\\Classes\\ms-settings\\shell\\open\\command"
| extend TimeKey = bin(TimeGenerated, 1h)
| join (
SecurityEvent
| where EventID == 4688
| where Process =~ "fodhelper.exe"
| where ParentProcessName endswith "cmd.exe" or ParentProcessName endswith "powershell.exe" or ParentProcessName endswith "powershell_ise.exe"
| extend TimeKey = bin(TimeGenerated, 1h)) on TimeKey, Computer
| extend HostName = tostring(split(Computer, ".")[0]), DomainIndex = toint(indexof(Computer, '.'))
| extend HostNameDomain = iff(DomainIndex != -1, substring(Computer, DomainIndex + 1), Computer)
| extend AccountName = tostring(split(TargetAccount, @'\')[1]), AccountNTDomain = tostring(split(TargetAccount, @'\')[0])
entityMappings:
- entityType: Host
fieldMappings:
- identifier: FullName
columnName: Computer
- identifier: HostName
columnName: HostName
- identifier: DnsDomain
columnName: HostNameDomain
- entityType: Account
fieldMappings:
- identifier: FullName
columnName: TargetAccount
- identifier: Name
columnName: AccountName
- identifier: NTDomain
columnName: AccountNTDomain
version: 1.0.2
kind: Scheduled
Stages and Predicates
Stage 1: source
SecurityEvent
Stage 2: where
| where EventID == 4657
Stage 3: parse
| parse ObjectName with "\\REGISTRY\\" KeyPrefix "\\" RegistryKey
Stage 4: project-reorder
| project-reorder RegistryKey
Stage 5: where
| where RegistryKey has "Software\\Classes\\ms-settings\\shell\\open\\command"
Stage 6: extend
| extend TimeKey = bin(TimeGenerated, 1h)
Stage 7: join
| join (
SecurityEvent
| where EventID == 4688
| where Process =~ "fodhelper.exe"
| where ParentProcessName endswith "cmd.exe" or ParentProcessName endswith "powershell.exe" or ParentProcessName endswith "powershell_ise.exe"
| extend TimeKey = bin(TimeGenerated, 1h)) on TimeKey, Computer
Stage 8: extend (3 consecutive steps)
| extend HostName = tostring(split(Computer, ".")[0]), DomainIndex = toint(indexof(Computer, '.'))
| extend HostNameDomain = iff(DomainIndex != -1, substring(Computer, DomainIndex + 1), Computer)
| extend AccountName = tostring(split(TargetAccount, @'\')[1]), AccountNTDomain = tostring(split(TargetAccount, @'\')[0])
Indicators
These rows show field, operator, and value matches.
| Field | Kind | Values | Search |
|---|---|---|---|
EventID | eq |
| field:"EventID" kind:eq |
ParentProcessName | ends_with |
| field:"ParentImage" kind:ends_with |
Process | eq |
| field:"Process" kind:eq value:"fodhelper.exe" |
RegistryKey | match |
| field:"TargetObject" kind:match value:"Software\Classes\ms-settings\shell\open\command" |
Output fields
These fields are emitted when the rule matches.
| Field | Source |
|---|---|
TimeKey | extend |
DomainIndex | extend |
HostName | extend |
HostNameDomain | extend |
AccountNTDomain | extend |
AccountName | extend |