Merge pull request #2195 from Azure/pebryan/2021-4-8_HuntingTimeFrameFix

Pebryan/2021 4 8 hunting time frame fix
This commit is contained in:
Shain 2021-05-03 07:21:35 -07:00 коммит произвёл GitHub
Родитель 9bb5396394 a10c26d96c
Коммит 158019e9f6
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
126 изменённых файлов: 24 добавлений и 317 удалений

Просмотреть файл

@ -17,9 +17,7 @@ relevantTechniques:
- T1484
query: |
let timeframe = 7d;
AWSCloudTrail
| where TimeGenerated >= ago(timeframe)
| where EventName in~ ("AttachGroupPolicy", "AttachRolePolicy", "AttachUserPolicy", "CreatePolicy",
"DeleteGroupPolicy", "DeletePolicy", "DeleteRolePolicy", "DeleteUserPolicy", "DetachGroupPolicy",
"PutUserPolicy", "PutGroupPolicy", "CreatePolicyVersion", "DeletePolicyVersion", "DetachRolePolicy", "CreatePolicy")

Просмотреть файл

@ -16,10 +16,8 @@ relevantTechniques:
- T1098
query: |
let timeframe = 1d;
// Creating separate table for RemoveRoleToInstanceProfile
let RemoveRole=AWSCloudTrail
| where TimeGenerated >= ago(timeframe)
| where EventName in~ ("RemoveRoleFromInstanceProfile") and isempty(ErrorMessage)
| extend RoleRemoved = tostring(parse_json(RequestParameters).roleName), InstanceProfileName = tostring(parse_json(RequestParameters).instanceProfileName), TimeRemoved=TimeGenerated
| extend UserIdentityUserName = iff(isnotempty(UserIdentityUserName), UserIdentityUserName, tostring(split(UserIdentityArn,'/')[-1]))
@ -27,7 +25,6 @@ query: |
SourceIpAddress, AWSRegion, EventSource, RoleRemoved, InstanceProfileName;
// Creating separate table for AddRoleToInstanceProfile
let AddRole=AWSCloudTrail
| where TimeGenerated >= ago(timeframe)
| where EventName in~ ("AddRoleToInstanceProfile") and isempty(ErrorMessage)
| extend UserIdentityUserName = iff(isnotempty(UserIdentityUserName), UserIdentityUserName, tostring(split(UserIdentityArn,'/')[-1]))
| extend RoleAdded = tostring(parse_json(RequestParameters).roleName), InstanceProfileName = tostring(parse_json(RequestParameters).instanceProfileName), TimeAdded=TimeGenerated

Просмотреть файл

@ -23,11 +23,9 @@ tactics:
relevantTechniques:
- T1550.001
query: |
let auditLookback = 1d;
// Include your additions to the allow list below as needed
let AllowedUserList = dynamic(["Microsoft Cloud App Security","ADConnectSyncAccount1","SyncAccount2"]);
AuditLogs
| where TimeGenerated > ago(auditLookback)
| where OperationName has 'StsRefreshTokenValidFrom'
| where TargetResources[0].modifiedProperties != '[]'
| where TargetResources[0].modifiedProperties !has 'DirectorySync'

Просмотреть файл

@ -13,11 +13,9 @@ relevantTechniques:
- T1496
query: |
let timeframe = 1d;
let opValues = dynamic(["Microsoft.SecurityInsights/alertRules/write", "Microsoft.SecurityInsights/alertRules/delete"]);
// Azure Sentinel Analytics - Rule Create / Update / Delete
AzureActivity
| where TimeGenerated >= ago(timeframe)
| where Category == "Administrative"
| where OperationNameValue in (opValues)
| where ActivitySubstatusValue in ("Created", "OK")

Просмотреть файл

