Detection rules › Kusto
Detect Local File Inclusion(LFI) in web requests (ASIM Web Session)
'LFI vulnerabilities allow an attacker to read (and sometimes execute) files on the victim machine. This can be very dangerous because if the web server is misconfigured and running with high privileges, the attacker may gain access to sensitive information'
MITRE ATT&CK coverage
| Tactic | Techniques |
|---|---|
| Initial Access | T1133 External Remote Services, T1190 Exploit Public-Facing Application |
| Execution | T1059 Command and Scripting Interpreter |
Rule body kusto
id: 7bb55d05-ef39-4a40-8079-0bc3c05e7881
name: Detect Local File Inclusion(LFI) in web requests (ASIM Web Session)
description: |
'LFI vulnerabilities allow an attacker to read (and sometimes execute) files on the victim machine. This can be very dangerous because if the web server is misconfigured and running with high privileges, the attacker may gain access to sensitive information'
severity: High
status: Available
tags:
- Schema: WebSession
SchemaVersion: 0.2.6
requiredDataConnectors: []
queryFrequency: 5m
queryPeriod: 5m
triggerOperator: gt
triggerThreshold: 0
tactics:
- InitialAccess
- Execution
relevantTechniques:
- T1190
- T1133
- T1059
query: |
let lookback = 5m;
let LFI_Indicators = materialize(externaldata(Indicators: string)
[@"https://raw.githubusercontent.com/Azure/Azure-Sentinel/master/Sample%20Data/Feeds/LocalFileInclusionIndicators.csv"]
with(format="csv", ignoreFirstRecord=True));
let CustomLocalFileInclusionIndicators = (_ASIM_GetWatchlistRaw("Web_LocalFileInclusionIndicators") // Create new Watchlist and add your custom indicators(Optional)
| extend
Indicators = tostring(WatchlistItem["Indicators"])
| project Indicators
| where isnotempty(Indicators));
let CombinedLFIList = union LFI_Indicators, CustomLocalFileInclusionIndicators;
let knownLFIIndicators=toscalar(CombinedLFIList
| where isnotempty(Indicators)
| summarize make_set(Indicators, 1000));
_Im_WebSession(starttime=ago(lookback), url_has_any=knownLFIIndicators, eventresult='Success')
| where isnotempty(Url)
| project Url, SrcIpAddr, SrcUsername, SrcHostname, TimeGenerated
| extend Decoded_url = url_decode(Url)
| where Decoded_url has_any (knownLFIIndicators)
| summarize
EventCount=count(),
EventStartTime=min(TimeGenerated),
EventEndTime=max(TimeGenerated)
by SrcIpAddr, SrcUsername, SrcHostname, Url, Decoded_url
| extend
Name = iif(SrcUsername contains "@", tostring(split(SrcUsername, '@', 0)[0]), SrcUsername),
UPNSuffix = iif(SrcUsername contains "@", tostring(split(SrcUsername, '@', 1)[0]), "")
| order by EventCount desc
entityMappings:
- entityType: IP
fieldMappings:
- identifier: Address
columnName: SrcIpAddr
- entityType: URL
fieldMappings:
- identifier: Url
columnName: Url
- entityType: Account
fieldMappings:
- identifier: Name
columnName: Name
- identifier: UPNSuffix
columnName: UPNSuffix
- entityType: Host
fieldMappings:
- identifier: HostName
columnName: SrcHostname
eventGroupingSettings:
aggregationKind: AlertPerResult
customDetails:
EventCount: EventCount
Decoded_url: Decoded_url
EventStartTime: EventStartTime
EventEndTime: EventEndTime
alertDetailsOverride:
alertDisplayNameFormat: "Potential Local File Inlcusion(LFI) performed by user '{{SrcUsername}}' from IP '{{SrcIpAddr}}'"
alertDescriptionFormat: "User requested for URL '{{Url}}' which contains LFI related keywords or indicators. It suggests an attempt to traverse directories and access files outside the intended directory structure"
version: 1.0.0
kind: Scheduled
Stages and Predicates
Parameters
let lookback = 5m;
let CombinedLFIList = union LFI_Indicators, CustomLocalFileInclusionIndicators;
Let binding: LFI_Indicators
let LFI_Indicators = materialize(externaldata(Indicators: string)
[@"https://raw.githubusercontent.com/Azure/Azure-Sentinel/master/Sample%20Data/Feeds/LocalFileInclusionIndicators.csv"]
with(format="csv", ignoreFirstRecord=True));
Let binding: CustomLocalFileInclusionIndicators
let CustomLocalFileInclusionIndicators = (_ASIM_GetWatchlistRaw("Web_LocalFileInclusionIndicators")
| extend
Indicators = tostring(WatchlistItem["Indicators"])
| project Indicators
| where isnotempty(Indicators));
Let binding: knownLFIIndicators
let knownLFIIndicators = toscalar(CombinedLFIList
| where isnotempty(Indicators)
| summarize make_set(Indicators, 1000));
Derived from CombinedLFIList.
Stage 1: source
_Im_WebSession(starttime=ago(lookback), url_has_any=knownLFIIndicators, eventresult='Success')
Stage 2: where
| where isnotempty(Url)
Stage 3: project
| project Url, SrcIpAddr, SrcUsername, SrcHostname, TimeGenerated
Stage 4: extend
| extend Decoded_url = url_decode(Url)
Stage 5: where
| where Decoded_url has_any (knownLFIIndicators)
References knownLFIIndicators (defined above).
Stage 6: summarize
| summarize
EventCount=count(),
EventStartTime=min(TimeGenerated),
EventEndTime=max(TimeGenerated)
by SrcIpAddr, SrcUsername, SrcHostname, Url, Decoded_url
Stage 7: extend
| extend
Name = iif(SrcUsername contains "@", tostring(split(SrcUsername, '@', 0)[0]), SrcUsername),
UPNSuffix = iif(SrcUsername contains "@", tostring(split(SrcUsername, '@', 1)[0]), "")
Stage 8: sort
| order by EventCount desc
Indicators
Each row is a field, operator, and value that the rule matches. The corpus column counts how many other rules in the catalog look for the same combination: high numbers point to widely-used, community-vetted indicators. Blank or 1 shows that the indicator is specific to this rule.
| Field | Kind | Values |
|---|---|---|
Decoded_url | match |
|
Url | is_not_null |
Output fields
Fields the rule emits when it matches. Chronicle authors list these in the outcome block; they appear on the detection and $risk_score drives alerting. Sentinel / Defender XDR rules build them up through project / summarize / extend stages. Sentinel maps these into alert fields via entityMappings and customDetails; Defender XDR custom detections surface them as alert fields directly.
| Field | Source |
|---|---|
Decoded_url | summarize |
EventCount | summarize |
EventEndTime | summarize |
EventStartTime | summarize |
SrcHostname | summarize |
SrcIpAddr | summarize |
SrcUsername | summarize |
Url | summarize |
Name | extend |
UPNSuffix | extend |