mirror of
https://github.com/marcredhat/kql
synced 2026-06-08 21:27:09 +00:00
Initial commit: KQL ↔ SDL PowerQuery proof of equivalence
This commit is contained in:
@@ -0,0 +1,22 @@
|
||||
SigninLogs
|
||||
| where TimeGenerated > ago(1d)
|
||||
| extend locationString = strcat(tostring(LocationDetails["countryOrRegion"]), "/",
|
||||
tostring(LocationDetails["state"]), "/",
|
||||
tostring(LocationDetails["city"]), ";")
|
||||
| project TimeGenerated, AppDisplayName, UserPrincipalName, locationString
|
||||
| make-series dLocationCount = dcount(locationString) on TimeGenerated step 1d
|
||||
by UserPrincipalName, AppDisplayName
|
||||
| extend (RSquare, Slope, Variance, RVariance, Interception, LineFit)
|
||||
= series_fit_line(dLocationCount)
|
||||
| top 3 by Slope desc
|
||||
| join kind=inner (
|
||||
SigninLogs
|
||||
| extend locationString = strcat(tostring(LocationDetails["countryOrRegion"]),
|
||||
"/", tostring(LocationDetails["state"]), "/",
|
||||
tostring(LocationDetails["city"]), ";")
|
||||
| summarize locationList = makeset(locationString),
|
||||
threeDayWindowLocationCount = dcount(locationString)
|
||||
by AppDisplayName, UserPrincipalName, timerange = bin(TimeGenerated, 21d)
|
||||
) on AppDisplayName, UserPrincipalName
|
||||
| project timerange, AppDisplayName, UserPrincipalName,
|
||||
threeDayWindowLocationCount, locationList
|
||||
@@ -0,0 +1,13 @@
|
||||
let auditLookback = ago(14d);
|
||||
let baseline = AuditLogs
|
||||
| where TimeGenerated between(auditLookback..ago(1d))
|
||||
| extend InitiatedByApp = tostring(parse_json(tostring(InitiatedBy.app)).displayName)
|
||||
| where isnotempty(InitiatedByApp)
|
||||
| summarize by OperationName, InitiatedByApp;
|
||||
AuditLogs
|
||||
| where TimeGenerated >= ago(1d)
|
||||
| extend InitiatedByApp = tostring(parse_json(tostring(InitiatedBy.app)).displayName)
|
||||
| extend InitiatedByUser = tostring(parse_json(tostring(InitiatedBy.user)).userPrincipalName)
|
||||
| extend Actor = iff(isnotempty(InitiatedByApp), InitiatedByApp, InitiatedByUser)
|
||||
| where isnotempty(Actor)
|
||||
| join kind=leftanti baseline on $left.OperationName == $right.OperationName
|
||||
@@ -0,0 +1,11 @@
|
||||
let SensitiveOps = dynamic([
|
||||
"microsoft.compute/snapshots/write",
|
||||
"microsoft.network/networksecuritygroups/write",
|
||||
"microsoft.storage/storageaccounts/listkeys/action"]);
|
||||
let threshold = 5;
|
||||
AzureActivity
|
||||
| where OperationNameValue in~ (SensitiveOps)
|
||||
| where ActivityStatusValue =~ "Success"
|
||||
| where TimeGenerated >= ago(1d)
|
||||
| summarize ActivityCount = count() by CallerIpAddress, Caller, OperationNameValue
|
||||
| where ActivityCount >= threshold
|
||||
@@ -0,0 +1,10 @@
|
||||
SigninLogs
|
||||
| where TimeGenerated > ago(1d)
|
||||
| extend locationString = strcat(tostring(LocationDetails["countryOrRegion"]), "/",
|
||||
tostring(LocationDetails["state"]), "/", tostring(LocationDetails["city"]), ";")
|
||||
| extend Day = format_datetime(TimeGenerated, "yyyy-MM-dd")
|
||||
| summarize LocationList = make_set(locationString),
|
||||
LocationCount = dcount(locationString),
|
||||
DistinctSourceIp = dcount(IPAddress),
|
||||
LogonCount = count()
|
||||
by Day, AppDisplayName, UserPrincipalName
|
||||
@@ -0,0 +1,7 @@
|
||||
CommonSecurityLog
|
||||
| where TimeGenerated > ago(1d)
|
||||
| summarize Count = count(),
|
||||
DistinctDestinationIps = dcount(DestinationIP),
|
||||
NoofBytesTransferred = sum(SentBytes),
|
||||
NoofBytesReceived = sum(ReceivedBytes)
|
||||
by SourceIP, DeviceVendor
|
||||
@@ -0,0 +1,9 @@
|
||||
SecurityEvent
|
||||
| where TimeGenerated > ago(1d)
|
||||
| where EventID == 4688
|
||||
| summarize Count = count(),
|
||||
DistinctComputers = dcount(Computer),
|
||||
DistinctAccounts = dcount(Account),
|
||||
DistinctParent = dcount(ParentProcessName),
|
||||
NoofCommandLines = dcount(CommandLine)
|
||||
by NewProcessName
|
||||
@@ -0,0 +1,9 @@
|
||||
let timeframe = 1d; let lookback = 7d;
|
||||
let Recent = SigninLogs | where TimeGenerated > ago(timeframe) | where ResultType == 0;
|
||||
let Baseline = SigninLogs
|
||||
| where TimeGenerated between(ago(lookback + timeframe) .. ago(timeframe))
|
||||
| where ResultType == 0
|
||||
| summarize by AppDisplayName, UserAgent;
|
||||
Recent
|
||||
| join kind=leftanti Baseline on AppDisplayName, UserAgent
|
||||
| project TimeGenerated, UserPrincipalName, AppDisplayName, UserAgent
|
||||
@@ -0,0 +1,9 @@
|
||||
let IP_Indicators = ThreatIntelIndicators
|
||||
| extend IndicatorType = tostring(split(ObservableKey, ":", 0)[0])
|
||||
| where IndicatorType in ("ipv4-addr", "ipv6-addr", "network-traffic")
|
||||
| where IsActive == true;
|
||||
IP_Indicators
|
||||
| join kind=innerunique (
|
||||
CommonSecurityLog | where TimeGenerated >= ago(1h)
|
||||
) on $left.ObservableValue == $right.DestinationIP
|
||||
| project TimeGenerated, SourceIP, DestinationIP, Id, Confidence, DeviceVendor
|
||||
@@ -0,0 +1,8 @@
|
||||
let baseline = SecurityEvent
|
||||
| where TimeGenerated between (ago(14d) .. ago(1d))
|
||||
| where EventID == 4688
|
||||
| summarize by FileName = tostring(split(NewProcessName, '\\')[-1]);
|
||||
SecurityEvent
|
||||
| where TimeGenerated >= ago(1d) | where EventID == 4688
|
||||
| extend FileName = tostring(split(NewProcessName, '\\')[-1])
|
||||
| join kind=leftanti baseline on FileName
|
||||
@@ -0,0 +1,14 @@
|
||||
let threshold = 25;
|
||||
let baseline = OfficeActivity
|
||||
| where TimeGenerated between(ago(14d) .. ago(1d))
|
||||
| where RecordType == "SharePointFileOperation"
|
||||
| where Operation in ("FileDownloaded", "FileUploaded")
|
||||
| summarize Count = count() by UserId, Operation, Site_Url, ClientIP
|
||||
| summarize AvgCount = avg(Count) by UserId, Operation, Site_Url, ClientIP;
|
||||
let recent = OfficeActivity
|
||||
| where TimeGenerated > ago(1d)
|
||||
| where RecordType == "SharePointFileOperation"
|
||||
| summarize RecentCount = count() by UserId, Operation, Site_Url, ClientIP;
|
||||
baseline | join kind=inner (recent) on UserId, Operation, Site_Url, ClientIP
|
||||
| extend Deviation = abs(RecentCount - AvgCount) / AvgCount
|
||||
| where Deviation > threshold
|
||||
@@ -0,0 +1,11 @@
|
||||
let TotalEventsThreshold = 30; let PercentBeaconThreshold = 80;
|
||||
CommonSecurityLog
|
||||
| where DeviceVendor == "Palo Alto Networks" and Activity == "TRAFFIC"
|
||||
| where TimeGenerated > ago(1d)
|
||||
| sort by SourceIP asc, TimeGenerated asc
|
||||
| serialize | extend nextT = next(TimeGenerated, 1), nextIP = next(SourceIP, 1)
|
||||
| extend Delta = datetime_diff('second', nextT, TimeGenerated)
|
||||
| where SourceIP == nextIP and Delta > 25
|
||||
| summarize TotalEvents = count(), ModalDelta = arg_max(count(), Delta)
|
||||
by SourceIP, DestinationIP, DestinationPort
|
||||
| where TotalEvents > TotalEventsThreshold
|
||||
@@ -0,0 +1,13 @@
|
||||
let baseline = SecurityEvent
|
||||
| where TimeGenerated between (ago(14d) .. ago(1d))
|
||||
| where EventID in (4624, 4625)
|
||||
| where LogonTypeName in~ ("2 - Interactive", "10 - RemoteInteractive")
|
||||
| where AccountType =~ "User"
|
||||
| extend HourOfLogin = hourofday(TimeGenerated)
|
||||
| summarize MaxHour = max(HourOfLogin), MinHour = min(HourOfLogin) by TargetUserName;
|
||||
SecurityEvent
|
||||
| where TimeGenerated >= ago(1d) | where EventID in (4624, 4625)
|
||||
| where LogonTypeName in~ ("2 - Interactive", "10 - RemoteInteractive")
|
||||
| extend HourOfLogin = hourofday(TimeGenerated)
|
||||
| join kind=inner baseline on TargetUserName
|
||||
| where HourOfLogin > MaxHour or HourOfLogin < MinHour
|
||||
@@ -0,0 +1,7 @@
|
||||
DeviceFileEvents
|
||||
| where FileName endswith ".docx" or FileName endswith ".pdf" or FileName endswith ".xlsx"
|
||||
| where FolderPath contains "Confidential" or FolderPath contains "Sensitive"
|
||||
or FolderPath contains "Restricted"
|
||||
| where ActionType in ("FileAccessed","FileRead","FileModified","FileCopied","FileMoved")
|
||||
| extend User = tostring(InitiatingProcessAccountName)
|
||||
| summarize AccessCount = count() by FileName, User
|
||||
@@ -0,0 +1,8 @@
|
||||
AuditLogs
|
||||
| where TimeGenerated > ago(1d)
|
||||
| where OperationName has_any ("Add service principal","Certificates and secrets management")
|
||||
| extend Actor = tostring(parse_json(tostring(InitiatedBy.user)).userPrincipalName)
|
||||
| join kind=inner (
|
||||
SigninLogs | where ResultType == 0 and TimeGenerated > ago(1d)
|
||||
| project LoginTime = TimeGenerated, Identity, IPAddress, AppDisplayName
|
||||
) on $left.Actor == $right.Identity
|
||||
@@ -0,0 +1,7 @@
|
||||
let codes = dynamic([50053,50126,50055,50057,50155,50105,50133,50005,50076,
|
||||
50079,50173,50158,50072,50074,53003,53000,53001,50129]);
|
||||
SigninLogs
|
||||
| where TimeGenerated > ago(1d) | where ResultType in (codes)
|
||||
| summarize FailedAttempts = count(), UniqueUsers = dcount(UserPrincipalName)
|
||||
by IPAddress
|
||||
| where FailedAttempts > 5 and UniqueUsers > 5
|
||||
@@ -0,0 +1,3 @@
|
||||
SigninLogs | where TimeGenerated > ago(1d) | where ResultType == 0
|
||||
| summarize CountriesAccessed = make_set(Location) by UserPrincipalName
|
||||
| where array_length(CountriesAccessed) > 3
|
||||
@@ -0,0 +1,9 @@
|
||||
let historical = SigninLogs
|
||||
| where ResultType == 0
|
||||
| where TimeGenerated between (ago(14d) .. ago(1d))
|
||||
| summarize HistoricalCountries = make_set(Location) by UserPrincipalName;
|
||||
SigninLogs | where ResultType == 0 | where TimeGenerated > ago(1d)
|
||||
| summarize TodayCountries = make_set(Location) by UserPrincipalName
|
||||
| join kind=inner (historical) on UserPrincipalName
|
||||
| extend NewLocations = set_difference(TodayCountries, HistoricalCountries)
|
||||
| where array_length(NewLocations) > 0
|
||||
Reference in New Issue
Block a user