@ -19,14 +19,11 @@ relevantTechniques:
- T1087
query: |
let timeframe = 7d;
AzureActivity
| where TimeGenerated >= ago(timeframe)
| where OperationName == "List Storage Account Keys"
| where ActivityStatus == "Succeeded"
| join kind= inner (
AzureActivity
| where TimeGenerated >= ago(timeframe)
| where OperationName == "List Storage Account Keys"
| where ActivityStatus == "Succeeded"
| project ExpectedIpAddress=CallerIpAddress, Caller

Просмотреть файл

@ -15,7 +15,6 @@ relevantTechniques:
query: |
AzureActivity
| where TimeGenerated >= ago(1d)
| where ActivityStatusValue == "Succeeded"
| where ResourceGroup has "cloud-shell-storage"
| where OperationNameValue == "Microsoft.Storage/storageAccounts/listKeys/action"

Просмотреть файл

@ -18,7 +18,6 @@ query: |
let IP_Data = (externaldata(network:string)
[@"https://raw.githubusercontent.com/Azure/Azure-Sentinel/master/Sample%20Data/Feeds/VPS_Networks.csv"] with (format="csv"));
AzureActivity
| where TimeGenerated > ago(3d)
| where CategoryValue =~ "Administrative"
| evaluate ipv4_lookup(IP_Data, CallerIpAddress, network, return_unmatched = false)
| summarize Operations = make_set(OperationNameValue), StartTime = min(TimeGenerated), EndTime = max(TimeGenerated) by CallerIpAddress, Caller

Просмотреть файл

@ -13,11 +13,9 @@ relevantTechniques:
- T1496
query: |
let timeframe = 1d;
let opValues = dynamic(["Microsoft.Network/networkSecurityGroups/write", "Microsoft.Network/networkSecurityGroups/delete"]);
// Azure NSG Create / Update / Delete
AzureActivity
| where TimeGenerated >= ago(timeframe)
| where Category == "Administrative"
| where OperationNameValue in (opValues)
| where ActivitySubstatusValue in ("Created", "OK")

Просмотреть файл

@ -13,11 +13,9 @@ relevantTechniques:
- T1496
query: |
let timeframe = 1d;
let opValues = dynamic(["Microsoft.SecurityInsights/dataConnectors/write", "Microsoft.SecurityInsights/dataConnectors/delete"]);
// Azure Sentinel Data Connectors Update / Delete
AzureActivity
| where TimeGenerated >= ago(timeframe)
| where Category == "Administrative"
| where OperationNameValue in (opValues)
| where ActivitySubstatusValue in ("Created", "OK")

Просмотреть файл

@ -13,11 +13,9 @@ relevantTechniques:
- T1496
query: |
let timeframe = 1d;
let opValues = dynamic(["microsoft.insights/workbooks/write", "microsoft.insights/workbooks/delete"]);
// Azure Sentinel Workbook Create / Update / Delete
AzureActivity
| where TimeGenerated >= ago(timeframe)
| where Category == "Administrative"
| where OperationNameValue in (opValues)
| where ActivitySubstatusValue in ("Created", "OK")

Просмотреть файл

@ -14,9 +14,7 @@ relevantTechniques:
- T1496
query: |
let timeframe = 7d;
AzureActivity
| where TimeGenerated >= ago(timeframe)
| where OperationName == "Create or Update Virtual Machine" or OperationName == "Create Deployment"
| where ActivityStatus == "Succeeded"
| project Resource, ResourceGroup

Просмотреть файл

@ -13,9 +13,7 @@ relevantTechniques:
- T1496
query: |
let timeframe = 7d;
AzureActivity
| where TimeGenerated >= ago(timeframe)
| where OperationName == "Create or Update Virtual Machine" or OperationName == "Create Deployment"
| where ActivityStatus == "Succeeded"
| make-series dcount(ResourceId) default=0 on EventSubmissionTimestamp in range(ago(7d), now(), 1d) by Caller

Просмотреть файл

@ -14,15 +14,12 @@ relevantTechniques:
- T1098
query: |
let timeframe = 7d;
AzureActivity
| where TimeGenerated >= ago(timeframe)
| where OperationName == "Create role assignment"
| where ActivityStatus == "Succeeded"
| project Caller, CallerIpAddress
| evaluate basket()
| join kind=leftouter (AzureActivity
| where TimeGenerated >= ago(timeframe)
| where OperationName == "Create role assignment"
| where ActivityStatus == "Succeeded"
| summarize StartTime = min(TimeGenerated), EndTime = max(TimeGenerated) by Caller, CallerIpAddress)

Просмотреть файл

@ -15,9 +15,7 @@ relevantTechniques:
- T1496
query: |
let timeframe = 7d;
AzureActivity
| where TimeGenerated >= ago(timeframe)
| where OperationName has_any ("Create", "Update") and OperationName has_any ("Ip", "Security Rule")
// Choosing Accepted here because it has the Rule Attributes included
| where ActivityStatus == "Accepted"

Просмотреть файл

@ -13,9 +13,7 @@ relevantTechniques:
- T1098
- T1089
query: |
let timeframe = 7d;
AzureDevOpsAuditing
| where TimeGenerated >= ago(timeframe)
| where OperationName =="OrganizationPolicy.PolicyValueUpdated"
| where Data.PolicyName == "Policy.EnforceAADConditionalAccess"
| where Data.PolicyValue == "OFF"

Просмотреть файл

@ -8,16 +8,13 @@ tactics:
relevantTechniques:
- T1195
query: |
let timeframe = 30d;
let alert_threshold = 0;
AzureDevOpsAuditing
| where TimeGenerated > ago(timeframe)
| where OperationName matches regex "Artifacts.Feed.(Org|Project).Create"
| extend FeedName = tostring(Data.FeedName)
| extend FeedId = tostring(Data.FeedId)
| join kind = leftouter (
SecurityAlert
| where TimeGenerated > ago(timeframe)
| where ProviderName == "IPC"
| extend AadUserId = tostring(parse_json(Entities)[0].AadUserId)
| summarize Alerts=count() by AadUserId) on $left.ActorUserId == $right.AadUserId

Просмотреть файл

@ -8,14 +8,11 @@ tactics:
relevantTechniques:
- T1578
query: |
let timeframe = 7d;
AzureDevOpsAuditing
| where TimeGenerated > ago(timeframe)
| where OperationName =~ "Library.VariableGroupModified"
| extend variables = Data.Variables
| extend VariableGroupName = tostring(Data.VariableGroupName)
| join (AzureDevOpsAuditing
| where TimeGenerated > ago(timeframe)
| where OperationName =~ "Library.VariableGroupModified"
| extend variables = Data.Variables
| extend VariableGroupName = tostring(Data.VariableGroupName)) on VariableGroupName

Просмотреть файл

@ -13,9 +13,7 @@ relevantTechniques:
- T1098
- T1089
query: |
let timeframe = 7d;
AzureDevOpsAuditing
| where TimeGenerated >= ago(timeframe)
| where OperationName == "Group.UpdateGroupMembership.Add"
| where Category == "Modify"
| where Area == "Group"

Просмотреть файл

@ -14,9 +14,7 @@ relevantTechniques:
- T1036
query: |
let timeframe = 14d;
AzureDevOpsAuditing
| where TimeGenerated > ago(timeframe)
| where ActorCUID != '00000000-0000-0000-0000-000000000000' and ActorDisplayName != "Azure DevOps User"
| summarize StartTime = min(TimeGenerated), EndTime = max(TimeGenerated), DisplayNameCount = dcount(ActorDisplayName), ActorDisplayNames = make_set(ActorDisplayName), make_set(IpAddress), make_set(ProjectName) by ActorCUID, ActorUPN
| where DisplayNameCount > 1

Просмотреть файл

@ -12,8 +12,6 @@ relevantTechniques:
- T1098
query: |
let timeframe = 7d;
AzureDevOpsAuditing
| where TimeGenerated >= ago(timeframe)
| where OperationName == 'Git.RefUpdatePoliciesBypassed'
| extend timestamp = TimeGenerated, AccountCustomEntity = ActorUPN, IPCustomEntity = IpAddress

Просмотреть файл

@ -13,9 +13,7 @@ relevantTechniques:
- T1098
- T1089
query: |
let timeframe = 7d;
AzureDevOpsAuditing
| where TimeGenerated >= ago(timeframe)
| where OperationName =="OrganizationPolicy.PolicyValueUpdated"
| where Data.PolicyName == "Policy.DisallowAadGuestUserAccess"
| where Data.PolicyValue == "OFF"

Просмотреть файл

@ -11,9 +11,7 @@ tactics:
relevantTechniques:
- T1213
query: |
let timeframe = 7d;
AzureDevOpsAuditing
| where TimeGenerated >= ago(timeframe)
| where Area == "Project"
| where OperationName == "Project.UpdateVisibilityCompleted"
| where Data.PreviousProjectVisibility == "private"

Просмотреть файл

@ -13,9 +13,7 @@ relevantTechniques:
- T1098
- T1089
query: |
let timeframe = 7d;
AzureDevOpsAuditing
| where TimeGenerated >= ago(timeframe)
| where OperationName == "OrganizationPolicy.PolicyValueUpdated"
| where Data.PolicyName == "Policy.AllowAnonymousAccess"
| where Data.PolicyValue == "ON"

Просмотреть файл

@ -13,9 +13,7 @@ relevantTechniques:
- T1098
- T1089
query: |
let timeframe = 7d;
AzureDevOpsAuditing
| where TimeGenerated >= ago(timeframe)
| where Data.ProjectVisibility == "Public"
| where OperationName == "Project.CreateCompleted"
| extend timestamp = TimeGenerated, AccountCustomEntity = ActorUPN, IPCustomEntity = IpAddress

Просмотреть файл

@ -14,7 +14,6 @@ tags:
query: |
let threshold = 5m;
let timeRange = 15d;
//Union the file and blob data
let StorageData =
union
@ -22,7 +21,6 @@ query: |
StorageBlobLogs;
//Get file and blob uploads
StorageData
| where TimeGenerated > ago(timeRange)
//File upload operations
| where StatusText =~ "Success"
| where OperationName =~ "PutBlob" or OperationName =~ "PutRange"
@ -30,8 +28,7 @@ query: |
| extend Uri = tostring(split(Uri, "?", 0)[0])
//Join with deletions, this will return 0 rows if there was no deletion
| join (
StorageData
|where TimeGenerated > ago(timeRange)
StorageData
//File deletion operations
| where OperationName =~ "DeleteBlob" or OperationName =~ "DeleteFile"
| extend Uri = tostring(split(Uri, "?", 0)[0])
@ -42,7 +39,6 @@ query: |
| join (
StorageData
|where Category =~ "StorageRead"
|where TimeGenerated > ago(timeRange)
//File download events
| where OperationName =~ "GetBlob" or OperationName =~ "GetFile"
//Again, parse the URI to remove the parameters as they change per request

Просмотреть файл

@ -15,19 +15,16 @@ tags:
query: |
let threshold = 5m;
let timerange = 7d;
let StorageData =
union
StorageFileLogs,
StorageBlobLogs;
StorageData
| where TimeGenerated > ago(timerange)
| where StatusText =~ "Success"
| where OperationName =~ "PutBlob" or OperationName =~ "PutRange"
| extend Uri = tostring(split(Uri, "?", 0)[0])
| join (
StorageData
| where TimeGenerated > ago(timerange)
| where StatusText =~ "Success"
| where OperationName =~ "DeleteBlob" or OperationName =~ "DeleteFile"
| extend Uri = tostring(split(Uri, "?", 0)[0])

Просмотреть файл

@ -16,7 +16,6 @@ query: |
union StorageFileLogs,
StorageBlobLogs
| where TimeGenerated > ago(7d)
//File upload operations
| where OperationName =~ "PutBlob" or OperationName =~ "PutRange"
//Parse out the uploader IP
@ -35,7 +34,6 @@ query: |
| project-away list_hexChar, ResponseMd5
| join (
DeviceFileEvents
| where TimeGenerated > ago(7d)
| where ActionType =~ "FileCreated"
| where isnotempty(MD5)
| extend p = pack("FileCreateTime", TimeGenerated, "Device", DeviceName, "DeviceId", DeviceId, "FileName", FileName, "InititatingProcess", InitiatingProcessFileName)

Просмотреть файл

@ -19,7 +19,6 @@ query: |
union
StorageFileLogs,
StorageBlobLogs
| where TimeGenerated > ago(3d)
| where StatusText =~ "Success"
| where OperationName =~ "DeleteBlob" or OperationName =~ "DeleteFile"
| extend CallerIpAddress = tostring(split(CallerIpAddress, ":", 0)[0])

Просмотреть файл

@ -17,7 +17,6 @@ query: |
union
StorageFileLogs,
StorageBlobLogs
| where TimeGenerated > ago(7d)
//File upload operations
| where StatusText =~ "Success"
| where OperationName =~ "PutBlob" or OperationName =~ "PutRange"

Просмотреть файл

@ -15,14 +15,12 @@ tags:
- Ignite2021
query: |
let TimeRange = 7d;
//Period of time to look back in signin logs
let lookback = 1m;
let TargetFile = "mimikatz.exe"; //Example
union
StorageFileLogs,
StorageBlobLogs
| where TimeGenerated > ago(TimeRange)
//Collect file uploads
| where StatusText =~ "Success"
| where OperationName =~ "PutBlob" or OperationName =~ "PutRange"
@ -35,7 +33,6 @@ query: |
| extend WindowStart = FileUploadTime - lookback
| join (
SigninLogs
| where TimeGenerated > ago(TimeRange)
| project AzureLoginTime=TimeGenerated, UserPrincipalName, IPAddress, LoginUserAgent=UserAgent
) on $left.CallerIpAddress == $right.IPAddress
//Look back in the signinlogs for the most recent login

Просмотреть файл

@ -18,11 +18,9 @@ relevantTechniques:
- T1048
query: |
let timeframe = 7d;
// Add additional TLDs to this list are reuqired.
// Add additional TLDs to this list are required.
let abusedTLD = dynamic(["click", "club", "download", "xxx", "xyz"]);
DnsEvents
| where TimeGenerated >= ago(timeframe)
| where Name has "."
| extend tld = tostring(split(Name, ".")[-1])
| where tld in~ (abusedTLD)

Просмотреть файл

@ -12,10 +12,8 @@ relevantTechniques:
- T1046
query: |
let timeframe = 1d;
let threshold = 10;
DnsEvents
| where TimeGenerated >= ago(timeframe)
| where Name contains "in-addr.arpa"
| summarize StartTimeUtc = min(TimeGenerated), EndTimeUtc = max(TimeGenerated), NameCount = dcount(Name), Names = make_set(Name), ClientIPCount = count() by ClientIP
| where NameCount > threshold

Просмотреть файл

@ -19,19 +19,18 @@ relevantTechniques:
- T1048
query: |
let timeframe = 1d;
// Setting URI length threshold count, shorter URI's may cause noise, change as needed
let uriThreshold = 150;
let LocalDomains =
(
DnsEvents | where TimeGenerated >= ago(1d)
DnsEvents
| summarize count() by Computer
| extend SubDomain = tolower(strcat(tostring(split(Computer, ".")[-2]),".", tostring(split(Computer, ".")[-1])))
| distinct SubDomain
);
let DomainLookups =
(
DnsEvents | where TimeGenerated >= ago(1d)
DnsEvents
| where SubType =~ "LookupQuery"
| where ipv4_is_match("127.0.0.1", ClientIP) == False
| where Name !endswith ".local" and Name !startswith "_" and Name !startswith "#"

Просмотреть файл

@ -16,7 +16,6 @@ relevantTechniques:
- T1496
query: |
let timeframe = 1d;
let badDomains = dynamic(["agrdwrtj.us", "bctxawdt.us", "cokfqwjmferc.us", "cxbenjiikmhjcerbj.us", "depuisgef.us", "edoknehyvbl.us",
"enyeikruptiukjorq.com", "frullndjtkojlu.us", "gcidpiuvamynj.us", "gxrytjoclpvv.us", "hanoluexjqcf.us", "iarirjjrnuornts.us",
"ifbjoosjqhaeqjjwaerri.us", "iouenviwrc.us", "kuuelejkfwk.us", "lkbsxkitgxttgaobxu.us", "nnnlafqfnrbynwor.us", "ns768.com",
@ -24,7 +23,6 @@ query: |
"ryitsfeogisr.us", "srwcjdfrtnhnjekjerl.us", "thstlufnunxaksr.us", "udrgtaxgdyv.us", "w5q7spejg96n.com", "xmqlcikldft.us",
"yobvyjmjbsgdfqnh.us", "yrwgugricfklb.us", "ywpvqhlqnssecpdemq.us"]);
DnsEvents
| where TimeGenerated >= ago(timeframe)
| where Name in~ (badDomains)
| summarize StartTimeUtc = min(TimeGenerated), EndTimeUtc = max(TimeGenerated), count() by Computer, ClientIP, WannaCrypt_Related_Domain = Name
| extend timestamp = StartTimeUtc, HostCustomEntity = Computer, IPCustomEntity = ClientIP

Просмотреть файл

@ -22,7 +22,6 @@ query: |
let dictionary = dynamic(["r","q","3","g","s","a","l","t","6","u","1","i","y","f","z","o","p","5","7","2","d","4","9","b","n","x","8","c","v","m","k","e","w","h","j"]);
let regex_bad_domains = SigninLogs
//Collect domains from tenant from signin logs
| where TimeGenerated > ago(1d)
| extend domain = tostring(split(UserPrincipalName, "@", 1)[0])
| where domain != ""
| summarize by domain
@ -50,7 +49,6 @@ query: |
//Key to join to DNS
| extend key = 1;
DnsEvents
| where TimeGenerated > ago(1d)
| summarize by Name
| extend key = 1
//For each DNS query join the malicious domain list

Просмотреть файл

@ -11,8 +11,6 @@ relevantTechniques:
- T1089
query: |
let timeframe = 14d;
GitHubAudit
| where TimeGenerated > ago(timeframe)
| where Action == "org.disable_oauth_app_restrictions"
| project TimeGenerated, Action, Actor, Country

Просмотреть файл

@ -9,9 +9,7 @@ relevantTechniques:
- T1213
query: |
let timeframe = 14d;
GitHubAudit
| where TimeGenerated > ago(timeframe)
| where Action == "repo.access"
| where OperationType == "MODIFY"
| where Visibility == "PUBLIC"

Просмотреть файл

@ -9,22 +9,18 @@ relevantTechniques:
- T1537
query: |
let RunTime = 1h;
let CollaboratorsUserToRepoMapping = (
GitHubRepo
| where TimeGenerated < ago(RunTime)
| where Action == "Collaborators"
| distinct Repository , Actor, Organization);
let UserCommitsInRepoMapping = (
GitHubRepo
| where Action == "Commits"
| where TimeGenerated < ago(RunTime)
| distinct Repository ,Actor, Organization);
union CollaboratorsUserToRepoMapping, UserCommitsInRepoMapping
| summarize ContributedToRepos = make_set(Repository) by Actor, Organization
| join kind=innerunique (
GitHubRepo
| where TimeGenerated > ago(RunTime)
| where Action == "Forks"
| distinct Repository , Actor, Organization
) on Actor, Organization

Просмотреть файл

@ -15,15 +15,12 @@ query: |
let UI_apps = dynamic(['ASI_Portal','AzureMonitorLogsConnector','AppAnalytics']);
let threshold = 3;
let timeframe = 1d;
LAQueryLogs
| where TimeGenerated > ago(timeframe)
| where (ResponseRowCount == 10001 and RequestClientApp in(UI_apps)) or (ResponseRowCount > 10001 and RequestClientApp !in(UI_apps))
| summarize count() by AADEmail
| where count_ > threshold
| join kind=rightsemi (
LAQueryLogs
| where TimeGenerated > ago(timeframe)
| where (ResponseRowCount == 10001 and RequestClientApp in(UI_apps)) or (ResponseRowCount > 10001 and RequestClientApp !in(UI_apps)))
on AADEmail
| extend timestamp = TimeGenerated, AccountCustomEntity = AADEmail

Просмотреть файл

@ -18,16 +18,13 @@ query: |
// To exclude key phrases or tables to exclude add to these lists
let table_exclusions = dynamic(["AuditLogs","SigninLogs", "LAQueryLogs", "SecurityEvent"]);
let keyword_exclusion = dynamic(["reset user password", "change user password"]);
let timeframe = 7d;
LAQueryLogs
| where TimeGenerated > ago(timeframe)
| where RequestClientApp != 'Sentinel-General'
| extend querytext_lower = tolower(QueryText)
| where querytext_lower has_any(keywords)
| project TimeGenerated, AADEmail, QueryText, RequestClientApp, RequestTarget, ResponseCode, ResponseRowCount, ResponseDurationMs, CorrelationId
| extend timestamp = TimeGenerated, AccountCustomEntity = AADEmail
| join kind=leftanti ( LAQueryLogs
| where TimeGenerated > ago(timeframe)
| where RequestClientApp != 'Sentinel-General'
| extend querytext_lower = tolower(QueryText)
| where QueryText has_any(table_exclusions) or querytext_lower has_any(keyword_exclusion))

Просмотреть файл

@ -18,9 +18,7 @@ relevantTechniques:
- T1496
query: |
let timeframe = 7d;
AzureActivity
| where TimeGenerated >= ago(timeframe)
// We look for any Operation that modified and then was accepted or succeeded where a publicipaddress component is referenced
| where OperationName has_any ("Create", "Update", "Delete")// Virtual Machine" or OperationName == "Create Deployment"
| where ActivityStatus has_any ("Succeeded", "Accepted")
@ -37,7 +35,6 @@ query: |
| join kind= inner (
union isfuzzy=true
(AzureNetworkAnalytics_CL
| where TimeGenerated >= ago(timeframe)
// Controlling for Schema Version and later parsing - This is Version 2 and Public IPs only
| where isnotempty(FASchemaVersion_s) and isnotempty(DestPublicIPs_s)
| extend SchemaVersion = FASchemaVersion_s
@ -51,8 +48,7 @@ query: |
| extend NSG_Name = tostring(split(NSG, "/")[-1])
),
(
AzureNetworkAnalytics_CL
| where TimeGenerated >= ago(timeframe)
AzureNetworkAnalytics_CL
// Controlling for Schema Version and later parsing - This is Version 1
| where isempty(FASchemaVersion_s)
// Controlling for public IPs only

Просмотреть файл

@ -18,17 +18,14 @@ relevantTechniques:
- T1008
query: |
let timeframe = 1d;
let badNames = dynamic(["aaa.stage.", "post.1"]);
(union isfuzzy=true
(DnsEvents
| where TimeGenerated >= ago(timeframe)
(DnsEvents
| where Name has_any (badNames)
| extend Domain = Name, SourceIp = ClientIP, RemoteIP = todynamic(IPAddresses)
| mvexpand RemoteIP
| extend RemoteIP = tostring(RemoteIP)),
(VMConnection
| where TimeGenerated >= ago(timeframe)
| where isnotempty(RemoteDnsCanonicalNames)
| parse RemoteDnsCanonicalNames with * '["' DNSName '"]' *
| where DNSName has_any (badNames)

Просмотреть файл

@ -14,12 +14,9 @@ relevantTechniques:
- T1071.001
query: |
let lookback = 7d;
let domainLookback = 7d;
let domainCountThreshold = 100; //Maxiumum number of times a domain ahs been visited
//Backdoor.HTTP.BEACON.[Yelp GET]
let FEQuery1 = CommonSecurityLog
| where TimeGenerated > ago(lookback)
| where RequestMethod == "GET"
| where RequestURL contains "&parent_request_id="
| where RequestURL matches regex @"&parent_request_id=(?:[A-Za-z0-9_\/\+\-\%]{128,1000})={0,2}[^\r\n]{0,256}"
@ -28,7 +25,6 @@ query: |
| project TimeGenerated, Quality, RuleName, DeviceVendor, DeviceProduct, TenantId, SourceIP, DestinationIP, DestinationHostName, RequestMethod, RequestURL;
//Backdoor.HTTP.BEACON.[CSBundle CDN GET]
let FEQuery2 = CommonSecurityLog
| where TimeGenerated > ago(lookback)
| where RequestMethod == "GET"
| where FileType =~ "GZIP"
| where RequestURL matches regex @"(?:\/v1\/queue|\/v1\/profile|\/v1\/docs\/wsdl|\/v1\/pull)"
@ -37,7 +33,6 @@ query: |
| project TimeGenerated, Quality, RuleName, DeviceVendor, DeviceProduct, TenantId, SourceIP, DestinationIP, DestinationHostName, RequestMethod, RequestURL;
//Backdoor.HTTP.BEACON.[CSBundle USAToday GET]
let FEQuery3 = CommonSecurityLog
| where TimeGenerated > ago(lookback)
| where RequestMethod == "GET"
| where isempty(RequestContext)
| where RequestURL matches regex @"(?:\/USAT-GUP\/user\/|\/entertainment\/|\/entertainment\/navdd-q1a2z3Z6TET4gv2PNfXpaJAniOzOajK7M\.min\.json|\/global-q1a2z3C4M2nNlQYzWhCC0oMSEFjQbW1KA\.min\.json|\/life\/|\/news\/weather\/|\/opinion\/|\/sports\/|\/sports\/navdd-q1a2z3JHa8KzCRLOQAnDoVywVWF7UwxJs\.min\.json|\/tangstatic\/js\/main-q1a2z3b37df2b1\.min\.js|\/tangstatic\/js\/pbjsandwich-q1a2z300ab4198\.min\.js|\/tangstatic\/js\/pg-q1a2z3bbc110a4\.min\.js|\/tangsvc\/pg\/3221104001\/|\/ta`ngsvc\/pg\/5059005002\/|\/tangsvc\/pg\/5066496002\/|\/tech\/|\/travel\/)"
@ -47,7 +42,6 @@ query: |
| project TimeGenerated, Quality, RuleName, DeviceVendor, DeviceProduct, TenantId, SourceIP, DestinationIP, DestinationHostName, RequestMethod, RequestURL;
//Backdoor.HTTP.BEACON.[CSBundle Original POST]
let FEQuery4 = CommonSecurityLog
| where TimeGenerated > ago(lookback)
| where RequestMethod == "POST"
| where isempty(RequestContext)
| where RequestURL matches regex @"(?:\/v4\/links\/check-activity\/check|\/v1\/stats|\/gql|\/api2\/json\/check\/ticket|\/1.5\/95648064\/storage\/history|\/1.5\/95648064\/storage\/tabs|\/u\/0\/_\/og\/botguard\/get|\/ev\/prd001001|\/ev\/ext001001|\/gp\/aw\/ybh\/handlers|\/v3\/links\/ping-beat\/check)"
@ -56,7 +50,6 @@ query: |
| project TimeGenerated, Quality, RuleName, DeviceVendor, DeviceProduct, TenantId, SourceIP, DestinationIP, DestinationHostName, RequestMethod, RequestURL;
//Backdoor.HTTP.BEACON.[CSBundle MSOffice POST
let FEQuery5 = CommonSecurityLog
| where TimeGenerated > ago(lookback)
| where RequestMethod == "POST"
| where isempty(RequestContext)
| where RequestURL contains "/v1/push"
@ -65,7 +58,6 @@ query: |
| project TimeGenerated, Quality, RuleName, DeviceVendor, DeviceProduct, TenantId, SourceIP, DestinationIP, DestinationHostName, RequestMethod, RequestURL;
//Backdoor.HTTP.BEACON.[CSBundle NYTIMES POST]
let FEQuery6 = CommonSecurityLog
| where TimeGenerated > ago(lookback)
| where RequestMethod == "POST"
| where isempty(RequestContext)
| where RequestURL matches regex @"(?:\/track|\/api\/v1\/survey\/embed|\/svc\/weather\/v2)"
@ -74,7 +66,6 @@ query: |
| project TimeGenerated, Quality, RuleName, DeviceVendor, DeviceProduct, TenantId, SourceIP, DestinationIP, DestinationHostName, RequestMethod, RequestURL;
//Backdoor.HTTP.BEACON.[CSBundle MSOffice GET]
let FEQuery7 = CommonSecurityLog
| where TimeGenerated > ago(lookback)
| where RequestMethod == "GET"
| where isempty(RequestContext)
| where RequestURL matches regex @"(?:\/updates|\/license\/eula|\/docs\/office|\/software-activation)"
@ -83,7 +74,6 @@ query: |
| project TimeGenerated, Quality, RuleName, DeviceVendor, DeviceProduct, TenantId, SourceIP, DestinationIP, DestinationHostName, RequestMethod, RequestURL;
//Backdoor.HTTP.BEACON.[CSBundle MSOffice POST]
let FEQuery8 = CommonSecurityLog
| where TimeGenerated > ago(lookback)
| where RequestMethod == "POST"
| where isempty(RequestContext)
| where RequestURL contains "/notification"
@ -92,7 +82,6 @@ query: |
| project TimeGenerated, Quality, RuleName, DeviceVendor, DeviceProduct, TenantId, SourceIP, DestinationIP, DestinationHostName, RequestMethod, RequestURL;
//Backdoor.HTTP.BEACON.[CSBundle Original GET]
let FEQuery9 = CommonSecurityLog
| where TimeGenerated > ago(lookback)
| where RequestMethod == "GET"
| where isempty(RequestContext)
| where RequestURL matches regex @"(?:\/api2\/json\/access\/ticket|\/api2\/json\/cluster\/resources|\/api2\/json\/cluster\/tasks|\/en-us\/p\/onerf\/MeSilentPassport|\/en-us\/p\/book-2\/8MCPZJJCC98C|\/en-us\/store\/api\/checkproductinwishlist|\/gp\/cerberus\/gv|\/gp\/aj\/private\/reviewsGallery\/get-application-resources|\/gp\/aj\/private\/reviewsGallery\/get-image-gallery-assets|\/v1\/buckets\/default\/ext-5dkJ19tFufpMZjVJbsWCiqDcclDw\/records|\/v3\/links\/ping-centre|\/v4\/links\/activity-stream|\/wp-content\/themes\/am43-6\/dist\/records|\/wp-content\/themes\/am43-6\/dist\/records|\/wp-includes\/js\/script\/indigo-migrate)"
@ -104,7 +93,6 @@ query: |
Results
| join (
CommonSecurityLog
| where TimeGenerated > ago(domainLookback)
| where DestinationHostName != ""
| summarize DomainCount=count() by DestinationHostName)
on $left.DestinationHostName == $right.DestinationHostName

Просмотреть файл

@ -16,10 +16,8 @@ relevantTechniques:
- T1078
query: |
let timeframe = 1d;
(union isfuzzy=true
(SecurityEvent
| where TimeGenerated >= ago(timeframe)
(SecurityEvent
| where EventID == 4625
//4625: An account failed to log on
| where AccountType == 'User'
@ -30,8 +28,7 @@ query: |
| project Computer, Account, Reason , TimeGenerated
),
(
SecurityEvent
| where TimeGenerated >= ago(timeframe)
SecurityEvent
| where EventID == 4769
//4769: A Kerberos service ticket was requested ( Kerberos Auth)
| parse EventData with * 'Status">' Status "<" *
@ -46,7 +43,6 @@ query: |
),
(
SecurityEvent
| where TimeGenerated >= ago(timeframe)
| where EventID == 4776
// 4776: The domain controller attempted to validate the credentials for an account ( NTLM Auth)
| where Status == "0xc0000193"
@ -60,8 +56,7 @@ query: |
| project Computer, Account, Reason , TimeGenerated
) ,
(
SigninLogs
| where TimeGenerated >= ago(timeframe)
SigninLogs
| where ResultType == "50057"
| extend Reason =
case(

Просмотреть файл

@ -18,11 +18,10 @@ relevantTechniques:
- T1110
query: |
let lookback = 1d;
let fl_Min = 3;
let un_MatchMin = 2;
let upnFunc = (startTimeSpan:timespan, tableName:string){
table(tableName) | where TimeGenerated >= ago(lookback)
let upnFunc = (tableName:string){
table(tableName)
| extend Operation = columnifexists("Operation", "Sign-in activity")
| where Operation == "UserLoginFailed" or Operation == "Sign-in activity"
| extend Result = columnifexists("ResultType", "tempValue")
@ -57,8 +56,8 @@ query: |
| summarize UserNames = makeset(UserNameOnly),
fl_Count = count() by bin(TimeGenerated, 10m), First4char, First6char, First8char, Last4char, Last6char, Last8char, Type
};
let SigninList = upnFunc(lookback,"SigninLogs");
let OffActList = upnFunc(lookback,"OfficeActivity");
let SigninList = upnFunc("SigninLogs");
let OffActList = upnFunc("OfficeActivity");
let UserNameList = (union isfuzzy=true SigninList, OffActList);
let Char4List = UserNameList
| project TimeGenerated, First4char, Last4char, UserNames, fl_Count, Type

Просмотреть файл

@ -31,11 +31,9 @@ query: |
let regparams5 = dynamic(['reg add "HKLM\\SYSTEM\\CurrentControlSet\\services\\HealthService"', 'reg add "HKLM\\SYSTEM\\CurrentControlSet\\Services\\Sense"', 'reg add "HKLM\\SYSTEM\\CurrentControlSet\\Services\\WinDefend"', 'reg add "HKLM\\SYSTEM\\CurrentControlSet\\Services\\MsSecFlt"', 'reg add "HKLM\\SYSTEM\\CurrentControlSet\\Services\\DiagTrack"', 'reg add "HKLM\\SYSTEM\\CurrentControlSet\\Services\\SgrmBroker"', 'reg add "HKLMSYSTEM\\CurrentControlSet\\Services\\SgrmAgent"', 'reg add "HKLM\\SYSTEM\\CurrentControlSet\\Services\\AATPSensorUpdater"' , 'reg add "HKLM\\SYSTEM\\CurrentControlSet\\Services\\AATPSensor"', 'reg add "HKLM\\SYSTEM\\CurrentControlSet\\Services\\mpssvc"']);
let regparams6 = dynamic(['/d 4','/d "4"','/d 0x00000004']);
let regparams7 = dynamic(['/d 1','/d "1"','/d 0x00000001']);
let timeframe = 1d;
(union isfuzzy=true
(
SecurityEvent
| where TimeGenerated >= ago(timeframe)
| where EventID == 4688
| extend ProcessName = tostring(split(NewProcessName, '\\')[-1])
| where ProcessName in~ (includeProc)
@ -49,14 +47,12 @@ query: |
),
(
Event
| where TimeGenerated >= ago(timeframe)
| where Source =~ "Microsoft-Windows-SENSE"
| where EventID == 87 and ParameterXml in ("<Param>sgrmbroker</Param>", "<Param>WinDefend</Param>")
| project TimeGenerated, Computer, Account = UserName, EventID, Activity = RenderedDescription, EventSourceName = Source, Type
),
(
DeviceProcessEvents
| where TimeGenerated >= ago(timeframe)
| where InitiatingProcessFileName in~ (includeProc)
| where (InitiatingProcessCommandLine has_any(action) and InitiatingProcessCommandLine has_any (service2) and InitiatingProcessParentFileName != 'cscript.exe')
or (InitiatingProcessCommandLine has_any (params1) and InitiatingProcessCommandLine has 'Set-MpPreference' and InitiatingProcessCommandLine has '$true')

Просмотреть файл

@ -28,10 +28,8 @@ query: |
// Provide customLimit value with default above domainLimit value so it will not block unless changed
let customLimit = 11;
let domainLimit = 10;
let lookback = 14d;
let domainLookback = union isfuzzy=true
(AuditLogs
| where TimeGenerated >= ago(lookback)
| extend UserPrincipalName = tolower(tostring(TargetResources.[0].userPrincipalName))
// parse out AuditLog values for various locations where UPN could be
| extend UserPrincipalName = iff(isnotempty(UserPrincipalName),
@ -49,7 +47,6 @@ query: |
//| where RareDomainCount <= customLimit
),
(OfficeActivity
| where TimeGenerated >= ago(lookback)
| extend UserPrincipalName = tolower(UserId)
| where UserPrincipalName has "@" or UserPrincipalName startswith "NT AUTHORITY"
| extend RareDomain = toupper(tostring(split(UserPrincipalName, "@")[-1]))
@ -60,7 +57,6 @@ query: |
//| where RareDomainCount <= customLimit
),
(SigninLogs
| where TimeGenerated >= ago(lookback)
| where UserPrincipalName has "@" or UserPrincipalName startswith "NT AUTHORITY"
| extend RareDomain = toupper(tostring(split(UserPrincipalName, "@")[-1]))
| summarize RareDomainCount = count() by Type, RareDomain
@ -70,7 +66,6 @@ query: |
);
let AuditLogsRef = domainLookback | join (
AuditLogs
| where TimeGenerated >= ago(lookback)
| extend UserPrincipalName = tolower(tostring(TargetResources.[0].userPrincipalName))
| extend UserPrincipalName = iff(isempty(UserPrincipalName), tostring(InitiatedBy.user.userPrincipalName), UserPrincipalName)
| extend RareDomain = toupper(tostring(split(UserPrincipalName, "@")[-1]))
@ -80,7 +75,6 @@ query: |
) on Type, RareDomain;
let OfficeActivityRef = domainLookback | join (
OfficeActivity
| where TimeGenerated >= ago(lookback)
| extend UserPrincipalName = tolower(UserId)
| where UserPrincipalName has "@" or UserPrincipalName startswith "NT AUTHORITY"
| extend RareDomain = toupper(tostring(split(UserPrincipalName, "@")[-1]))
@ -89,7 +83,6 @@ query: |
) on Type, RareDomain;
let SigninLogsRef = domainLookback | join (
SigninLogs
| where TimeGenerated >= ago(lookback)
| extend UserPrincipalName = tolower(UserId)
| where UserPrincipalName has "@" or UserPrincipalName startswith "NT AUTHORITY"
| extend RareDomain = toupper(tostring(split(UserPrincipalName, "@")[-1]))

Просмотреть файл

@ -18,11 +18,9 @@ tags:
- NOBELIUM
query: |
let timeframe = 30d;
(union isfuzzy=true
(
SecurityEvent
| where TimeGenerated >= ago(timeframe)
SecurityEvent
| where EventID == '4688'
| where tolower(NewProcessName) has 'solarwinds'
| extend MachineName = Computer , Process = NewProcessName
@ -30,14 +28,12 @@ query: |
),
(
DeviceProcessEvents
| where TimeGenerated >= ago(timeframe)
| where tolower(InitiatingProcessFolderPath) has 'solarwinds'
| extend MachineName = DeviceName , Process = InitiatingProcessFolderPath, Account = AccountName
| summarize StartTime = min(TimeGenerated), EndTime = max(TimeGenerated), MachineCount = dcount(MachineName), AccountCount = dcount(Account), MachineNames = make_set(MachineName), Accounts = make_set(Account) by Process, Type
),
(
Event
| where TimeGenerated >= ago(timeframe)
| where Source == "Microsoft-Windows-Sysmon"
| where EventID == 1
| extend Image = EventDetail.[4].["#text"]

Просмотреть файл

@ -28,17 +28,14 @@ relevantTechniques:
- T1110
query: |
let timeframe = 7d;
let action = dynamic(["change ", "changed ", "reset "]);
let pWord = dynamic(["password ", "credentials "]);
(union isfuzzy=true
(SecurityEvent
| where TimeGenerated >= ago(timeframe)
| where EventID in (4723,4724)
| summarize StartTimeUtc = min(TimeGenerated), EndTimeUtc = max(TimeGenerated), ResultDescriptions = makeset(Activity), ActionCount = count() by Resource = Computer, OperationName = strcat("TargetAccount: ", TargetUserName), UserId = Account, Type
),
(AuditLogs
| where TimeGenerated >= ago(timeframe)
| where OperationName has_any (pWord) and OperationName has_any (action)
| extend InitiatedBy = tostring(parse_json(tostring(InitiatedBy.user)).userPrincipalName)
| extend TargetUserPrincipalName = tostring(TargetResources[0].userPrincipalName)
@ -47,7 +44,6 @@ query: |
| extend ResultDescriptions = tostring(ResultDescriptions)
),
(OfficeActivity
| where TimeGenerated >= ago(timeframe)
| where (ExtendedProperties has_any (pWord) or ModifiedProperties has_any (pWord)) and (ExtendedProperties has_any (action) or ModifiedProperties has_any (action))
| extend ResultDescriptions = case(
OfficeWorkload =~ "AzureActiveDirectory", tostring(ExtendedProperties),
@ -56,12 +52,10 @@ query: |
| summarize StartTimeUtc = min(TimeGenerated), EndTimeUtc = max(TimeGenerated), ResultDescriptions = makeset(ResultDescriptions), ActionCount = count() by Resource = OfficeWorkload, OperationName = strcat(Operation, " - ", ResultStatus), IPAddress = ClientIP, UserId, Type
),
(Syslog
| where TimeGenerated >= ago(timeframe)
| where SyslogMessage has_any (pWord) and SyslogMessage has_any (action)
| summarize StartTimeUtc = min(TimeGenerated), EndTimeUtc = max(TimeGenerated), ResultDescriptions = makeset(SyslogMessage), ActionCount = count() by Resource = HostName, OperationName = Facility , IPAddress = HostIP, ProcessName, Type
),
(SigninLogs
| where TimeGenerated >= ago(timeframe)
| where OperationName =~ "Sign-in activity" and ResultType has_any ("50125", "50133")
| summarize StartTimeUtc = min(TimeGenerated), EndTimeUtc = max(TimeGenerated), ResultDescriptions = makeset(ResultDescription), CorrelationIds = makeset(CorrelationId), ActionCount = count() by Resource, OperationName = strcat(OperationName, " - ", ResultType), IPAddress, UserId = UserPrincipalName, Type
)

Просмотреть файл

@ -26,13 +26,11 @@ relevantTechniques:
- T1203
query: |
let timeframe = 14d;
let UserAgentList = "Internet Explorer |Mozilla/4\\.0 \\(compatible; MSIE 6\\.0; Windows NT 5\\.1; SV1; InfoPath\\.2\\)|Mozilla/5\\.0 \\(Windows NT 10\\.0; Win32; x32; rv:60\\.0\\)|Mozilla/4\\.0 \\(compatible; Metasploit RSPEC\\)|Mozilla/4\\.0 \\(compatible; MSIE 6\\.1; Windows NT\\)|Mozilla/4\\.0 \\(compatible; MSIE 6\\.0; Windows NT 5\\.1\\)|Mozilla/4\\.0 \\(compatible; MSIE 8\\.0; Windows NT 6\\.0; Trident/4\\.0\\)|Mozilla/4\\.0 \\(compatible; MSIE 7\\.0; Windows NT 6\\.0; Trident/4\\.0; SIMBAR={7DB0F6DE-8DE7-4841-9084-28FA914B0F2E}; SLCC1; \\.N|Mozilla/5\\.0 \\(Windows; U; Windows NT 5\\.1; en-US\\) AppleWebKit/525\\.13 \\(KHTML, like Gecko\\) Chrome/4\\.0\\.221\\.6 Safari/525\\.13|Mozilla/5\\.0 \\(compatible; MSIE 9\\.0; Windows NT 6\\.1; WOW64; Trident/5\\.0; MAAU\\)|Mozilla/5\\.0[^\\s]|Mozilla/4\\.0 \\(compatible; SPIPE/1\\.0|Mozilla/5\\.0 \\(Windows NT 6\\.3; rv:39\\.0\\) Gecko/20100101 Firefox/35\\.0|Sametime Community Agent|X-FORWARDED-FOR|DotDotPwn v2\\.1|SIPDROID|wordpress hash grabber|exploit|okhttp/";
// Excluding for IIS, as the main malicious usage for okhttp that we have seen was in the OfficeActivity logs and this can create noise for IIS.
let ExcludeIIS = "okhttp/";
(union isfuzzy=true
(OfficeActivity
| where TimeGenerated >= ago(timeframe)
| where ExtendedProperties has "UserAgent"
| extend UserAgent = extractjson("$[0].Value", ExtendedProperties, typeof(string))
| where UserAgent matches regex UserAgentList
@ -41,7 +39,6 @@ query: |
),
(
W3CIISLog
| where TimeGenerated >= ago(timeframe)
| extend UserAgent = replace('\\+', ' ', csUserAgent)
| where UserAgent matches regex UserAgentList
| where UserAgent !startswith ExcludeIIS
@ -51,7 +48,6 @@ query: |
),
(
AWSCloudTrail
| where TimeGenerated >= ago(timeframe)
| where UserAgent matches regex UserAgentList
| extend SourceIP = SourceIpAddress
| project TimeGenerated, Type, UserAgent, SourceIP

Просмотреть файл

@ -13,11 +13,9 @@ relevantTechniques:
query: |
// If you want to look at user added further than 7 days ago adjust this value
let time_ago = 7d;
// If you want to change the timeframe of how quickly accounts need to be added and removed change this value
let time_delta = 1h;
OfficeActivity
| where TimeGenerated > ago(time_ago)
| where OfficeWorkload =~ "MicrosoftTeams"
| where Operation =~ "MemberAdded"
| extend UPN = tostring(parse_json(Members)[0].UPN)
@ -25,7 +23,6 @@ query: |
| project TimeAdded=TimeGenerated, Operation, UPN, UserWhoAdded = UserId, TeamName, TeamGuid
| join (
OfficeActivity
| where TimeGenerated > ago(time_ago)
| where OfficeWorkload =~ "MicrosoftTeams"
| where Operation =~ "MemberRemoved"
| extend UPN = tostring(parse_json(Members)[0].UPN)

Просмотреть файл

@ -15,9 +15,7 @@ relevantTechniques:
- T1020
query: |
let timeframe = 14d;
OfficeActivity
| where TimeGenerated >= ago(timeframe)
| where OfficeWorkload == "Exchange"
| where Operation in~ ("New-TransportRule", "Set-TransportRule")
| extend p = parse_json(Parameters)

Просмотреть файл

@ -17,9 +17,7 @@ query: |
// Adjust these thresholds to suit your environment.
let threshold = 2;
let time_threshold = timespan(5m);
let timeframe = 30d;
OfficeActivity
| where TimeGenerated > ago(timeframe)
| where OfficeWorkload =~ "MicrosoftTeams"
| where Operation =~ "BotAddedToTeam"
| summarize Start=max(TimeGenerated), End=min(TimeGenerated), Teams = makeset(TeamName)

Просмотреть файл

@ -15,9 +15,7 @@ query: |
// Adjust this value to change how many teams a user is made owner of before detecting
let max_owner_count = 3;
// Change this value to adjust how larger timeframe the query is run over.
let time_window = 1d;
let high_owner_count = (OfficeActivity
| where TimeGenerated > ago(time_window)
| where OfficeWorkload =~ "MicrosoftTeams"
| where Operation =~ "MemberRoleChanged"
| extend Member = tostring(parse_json(Members)[0].UPN)
@ -27,7 +25,6 @@ query: |
| where dcount_TeamName > max_owner_count
| project Member);
OfficeActivity
| where TimeGenerated > ago(time_window)
| where OfficeWorkload =~ "MicrosoftTeams"
| where Operation =~ "MemberRoleChanged"
| extend Member = tostring(parse_json(Members)[0].UPN)

Просмотреть файл

@ -15,18 +15,14 @@ query: |
// Adjust this value to change how many Teams should be deleted before including
let max_delete = 3;
// Adjust this value to change the timewindow the query runs over
let time_window = 1d;
let deleting_users = (
OfficeActivity
| where TimeGenerated > ago(time_window)
| where OfficeWorkload =~ "MicrosoftTeams"
| where Operation =~ "TeamDeleted"
| summarize count() by UserId
| where count_ > max_delete
| project UserId);
OfficeActivity
| where TimeGenerated > ago(time_window)
| where OfficeWorkload =~ "MicrosoftTeams"
| where Operation =~ "TeamDeleted"
| where UserId in (deleting_users)

Просмотреть файл

@ -16,9 +16,7 @@ relevantTechniques:
- T1020
query: |
let timeframe = 14d;
OfficeActivity
| where TimeGenerated >= ago(timeframe)
| where (Operation =~ "Set-Mailbox" and Parameters contains 'ForwardingSmtpAddress')
or (Operation =~ 'New-InboxRule' and Parameters contains 'ForwardTo')
| extend parsed=parse_json(Parameters)

Просмотреть файл

@ -14,17 +14,14 @@ relevantTechniques:
- T1566
query: |
let timeframe = 7d;
let threshold = 1m;
OfficeActivity
| where TimeGenerated > ago(timeframe)
| where OfficeWorkload =~ "MicrosoftTeams"
| where Operation == "MemberAdded"
| extend TeamName = iff(isempty(TeamName), Members[0].UPN, TeamName)
| project TimeGenerated, UploaderID=UserId, TeamName
| join (
OfficeActivity
| where TimeGenerated > ago(timeframe)
| where RecordType == "SharePointFileOperation"
| where SourceRelativeUrl has "Microsoft Teams Chat Files"
| where Operation == "FileUploaded"

Просмотреть файл

@ -19,8 +19,7 @@ query: |
// Reserved FileNames/Extension for Windows
let Reserved = dynamic(['CON', 'PRN', 'AUX', 'NUL', 'COM1', 'COM2', 'COM3', 'COM4', 'COM5', 'COM6', 'COM7', 'COM8', 'COM9', 'LPT1', 'LPT2', 'LPT3', 'LPT4', 'LPT5', 'LPT6', 'LPT7', 'LPT8', 'LPT9']);
let endtime = 1d;
OfficeActivity | where TimeGenerated >= ago(endtime)
OfficeActivity
| where isnotempty(SourceFileExtension)
| where SourceFileExtension in~ (Reserved) or SourceFileName in~ (Reserved)
| where UserAgent !has "Mac OS"

Просмотреть файл

@ -13,17 +13,14 @@ relevantTechniques:
- T1036
query: |
let timeframe = 14d;
let known_ext = dynamic(["lnk","log","option","config", "manifest", "partial"]);
let excluded_users = dynamic(["app@sharepoint"]);
OfficeActivity
| where TimeGenerated > ago(timeframe)
| where RecordType =~ "SharePointFileOperation" and isnotempty(SourceFileName)
| where OfficeObjectId has ".exe." and SourceFileExtension !in~ (known_ext)
| extend Extension = extract("[^.]*.[^.]*$",0, OfficeObjectId)
| join kind= leftouter (
OfficeActivity
| where TimeGenerated > ago(timeframe)
| where RecordType =~ "SharePointFileOperation" and (Operation =~ "FileDownloaded" or Operation =~ "FileAccessed")
| where SourceFileExtension !in~ (known_ext)
) on OfficeObjectId

Просмотреть файл

@ -21,9 +21,7 @@ tags:
- NOBELIUM
query: |
let timeframe = 1d;
OfficeActivity
| where TimeGenerated >= ago(timeframe)
| where Operation == "MailboxLogin" and Logon_Type != "Owner"
| summarize StartTime = min(TimeGenerated), EndTime = max(TimeGenerated), count() by Operation, OrganizationName, UserType, UserId, MailboxOwnerUPN, Logon_Type, ClientIP
| extend timestamp = StartTime, AccountCustomEntity = UserId, IPCustomEntity = ClientIP

Просмотреть файл

@ -20,9 +20,7 @@ relevantTechniques:
- T1114
query: |
let timeframe = 1d;
OfficeActivity
| where TimeGenerated >= ago(timeframe)
| where Operation == "MailboxLogin"
| where ClientInfoString == "Client=Microsoft.Exchange.Powershell; Microsoft WinRM Client"
| summarize StartTime = min(TimeGenerated), EndTime = max(TimeGenerated), count() by Operation, OrganizationName, UserType, UserId, MailboxOwnerUPN, Logon_Type, ClientInfoString

Просмотреть файл

@ -9,7 +9,6 @@ requiredDataConnectors:
tactics:
- InitialAccess
query: |
let lbtime = 24h;
let scoreThreshold = 80;
ProofpointPOD
| where EventType == 'message'

Просмотреть файл

@ -9,7 +9,6 @@ requiredDataConnectors:
tactics:
- InitialAccess
query: |
let lbtime = 24h;
let scoreThreshold = 80;
ProofpointPOD
| where EventType == 'message'

Просмотреть файл

@ -9,7 +9,6 @@ requiredDataConnectors:
tactics:
- InitialAccess
query: |
let lbtime = 24h;
let scoreThreshold = 80;
ProofpointPOD
| where EventType == 'message'

Просмотреть файл

@ -9,7 +9,6 @@ requiredDataConnectors:
tactics:
- InitialAccess
query: |
let lbtime = 24h;
let scoreThreshold = 80;
ProofpointPOD
| where EventType == 'message'

Просмотреть файл

@ -9,7 +9,6 @@ requiredDataConnectors:
tactics:
- InitialAccess
query: |
let lbtime = 24h;
let scoreThreshold = 80;
ProofpointPOD
| where EventType == 'message'

Просмотреть файл

@ -11,7 +11,6 @@ tactics:
query: |
let threshold = 10;
ProofpointPOD
| where TimeGenerated > ago(24h)
| where EventType == 'message'
| where NetworkDirection == 'inbound'
| where FilterDisposition !in ('reject', 'discard')

Просмотреть файл

@ -9,9 +9,7 @@ requiredDataConnectors:
tactics:
- InitialAccess
query: |
let lbtime = 24h;
ProofpointPOD
| where TimeGenerated > ago(lbtime)
| where EventType == 'message'
| where NetworkDirection == 'inbound'
| extend isCorrupted = todynamic(MsgParts)[0]['isCorrupted']

Просмотреть файл

@ -9,9 +9,7 @@ requiredDataConnectors:
tactics:
- InitialAccess
query: |
let lbtime = 24h;
ProofpointPOD
| where TimeGenerated > ago(lbtime)
| where EventType == 'message'
| where NetworkDirection == 'outbound'
| extend isCorrupted = todynamic(MsgParts)[0]['isCorrupted']

Просмотреть файл

@ -9,9 +9,7 @@ requiredDataConnectors:
tactics:
- InitialAccess
query: |
let lbtime = 24h;
ProofpointPOD
| where TimeGenerated > ago(lbtime)
| where EventType == 'message'
| where NetworkDirection == 'inbound'
| extend attachedFileType = todynamic(MsgParts)[0]['detectedExt']

Просмотреть файл

@ -17,7 +17,6 @@ query: |
// SQLEvent is not the table name, it is the function name that should already be imported into your workspace.
// The underlying table where the data exists is the Event table.
SQLEvent
| where TimeGenerated >= ago(1d)
| where LogonResult has "failed"
| summarize count() by TimeGenerated, CurrentUser, Reason, ClientIP
| extend timestamp = TimeGenerated, AccountCustomEntity = CurrentUser, IPCustomEntity = ClientIP

Просмотреть файл

@ -17,12 +17,10 @@ query: |
// SQLEvent is not the table name, it is the function name that should already be imported into your workspace.
// The underlying table where the data exists is the Event table.
// the timeframe and threshold can be changed below as per requirement.
// the threshold can be changed below as per requirement.
//
let TimeFrame = 1d;
let failedThreshold = 3;
SQLEvent
| where TimeGenerated >= ago(TimeFrame)
| where LogonResult has "failed"
| summarize StartTime = min(TimeGenerated), EndTime = max(TimeGenerated), TotalFailedLogons = count() by ClientIP, CurrentUser, Computer
| where TotalFailedLogons >= failedThreshold

Просмотреть файл

@ -17,12 +17,10 @@ query: |
// SQLEvent is not the table name, it is the function name that should already be imported into your workspace.
// The underlying table where the data exists is the Event table.
// the timeframe and threshold can be changed below as per requirement
// the threshold can be changed below as per requirement
//
let TimeFrame = 1d;
let failedThreshold = 3;
SQLEvent
| where TimeGenerated >= ago(TimeFrame)
| where LogonResult has "failed"
| summarize StartTime = min(TimeGenerated), EndTime = max(TimeGenerated), TotalFailedLogons = count() by CurrentUser, ClientIP
| where TotalFailedLogons >= failedThreshold

Просмотреть файл

@ -20,7 +20,6 @@ query: |
// This query checks for new user account created on SQL Server using the SQLEvent() parser
//
SQLEvent
| where TimeGenerated >= ago(1d)
| where Statement has "Create Login"
| parse Statement with "CREATE LOGIN [" TargetUser:string "]" *
| project TimeGenerated, Computer, Action, ClientIP, CurrentUser, DatabaseName, TargetUser, ObjectName, Statement

Просмотреть файл

@ -21,7 +21,6 @@ query: |
// The underlying table where the data exists is the Event table.
// This query tracks user added into SecurityAdmingroup
SQLEvent
| where TimeGenerated >= ago(1d)
| where Statement has "Alter Server role" and Statement has "add member"
| parse Statement with * "ADD MEMBER [" TargetUser:string "]" *
| where ObjectName has "securityadmin"

Просмотреть файл

@ -24,7 +24,6 @@ query: |
// This query checks for user removed from a database by parsing the statement field at the query time.
//
SQLEvent
| where TimeGenerated >= ago(1d)
| where Statement has "Alter role" and Statement has "drop member"
| parse Statement with * "DROP MEMBER [" TargetUser:string "]" *
| project TimeGenerated, Computer, Action, ClientIP, CurrentUser, DatabaseName, TargetUser, ObjectName, Statement

Просмотреть файл

@ -23,7 +23,6 @@ query: |
// The underlying table where the data exists is the Event table.
// This query checks for user removed from SecurityAdmin Role
SQLEvent
| where TimeGenerated >= ago(1d)
| where Statement has "Alter Server role" and Statement has "drop member"
| parse Statement with * "DROP MEMBER [" TargetUser:string "]" *
| where ObjectName has "securityadmin"

Просмотреть файл

@ -23,7 +23,6 @@ query: |
// The underlying table where the data exists is the Event table.
// This query checks for user removed from a ServerRole
SQLEvent
| where TimeGenerated >= ago(1d)
| where Statement has "Alter Server role" and Statement has "drop member"
| parse Statement with * "DROP MEMBER [" TargetUser:string "]" *
| project TimeGenerated, Computer, Action, ClientIP, CurrentUser, DatabaseName, TargetUser, ObjectName, Statement

Просмотреть файл

@ -21,7 +21,6 @@ query: |
// The underlying table where the data exists is the Event table.
// This query looking for Alter role commands and extracts username which was altered and target objectName
SQLEvent
| where TimeGenerated >= ago(1d)
| where Statement contains "Alter role" and Statement has "add member"
| parse Statement with * "ADD MEMBER [" TargetUser:string "]" *
| project TimeGenerated, Computer, Action, ClientIP, CurrentUser, DatabaseName, TargetUser, ObjectName, Statement

Просмотреть файл

@ -14,12 +14,10 @@ tactics:
- Persistence
query: |
let scriptExtensions = dynamic([".php", ".jsp", ".js", ".aspx", ".asmx", ".asax", ".cfm", ".shtml"]);
let timeRange = 3d;
let lookupWindow = 1m;
let lookupBin = lookupWindow / 2.0;
let distinctIpThreshold = 3;
let alerts = SecurityAlert
| where TimeGenerated > ago(timeRange)
| extend alertData = parse_json(Entities), recordGuid = new_guid();
let shellAlerts = alerts
| where ProviderName =~ "MDATP"
@ -53,14 +51,12 @@ query: |
| project recordGuid, TimeGenerated, ImageName, CommandLine, TimeKey = bin(TimeGenerated, lookupBin), HostName, DnsDomain
| extend Start = TimeGenerated;
let baseline = W3CIISLog
| where TimeGenerated > ago(timeRange)
| project-rename SourceIP=cIP, PageAccessed=csUriStem
| summarize dcount(SourceIP) by PageAccessed
| where dcount_SourceIP <= distinctIpThreshold;
commandKeyedData
| join kind=inner (
W3CIISLog
| where TimeGenerated > ago(timeRange)
W3CIISLog
| where csUriStem has_any(scriptExtensions)
| extend splitUriStem = split(csUriStem, "/")
| extend FileName = splitUriStem[-1] | extend firstDir = splitUriStem[-2] | extend TimeKey = range(bin(TimeGenerated-lookupWindow, lookupBin), bin(TimeGenerated, lookupBin),lookupBin)

Просмотреть файл

@ -13,10 +13,8 @@ tactics:
- PrivilegeEscalation
- Persistence
query: |
let timeWindow = 3d;
let scriptExtensions = dynamic([".php", ".jsp", ".js", ".aspx", ".asmx", ".asax", ".cfm", ".shtml"]);
SecurityAlert
| where TimeGenerated > ago(timeWindow)
SecurityAlert
| where ProviderName =~ "MDATP"
| extend alertData = parse_json(Entities)
| mvexpand alertData
@ -27,8 +25,7 @@ query: |
| extend FileName = alertData.Name
| project TimeGenerated, tostring(FileName), alertData.Directory
| join (
W3CIISLog
| where TimeGenerated > ago(timeWindow)
W3CIISLog
| where csUriStem has_any(scriptExtensions)
| extend splitUriStem = split(csUriStem, "/")
| extend FileName = splitUriStem[-1]

Просмотреть файл

@ -11,9 +11,7 @@ tactics:
relevantTechniques:
- T1531
query: |
let timeframe = 7d;
SecurityEvent
| where TimeGenerated >= ago(timeframe)
| where EventID == 4740
| summarize StartTime = min(TimeGenerated), EndTime = max(TimeGenerated), LockoutsCount = count() by Activity, Account, TargetSid, TargetDomainName, SourceComputerId, SourceDomainController = Computer
| extend timestamp = StartTime, AccountCustomEntity = Account, HostCustomEntity = TargetDomainName

Просмотреть файл

@ -13,10 +13,8 @@ relevantTechniques:
- T1105
query: |
let timeframe = 1d;
Event
//This query uses sysmon data depending on table name used this may need updataing
| where TimeGenerated >= ago(timeframe)
| where Source == "Microsoft-Windows-Sysmon"
| where EventID == 1
| extend RenderedDescription = tostring(split(RenderedDescription, ":")[0])

Просмотреть файл

@ -13,9 +13,7 @@ relevantTechniques:
- T1110
query: |
let timeframe = 1d;
SecurityEvent
| where TimeGenerated >= ago(timeframe)
| where AccountType == 'User' and EventID == 4625
| extend Reason = case(
SubStatus == '0xc000005e', 'No logon servers available to service the logon request',

Просмотреть файл

@ -24,7 +24,6 @@ query: |
let WellKnownLocalSIDs = "S-1-5-[0-9][0-9]$";
let protocols = dynamic(['cifs', 'ldap', 'RPCSS', 'host' , 'HTTP', 'RestrictedKrbHost', 'TERMSRV', 'msomsdksvc', 'mssqlsvc']);
SecurityEvent
| where TimeGenerated >= ago(1d)
| where EventID == 4648
| where SubjectUserSid != 'S-1-0-0' // this is the Nobody SID which really means No security principal was included.
| where not(SubjectUserSid matches regex WellKnownLocalSIDs) //excluding system account/service account as this is generally normal

Просмотреть файл

@ -26,14 +26,12 @@ tags:
- Solorigate
- NOBELIUM
query: |
let startdate = 1d;
let lookupwindow = 2m;
let threshold = 3; //number of commandlines in the set below
let DCADFSServersList = dynamic (["DCServer01", "DCServer02", "ADFSServer01"]); // Enter a reference list of hostnames for your DC/ADFS servers
let tokens = dynamic(["objectcategory","domainlist","dcmodes","adinfo","trustdmp","computers_pwdnotreqd","Domain Admins", "objectcategory=person", "objectcategory=computer", "objectcategory=*"]);
SecurityEvent
//| where Computer in (DCADFSServersList) // Uncomment to limit it to your DC/ADFS servers list if specified above or any pattern in hostnames (startswith, matches regex, etc).
| where TimeGenerated between (ago(startdate) .. now())
| where EventID == 4688
| where CommandLine has_any (tokens)
| where CommandLine matches regex "(.*)>(.*)"

Просмотреть файл

@ -14,9 +14,7 @@ relevantTechniques:
- T1110
query: |
let timeframe = 1d;
SecurityEvent
| where TimeGenerated >= ago(timeframe)
| where EventID in (4624, 4625)
| where AccountType == 'User'
| summarize StartTimeUtc = min(TimeGenerated), EndTimeUtc = max(TimeGenerated), Amount = count() by LogonTypeName

Просмотреть файл

@ -15,12 +15,10 @@ relevantTechniques:
- T1078
query: |
let timeframe = 10d;
// For AD SID mappings - https://docs.microsoft.com/windows/security/identity-protection/access-control/active-directory-security-groups
let WellKnownLocalSID = "S-1-5-32-5[0-9][0-9]$";
let WellKnownGroupSID = "S-1-5-21-[0-9]*-[0-9]*-[0-9]*-5[0-9][0-9]$|S-1-5-21-[0-9]*-[0-9]*-[0-9]*-1102$|S-1-5-21-[0-9]*-[0-9]*-[0-9]*-1103$";
SecurityEvent
| where TimeGenerated > ago(timeframe)
| where AccountType == "User"
// 4728 - A member was added to a security-enabled global group
// 4732 - A member was added to a security-enabled local group

Просмотреть файл

@ -14,12 +14,9 @@ relevantTechniques:
- T1078
query: |
// TimeFrame is the number of lookback days, default is last 14 days
let timeframe = 14d;
// TimeDelta is the difference between when the account was created and when it was deleted, default is set to 10min or less
let timedelta = 10m;
SecurityEvent
| where TimeGenerated > ago(timeframe)
// A user account was created
| where EventID == "4720"
| where AccountType == "User"
@ -27,7 +24,6 @@ query: |
AccountUsedToCreate = SubjectUserName, TargetSid, SubjectUserSid
| join kind= inner (
SecurityEvent
| where TimeGenerated > ago(timeframe)
// A user account was deleted
| where EventID == "4726"
| where AccountType == "User"

Просмотреть файл

@ -16,9 +16,7 @@ query: |
// Create DataTable with your own values, example below shows dummy usernames that are authorized and for what domain
let List = datatable(AuthorizedUser:string, Domain:string)["Bob", "Domain", "joe", "domain", "MATT", "DOMAIN"];
let timeframe = 1d;
SecurityEvent
| where TimeGenerated >= ago(timeframe)
| where EventID in (4728, 4729, 4732, 4733, 4746, 4747, 4751, 4752, 4756, 4757, 4761, 4762)
| join kind= leftanti (
List

Просмотреть файл

@ -16,9 +16,7 @@ query: |
// Create DataTable with your own values, example below shows dummy usernames that are authorized and for what domain
let List = datatable(AuthorizedUser:string, Domain:string)["Bob", "Domain", "joe", "domain", "MATT", "DOMAIN"];
let timeframe = 1d;
SecurityEvent
| where TimeGenerated >= ago(timeframe)
| where EventID == 4720
| where AccountType == "User"
| join kind= leftanti (

Просмотреть файл

@ -14,10 +14,8 @@ query: |
// Create DataTable with your own values, example below shows dummy usernames that are authorized and for what domain
let List = datatable(VIPUser:string, Domain:string)["Bob", "Domain", "joe", "domain", "MATT", "DOMAIN"];
let timeframe = 10m;
List | extend Account = strcat(Domain,"\\",VIPUser) | join kind= inner (
SecurityEvent
| where TimeGenerated > ago(timeframe)
| where EventID == "4625"
| where AccountType == "User"
| where LogonType == "2" or LogonType == "3"

Просмотреть файл

@ -10,7 +10,6 @@ tactics:
- Execution
query: |
let timeframe = 1d;
let ProcessCreationEvents=() {
let processEvents=SecurityEvent
| where EventID==4688
@ -21,7 +20,6 @@ query: |
};
// Daily summary of cscript activity - extracting script name and parameters from commandline:
ProcessCreationEvents
| where EventTime >= ago(timeframe)
| where FileName =~ "cscript.exe"
// remove commandline switches
| project EventTime, ComputerName, AccountName, removeSwitches = replace(@"/+[a-zA-Z0-9:]+", "", ProcessCommandLine)

Просмотреть файл

@ -10,7 +10,6 @@ tactics:
- Discovery
query: |
let timeframe = 1d;
let ProcessCreationEvents=() {
let processEvents=SecurityEvent
| where EventID==4688
@ -21,7 +20,6 @@ query: |
InitiatingProcessFileName=ParentProcessName,InitiatingProcessCommandLine="",InitiatingProcessParentFileName="";
processEvents};
ProcessCreationEvents
| where TimeGenerated >= ago(timeframe)
| where FileName == 'net.exe' and AccountName != "" and ProcessCommandLine !contains '\\' and ProcessCommandLine !contains '/add'
| where (ProcessCommandLine contains ' user ' or ProcessCommandLine contains ' group ') and (ProcessCommandLine endswith ' /do' or ProcessCommandLine endswith ' /domain')
| extend Target = extract("(?i)[user|group] (\"*[a-zA-Z0-9-_ ]+\"*)", 1, ProcessCommandLine) | filter Target != ''

Просмотреть файл

@ -14,9 +14,7 @@ tactics:
- Execution
query: |
let timeframe = 1d;
SecurityEvent
| where TimeGenerated >= ago(timeframe)
| where NewProcessName endswith "\\svchost.exe"
| where SubjectUserSid !in ("S-1-5-18", "S-1-5-19", "S-1-5-20")
| where NewProcessName !contains ":\\Windows\\System32"

Просмотреть файл

@ -18,9 +18,7 @@ relevantTechniques:
- T1110
query: |
let timeframe = 1d;
SecurityEvent
| where TimeGenerated >= ago(timeframe)
| where EventID==4688
| project TimeGenerated, ComputerName=Computer,AccountName=SubjectUserName,
AccountDomain=SubjectDomainName, FileName=tostring(split(NewProcessName, '\\')[-1]),

Просмотреть файл

@ -11,7 +11,6 @@ tactics:
- CommandAndControl
query: |
let timeframe = 1d;
let ProcessCreationEvents=() {
let processEvents=SecurityEvent
| where EventID==4688
@ -21,7 +20,6 @@ query: |
InitiatingProcessFileName=ParentProcessName,InitiatingProcessCommandLine="",InitiatingProcessParentFileName="";
processEvents};
ProcessCreationEvents
| where TimeGenerated >= ago(timeframe)
| where FileName in~ ("powershell.exe", "powershell_ise.exe")
| where ProcessCommandLine has "Net.WebClient"
or ProcessCommandLine has "DownloadFile"

Просмотреть файл

@ -13,7 +13,6 @@ tactics:
- Execution
query: |
let timeframe = 1d;
let ProcessCreationEvents=() {
let processEvents=SecurityEvent
| where EventID==4688
@ -28,7 +27,6 @@ query: |
processEvents;
};
let normalizedProcesses = ProcessCreationEvents
| where TimeGenerated >= ago(timeframe)
// normalize guids
| project TimeGenerated, FileName = replace("[0-9A-Fa-f]{8}[-][0-9A-Fa-f]{4}[-][0-9A-Fa-f]{4}[-][0-9A-Fa-f]{4}[-][0-9A-Fa-f]{12}", "<guid>", FileName)
// normalize digits away

Просмотреть файл

@ -15,10 +15,8 @@ relevantTechniques:
- T1078
query: |
let timeRange=ago(14d);
SigninLogs
// Forces Log Analytics to recognize that the query should be run over full time range
| where TimeGenerated >= timeRange
| extend locationString= strcat(tostring(LocationDetails["countryOrRegion"]), "/",
tostring(LocationDetails["state"]), "/", tostring(LocationDetails["city"]), ";")
| project TimeGenerated, AppDisplayName, UserPrincipalName, locationString

Просмотреть файл

@ -17,10 +17,8 @@ relevantTechniques:
- T1078
query: |
let timeRange = ago(14d);
SigninLogs
// Forces Log Analytics to recognize that the query should be run over full time range
| where TimeGenerated >= timeRange
| extend locationString= strcat(tostring(LocationDetails["countryOrRegion"]), "/",
tostring(LocationDetails["state"]), "/", tostring(LocationDetails["city"]), ";")
| project TimeGenerated, AppDisplayName , UserPrincipalName, locationString
@ -34,7 +32,6 @@ query: |
| top 3 by Slope desc
// Extract the set of locations for each top user:
| join kind=inner (SigninLogs
| where TimeGenerated >= timeRange
| extend locationString= strcat(tostring(LocationDetails["countryOrRegion"]), "/",
tostring(LocationDetails["state"]), "/", tostring(LocationDetails["city"]), ";")
| summarize locationList = makeset(locationString), threeDayWindowLocationCount=dcount(locationString) by AppDisplayName, UserPrincipalName,

Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше