This commit is contained in:
Bart Lauwers 2023-11-22 18:42:34 -06:00
Родитель 72f9b8bda8
Коммит 7deef9bb6f
Не найден ключ, соответствующий данной подписи
50 изменённых файлов: 816 добавлений и 695 удалений

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

@ -0,0 +1,73 @@
{
"Name":"UrlClickEvents",
"Properties":[
{
"Name": "AccountUpn",
"Type": "string"
},
{
"Name": "ActionType",
"Type": "string"
},
{
"Name": "DetectionMethods",
"Type": "string"
},
{
"Name": "IPAddress",
"Type": "string"
},
{
"Name": "IsClickedThrough",
"Type": "bool"
},
{
"Name": "NetworkMessageId",
"Type": "string"
},
{
"Name": "ReportId",
"Type": "string"
},
{
"Name": "SourceSystem",
"Type": "string"
},
{
"Name": "TenantId",
"Type": "string"
},
{
"Name": "ThreatTypes",
"Type": "string"
},
{
"Name": "TimeGenerated",
"Type": "datetime"
},
{
"Name": "Type",
"Type": "string"
},
{
"Name": "Url",
"Type": "string"
},
{
"Name": "UrlChain",
"Type": "string"
},
{
"Name": "Workload",
"Type": "string"
},
{
"Name": "_BilledSize",
"Type": "real"
},
{
"Name": "_IsBillable",
"Type": "string"
}
]
}

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

@ -394,8 +394,8 @@ namespace Kqlvalidations.Tests
bool match = Regex.IsMatch(queryStr, tiTablepattern);
if (match)
{
string queryPattern = @"ThreatIntelligenceIndicator\s*\|\s*where\s*TimeGenerated\s*>=\s*ago\(\w+\)\s*\|\s*summarize\s*LatestIndicatorTime\s*=\s*arg_max\(TimeGenerated,\s*\*\)\s*by\s*IndicatorId\s*\|\s*where\s*(?:ExpirationDateTime\s*>\s*now\(\)\s*and\s*Active\s*==\s*true|Active\s*==\s*true\s*and\s*ExpirationDateTime\s*>\s*now\(\))";
return Regex.IsMatch(queryStr, queryPattern);
string queryPattern = @"ThreatIntelligenceIndicator\s*\|\s*where\s*TimeGenerated\s*>=\s*ago\(\w+\).*|\s*summarize\s*LatestIndicatorTime\s*=\s*arg_max\(TimeGenerated,\s*\*\)\s*by\s*IndicatorId\s*\|\s*where\s*(?:ExpirationDateTime\s*>\s*now\(\)\s*and\s*Active\s*==\s*true|Active\s*==\s*true\s*and\s*ExpirationDateTime\s*>\s*now\(\))";
return Regex.IsMatch(queryStr, queryPattern, RegexOptions.Singleline);
}
return true;
}
@ -442,7 +442,9 @@ namespace Kqlvalidations.Tests
private bool ShouldSkipTemplateValidation(string templateId)
{
return TemplatesToSkipValidationReader.WhiteListTemplates
.Where(template => template.id == templateId)
.Where(template =>
template.id
== templateId)
.Where(template => !string.IsNullOrWhiteSpace(template.validationFailReason))
.Where(template => !string.IsNullOrWhiteSpace(template.templateName))
.Any();

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

@ -1519,11 +1519,6 @@
"templateName": "EmailEntity_OfficeActivity.yaml",
"validationFailReason": "Since the content moved to new location, created dummy file with guidence for redirecting the customers to new location"
},
{
"id": "6bb63ef4-9083-4dc3-bc48-7aeb569b13b2",
"templateName": "EmailEntity_PaloAlto.yaml",
"validationFailReason": "Since the content moved to new location, created dummy file with guidence for redirecting the customers to new location"
},
{
"id": "6db4b928-4029-454e-a4e3-cf761db681e8",
"templateName": "EmailEntity_SecurityAlert.yaml",
@ -1534,11 +1529,6 @@
"templateName": "EmailEntity_SecurityEvent.yaml",
"validationFailReason": "Since the content moved to new location, created dummy file with guidence for redirecting the customers to new location"
},
{
"id": "6d33f647-149a-4339-9db7-0cbf7d7c4e60",
"templateName": "EmailEntity_SigninLogs.yaml",
"validationFailReason": "Since the content moved to new location, created dummy file with guidence for redirecting the customers to new location"
},
{
"id": "6bbefa0a-d0f2-4a45-91a5-9b8f332edb41",
"templateName": "FileHashEntity_CommonSecurityLog.yaml",
@ -2571,11 +2561,6 @@
"templateName": "imDns_DomainEntity_DnsEvents.yaml",
"validationFailReason": "Since the content moved to new location, created dummy file with guidence for redirecting the customers to new location"
},
{
"id": "cc0a1f32-5bad-412c-96cc-67319dbcd735",
"templateName": "imDns_IPEntity_DnsEvents.yaml",
"validationFailReason": "Since the content moved to new location, created dummy file with guidence for redirecting the customers to new location"
},
// Temporarily adding Data connector template id's for KQL Validations - Start
// Temporarily adding Data connector template id's for KQL Validations - End
@ -2583,181 +2568,21 @@
// Temporarily adding Analytic rules and hunting queries id's for TI KQL Validations - Start
{
"id": "b1832f60-6c3d-4722-a0a5-3d564ee61a63",
"templateName": "DomainEntity_imWebSession.yaml",
"validationFailReason": "Temporarily Added for Threat Intelligence KQL Queries validation"
},
{
"id": "cca3b4d9-ac39-4109-8b93-65bb284003e6",
"templateName": "EmailEntity_AzureActivity.yaml",
"validationFailReason": "Temporarily Added for Threat Intelligence KQL Queries validation"
},
{
"id": "4a3f5ed7-8da5-4ce2-af6f-c9ada45060f2",
"templateName": "EmailEntity_OfficeActivity.yaml",
"validationFailReason": "Temporarily Added for Threat Intelligence KQL Queries validation"
},
{
"id": "ffcd575b-3d54-482a-a6d8-d0de13b6ac63",
"templateName": "EmailEntity_PaloAlto.yaml",
"validationFailReason": "Temporarily Added for Threat Intelligence KQL Queries validation"
},
{
"id": "a2e36ce0-da4d-4b6e-88c6-4e40161c5bfc",
"templateName": "EmailEntity_SecurityAlert.yaml",
"validationFailReason": "Temporarily Added for Threat Intelligence KQL Queries validation"
},
{
"id": "2fc5d810-c9cc-491a-b564-841427ae0e50",
"templateName": "EmailEntity_SecurityEvent.yaml",
"validationFailReason": "Temporarily Added for Threat Intelligence KQL Queries validation"
},
{
"id": "30fa312c-31eb-43d8-b0cc-bcbdfb360822",
"templateName": "EmailEntity_SigninLogs.yaml",
"validationFailReason": "Temporarily Added for Threat Intelligence KQL Queries validation"
},
{
"id": "5d33fc63-b83b-4913-b95e-94d13f0d379f",
"templateName": "FileHashEntity_CommonSecurityLog.yaml",
"validationFailReason": "Temporarily Added for Threat Intelligence KQL Queries validation"
},
{
"id": "a7427ed7-04b4-4e3b-b323-08b981b9b4bf",
"templateName": "FileHashEntity_SecurityEvent.yaml",
"validationFailReason": "Temporarily Added for Threat Intelligence KQL Queries validation"
},
{
"id": "7241740a-5280-4b74-820a-862312d721a8",
"templateName": "GitLab_MaliciousIP.yaml",
"validationFailReason": "Temporarily Added for Threat Intelligence KQL Queries validation"
},
{
"id": "999e9f5d-db4a-4b07-a206-29c4e667b7e8",
"templateName": "imDns_DomainEntity_DnsEvents.yaml",
"validationFailReason": "Temporarily Added for Threat Intelligence KQL Queries validation"
},
{
"id": "67775878-7f8b-4380-ac54-115e1e828901",
"templateName": "imDns_IPEntity_DnsEvents.yaml",
"validationFailReason": "Temporarily Added for Threat Intelligence KQL Queries validation"
},
{
"id": "57c7e832-64eb-411f-8928-4133f01f4a25",
"templateName": "IPEntity_AzureKeyVault.yaml",
"validationFailReason": "Temporarily Added for Threat Intelligence KQL Queries validation"
},
{
"id": "d23ed927-5be3-4902-a9c1-85f841eb4fa1",
"templateName": "IPEntity_DuoSecurity.yaml",
"validationFailReason": "Temporarily Added for Threat Intelligence KQL Queries validation"
},
{
"id": "e2399891-383c-4caf-ae67-68a008b9f89e",
"templateName": "IPEntity_imNetworkSession.yaml",
"validationFailReason": "Temporarily Added for Threat Intelligence KQL Queries validation"
},
{
"id": "f2eb15bd-8a88-4b24-9281-e133edfba315",
"templateName": "IPentity_SigninLogs.yaml",
"validationFailReason": "Temporarily Added for Threat Intelligence KQL Queries validation"
},
{
"id": "35a0792a-1269-431e-ac93-7ae2980d4dde",
"templateName": "ProofpointPODEmailSenderInTIList.yaml",
"validationFailReason": "Temporarily Added for Threat Intelligence KQL Queries validation"
},
{
"id": "78979d32-e63f-4740-b206-cfb300c735e0",
"templateName": "ProofpointPODEmailSenderIPinTIList.yaml",
"validationFailReason": "Temporarily Added for Threat Intelligence KQL Queries validation"
},
{
"id": "a1c02815-4248-4728-a9ae-dac73c67db23",
"templateName": "RecordedFutureDomainMalwareC2inDNSEvents.yaml",
"validationFailReason": "Temporarily Added for Threat Intelligence KQL Queries validation"
},
{
"id": "dffd068f-fdab-440e-bbc0-34c14b623c89",
"templateName": "RecordedFutureDomainMalwareC2inSyslogEvents.yaml",
"validationFailReason": "Temporarily Added for Threat Intelligence KQL Queries validation"
},
{
"id": "388e197d-ec9e-46b6-addb-947d74d2a5c4",
"templateName": "RecordedFutureHashObservedInUndergroundinCommonSecurityLog.yaml",
"validationFailReason": "Temporarily Added for Threat Intelligence KQL Queries validation"
},
{
"id": "aac495a9-feb1-446d-b08e-a1164a539452",
"templateName": "Threat Intel Matches to GitHub Audit Logs.yaml",
"validationFailReason": "Temporarily Added for Threat Intelligence KQL Queries validation"
},
{
"id": "2a723664-22c2-4d3e-bbec-5843b90166f3",
"templateName": "TIMapIPEntityToLastPass.yaml",
"validationFailReason": "Temporarily Added for Threat Intelligence KQL Queries validation"
},
{
"id": "db60ca0b-b668-439b-b889-b63b57ef20fb",
"templateName": "UbiquitiDestinationInTiList.yaml",
"validationFailReason": "Temporarily Added for Threat Intelligence KQL Queries validation"
},
{
"id": "712fab52-2a7d-401e-a08c-ff939cc7c25e",
"templateName": "URLEntity_AuditLogs.yaml",
"validationFailReason": "Temporarily Added for Threat Intelligence KQL Queries validation"
},
{
"id": "36a9c9e5-3dc1-4ed9-afaa-1d13617bfc2b",
"templateName": "URLEntity_OfficeActivity.yaml",
"validationFailReason": "Temporarily Added for Threat Intelligence KQL Queries validation"
},
{
"id": "106813db-679e-4382-a51b-1bfc463befc3",
"templateName": "URLEntity_PaloAlto.yaml",
"validationFailReason": "Temporarily Added for Threat Intelligence KQL Queries validation"
},
{
"id": "f30a47c1-65fb-42b1-a7f4-00941c12550b",
"templateName": "URLEntity_SecurityAlerts.yaml",
"validationFailReason": "Temporarily Added for Threat Intelligence KQL Queries validation"
},
{
"id": "b31037ea-6f68-4fbd-bab2-d0d0f44c2fcf",
"templateName": "URLEntity_Syslog.yaml",
"validationFailReason": "Temporarily Added for Threat Intelligence KQL Queries validation"
},
{
"id": "410da56d-4a63-4d22-b68c-9fb1a303be6d",
"templateName": "FileEntity_OfficeActivity.yaml",
"validationFailReason": "Temporarily Added for Threat Intelligence KQL Queries validation"
},
{
"id": "233441b9-cc92-4c9b-87fa-73b855fcd4b8",
"templateName": "FileEntity_SecurityEvent.yaml",
"validationFailReason": "Temporarily Added for Threat Intelligence KQL Queries validation"
},
{
"id": "18f7de84-de55-4983-aca3-a18bc846b4e0",
"templateName": "FileEntity_Syslog.yaml",
"validationFailReason": "Temporarily Added for Threat Intelligence KQL Queries validation"
},
{
"id": "172a321b-c46b-4508-87c6-e2691c778107",
"templateName": "FileEntity_VMConnection.yaml",
"validationFailReason": "Temporarily Added for Threat Intelligence KQL Queries validation"
},
{
"id": "689a9475-440b-4e69-8ab1-a5e241685f39",
"templateName": "FileEntity_WireData.yaml",
"validationFailReason": "Temporarily Added for Threat Intelligence KQL Queries validation"
},
{
"id": "388e197d-ec9e-46b6-addb-947d74d2a5c4",
"templateName": "RecordedFutureHashObservedInUndergroundinCommonSecurityLog.yaml",
"validationFailReason": "Temporarily Added for Threat Intelligence KQL Queries validation"
},
{
"id": "0f872637-8817-44a0-bb9d-ceab3dbd4ecd",
"templateName": "Brute Force Attack against GitHub Account.yaml",

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

@ -90,7 +90,8 @@
"EmailEvents\n | summarize LastLogReceived = max(TimeGenerated)\n | project IsConnected = LastLogReceived > ago(7d)",
"EmailUrlInfo\n | summarize LastLogReceived = max(TimeGenerated)\n | project IsConnected = LastLogReceived > ago(7d)",
"EmailAttachmentInfo\n | summarize LastLogReceived = max(TimeGenerated)\n | project IsConnected = LastLogReceived > ago(7d)",
"EmailPostDeliveryEvents\n | summarize LastLogReceived = max(TimeGenerated)\n | project IsConnected = LastLogReceived > ago(7d)"
"EmailPostDeliveryEvents\n | summarize LastLogReceived = max(TimeGenerated)\n | project IsConnected = LastLogReceived > ago(7d)",
"UrlClickEvents\n | summarize LastLogReceived = max(TimeGenerated)\n | project IsConnected = LastLogReceived > ago(7d)"
]
},
{
@ -180,6 +181,10 @@
"name": "EmailPostDeliveryEvents",
"lastDataReceivedQuery": "EmailPostDeliveryEvents\n | summarize Time = max(TimeGenerated)\n | where isnotempty(Time)"
},
{
"name": "UrlClickEvents",
"lastDataReceivedQuery": "UrlClickEvents\n | summarize Time = max(TimeGenerated)\n | where isnotempty(Time)"
},
{
"name": "IdentityLogonEvents",
"lastDataReceivedQuery": "IdentityLogonEvents\n | summarize Time = max(TimeGenerated)\n | where isnotempty(Time)"

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

@ -30,7 +30,7 @@
"Workbooks/MicrosoftDefenderForIdentity.json"
],
"BasePath": "C:\\GitHub\\Azure-Sentinel\\Solutions\\Microsoft Defender XDR",
"Version": "3.0.0",
"Version": "3.0.1",
"Metadata": "SolutionMetadata.json",
"TemplateSpec": true,
"Is1Pconnector": true

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

@ -1,7 +1,7 @@
id: dd0a6029-ecef-4507-89c4-fc355ac52111
name: TI map Domain entity to CommonSecurityLog
name: TI map Domain entity to PaloAlto CommonSecurityLog
description: |
Identifies a match in CommonSecurityLog table from any Domain IOC from TI
Identifies a match in PaloAlto CommonSecurityLog table from any Domain IOC from TI
severity: Medium
requiredDataConnectors:
- connectorId: ThreatIntelligence
@ -23,35 +23,8 @@ query: |
let dt_lookBack = 1h; // Look back 1 hour
let ioc_lookBack = 14d; // Look back 14 days
// Create a list of top-level domains (TLDs) from the threat feed data for later validation
let list_tlds =
ThreatIntelligenceIndicator
// Filter indicators based on the specified time range and active indicators
| where TimeGenerated >= ago(ioc_lookBack)
| summarize LatestIndicatorTime = arg_max(TimeGenerated, *) by IndicatorId
| where Active == true and ExpirationDateTime > now()
| where isnotempty(DomainName)
// Convert domain names to lowercase for consistency
| extend DomainName = tolower(DomainName)
// Split domain names into parts and extract the TLD
| extend parts = split(DomainName, '.')
| extend tld = parts[(array_length(parts) - 1)]
// Count the occurrences of each TLD
| summarize count() by tostring(tld)
// Create a list of TLDs
| summarize make_list(tld);
// Retrieve threat intelligence indicators within the specified time range
let Domain_Indicators =
ThreatIntelligenceIndicator
| where TimeGenerated >= ago(ioc_lookBack)
| summarize LatestIndicatorTime = arg_max(TimeGenerated, *) by IndicatorId
| where Active == true and ExpirationDateTime > now()
// Filter indicators that have a non-empty domain name
| where isnotempty(DomainName)
| extend TI_DomainEntity = DomainName;
// Join threat intelligence indicators with common security logs
Domain_Indicators
| join kind=innerunique (
CommonSecurityLog
let SecurityLog = materialize(
CommonSecurityLog
// Filter common security logs based on the specified time range
| extend IngestionTime = ingestion_time()
| where IngestionTime > ago(dt_lookBack)
@ -65,12 +38,20 @@ query: |
| extend Domain = trim('"', tostring(parse_url(PA_Url).Host))
| where isnotempty(Domain)
| extend Domain = tolower(Domain)
| extend parts = split(Domain, '.')
| extend tld = parts[(array_length(parts) - 1)]
// Validate parsed domain by checking if the TLD is in the threat feed's TLD list
| where tld in~ (list_tlds)
| extend CommonSecurityLog_TimeGenerated = TimeGenerated
) on $left.TI_DomainEntity == $right.Domain
);
let LogDomains = SecurityLog | distinct Domain | summarize make_list(Domain);
// Retrieve threat intelligence indicators within the specified time range
let Domain_Indicators = materialize(
ThreatIntelligenceIndicator
| where isnotempty(DomainName)
| where TimeGenerated >= ago(ioc_lookBack)
| extend TI_DomainEntity = tolower(DomainName)
| where TI_DomainEntity in (LogDomains)
| summarize LatestIndicatorTime = arg_max(TimeGenerated, *) by IndicatorId
| where Active == true and ExpirationDateTime > now());
// Join threat intelligence indicators with common security logs
Domain_Indicators | join kind=innerunique (SecurityLog) on $left.TI_DomainEntity == $right.Domain
| where CommonSecurityLog_TimeGenerated < ExpirationDateTime
| summarize CommonSecurityLog_TimeGenerated = arg_max(CommonSecurityLog_TimeGenerated, *) by IndicatorId
| project CommonSecurityLog_TimeGenerated, Description, ActivityGroupNames, PA_Url, Domain, IndicatorId, ThreatType, ExpirationDateTime, ConfidenceScore, DeviceAction, DestinationIP, DestinationPort, DeviceName, SourceIP, SourcePort, ApplicationProtocol, RequestMethod, Type, TI_DomainEntity
@ -88,5 +69,5 @@ entityMappings:
fieldMappings:
- identifier: Url
columnName: PA_Url
version: 1.4.0
version: 1.4.1
kind: Scheduled

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

@ -28,11 +28,11 @@ query: |
let ioc_lookBack = 14d; // Look back 14 days for threat intelligence indicators
// Fetch threat intelligence indicators related to domains
let Domain_Indicators = ThreatIntelligenceIndicator
// Filter out indicators without domain names
| where isnotempty(DomainName)
| where TimeGenerated >= ago(ioc_lookBack)
| summarize LatestIndicatorTime = arg_max(TimeGenerated, *) by IndicatorId
| where Active == true and ExpirationDateTime > now()
// Filter out indicators without domain names
| where isnotempty(DomainName)
| extend TI_DomainEntity = DomainName;
// Create a list of TLDs in our threat feed for later validation
let maxListSize = 100000; // Define the maximum allowed size for each list
@ -81,5 +81,5 @@ entityMappings:
fieldMappings:
- identifier: Url
columnName: Url
version: 1.4.0
version: 1.4.1
kind: Scheduled

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

@ -0,0 +1,54 @@
id: 96307710-8bb9-4b45-8363-a90c72ebf86f
name: TI map Domain entity to EmailEvents
description: |
'Identifies a match in EmailEvents table from any Domain IOC from TI'
severity: Medium
requiredDataConnectors:
- connectorId: Office365
dataTypes:
- EmailEvents
- connectorId: ThreatIntelligence
dataTypes:
- ThreatIntelligenceIndicator
- connectorId: ThreatIntelligenceTaxii
dataTypes:
- ThreatIntelligenceIndicator
- connectorId: MicrosoftDefenderThreatIntelligence
dataTypes:
- ThreatIntelligenceIndicator
queryFrequency: 1h
queryPeriod: 14d
triggerOperator: gt
triggerThreshold: 0
tactics:
- Impact
query: |
let dt_lookBack = 1h;
let ioc_lookBack = 14d;
let EmailEvents_ = materialize(EmailEvents | where isnotempty(RecipientEmailAddress) and isnotempty(SenderFromAddress) and TimeGenerated >= ago(dt_lookBack) and DeliveryAction !has "Blocked" | project-rename EmailEvents_TimeGenerated = TimeGenerated | extend SenderFromDomain = tolower(SenderFromDomain) | extend RecipientEmailDomain = tolower(tostring(split(RecipientEmailAddress, '@', 1))));
let SenderDomains = EmailEvents_ | distinct SenderFromDomain | summarize make_list(SenderFromDomain);
let RecipientDomains = EmailEvents_ | distinct RecipientEmailDomain | summarize make_list(RecipientEmailDomain);
let TI = materialize(ThreatIntelligenceIndicator
| where TimeGenerated >= ago(ioc_lookBack)
| where isnotempty(DomainName)
| extend TI_Domain = tolower(DomainName)
| where TI_Domain in (SenderDomains) or TI_Domain in (RecipientDomains)
| summarize LatestIndicatorTime = arg_max(TimeGenerated, *) by IndicatorId
| where Active == true and ExpirationDateTime > now());
(union
(TI | join kind=innerunique (EmailEvents_) on $left.TI_Domain == $right.SenderFromDomain),
(TI | join kind=innerunique (EmailEvents_) on $left.TI_Domain == $right.RecipientEmailDomain))
| where EmailEvents_TimeGenerated < ExpirationDateTime
| summarize EmailEvents_TimeGenerated = arg_max(EmailEvents_TimeGenerated, *) by IndicatorId, RecipientEmailAddress
| project EmailEvents_TimeGenerated, Description, ActivityGroupNames, IndicatorId, ThreatType, ExpirationDateTime, ConfidenceScore, DomainName, RecipientEmailAddress, SenderFromAddress, Subject, ConfidenceLevel, Url, Type, TI_Domain, TrafficLightProtocolLevel, DeliveryAction, DeliveryLocation, EmailDirection
| extend Name = tostring(split(RecipientEmailAddress, '@', 0)[0]), UPNSuffix = tostring(split(RecipientEmailAddress, '@', 1)[0])
| extend timestamp = EmailEvents_TimeGenerated
entityMappings:
- entityType: Account
fieldMappings:
- identifier: Name
columnName: Name
- identifier: UPNSuffix
columnName: UPNSuffix
version: 1.0.0
kind: Scheduled

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

@ -28,10 +28,10 @@ query: |
// Create a list of top-level domains (TLDs) in our threat feed for later validation of extracted domains
let list_tlds =
ThreatIntelligenceIndicator
| where isnotempty(DomainName)
| where TimeGenerated >= ago(ioc_lookBack)
| summarize LatestIndicatorTime = arg_max(TimeGenerated, *) by IndicatorId
| where Active == true and ExpirationDateTime > now()
| where isnotempty(DomainName)
| extend DomainName = tolower(DomainName)
| extend parts = split(DomainName, '.')
| extend tld = parts[(array_length(parts)-1)]
@ -39,11 +39,11 @@ query: |
| summarize make_list(tld);
let Domain_Indicators =
ThreatIntelligenceIndicator
// Filter to pick up only IOC's that contain the entities we want (in this case, DomainName)
| where isnotempty(DomainName)
| where TimeGenerated >= ago(ioc_lookBack)
| summarize LatestIndicatorTime = arg_max(TimeGenerated, *) by IndicatorId
| where Active == true and ExpirationDateTime > now()
// Filter to pick up only IOC's that contain the entities we want (in this case, DomainName)
| where isnotempty(DomainName)
| extend TI_DomainEntity = DomainName;
Domain_Indicators
// Join with CommonSecurityLog to find potential malicious activity
@ -90,5 +90,5 @@ entityMappings:
fieldMappings:
- identifier: Url
columnName: PA_Url
version: 1.4.0
version: 1.4.1
kind: Scheduled

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

@ -26,55 +26,40 @@ triggerThreshold: 0
tactics:
- Impact
query: |
let dt_lookBack = 1h; // Lookback time for recent data, set to 1 hour
let ioc_lookBack = 14d; // Lookback time for threat feed data, set to 14 days
// Create a list of TLDs in our threat feed for later validation
let list_tlds = ThreatIntelligenceIndicator
| where TimeGenerated >= ago(ioc_lookBack)
| summarize LatestIndicatorTime = arg_max(TimeGenerated, *) by IndicatorId
| where Active == true and ExpirationDateTime > now()
| where isnotempty(DomainName)
| extend parts = split(DomainName, '.')
| extend tld = parts[(array_length(parts)-1)]
| summarize count() by tostring(tld)
| summarize make_list(tld);
let Domain_Indicators = ThreatIntelligenceIndicator
| where TimeGenerated >= ago(ioc_lookBack)
| summarize LatestIndicatorTime = arg_max(TimeGenerated, *) by IndicatorId
| where Active == true and ExpirationDateTime > now()
// Picking up only IOC's that contain the entities we want
| where isnotempty(DomainName)
| extend TI_DomainEntity = DomainName;
Domain_Indicators
// Using innerunique to keep performance fast and result set low, we only need one match to indicate potential malicious activity that needs to be investigated
| join kind=innerunique (
SecurityAlert
| where TimeGenerated > ago(dt_lookBack)
| extend MSTI = case(AlertName has "TI map" and VendorName == "Microsoft" and ProductName == 'Azure Sentinel', true, false)
| where MSTI == false
// Extract domain patterns from message
| extend domain = todynamic(dynamic_to_json(extract_all(@"(((xn--)?[a-z0-9\-]+\.)+([a-z]+|(xn--[a-z0-9]+)))", dynamic([1,1]), tolower(Entities))))
| mv-expand domain
| extend domain = tostring(domain[0])
| extend parts = split(domain, '.')
// Split out the TLD
| extend tld = parts[(array_length(parts)-1)]
// Validate parsed domain by checking if the TLD is in the list of TLDs in our threat feed
| where tld in~ (list_tlds)
// Converting Entities into dynamic data type and use mv-expand to unpack the array
| extend EntitiesDynamicArray = parse_json(Entities)
| mv-apply EntitiesDynamicArray on
(summarize
let dt_lookBack = 1h;
let ioc_lookBack = 14d;
let SecurityAlerts = SecurityAlert
| where TimeGenerated > ago(dt_lookBack)
| extend domain = todynamic(dynamic_to_json(extract_all(@"(((xn--)?[a-z0-9\-]+\.)+([a-z]+|(xn--[a-z0-9]+)))", dynamic([1]), tolower(Entities))))
| where isnotempty(domain)
| mv-expand domain
| extend domain = tostring(domain)
| extend EntitiesDynamicArray = parse_json(Entities)
| mv-apply EntitiesDynamicArray on
(summarize
HostName = take_anyif(tostring(EntitiesDynamicArray.HostName), EntitiesDynamicArray.Type == "host"),
IP_addr = take_anyif(tostring(EntitiesDynamicArray.Address), EntitiesDynamicArray.Type == "ip")
)
| extend Alert_TimeGenerated = TimeGenerated
| extend Alert_Description = Description
) on $left.TI_DomainEntity == $right.domain
| where Alert_TimeGenerated < ExpirationDateTime
| summarize Alert_TimeGenerated = arg_max(Alert_TimeGenerated, *) by IndicatorId, AlertName
| project Alert_TimeGenerated, Description, ActivityGroupNames, IndicatorId, ThreatType, ExpirationDateTime, ConfidenceScore, DomainName, AlertName, Alert_Description, ProviderName, AlertSeverity, ConfidenceLevel, HostName, IP_addr, Url, Entities, Type, TI_DomainEntity
| extend timestamp = Alert_TimeGenerated
)
| extend Alert_TimeGenerated = TimeGenerated
| extend Alert_Description = Description;
let AlertDomains = SecurityAlerts
| distinct domain
| summarize make_list(domain);
let Domain_Indicators = materialize(ThreatIntelligenceIndicator
| where isnotempty(DomainName)
| where TimeGenerated >= ago(ioc_lookBack)
| extend TI_DomainEntity = tolower(DomainName)
| where TI_DomainEntity in (AlertDomains)
| summarize LatestIndicatorTime = arg_max(TimeGenerated, *) by IndicatorId
| where Active == true and ExpirationDateTime > now()
| where Description !contains "State: inactive");
Domain_Indicators
// Using innerunique to keep performance fast and result set low, we only need one match to indicate potential malicious activity that needs to be investigated
| join kind=innerunique (SecurityAlerts) on $left.TI_DomainEntity == $right.domain
| where Alert_TimeGenerated < ExpirationDateTime
| summarize Alert_TimeGenerated = arg_max(Alert_TimeGenerated, *) by IndicatorId, AlertName
| project Alert_TimeGenerated, Description, ActivityGroupNames, IndicatorId, ThreatType, ExpirationDateTime, ConfidenceScore, DomainName, AlertName, Alert_Description, ProviderName, AlertSeverity, ConfidenceLevel, HostName, IP_addr, Url, Entities, Type, TI_DomainEntity
| extend timestamp = Alert_TimeGenerated
entityMappings:
- entityType: Host
fieldMappings:
@ -88,5 +73,5 @@ entityMappings:
fieldMappings:
- identifier: Url
columnName: Url
version: 1.4.1
version: 1.4.2
kind: Scheduled

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

@ -27,20 +27,20 @@ query: |
let ioc_lookBack = 14d; // Define the time range to look back for threat intelligence indicators (14 days)
// Create a list of top-level domains (TLDs) from the threat feed for later validation
let list_tlds = ThreatIntelligenceIndicator
| where isnotempty(DomainName)
| where TimeGenerated > ago(ioc_lookBack)
| summarize LatestIndicatorTime = arg_max(TimeGenerated, *) by IndicatorId
| where Active == true and ExpirationDateTime > now()
| where isnotempty(DomainName)
| extend parts = split(DomainName, '.')
| extend tld = parts[(array_length(parts)-1)]
| summarize count() by tostring(tld)
| summarize make_list(tld);
// Fetch the latest active domain indicators from the threat intelligence data within the specified time range
let Domain_Indicators = ThreatIntelligenceIndicator
| where isnotempty(DomainName)
| where TimeGenerated >= ago(ioc_lookBack)
| summarize LatestIndicatorTime = arg_max(TimeGenerated, *) by IndicatorId
| where Active == true and ExpirationDateTime > now()
| where isnotempty(DomainName)
| extend TI_DomainEntity = DomainName;
// Join the threat intelligence indicators with syslog data on matching domain entities
Domain_Indicators
@ -83,5 +83,5 @@ entityMappings:
fieldMappings:
- identifier: Url
columnName: Url
version: 1.4.0
version: 1.4.1
kind: Scheduled

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

@ -13,6 +13,9 @@ requiredDataConnectors:
- connectorId: ThreatIntelligence
dataTypes:
- ThreatIntelligenceIndicator
- connectorId: ThreatIntelligenceTaxii
dataTypes:
- ThreatIntelligenceIndicator
- connectorId: MicrosoftDefenderThreatIntelligence
dataTypes:
- ThreatIntelligenceIndicator
@ -28,11 +31,11 @@ query: |
let ioc_lookBack = 14d;
//Create a list of TLDs in our threat feed for later validation
let DOMAIN_TI=ThreatIntelligenceIndicator
| where TimeGenerated >= ago(ioc_lookBack) and ExpirationDateTime > now()
| summarize LatestIndicatorTime = arg_max(TimeGenerated, *) by IndicatorId
| where Active == true
// Picking up only IOC's that contain the entities we want
| where isnotempty(DomainName);
| where isnotempty(DomainName)
| where TimeGenerated >= ago(ioc_lookBack)
| summarize LatestIndicatorTime = arg_max(TimeGenerated, *) by IndicatorId
| where Active == true and ExpirationDateTime > now();
let DOMAIN_TI_list= todynamic(toscalar(DOMAIN_TI | summarize NIoCs = dcount(DomainName), Domains = make_set(DomainName)
| project Domains=iff(NIoCs > HAS_ANY_MAX, dynamic([]), Domains) ));
DOMAIN_TI
@ -68,5 +71,5 @@ customDetails:
alertDetailsOverride:
alertDisplayNameFormat: A web request from {{SrcIpAddr}} to hostname {{domain}} matched an IoC
alertDescriptionFormat: A client with address {{SrcIpAddr}} requested the URL {{Url}}, whose hostname is a known indicator of compromise of {{ThreatType}}. Consult the threat intelligence blade for more information on the indicator.
version: 1.0.4
version: 1.0.5
kind: Scheduled

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

@ -27,11 +27,11 @@ query: |
let ioc_lookBack = 14d;
let emailregex = @'^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+$';
ThreatIntelligenceIndicator
| where TimeGenerated >= ago(ioc_lookBack) and ExpirationDateTime > now()
| summarize LatestIndicatorTime = arg_max(TimeGenerated, *) by IndicatorId
| where Active == true
//Filtering the table for Email related IOCs
| where isnotempty(EmailSenderAddress)
| where TimeGenerated >= ago(ioc_lookBack)
| summarize LatestIndicatorTime = arg_max(TimeGenerated, *) by IndicatorId
| where Active == true and ExpirationDateTime > now()
// using innerunique to keep perf fast and result set low, we only need one match to indicate potential malicious activity that needs to be investigated
| join kind=innerunique (
AzureActivity | where TimeGenerated >= ago(dt_lookBack) and isnotempty(Caller)
@ -62,5 +62,5 @@ entityMappings:
fieldMappings:
- identifier: Url
columnName: Url
version: 1.2.4
version: 1.2.5
kind: Scheduled

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

@ -0,0 +1,54 @@
id: 11f7c6e3-f066-4b3c-9a81-b487ec0a6873
name: TI map Email entity to EmailEvents
description: |
'Identifies a match in EmailEvents table from any Email IOC from TI'
severity: Medium
requiredDataConnectors:
- connectorId: Office365
dataTypes:
- EmailEvents
- connectorId: ThreatIntelligence
dataTypes:
- ThreatIntelligenceIndicator
- connectorId: ThreatIntelligenceTaxii
dataTypes:
- ThreatIntelligenceIndicator
- connectorId: MicrosoftDefenderThreatIntelligence
dataTypes:
- ThreatIntelligenceIndicator
queryFrequency: 1h
queryPeriod: 14d
triggerOperator: gt
triggerThreshold: 0
tactics:
- Impact
query: |
let dt_lookBack = 1h;
let ioc_lookBack = 14d;
let EmailEvents_ = materialize(EmailEvents | where isnotempty(RecipientEmailAddress) and isnotempty(SenderFromAddress) and TimeGenerated >= ago(dt_lookBack) and DeliveryAction !has "Blocked" | project-rename EmailEvents_TimeGenerated = TimeGenerated | extend SenderFromAddress = tolower(SenderFromAddress) | extend RecipientEmailAddress = tolower(RecipientEmailAddress));
let SenderAddresses = EmailEvents_ | distinct SenderFromAddress | summarize make_list(SenderFromAddress);
let RecipientAddresses = EmailEvents_ | distinct RecipientEmailAddress | summarize make_list(RecipientEmailAddress);
let TI = materialize(ThreatIntelligenceIndicator
| where TimeGenerated >= ago(ioc_lookBack)
| where isnotempty(EmailSenderAddress)
| extend TI_EmailAddress = tolower(EmailSenderAddress)
| where TI_EmailAddress in (SenderAddresses) or TI_EmailAddress in (RecipientAddresses)
| summarize LatestIndicatorTime = arg_max(TimeGenerated, *) by IndicatorId
| where Active == true and ExpirationDateTime > now());
(union
(TI | join kind=innerunique (EmailEvents_) on $left.TI_EmailAddress == $right.SenderFromAddress),
(TI | join kind=innerunique (EmailEvents_) on $left.TI_EmailAddress == $right.RecipientEmailAddress))
| where EmailEvents_TimeGenerated < ExpirationDateTime
| summarize EmailEvents_TimeGenerated = arg_max(EmailEvents_TimeGenerated, *) by IndicatorId, TI_EmailAddress
| project EmailEvents_TimeGenerated, Description, ActivityGroupNames, IndicatorId, ThreatType, ExpirationDateTime, ConfidenceScore, DomainName, RecipientEmailAddress, SenderFromAddress, Subject, ConfidenceLevel, Url, Type, TI_EmailAddress, TrafficLightProtocolLevel, DeliveryAction, DeliveryLocation, EmailDirection
| extend Name = tostring(split(RecipientEmailAddress, '@', 0)[0]), UPNSuffix = tostring(split(RecipientEmailAddress, '@', 1)[0])
| extend timestamp = EmailEvents_TimeGenerated
entityMappings:
- entityType: Account
fieldMappings:
- identifier: Name
columnName: Name
- identifier: UPNSuffix
columnName: UPNSuffix
version: 1.0.0
kind: Scheduled

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

@ -26,23 +26,25 @@ query: |
let dt_lookBack = 1h;
let ioc_lookBack = 14d;
let emailregex = @'^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+$';
let OfficeEvents = materialize(
OfficeActivity
| where isnotempty(UserId)
| where TimeGenerated >= ago(dt_lookBack)
| where UserId matches regex emailregex
| project-rename OfficeActivity_TimeGenerated = TimeGenerated);
let OfficeActivityUPNs = OfficeEvents | distinct UserId = tolower(UserId) | summarize make_list(UserId);
ThreatIntelligenceIndicator
| where TimeGenerated >= ago(ioc_lookBack) and ExpirationDateTime > now()
| summarize LatestIndicatorTime = arg_max(TimeGenerated, *) by IndicatorId
| where Active == true
//Filtering the table for Email related IOCs
| where isnotempty(EmailSenderAddress)
| where TimeGenerated >= ago(ioc_lookBack)
| where tolower(EmailSenderAddress) in (OfficeActivityUPNs)
| summarize LatestIndicatorTime = arg_max(TimeGenerated, *) by IndicatorId
| where Active == true and ExpirationDateTime > now()
| where Description !contains "State: inactive"
// using innerunique to keep perf fast and result set low, we only need one match to indicate potential malicious activity that needs to be investigated
| join kind=innerunique (
OfficeActivity | where TimeGenerated >= ago(dt_lookBack) and isnotempty(UserId)
| where UserId matches regex emailregex
| extend OfficeActivity_TimeGenerated = TimeGenerated
)
on $left.EmailSenderAddress == $right.UserId
| join kind=innerunique (OfficeEvents) on $left.EmailSenderAddress == $right.UserId
| where OfficeActivity_TimeGenerated < ExpirationDateTime
| summarize OfficeActivity_TimeGenerated = arg_max(OfficeActivity_TimeGenerated, *) by IndicatorId, UserId
| project OfficeActivity_TimeGenerated, Description, ActivityGroupNames, IndicatorId, ThreatType, Url, ExpirationDateTime, ConfidenceScore,
EmailSenderName, EmailRecipient, EmailSourceDomain, EmailSourceIpAddress, EmailSubject, FileHashValue, FileHashType, UserId, ClientIP, Operation, UserType, RecordType, OfficeWorkload, Parameters
| project OfficeActivity_TimeGenerated, Description, ActivityGroupNames, IndicatorId, ThreatType, Url, ExpirationDateTime, ConfidenceScore, EmailSenderName, EmailRecipient, EmailSourceDomain, EmailSourceIpAddress, EmailSubject, FileHashValue, FileHashType, UserId, ClientIP, Operation, UserType, RecordType, OfficeWorkload, Parameters
| extend Name = tostring(split(UserId, '@', 0)[0]), UPNSuffix = tostring(split(UserId, '@', 1)[0])
| extend timestamp = OfficeActivity_TimeGenerated
entityMappings:
@ -60,5 +62,5 @@ entityMappings:
fieldMappings:
- identifier: Url
columnName: Url
version: 1.2.4
version: 1.2.5
kind: Scheduled

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

@ -27,11 +27,11 @@ query: |
let ioc_lookBack = 14d;
let emailregex = @'^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+$';
ThreatIntelligenceIndicator
| where TimeGenerated >= ago(ioc_lookBack) and ExpirationDateTime > now()
| summarize LatestIndicatorTime = arg_max(TimeGenerated, *) by IndicatorId
| where Active == true
//Filtering the table for Email related IOCs
| where isnotempty(EmailSenderAddress)
| where TimeGenerated >= ago(ioc_lookBack)
| summarize LatestIndicatorTime = arg_max(TimeGenerated, *) by IndicatorId
| where Active == true and ExpirationDateTime > now()
// using innerunique to keep perf fast and result set low, we only need one match to indicate potential malicious activity that needs to be investigated
| join kind=innerunique (
CommonSecurityLog | where TimeGenerated >= ago(dt_lookBack) and isnotempty(DestinationUserID)
@ -61,5 +61,5 @@ entityMappings:
fieldMappings:
- identifier: Url
columnName: Url
version: 1.2.4
version: 1.2.5
kind: Scheduled

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

@ -27,11 +27,11 @@ query: |
let ioc_lookBack = 14d;
let emailregex = @'^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+$';
ThreatIntelligenceIndicator
| where TimeGenerated >= ago(ioc_lookBack) and ExpirationDateTime > now()
| summarize LatestIndicatorTime = arg_max(TimeGenerated, *) by IndicatorId
| where Active == true
//Filtering the table for Email related IOCs
| where isnotempty(EmailSenderAddress)
| where TimeGenerated >= ago(ioc_lookBack)
| summarize LatestIndicatorTime = arg_max(TimeGenerated, *) by IndicatorId
| where Active == true and ExpirationDateTime > now()
// using innerunique to keep perf fast and result set low, we only need one match to indicate potential malicious activity that needs to be investigated
| join kind=innerunique (
SecurityAlert
@ -67,5 +67,5 @@ entityMappings:
fieldMappings:
- identifier: Url
columnName: Url
version: 1.2.5
version: 1.2.6
kind: Scheduled

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

@ -33,11 +33,11 @@ query: |
let ioc_lookBack = 14d;
let emailregex = @'^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+$';
ThreatIntelligenceIndicator
| where TimeGenerated >= ago(ioc_lookBack) and ExpirationDateTime > now()
| summarize LatestIndicatorTime = arg_max(TimeGenerated, *) by IndicatorId
| where Active == true
//Filtering the table for Email related IOCs
| where isnotempty(EmailSenderAddress)
| where TimeGenerated >= ago(ioc_lookBack)
| summarize LatestIndicatorTime = arg_max(TimeGenerated, *) by IndicatorId
| where Active == true and ExpirationDateTime > now()
// using innerunique to keep perf fast and result set low, we only need one match to indicate potential malicious activity that needs to be investigated
| join kind=innerunique (
(union isfuzzy=true
@ -85,5 +85,5 @@ entityMappings:
fieldMappings:
- identifier: Url
columnName: Url
version: 1.3.4
version: 1.3.5
kind: Scheduled

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

@ -29,37 +29,31 @@ query: |
let dt_lookBack = 1h;
let ioc_lookBack = 14d;
let emailregex = @'^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+$';
let aadFunc = (tableName:string){
let Signins = materialize(union isfuzzy=true
( SigninLogs | where TimeGenerated >= ago(dt_lookBack)),
( AADNonInteractiveUserSignInLogs | where TimeGenerated >= ago(dt_lookBack)
| extend Status = todynamic(Status), LocationDetails = todynamic(LocationDetails))
| where isnotempty(UserPrincipalName) and UserPrincipalName matches regex emailregex
| extend UserPrincipalName = tolower(UserPrincipalName)
| extend Status = todynamic(Status), LocationDetails = todynamic(LocationDetails)
| extend StatusCode = tostring(Status.errorCode), StatusDetails = tostring(Status.additionalDetails)
| extend State = tostring(LocationDetails.state), City = tostring(LocationDetails.city), Region = tostring(LocationDetails.countryOrRegion)
| extend SigninLogs_TimeGenerated = TimeGenerated);
let SigninUPNs = Signins | distinct UserPrincipalName | summarize make_list(UserPrincipalName);
ThreatIntelligenceIndicator
| where TimeGenerated >= ago(ioc_lookBack) and ExpirationDateTime > now()
| summarize LatestIndicatorTime = arg_max(TimeGenerated, *) by IndicatorId
| where Active == true
//Filtering the table for Email related IOCs
| where isnotempty(EmailSenderAddress)
// using innerunique to keep perf fast and result set low, we only need one match to indicate potential malicious activity that needs to be investigated
| join kind=innerunique (
table(tableName) | where TimeGenerated >= ago(dt_lookBack) and isnotempty(UserPrincipalName)
//Normalizing the column to lower case for exact match with EmailSenderAddress column
| extend UserPrincipalName = tolower(UserPrincipalName)
| where UserPrincipalName matches regex emailregex
| extend Status = todynamic(DeviceDetail), LocationDetails = todynamic(LocationDetails)
| extend StatusCode = tostring(Status.errorCode), StatusDetails = tostring(Status.additionalDetails)
| extend State = tostring(LocationDetails.state), City = tostring(LocationDetails.city), Region = tostring(LocationDetails.countryOrRegion)
// renaming timestamp column so it is clear the log this came from SigninLogs table
| extend SigninLogs_TimeGenerated = TimeGenerated, Type = Type
)
on $left.EmailSenderAddress == $right.UserPrincipalName
| where TimeGenerated >= ago(ioc_lookBack)
| where EmailSenderAddress in (SigninUPNs)
| summarize LatestIndicatorTime = arg_max(TimeGenerated, *) by IndicatorId
| where Active == true and ExpirationDateTime > now()
| where Description !contains "State: inactive"
| join kind=innerunique (Signins) on $left.EmailSenderAddress == $right.UserPrincipalName
| where SigninLogs_TimeGenerated < ExpirationDateTime
| summarize SigninLogs_TimeGenerated = arg_max(SigninLogs_TimeGenerated, *) by IndicatorId, UserPrincipalName
| project SigninLogs_TimeGenerated, Description, ActivityGroupNames, IndicatorId, ThreatType, Url, ExpirationDateTime, ConfidenceScore,
EmailSenderName, EmailRecipient, EmailSourceDomain, EmailSourceIpAddress, EmailSubject, FileHashValue, FileHashType, IPAddress, UserPrincipalName, AppDisplayName,
StatusCode, StatusDetails, NetworkIP, NetworkDestinationIP, NetworkSourceIP, Type
| project SigninLogs_TimeGenerated, Description, ActivityGroupNames, IndicatorId, ThreatType, Url, ExpirationDateTime, ConfidenceScore, EmailSenderName, EmailRecipient, EmailSourceDomain, EmailSourceIpAddress, EmailSubject, FileHashValue, FileHashType, IPAddress, UserPrincipalName, AppDisplayName, StatusCode, StatusDetails, NetworkIP, NetworkDestinationIP, NetworkSourceIP, Type
| extend Name = tostring(split(UserPrincipalName, '@', 0)[0]), UPNSuffix = tostring(split(UserPrincipalName, '@', 1)[0])
| extend timestamp = SigninLogs_TimeGenerated
};
let aadSignin = aadFunc("SigninLogs");
let aadNonInt = aadFunc("AADNonInteractiveUserSignInLogs");
union isfuzzy=true aadSignin, aadNonInt
entityMappings:
- entityType: Account
fieldMappings:
@ -75,5 +69,5 @@ entityMappings:
fieldMappings:
- identifier: Url
columnName: Url
version: 1.2.4
version: 1.2.5
kind: Scheduled

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

@ -26,10 +26,10 @@ query: |
let dt_lookBack = 1h;
let ioc_lookBack = 14d;
let fileHashIndicators = ThreatIntelligenceIndicator
| where TimeGenerated >= ago(ioc_lookBack) and ExpirationDateTime > now()
| where isnotempty(FileHashValue)
| where TimeGenerated >= ago(ioc_lookBack)
| summarize LatestIndicatorTime = arg_max(TimeGenerated, *) by IndicatorId
| where Active == true
| where isnotempty(FileHashValue);
| where Active == true and ExpirationDateTime > now();
// Handle matches against both lower case and uppercase versions of the hash:
(fileHashIndicators | extend FileHashValue = tolower(FileHashValue)
| union (fileHashIndicators | extend FileHashValue = toupper(FileHashValue)))
@ -75,5 +75,5 @@ entityMappings:
columnName: FileHashValue
- identifier: Algorithm
columnName: FileHashType
version: 1.3.3
version: 1.3.4
kind: Scheduled

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

@ -32,11 +32,11 @@ query: |
let dt_lookBack = 1h;
let ioc_lookBack = 14d;
ThreatIntelligenceIndicator
| where TimeGenerated >= ago(ioc_lookBack) and ExpirationDateTime > now()
| summarize LatestIndicatorTime = arg_max(TimeGenerated, *) by IndicatorId
| where Active == true
| where isnotempty(FileHashValue)
| where TimeGenerated >= ago(ioc_lookBack)
| extend FileHashValue = toupper(FileHashValue)
| summarize LatestIndicatorTime = arg_max(TimeGenerated, *) by IndicatorId
| where Active == true and ExpirationDateTime > now()
// using innerunique to keep perf fast and result set low, we only need one match to indicate potential malicious activity that needs to be investigated
| join kind=innerunique ( union isfuzzy=true
(SecurityEvent | where TimeGenerated >= ago(dt_lookBack)
@ -81,5 +81,5 @@ entityMappings:
columnName: FileHashValue
- identifier: Algorithm
columnName: FileHashType
version: 1.4.3
version: 1.4.4
kind: Scheduled

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

@ -27,17 +27,17 @@ query: |
let ioc_lookBack = 14d; // Look back 14 days for threat intelligence indicators
// Fetch threat intelligence indicators related to IP addresses
let IP_Indicators = ThreatIntelligenceIndicator
| where TimeGenerated >= ago(ioc_lookBack)
| summarize LatestIndicatorTime = arg_max(TimeGenerated, *) by IndicatorId
| where Active == true and ExpirationDateTime > now()
// Filter out indicators without relevant IP address fields
| where isnotempty(NetworkIP) or isnotempty(EmailSourceIpAddress) or isnotempty(NetworkDestinationIP) or isnotempty(NetworkSourceIP)
| where TimeGenerated >= ago(ioc_lookBack)
// Select the IP entity based on availability of different IP fields
| extend TI_ipEntity = iff(isnotempty(NetworkIP), NetworkIP, NetworkDestinationIP)
| extend TI_ipEntity = iff(isempty(TI_ipEntity) and isnotempty(NetworkSourceIP), NetworkSourceIP, TI_ipEntity)
| extend TI_ipEntity = iff(isempty(TI_ipEntity) and isnotempty(EmailSourceIpAddress), EmailSourceIpAddress, TI_ipEntity)
// Exclude local addresses using the ipv4_is_private operator and filtering out specific address prefixes
| where ipv4_is_private(TI_ipEntity) == false and TI_ipEntity !startswith "fe80" and TI_ipEntity !startswith "::" and TI_ipEntity !startswith "127.";
| where ipv4_is_private(TI_ipEntity) == false and TI_ipEntity !startswith "fe80" and TI_ipEntity !startswith "::" and TI_ipEntity !startswith "127."
| summarize LatestIndicatorTime = arg_max(TimeGenerated, *) by IndicatorId
| where Active == true and ExpirationDateTime > now();
// Perform a join between IP indicators and AWSCloudTrail logs to identify potential malicious activity
IP_Indicators
// Use innerunique to keep performance fast and result set low, as we only need one match to indicate potential malicious activity that needs investigation
@ -70,5 +70,5 @@ entityMappings:
fieldMappings:
- identifier: Url
columnName: Url
version: 1.4.0
version: 1.4.1
kind: Scheduled

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

@ -24,23 +24,23 @@ query: |
let ioc_lookBack = 14d; // Look back 14 days for threat intelligence indicators
// Fetch threat intelligence indicators related to IP addresses
let IP_Indicators = ThreatIntelligenceIndicator
| where TimeGenerated >= ago(ioc_lookBack)
| summarize LatestIndicatorTime = arg_max(TimeGenerated, *) by IndicatorId
| where Active == true and ExpirationDateTime > now()
// Filter out indicators without relevant IP address fields
| where isnotempty(NetworkIP) or isnotempty(EmailSourceIpAddress) or isnotempty(NetworkDestinationIP) or isnotempty(NetworkSourceIP)
| where TimeGenerated >= ago(ioc_lookBack)
// Filtering out rows where the Confidence Score is less than 50 as they would not have an Alert Priority label.
| where ConfidenceScore > 50
// Select the IP entity based on availability of different IP fields
| extend TI_ipEntity = iff(isnotempty(NetworkIP), NetworkIP, NetworkDestinationIP)
| extend TI_ipEntity = iff(isempty(TI_ipEntity) and isnotempty(NetworkSourceIP), NetworkSourceIP, TI_ipEntity)
| extend TI_ipEntity = iff(isempty(TI_ipEntity) and isnotempty(EmailSourceIpAddress), EmailSourceIpAddress, TI_ipEntity)
// Filtering out rows where the Confidence Score is less than 50 as they would not have an Alert Priority label.
| where ConfidenceScore > 50
// Determine AlertPriority based on ConfidenceScore
| extend AlertPriority = case(ConfidenceScore > 82, "High",
ConfidenceScore > 74, "Medium",
"Low")
// Exclude local addresses using the ipv4_is_private operator and filtering out specific address prefixes
| where ipv4_is_private(TI_ipEntity) == false and TI_ipEntity !startswith "fe80" and TI_ipEntity !startswith "::" and TI_ipEntity !startswith "127.";
| where ipv4_is_private(TI_ipEntity) == false and TI_ipEntity !startswith "fe80" and TI_ipEntity !startswith "::" and TI_ipEntity !startswith "127."
| summarize LatestIndicatorTime = arg_max(TimeGenerated, *) by IndicatorId
| where Active == true and ExpirationDateTime > now();
// Perform a join between IP indicators and AppServiceHTTPLogs to identify potential malicious activity
IP_Indicators
// Use innerunique to keep performance fast and result set low, as we only need one match to indicate potential malicious activity that needs investigation
@ -86,6 +86,6 @@ entityMappings:
columnName: _ResourceId
alertDetailsOverride:
alertSeverityColumnName: AlertPriority
version: 1.5.0
version: 1.5.1
kind: Scheduled

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

@ -27,17 +27,17 @@ query: |
let ioc_lookBack = 14d; // Look back 14 days for threat intelligence indicators
// Fetch threat intelligence indicators related to IP addresses
let IP_Indicators = ThreatIntelligenceIndicator
| where TimeGenerated >= ago(ioc_lookBack)
| summarize LatestIndicatorTime = arg_max(TimeGenerated, *) by IndicatorId
| where Active == true and ExpirationDateTime > now()
// Filter out indicators without relevant IP address fields
| where isnotempty(NetworkIP) or isnotempty(EmailSourceIpAddress) or isnotempty(NetworkDestinationIP) or isnotempty(NetworkSourceIP)
| where TimeGenerated >= ago(ioc_lookBack)
// Select the IP entity based on availability of different IP fields
| extend TI_ipEntity = iff(isnotempty(NetworkIP), NetworkIP, NetworkDestinationIP)
| extend TI_ipEntity = iff(isempty(TI_ipEntity) and isnotempty(NetworkSourceIP), NetworkSourceIP, TI_ipEntity)
| extend TI_ipEntity = iff(isempty(TI_ipEntity) and isnotempty(EmailSourceIpAddress), EmailSourceIpAddress, TI_ipEntity)
// Exclude local addresses using the ipv4_is_private operator and filtering out specific address prefixes
| where ipv4_is_private(TI_ipEntity) == false and TI_ipEntity !startswith "fe80" and TI_ipEntity !startswith "::" and TI_ipEntity !startswith "127.";
| where ipv4_is_private(TI_ipEntity) == false and TI_ipEntity !startswith "fe80" and TI_ipEntity !startswith "::" and TI_ipEntity !startswith "127."
| summarize LatestIndicatorTime = arg_max(TimeGenerated, *) by IndicatorId
| where Active == true and ExpirationDateTime > now();
// Perform a join between IP indicators and AzureActivity logs to identify potential malicious activity
IP_Indicators
// using innerunique to keep perf fast and result set low, we only need one match to indicate potential malicious activity that needs to be investigated
@ -76,5 +76,5 @@ entityMappings:
fieldMappings:
- identifier: ResourceId
columnName: ResourceId
version: 1.4.0
version: 1.4.1
kind: Scheduled

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

@ -27,17 +27,17 @@ query: |
let ioc_lookBack = 14d; // Look back 14 days for threat intelligence indicators
// Fetch threat intelligence indicators related to IP addresses
let IP_Indicators = ThreatIntelligenceIndicator
| where TimeGenerated >= ago(ioc_lookBack)
| summarize LatestIndicatorTime = arg_max(TimeGenerated, *) by IndicatorId
| where Active == true and ExpirationDateTime > now()
// Filter out indicators without relevant IP address fields
| where isnotempty(NetworkIP) or isnotempty(EmailSourceIpAddress) or isnotempty(NetworkDestinationIP) or isnotempty(NetworkSourceIP)
| where TimeGenerated >= ago(ioc_lookBack)
// Select the IP entity based on availability of different IP fields
| extend TI_ipEntity = iff(isnotempty(NetworkIP), NetworkIP, NetworkDestinationIP)
| extend TI_ipEntity = iff(isempty(TI_ipEntity) and isnotempty(NetworkSourceIP), NetworkSourceIP, TI_ipEntity)
| extend TI_ipEntity = iff(isempty(TI_ipEntity) and isnotempty(EmailSourceIpAddress), EmailSourceIpAddress, TI_ipEntity)
// Exclude local addresses using the ipv4_is_private operator and filtering out specific address prefixes
| where ipv4_is_private(TI_ipEntity) == false and TI_ipEntity !startswith "fe80" and TI_ipEntity !startswith "::" and TI_ipEntity !startswith "127.";
| where ipv4_is_private(TI_ipEntity) == false and TI_ipEntity !startswith "fe80" and TI_ipEntity !startswith "::" and TI_ipEntity !startswith "127."
| summarize LatestIndicatorTime = arg_max(TimeGenerated, *) by IndicatorId
| where Active == true and ExpirationDateTime > now();
// Perform a join between IP indicators and AzureDiagnostics logs to identify potential malicious activity
IP_Indicators
// Use innerunique to keep performance fast and result set low, as we only need one match to indicate potential malicious activity that needs investigation
@ -72,5 +72,5 @@ entityMappings:
fieldMappings:
- identifier: Url
columnName: Url
version: 1.3.0
version: 1.3.1
kind: Scheduled

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

@ -27,14 +27,14 @@ query: |
let ioc_lookBack = 14d; // Look back 14 days for threat intelligence indicators
// Fetch threat intelligence indicators related to IP addresses
let IP_Indicators = ThreatIntelligenceIndicator
| summarize LatestIndicatorTime = arg_max(TimeGenerated, *) by IndicatorId
| where Active == true
| where isnotempty(NetworkIP) or isnotempty(EmailSourceIpAddress) or isnotempty(NetworkDestinationIP) or isnotempty(NetworkSourceIP)
| where LatestIndicatorTime >= ago(ioc_lookBack) and ExpirationDateTime > now()
| where TimeGenerated >= ago(ioc_lookBack)
| extend TI_ipEntity = iff(isnotempty(NetworkIP), NetworkIP, NetworkDestinationIP)
| extend TI_ipEntity = iff(isempty(TI_ipEntity) and isnotempty(NetworkSourceIP), NetworkSourceIP, TI_ipEntity)
| extend TI_ipEntity = iff(isempty(TI_ipEntity) and isnotempty(EmailSourceIpAddress), EmailSourceIpAddress, TI_ipEntity)
| where ipv4_is_private(TI_ipEntity) == false and TI_ipEntity !startswith "fe80" and TI_ipEntity !startswith "::" and TI_ipEntity !startswith "127.";
| where ipv4_is_private(TI_ipEntity) == false and TI_ipEntity !startswith "fe80" and TI_ipEntity !startswith "::" and TI_ipEntity !startswith "127."
| summarize LatestIndicatorTime = arg_max(TimeGenerated, *) by IndicatorId
| where Active == true and ExpirationDateTime > now();
// Perform a join between IP indicators and AzureDiagnostics logs for Key Vault events
IP_Indicators
// Use innerunique to keep performance fast and result set low, as we only need one match to indicate potential malicious activity that needs investigation
@ -64,5 +64,5 @@ entityMappings:
fieldMappings:
- identifier: ResourceId
columnName: ResourceId
version: 1.3.2
version: 1.3.3
kind: Scheduled

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

@ -24,14 +24,14 @@ query: |
let ioc_lookBack = 14d; // Look back 14 days for threat intelligence indicators
// Fetch threat intelligence indicators related to IP addresses
let IP_Indicators = ThreatIntelligenceIndicator
| where TimeGenerated >= ago(ioc_lookBack)
| summarize LatestIndicatorTime = arg_max(TimeGenerated, *) by IndicatorId
| where Active == true and ExpirationDateTime > now()
| where isnotempty(NetworkIP) or isnotempty(EmailSourceIpAddress) or isnotempty(NetworkDestinationIP) or isnotempty(NetworkSourceIP)
| where TimeGenerated >= ago(ioc_lookBack)
| extend TI_ipEntity = iff(isnotempty(NetworkIP), NetworkIP, NetworkDestinationIP)
| extend TI_ipEntity = iff(isempty(TI_ipEntity) and isnotempty(NetworkSourceIP), NetworkSourceIP, TI_ipEntity)
| extend TI_ipEntity = iff(isempty(TI_ipEntity) and isnotempty(EmailSourceIpAddress), EmailSourceIpAddress, TI_ipEntity)
| where ipv4_is_private(TI_ipEntity) == false and TI_ipEntity !startswith "fe80" and TI_ipEntity !startswith "::" and TI_ipEntity !startswith "127.";
| where ipv4_is_private(TI_ipEntity) == false and TI_ipEntity !startswith "fe80" and TI_ipEntity !startswith "::" and TI_ipEntity !startswith "127."
| summarize LatestIndicatorTime = arg_max(TimeGenerated, *) by IndicatorId
| where Active == true and ExpirationDateTime > now();
// Perform a join between IP indicators and AzureNetworkAnalytics_CL logs for NSG Flow information
IP_Indicators
// Use innerunique to keep performance fast and result set low, as we only need one match to indicate potential malicious activity that needs investigation
@ -71,5 +71,5 @@ entityMappings:
fieldMappings:
- identifier: Url
columnName: Url
version: 1.4.0
version: 1.4.1
kind: Scheduled

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

@ -27,14 +27,14 @@ query: |
let ioc_lookBack = 14d; // Look back 14 days for threat intelligence indicators
// Fetch threat intelligence indicators related to IP addresses
let IP_Indicators = ThreatIntelligenceIndicator
| where TimeGenerated >= ago(ioc_lookBack)
| summarize LatestIndicatorTime = arg_max(TimeGenerated, *) by IndicatorId
| where Active == true and ExpirationDateTime > now()
| where isnotempty(NetworkIP) or isnotempty(EmailSourceIpAddress) or isnotempty(NetworkDestinationIP) or isnotempty(NetworkSourceIP)
| where TimeGenerated >= ago(ioc_lookBack)
| extend TI_ipEntity = iff(isnotempty(NetworkIP), NetworkIP, NetworkDestinationIP)
| extend TI_ipEntity = iff(isempty(TI_ipEntity) and isnotempty(NetworkSourceIP), NetworkSourceIP, TI_ipEntity)
| extend TI_ipEntity = iff(isempty(TI_ipEntity) and isnotempty(EmailSourceIpAddress), EmailSourceIpAddress, TI_ipEntity)
| where ipv4_is_private(TI_ipEntity) == false and TI_ipEntity !startswith "fe80" and TI_ipEntity !startswith "::" and TI_ipEntity !startswith "127.";
| where ipv4_is_private(TI_ipEntity) == false and TI_ipEntity !startswith "fe80" and TI_ipEntity !startswith "::" and TI_ipEntity !startswith "127."
| summarize LatestIndicatorTime = arg_max(TimeGenerated, *) by IndicatorId
| where Active == true and ExpirationDateTime > now();
// Perform a join between IP indicators and AzureDiagnostics logs for SQL Security Audit events
IP_Indicators
// Use innerunique to keep performance fast and result set low, as we only need one match to indicate potential malicious activity that needs investigation
@ -64,5 +64,5 @@ entityMappings:
fieldMappings:
- identifier: Address
columnName: ClientIP
version: 1.3.0
version: 1.3.1
kind: Scheduled

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

@ -28,14 +28,14 @@ query: |
let ioc_lookBack = 14d; // Look back 14 days for threat intelligence indicators
// Fetch threat intelligence indicators related to IP addresses
let IP_Indicators = ThreatIntelligenceIndicator
| where TimeGenerated >= ago(ioc_lookBack)
| summarize LatestIndicatorTime = arg_max(TimeGenerated, *) by IndicatorId
| where Active == true and ExpirationDateTime > now()
| where isnotempty(NetworkIP) or isnotempty(EmailSourceIpAddress) or isnotempty(NetworkDestinationIP) or isnotempty(NetworkSourceIP)
| where TimeGenerated >= ago(ioc_lookBack)
| extend TI_ipEntity = iff(isnotempty(NetworkIP), NetworkIP, NetworkDestinationIP)
| extend TI_ipEntity = iff(isempty(TI_ipEntity) and isnotempty(NetworkSourceIP), NetworkSourceIP, TI_ipEntity)
| extend TI_ipEntity = iff(isempty(TI_ipEntity) and isnotempty(EmailSourceIpAddress), EmailSourceIpAddress, TI_ipEntity)
| where ipv4_is_private(TI_ipEntity) == false and TI_ipEntity !startswith "fe80" and TI_ipEntity !startswith "::" and TI_ipEntity !startswith "127.";
| where ipv4_is_private(TI_ipEntity) == false and TI_ipEntity !startswith "fe80" and TI_ipEntity !startswith "::" and TI_ipEntity !startswith "127."
| summarize LatestIndicatorTime = arg_max(TimeGenerated, *) by IndicatorId
| where Active == true and ExpirationDateTime > now();
// Perform a join between IP indicators and CommonSecurityLog events
IP_Indicators
// Use innerunique to keep performance fast and result set low, as we only need one match to indicate potential malicious activity that needs investigation
@ -59,5 +59,5 @@ entityMappings:
fieldMappings:
- identifier: Address
columnName: CS_ipEntity
version: 1.2.0
version: 1.2.1
kind: Scheduled

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

@ -27,14 +27,14 @@ query: |
let ioc_lookBack = 14d; // Look back 14 days for threat intelligence indicators
// Fetch threat intelligence indicators related to IP addresses
let IP_Indicators = ThreatIntelligenceIndicator
| where TimeGenerated >= ago(ioc_lookBack)
| summarize LatestIndicatorTime = arg_max(TimeGenerated, *) by IndicatorId
| where Active == true and ExpirationDateTime > now()
| where isnotempty(NetworkIP) or isnotempty(EmailSourceIpAddress) or isnotempty(NetworkDestinationIP) or isnotempty(NetworkSourceIP)
| where TimeGenerated >= ago(ioc_lookBack)
| extend TI_ipEntity = iff(isnotempty(NetworkIP), NetworkIP, NetworkDestinationIP)
| extend TI_ipEntity = iff(isempty(TI_ipEntity) and isnotempty(NetworkSourceIP), NetworkSourceIP, TI_ipEntity)
| extend TI_ipEntity = iff(isempty(TI_ipEntity) and isnotempty(EmailSourceIpAddress), EmailSourceIpAddress, TI_ipEntity)
| where ipv4_is_private(TI_ipEntity) == false and TI_ipEntity !startswith "fe80" and TI_ipEntity !startswith "::" and TI_ipEntity !startswith "127.";
| where ipv4_is_private(TI_ipEntity) == false and TI_ipEntity !startswith "fe80" and TI_ipEntity !startswith "::" and TI_ipEntity !startswith "127."
| summarize LatestIndicatorTime = arg_max(TimeGenerated, *) by IndicatorId
| where Active == true and ExpirationDateTime > now();
// Perform a join between IP indicators and DNS events
IP_Indicators
// Use innerunique to keep performance fast and result set low, as we only need one match to indicate potential malicious activity that needs investigation
@ -69,5 +69,5 @@ entityMappings:
fieldMappings:
- identifier: Url
columnName: Url
version: 1.4.0
version: 1.4.1
kind: Scheduled

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

@ -26,16 +26,16 @@ query: |
let dt_lookBack = 1h;
let ioc_lookBack = 14d;
ThreatIntelligenceIndicator
| where TimeGenerated >= ago(ioc_lookBack) and ExpirationDateTime > now()
| summarize LatestIndicatorTime = arg_max(TimeGenerated, *) by IndicatorId
| where Active == true
// Picking up only IOC's that contain the entities we want
| where isnotempty(NetworkIP) or isnotempty(EmailSourceIpAddress) or isnotempty(NetworkDestinationIP) or isnotempty(NetworkSourceIP)
| where TimeGenerated >= ago(ioc_lookBack)
// As there is potentially more than 1 indicator type for matching IP, taking NetworkIP first, then others if that is empty.
// Taking the first non-empty value based on potential IOC match availability
| extend TI_ipEntity = iff(isnotempty(NetworkIP), NetworkIP, NetworkDestinationIP)
| extend TI_ipEntity = iff(isempty(TI_ipEntity) and isnotempty(NetworkSourceIP), NetworkSourceIP, TI_ipEntity)
| extend TI_ipEntity = iff(isempty(TI_ipEntity) and isnotempty(EmailSourceIpAddress), EmailSourceIpAddress, TI_ipEntity)
| summarize LatestIndicatorTime = arg_max(TimeGenerated, *) by IndicatorId
| where Active == true and ExpirationDateTime > now()
| join (
DuoSecurityAuthentication_CL
| where TimeGenerated >= ago(dt_lookBack)
@ -44,7 +44,9 @@ query: |
| extend Duo_TimeGenerated = isotimestamp_t
)
on $left.TI_ipEntity == $right.access_device_ip_s
| where TimeGenerated >= ago(ioc_lookBack)
| summarize LatestIndicatorTime = arg_max(TimeGenerated, *) by IndicatorId
| where Active == true and ExpirationDateTime > now()
| project LatestIndicatorTime, Description, ActivityGroupNames, IndicatorId, ThreatType, Url, ExpirationDateTime, ConfidenceScore, Duo_TimeGenerated,
TI_ipEntity, user_name_s, factor_s, result_s, application_name_s, event_type_s, txid_g, user_key_s, access_device_ip_s, access_device_location_city_s, access_device_location_state_s, access_device_location_country_s
| extend timestamp = Duo_TimeGenerated, Name = tostring(split(user_name_s, '@', 0)[0]), UPNSuffix = tostring(split(user_name_s, '@', 1)[0])
@ -59,5 +61,5 @@ entityMappings:
fieldMappings:
- identifier: Address
columnName: access_device_ip_s
version: 1.0.3
version: 1.0.4
kind: Scheduled

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

@ -25,36 +25,33 @@ tactics:
query: |
let dt_lookBack = 1h; // Look back 1 hour for OfficeActivity events
let ioc_lookBack = 14d; // Look back 14 days for threat intelligence indicators
let OfficeActivity_ = materialize(OfficeActivity
| where isnotempty(ClientIP)
| where TimeGenerated >= ago(dt_lookBack)
| extend ClientIPValues = extract_all(@'\[?(::ffff:)?(?P<IPAddress>(\d+\.\d+\.\d+\.\d+)|[^\]%]+)(%\d+)?\]?([-:](?P<Port>\d+))?', dynamic(["IPAddress", "Port"]), ClientIP)[0]
| extend IPAddress = iff(array_length(ClientIPValues) > 0, tostring(ClientIPValues[0]), '')
| project-rename OfficeActivity_TimeGenerated = TimeGenerated);
let ActivityIPs = OfficeActivity_ | summarize IPs = make_list(IPAddress);
// Fetch threat intelligence indicators related to IP addresses
let IP_Indicators = ThreatIntelligenceIndicator
| where TimeGenerated >= ago(ioc_lookBack)
| summarize LatestIndicatorTime = arg_max(TimeGenerated, *) by IndicatorId
| where Active == true and ExpirationDateTime > now()
let IP_Indicators = materialize(ThreatIntelligenceIndicator
| where isnotempty(NetworkIP) or isnotempty(EmailSourceIpAddress) or isnotempty(NetworkDestinationIP) or isnotempty(NetworkSourceIP)
| extend TI_ipEntity = iff(isnotempty(NetworkIP), NetworkIP, NetworkDestinationIP)
| extend TI_ipEntity = iff(isempty(TI_ipEntity) and isnotempty(NetworkSourceIP), NetworkSourceIP, TI_ipEntity)
| extend TI_ipEntity = iff(isempty(TI_ipEntity) and isnotempty(EmailSourceIpAddress), EmailSourceIpAddress, TI_ipEntity)
| where ipv4_is_private(TI_ipEntity) == false and TI_ipEntity !startswith "fe80" and TI_ipEntity !startswith "::" and TI_ipEntity !startswith "127.";
// Perform a join between IP indicators and OfficeActivity events
| where TimeGenerated >= ago(ioc_lookBack)
| extend TI_ipEntity = coalesce(NetworkDestinationIP, NetworkSourceIP, EmailSourceIpAddress)
| where TI_ipEntity in (ActivityIPs)
| summarize LatestIndicatorTime = arg_max(TimeGenerated, *) by IndicatorId
| where Active == true and ExpirationDateTime > now()
| where Description !contains "State: inactive");
IP_Indicators
// Use innerunique to keep performance fast and result set low, as we only need one match to indicate potential malicious activity that needs investigation
| join kind=innerunique (
OfficeActivity
| where TimeGenerated >= ago(dt_lookBack)
| where isnotempty(ClientIP)
| extend ClientIPValues = extract_all(@'\[?(::ffff:)?(?P<IPAddress>(\d+\.\d+\.\d+\.\d+)|[^\]%]+)(%\d+)?\]?([-:](?P<Port>\d+))?', dynamic(["IPAddress", "Port"]), ClientIP)[0]
| extend IPAddress = iff(array_length(ClientIPValues) > 0, tostring(ClientIPValues[0]), '')
| extend OfficeActivity_TimeGenerated = TimeGenerated
)
// Use innerunique to keep performance fast and result set low, as we only need one match to indicate potential malicious activity that needs investigation
| join kind=innerunique (OfficeActivity_)
on $left.TI_ipEntity == $right.IPAddress
// Filter out OfficeActivity events that occurred after the expiration of the corresponding indicator
| where OfficeActivity_TimeGenerated < ExpirationDateTime
// Group the results by IndicatorId and keep the OfficeActivity event with the latest timestamp
| summarize OfficeActivity_TimeGenerated = arg_max(OfficeActivity_TimeGenerated, *) by IndicatorId
// Select the desired output fields
| project OfficeActivity_TimeGenerated, Description, ActivityGroupNames, IndicatorId, ThreatType, Url, ExpirationDateTime, ConfidenceScore,
TI_ipEntity, ClientIP, UserId, Operation, ResultStatus, RecordType, OfficeObjectId, NetworkIP, NetworkDestinationIP, NetworkSourceIP, EmailSourceIpAddress, Type
| extend timestamp = OfficeActivity_TimeGenerated, Name = tostring(split(UserId, '@', 0)[0]), UPNSuffix = tostring(split(UserId, '@', 1)[0])
// Filter out OfficeActivity events that occurred after the expiration of the corresponding indicator
| where OfficeActivity_TimeGenerated < ExpirationDateTime
// Group the results by IndicatorId and keep the OfficeActivity event with the latest timestamp
| summarize OfficeActivity_TimeGenerated = arg_max(OfficeActivity_TimeGenerated, *) by IndicatorId
// Select the desired output fields
| project OfficeActivity_TimeGenerated, Description, ActivityGroupNames, IndicatorId, ThreatType, Url, ExpirationDateTime, ConfidenceScore, TI_ipEntity, ClientIP, UserId, Operation, ResultStatus, RecordType, OfficeObjectId, NetworkIP, NetworkDestinationIP, NetworkSourceIP, EmailSourceIpAddress, Type
| extend timestamp = OfficeActivity_TimeGenerated, Name = tostring(split(UserId, '@', 0)[0]), UPNSuffix = tostring(split(UserId, '@', 1)[0])
entityMappings:
- entityType: Account
fieldMappings:
@ -70,5 +67,5 @@ entityMappings:
fieldMappings:
- identifier: Url
columnName: Url
version: 1.4.0
version: 1.4.1
kind: Scheduled

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

@ -28,37 +28,30 @@ tactics:
query: |
let dt_lookBack = 1h;
let ioc_lookBack = 14d;
let aadFunc = (tableName:string){
ThreatIntelligenceIndicator
| where TimeGenerated >= ago(ioc_lookBack) and ExpirationDateTime > now()
| summarize LatestIndicatorTime = arg_max(TimeGenerated, *) by IndicatorId
| where Active == true
// Picking up only IOC's that contain the entities we want
| where isnotempty(NetworkIP) or isnotempty(EmailSourceIpAddress) or isnotempty(NetworkDestinationIP) or isnotempty(NetworkSourceIP)
// As there is potentially more than 1 indicator type for matching IP, taking NetworkIP first, then others if that is empty.
// Taking the first non-empty value based on potential IOC match availability
| extend TI_ipEntity = iff(isnotempty(NetworkIP), NetworkIP, NetworkDestinationIP)
| extend TI_ipEntity = iff(isempty(TI_ipEntity) and isnotempty(NetworkSourceIP), NetworkSourceIP, TI_ipEntity)
| extend TI_ipEntity = iff(isempty(TI_ipEntity) and isnotempty(EmailSourceIpAddress), EmailSourceIpAddress, TI_ipEntity)
let Signins = materialize(union isfuzzy=true
(SigninLogs
| where TimeGenerated >= ago(dt_lookBack)),
(AADNonInteractiveUserSignInLogs
| where TimeGenerated >= ago(dt_lookBack)
| extend Status = todynamic(Status), LocationDetails = todynamic(LocationDetails)));
let SigninIPs = Signins | summarize make_list(IPAddress);
let TI = materialize(ThreatIntelligenceIndicator
| where isnotempty(NetworkIP) or isnotempty(EmailSourceIpAddress) or isnotempty(NetworkDestinationIP) or isnotempty(NetworkSourceIP)
| where TimeGenerated >= ago(ioc_lookBack)
| extend TI_ipEntity = coalesce(NetworkIP, EmailSourceIpAddress, NetworkDestinationIP, NetworkSourceIP)
| where TI_ipEntity in (SigninIPs)
| summarize LatestIndicatorTime = arg_max(TimeGenerated, *) by IndicatorId
| where Active == true and ExpirationDateTime > now()
| where Description !contains "State: inactive");
TI
// using innerunique to keep perf fast and result set low, we only need one match to indicate potential malicious activity that needs to be investigated
| join kind=innerunique (
table(tableName) | where TimeGenerated >= ago(dt_lookBack)
| extend Status = todynamic(Status), LocationDetails = todynamic(LocationDetails)
| extend StatusCode = tostring(Status.errorCode), StatusDetails = tostring(Status.additionalDetails), StatusReason = tostring(Status.failureReason)
| extend State = tostring(LocationDetails.state), City = tostring(LocationDetails.city), Region = tostring(LocationDetails.countryOrRegion)
// renaming time column so it is clear the log this came from
| extend SigninLogs_TimeGenerated = TimeGenerated, Type = Type
)
on $left.TI_ipEntity == $right.IPAddress
| join kind=innerunique (Signins) on $left.TI_ipEntity == $right.IPAddress
| project-rename SigninLogs_TimeGenerated = TimeGenerated
| where SigninLogs_TimeGenerated < ExpirationDateTime
| extend StatusCode = tostring(Status.errorCode), StatusDetails = tostring(Status.additionalDetails), StatusReason = tostring(Status.failureReason)
| summarize SigninLogs_TimeGenerated = arg_max(SigninLogs_TimeGenerated, *) by IndicatorId, IPAddress
| project SigninLogs_TimeGenerated, Description, ActivityGroupNames, IndicatorId, ThreatType, Url, ExpirationDateTime, ConfidenceScore,
TI_ipEntity, IPAddress, UserPrincipalName, AppDisplayName, StatusCode, StatusDetails, StatusReason, NetworkIP, NetworkDestinationIP, NetworkSourceIP, EmailSourceIpAddress, Type
| project SigninLogs_TimeGenerated, Description, ActivityGroupNames, IndicatorId, ThreatType, Url, ExpirationDateTime, ConfidenceScore, TI_ipEntity, IPAddress, UserPrincipalName, AppDisplayName, StatusCode, StatusDetails, StatusReason, NetworkIP, NetworkDestinationIP, NetworkSourceIP, EmailSourceIpAddress, Type
| extend timestamp = SigninLogs_TimeGenerated, Name = tostring(split(UserPrincipalName, '@', 0)[0]), UPNSuffix = tostring(split(UserPrincipalName, '@', 1)[0])
};
let aadSignin = aadFunc("SigninLogs");
let aadNonInt = aadFunc("AADNonInteractiveUserSignInLogs");
union isfuzzy=true aadSignin, aadNonInt
entityMappings:
- entityType: Account
fieldMappings:
@ -74,5 +67,5 @@ entityMappings:
fieldMappings:
- identifier: Url
columnName: Url
version: 1.2.5
version: 1.2.6
kind: Scheduled

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

@ -27,14 +27,14 @@ query: |
let ioc_lookBack = 14d; // Look back 14 days for threat intelligence indicators
// Fetch threat intelligence indicators related to IP addresses
let IP_Indicators = ThreatIntelligenceIndicator
| where TimeGenerated >= ago(ioc_lookBack)
| summarize LatestIndicatorTime = arg_max(TimeGenerated, *) by IndicatorId
| where Active == true and ExpirationDateTime > now()
| where isnotempty(NetworkIP) or isnotempty(EmailSourceIpAddress) or isnotempty(NetworkDestinationIP) or isnotempty(NetworkSourceIP)
| where TimeGenerated >= ago(ioc_lookBack)
| extend TI_ipEntity = iff(isnotempty(NetworkIP), NetworkIP, NetworkDestinationIP)
| extend TI_ipEntity = iff(isempty(TI_ipEntity) and isnotempty(NetworkSourceIP), NetworkSourceIP, TI_ipEntity)
| extend TI_ipEntity = iff(isempty(TI_ipEntity) and isnotempty(EmailSourceIpAddress), EmailSourceIpAddress, TI_ipEntity)
| where ipv4_is_private(TI_ipEntity) == false and TI_ipEntity !startswith "fe80" and TI_ipEntity !startswith "::" and TI_ipEntity !startswith "127.";
| where ipv4_is_private(TI_ipEntity) == false and TI_ipEntity !startswith "fe80" and TI_ipEntity !startswith "::" and TI_ipEntity !startswith "127."
| summarize LatestIndicatorTime = arg_max(TimeGenerated, *) by IndicatorId
| where Active == true and ExpirationDateTime > now();
// Perform a join between IP indicators and VMConnection events
IP_Indicators
// Use innerunique to keep performance fast and result set low, as we only need one match to indicate potential malicious activity that needs investigation
@ -67,5 +67,5 @@ entityMappings:
fieldMappings:
- identifier: Url
columnName: Url
version: 1.4.0
version: 1.4.1
kind: Scheduled

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

@ -27,14 +27,14 @@ query: |
let ioc_lookBack = 14d; // Look back 14 days for threat intelligence indicators
// Fetch threat intelligence indicators related to IP addresses
let IP_Indicators = ThreatIntelligenceIndicator
| where TimeGenerated >= ago(ioc_lookBack)
| summarize LatestIndicatorTime = arg_max(TimeGenerated, *) by IndicatorId
| where Active == true and ExpirationDateTime > now()
| where isnotempty(NetworkIP) or isnotempty(EmailSourceIpAddress) or isnotempty(NetworkDestinationIP) or isnotempty(NetworkSourceIP)
| where TimeGenerated >= ago(ioc_lookBack)
| extend TI_ipEntity = iff(isnotempty(NetworkIP), NetworkIP, NetworkDestinationIP)
| extend TI_ipEntity = iff(isempty(TI_ipEntity) and isnotempty(NetworkSourceIP), NetworkSourceIP, TI_ipEntity)
| extend TI_ipEntity = iff(isempty(TI_ipEntity) and isnotempty(EmailSourceIpAddress), EmailSourceIpAddress, TI_ipEntity)
| where ipv4_is_private(TI_ipEntity) == false and TI_ipEntity !startswith "fe80" and TI_ipEntity !startswith "::" and TI_ipEntity !startswith "127.";
| where ipv4_is_private(TI_ipEntity) == false and TI_ipEntity !startswith "fe80" and TI_ipEntity !startswith "::" and TI_ipEntity !startswith "127."
| summarize LatestIndicatorTime = arg_max(TimeGenerated, *) by IndicatorId
| where Active == true and ExpirationDateTime > now();
// Perform a join between IP indicators and W3CIISLog events
IP_Indicators
// Use innerunique to keep performance fast and result set low, as we only need one match to indicate potential malicious activity that needs investigation
@ -71,5 +71,5 @@ entityMappings:
fieldMappings:
- identifier: Url
columnName: Url
version: 1.4.0
version: 1.4.1
kind: Scheduled

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

@ -58,6 +58,9 @@ requiredDataConnectors:
dataTypes:
- Syslog
- CiscoMerakiNativePoller
- connectorId: ThreatIntelligenceTaxii
dataTypes:
- ThreatIntelligenceIndicator
queryFrequency: 1h
queryPeriod: 14d
@ -70,11 +73,11 @@ query: |
let ioc_lookBack = 14d;
let IP_TI = materialize (
ThreatIntelligenceIndicator
| where TimeGenerated >= ago(ioc_lookBack) and ExpirationDateTime > now()
| summarize LatestIndicatorTime = arg_max(TimeGenerated, *) by IndicatorId
| where Active == true
| where TimeGenerated >= ago(ioc_lookBack)
| extend TI_ipEntity = coalesce(NetworkIP, NetworkDestinationIP, NetworkSourceIP,EmailSourceIpAddress,"NO_IP")
| where TI_ipEntity != "NO_IP"
| summarize LatestIndicatorTime = arg_max(TimeGenerated, *) by IndicatorId
| where Active == true and ExpirationDateTime > now()
);
IP_TI
// using innerunique to keep perf fast and result set low, we only need one match to indicate potential malicious activity that needs to be investigated
@ -119,5 +122,5 @@ tags:
- Schema: ASIMNetworkSession
SchemaVersion: 0.2.4
version: 1.2.4
version: 1.2.5
kind: Scheduled

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

@ -31,15 +31,15 @@ query: |
let ioc_lookBack = 14d;
let IP_TI = ThreatIntelligenceIndicator
| where TimeGenerated >= ago(ioc_lookBack)
| summarize LatestIndicatorTime = arg_max(TimeGenerated, *) by IndicatorId
| where Active == true and ExpirationDateTime > now()
// As there is potentially more than 1 indicator type for matching IP, taking NetworkIP first, then others if that is empty.
// Taking the first non-empty value based on potential IOC match availability
| extend TI_ipEntity = coalesce(NetworkIP, NetworkDestinationIP, NetworkSourceIP, EmailSourceIpAddress, "NO_IP")
// Picking up only IOC's that contain the entities we want
| where TI_ipEntity != "NO_IP"
// Exclude local addresses, using the ipv4_is_private operator
| where ipv4_is_private(TI_ipEntity) == false and TI_ipEntity !startswith "fe80" and TI_ipEntity !startswith "::" and TI_ipEntity !startswith "127.";
| where ipv4_is_private(TI_ipEntity) == false and TI_ipEntity !startswith "fe80" and TI_ipEntity !startswith "::" and TI_ipEntity !startswith "127."
| summarize LatestIndicatorTime = arg_max(TimeGenerated, *) by IndicatorId
| where Active == true and ExpirationDateTime > now();
let IP_TI_list = toscalar(IP_TI
| summarize NIoCs = dcount(TI_ipEntity), IoCs = make_set(TI_ipEntity)
| project IoCs = iff(NIoCs > HAS_ANY_MAX, dynamic([]), IoCs));
@ -72,5 +72,5 @@ customDetails:
alertDetailsOverride:
alertDisplayNameFormat: The IP {{SrcIpAddr}} of the web request matches an IP IoC
alertDescriptionFormat: The source address {{SrcIpAddr}} of the web request for the URL {{Url}} matches a known indicator of compromise of {{ThreatType}}. Consult the threat intelligence feed for more information about the indicator.
version: 1.2.3
version: 1.2.4
kind: Scheduled

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

@ -14,26 +14,31 @@ requiredDataConnectors:
dataTypes:
- ThreatIntelligenceIndicator
queryFrequency: 1h
queryPeriod: 1d
queryPeriod: 14d
triggerOperator: gt
triggerThreshold: 0
tactics:
- Impact
query: |
let dt_lookBack = 1h; // Look back 1 hour for VMConnection events
let ioc_lookBack = 14d; // Look back 14 days for threat intelligence indicators
ThreatIntelligenceIndicator
| where Action == true
// Picking up only IOC's that contain the entities we want
| where isnotempty(NetworkIP) or isnotempty(EmailSourceIpAddress) or isnotempty(NetworkDestinationIP) or isnotempty(NetworkSourceIP)
| where Action == true
| where TimeGenerated >= ago(ioc_lookBack)
// Taking the first non-empty value based on potential IOC match availability
| extend TI_ipEntity = iff(isnotempty(NetworkIP), NetworkIP, NetworkDestinationIP)
| extend TI_ipEntity = iff(isempty(TI_ipEntity) and isnotempty(NetworkSourceIP), NetworkSourceIP, TI_ipEntity)
| extend TI_ipEntity = iff(isempty(TI_ipEntity) and isnotempty(EmailSourceIpAddress), EmailSourceIpAddress, TI_ipEntity)
| summarize LatestIndicatorTime = arg_max(TimeGenerated, *) by IndicatorId
| where Active == true and ExpirationDateTime > now()
| join (
GitHubAudit
| where TimeGenerated >= ago(dt_lookBack)
| extend GitHubAudit_TimeGenerated = TimeGenerated
)
on $left.TI_ipEntity == $right.IPaddress
| summarize LatestIndicatorTime = arg_max(TimeGenerated, *) by IndicatorId
| project LatestIndicatorTime, Description, ActivityGroupNames, IndicatorId, ThreatType, Url, ExpirationDateTime, ConfidenceScore, GitHubAudit_TimeGenerated, TI_ipEntity, IPaddress, Actor, Action, Country, OperationType, NetworkIP, NetworkDestinationIP, NetworkSourceIP, EmailSourceIpAddress
| extend timestamp = GitHubAudit_TimeGenerated, IPCustomEntity = IPaddress, AccountCustomEntity = Actor
entityMappings:
@ -45,5 +50,5 @@ entityMappings:
fieldMappings:
- identifier: Address
columnName: IPCustomEntity
version: 1.0.2
version: 1.0.3
kind: Scheduled

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

@ -25,23 +25,23 @@ tactics:
query: |
let dt_lookBack = 1h;
let ioc_lookBack = 14d;
ThreatIntelligenceIndicator
| where TimeGenerated >= ago(ioc_lookBack) and ExpirationDateTime > now()
| summarize LatestIndicatorTime = arg_max(TimeGenerated, *) by IndicatorId
| where Active == true
// Picking up only IOC's that contain the entities we want
| where isnotempty(Url)
// using innerunique to keep perf fast and result set low, we only need one match to indicate potential malicious activity that needs to be investigated
| join kind=innerunique (
AuditLogs
let AuditEvents = materialize(AuditLogs
| where TimeGenerated >= ago(dt_lookBack)
// Extract the URL that is contained within the JSON data
| extend Url = extract("(http[s]?://(?:[a-zA-Z]|[0-9]|[$-_@.&+]|[!*\\(\\),]|(?:%[0-9a-fA-F][0-9a-fA-F]))+);", 1,tostring(TargetResources))
| where isnotempty(Url)
| extend userPrincipalName = tostring(parse_json(tostring(InitiatedBy.user)).userPrincipalName)
| extend TargetResourceDisplayName = tostring(TargetResources[0].displayName)
| extend Audit_TimeGenerated = TimeGenerated
) on Url
| extend Audit_TimeGenerated = TimeGenerated);
let AuditUrls = AuditEvents | distinct Url = tolower(Url) | summarize make_list(Url);
ThreatIntelligenceIndicator
| where isnotempty(Url)
| where TimeGenerated >= ago(ioc_lookBack)
| where tolower(Url) in (AuditUrls)
| summarize LatestIndicatorTime = arg_max(TimeGenerated, *) by IndicatorId
| where Active == true and ExpirationDateTime > now()
// using innerunique to keep perf fast and result set low, we only need one match to indicate potential malicious activity that needs to be investigated
| join kind=innerunique (AuditEvents) on Url
| where Audit_TimeGenerated < ExpirationDateTime
| summarize Audit_TimeGenerated = arg_max(Audit_TimeGenerated, *) by IndicatorId, Url
| project Audit_TimeGenerated, Description, ActivityGroupNames, IndicatorId, ThreatType, ExpirationDateTime, ConfidenceScore,
@ -60,5 +60,5 @@ entityMappings:
fieldMappings:
- identifier: Url
columnName: URLCustomEntity
version: 1.2.4
version: 1.2.5
kind: Scheduled

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

@ -0,0 +1,65 @@
id: a0038239-72f4-4f7b-90ff-37f89f7881e0
name: TI Map URL Entity to EmailUrlInfo
description: |
'This query identifies any URL indicators of compromise (IOCs) from threat intelligence (TI) by searching for matches in EmailUrlInfo.'
severity: Medium
requiredDataConnectors:
- connectorId: AzureActiveDirectory
dataTypes:
- EmailUrlInfo
- connectorId: ThreatIntelligence
dataTypes:
- ThreatIntelligenceIndicator
- connectorId: ThreatIntelligenceTaxii
dataTypes:
- ThreatIntelligenceIndicator
- connectorId: MicrosoftDefenderThreatIntelligence
dataTypes:
- ThreatIntelligenceIndicator
queryFrequency: 1h
queryPeriod: 14d
triggerOperator: gt
triggerThreshold: 0
tactics:
- Impact
query: |
let dt_lookBack = 1h;
let ioc_lookBack = 14d;
let EmailUrlInfo_ = materialize(EmailUrlInfo
| where isnotempty(Url)
| where TimeGenerated >= ago(dt_lookBack)
| extend Url = tolower(Url)
| extend EmailUrlInfo_TimeGenerated = TimeGenerated);
let EmailUrls = EmailUrlInfo_ | distinct Url | summarize make_list(Url);
let EmailUrlDomains = EmailUrlInfo_ | distinct UrlDomain | summarize make_list(UrlDomain);
let EmailEvents_ = materialize(EmailEvents
| where TimeGenerated >= ago(dt_lookBack));
let TI = materialize(ThreatIntelligenceIndicator
| where TimeGenerated >= ago(ioc_lookBack)
| where (isnotempty(Url) or isnotempty(DomainName))
| where tolower(Url) in (EmailUrls) or tolower(DomainName) in (EmailUrlDomains)
| summarize LatestIndicatorTime = arg_max(TimeGenerated, *) by IndicatorId
| where Active == true and ExpirationDateTime > now());
(union
(TI | join kind=innerunique (EmailUrlInfo_) on Url),
(TI | join kind=innerunique (EmailUrlInfo_) on $left.DomainName == $right.UrlDomain))
| where EmailUrlInfo_TimeGenerated < ExpirationDateTime
| summarize EmailUrlInfo_TimeGenerated = arg_max(EmailUrlInfo_TimeGenerated, *) by IndicatorId, Url
| project EmailUrlInfo_TimeGenerated, Description, ActivityGroupNames, IndicatorId, ThreatType, ExpirationDateTime, ConfidenceScore, Url, UrlDomain, UrlLocation, NetworkMessageId
| extend timestamp = EmailUrlInfo_TimeGenerated
| join kind=inner (EmailEvents_) on NetworkMessageId
| where DeliveryAction !has "Blocked"
| extend Name = tostring(split(RecipientEmailAddress, '@', 0)[0]), UPNSuffix = tostring(split(RecipientEmailAddress, '@', 1)[0])
entityMappings:
- entityType: Account
fieldMappings:
- identifier: Name
columnName: Name
- identifier: UPNSuffix
columnName: UPNSuffix
- entityType: URL
fieldMappings:
- identifier: Url
columnName: Url
version: 1.0.0
kind: Scheduled

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

@ -1,7 +1,7 @@
id: 36a9c9e5-3dc1-4ed9-afaa-1d13617bfc2b
name: TI Map URL Entity to OfficeActivity Data
name: TI Map URL Entity to OfficeActivity Data [Deprecated]
description: |
'This query identifies any URL indicators of compromise (IOCs) from threat intelligence (TI) by searching for matches in OfficeActivity data.'
'This query is Deprecated as its filter conditions will never yield results. This query identifies any URL indicators of compromise (IOCs) from threat intelligence (TI) by searching for matches in OfficeActivity data.'
severity: Medium
requiredDataConnectors:
- connectorId: Office365
@ -13,6 +13,9 @@ requiredDataConnectors:
- connectorId: MicrosoftDefenderThreatIntelligence
dataTypes:
- ThreatIntelligenceIndicator
- connectorId: ThreatIntelligenceTaxii
dataTypes:
- ThreatIntelligenceIndicator
queryFrequency: 1h
queryPeriod: 14d
triggerOperator: gt
@ -21,31 +24,32 @@ tactics:
- Impact
query: |
let dt_lookBack = 1h;
let ioc_lookBack = 14d;
ThreatIntelligenceIndicator
| where TimeGenerated >= ago(ioc_lookBack) and ExpirationDateTime > now()
| summarize LatestIndicatorTime = arg_max(TimeGenerated, *) by IndicatorId
| where Active == true
// Picking up only IOC's that contain the entities we want
| where isnotempty(Url)
// using innerunique to keep perf fast and result set low, we only need one match to indicate potential malicious activity that needs to be investigated
| join kind=innerunique (
OfficeActivity
| where TimeGenerated >= ago(dt_lookBack)
//Extract the Url from a number of potential fields
| extend Url = iif(OfficeWorkload == "AzureActiveDirectory",extract("(http[s]?://(?:[a-zA-Z]|[0-9]|[$-_@.&+]|[!*\\(\\),]|(?:%[0-9a-fA-F][0-9a-fA-F]))+);", 1,ModifiedProperties),tostring(parse_json(ModifiedProperties)[12].NewValue))
| where isnotempty(Url)
// Ensure we get a clean URL
| extend Url = tostring(split(Url, ';')[0])
| extend OfficeActivity_TimeGenerated = TimeGenerated
// Project a single user identity that we can use for entity mapping
| extend User = iif(isnotempty(UserId), UserId, iif(isnotempty(Actor), tostring(parse_json(Actor)[0].ID), tostring(parse_json(Parameters)[0].Value)))
) on Url
| where OfficeActivity_TimeGenerated < ExpirationDateTime
| summarize OfficeActivity_TimeGenerated = arg_max(OfficeActivity_TimeGenerated, *) by IndicatorId, Url
| project OfficeActivity_TimeGenerated, Description, ActivityGroupNames, IndicatorId, ThreatType, ExpirationDateTime, ConfidenceScore, Operation,
UserType, OfficeWorkload, Parameters, Url, User
| extend timestamp = OfficeActivity_TimeGenerated, Name = tostring(split(User, '@', 0)[0]), UPNSuffix = tostring(split(User, '@', 1)[0])
// let ioc_lookBack = 14d;
// ThreatIntelligenceIndicator
// // Picking up only IOC's that contain the entities we want
// | where isnotempty(Url)
// | where TimeGenerated >= ago(ioc_lookBack)
// | summarize LatestIndicatorTime = arg_max(TimeGenerated, *) by IndicatorId
// | where Active == true and ExpirationDateTime > now()
// // using innerunique to keep perf fast and result set low, we only need one match to indicate potential malicious activity that needs to be investigated
// | join kind=innerunique (
// OfficeActivity
// | where TimeGenerated >= ago(dt_lookBack)
// //Extract the Url from a number of potential fields
// | extend Url = iif(OfficeWorkload == "AzureActiveDirectory",extract("(http[s]?://(?:[a-zA-Z]|[0-9]|[$-_@.&+]|[!*\\(\\),]|(?:%[0-9a-fA-F][0-9a-fA-F]))+);", 1,ModifiedProperties),tostring(parse_json(ModifiedProperties)[12].NewValue))
// | where isnotempty(Url)
// // Ensure we get a clean URL
// | extend Url = tostring(split(Url, ';')[0])
// | extend OfficeActivity_TimeGenerated = TimeGenerated
// // Project a single user identity that we can use for entity mapping
// | extend User = iif(isnotempty(UserId), UserId, iif(isnotempty(Actor), tostring(parse_json(Actor)[0].ID), tostring(parse_json(Parameters)[0].Value)))
// ) on Url
// | where OfficeActivity_TimeGenerated < ExpirationDateTime
// | summarize OfficeActivity_TimeGenerated = arg_max(OfficeActivity_TimeGenerated, *) by IndicatorId, Url
// | project OfficeActivity_TimeGenerated, Description, ActivityGroupNames, IndicatorId, ThreatType, ExpirationDateTime, ConfidenceScore, Operation,
// UserType, OfficeWorkload, Parameters, Url, User
// | extend timestamp = OfficeActivity_TimeGenerated, Name = tostring(split(User, '@', 0)[0]), UPNSuffix = tostring(split(User, '@', 1)[0])
datatable() []
entityMappings:
- entityType: Account
fieldMappings:
@ -57,5 +61,5 @@ entityMappings:
fieldMappings:
- identifier: Url
columnName: Url
version: 1.2.5
version: 1.2.6
kind: Scheduled

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

@ -26,11 +26,11 @@ query: |
let dt_lookBack = 1h;
let ioc_lookBack = 14d;
ThreatIntelligenceIndicator
| where TimeGenerated >= ago(ioc_lookBack) and ExpirationDateTime > now()
| summarize LatestIndicatorTime = arg_max(TimeGenerated, *) by IndicatorId
| where Active == true
// Picking up only IOC's that contain the entities we want
| where isnotempty(Url)
| where TimeGenerated >= ago(ioc_lookBack)
| summarize LatestIndicatorTime = arg_max(TimeGenerated, *) by IndicatorId
| where Active == true and ExpirationDateTime > now()
// using innerunique to keep perf fast and result set low, we only need one match to indicate potential malicious activity that needs to be investigated
| join kind=innerunique (
CommonSecurityLog
@ -64,5 +64,5 @@ entityMappings:
fieldMappings:
- identifier: Url
columnName: PA_Url
version: 1.2.3
version: 1.2.4
kind: Scheduled

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

@ -29,28 +29,30 @@ query: |
let dt_lookBack = 1h;
let ioc_lookBack = 14d;
let URLRegex = "((https?|ftp|ldap|wss?|file):\\/\\/(([\\:\\%\\w\\_\\-]+(\\.|@))*((xn--)?[a-zA-Z0-9\\-]+\\.)+(xn--[a-z0-9]+|[A-Za-z]+)|\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{0,3})[.,:\\w@?^=%&\\/~+#-]*[\\w@?^=%&\\/~+#-])";
let SecurityEvents = materialize(SecurityAlert
| where TimeGenerated >= ago(dt_lookBack)
| extend MSTI = case(AlertName has "TI map" and VendorName == "Microsoft" and ProductName == 'Azure Sentinel', true, false)
| where MSTI == false
// Extract URL from JSON data
| mv-expand parse_json(Entities)
| where isnotempty(Entities.Url) or isnotempty(Entities.Urls)
| extend Url = coalesce(Entities.Url, Entities.Urls)
| mv-expand Url
| extend Url = tolower(Url)
// Extract hostname from JSON data for entity mapping
| extend Compromised_Host = tostring(parse_json(ExtendedProperties).["Compromised Host"])
| extend Alert_TimeGenerated = TimeGenerated);
let EventUrls = materialize(SecurityEvents | distinct Url | summarize make_list(Url));
ThreatIntelligenceIndicator
| where TimeGenerated >= ago(ioc_lookBack) and ExpirationDateTime > now()
| where isnotempty(Url)
| where TimeGenerated >= ago(ioc_lookBack)
| extend Url = tolower(Url)
| where tolower(Url) in (EventUrls)
| summarize LatestIndicatorTime = arg_max(TimeGenerated, *) by IndicatorId
| where Active == true
// Picking up only IOC's that contain the entities we want
| where isnotempty(Url)
| where Active == true and ExpirationDateTime > now()
| where Description !contains "State: inactive"
// using innerunique to keep perf fast and result set low, we only need one match to indicate potential malicious activity that needs to be investigated
| join kind=innerunique (
SecurityAlert
| where TimeGenerated >= ago(dt_lookBack)
| extend MSTI = case(AlertName has "TI map" and VendorName == "Microsoft" and ProductName == 'Azure Sentinel', true, false)
| where MSTI == false
// Extract URL from JSON data
| extend Url = todynamic(dynamic_to_json(extract_all(URLRegex, dynamic([1]), Entities)))
| mv-expand Url
| extend Url = tostring(Url[0])
// We only want alerts that actually contain URL data
| where isnotempty(Url)
// Extract hostname from JSON data for entity mapping
| extend Compromised_Host = tostring(parse_json(ExtendedProperties).["Compromised Host"])
| extend Alert_TimeGenerated = TimeGenerated
) on Url
| join kind=innerunique (SecurityEvents) on Url
| where Alert_TimeGenerated < ExpirationDateTime
| summarize Alert_TimeGenerated = arg_max(Alert_TimeGenerated, *) by IndicatorId, AlertName
| project timestamp = Alert_TimeGenerated, ActivityGroupNames, IndicatorId, ThreatType, ExpirationDateTime, ConfidenceScore, AlertName, AlertSeverity, Description, Url, Compromised_Host
@ -63,5 +65,5 @@ entityMappings:
fieldMappings:
- identifier: Url
columnName: Url
version: 1.2.6
version: 1.2.7
kind: Scheduled

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

@ -26,11 +26,11 @@ query: |
let dt_lookBack = 1h;
let ioc_lookBack = 14d;
ThreatIntelligenceIndicator
| where TimeGenerated >= ago(ioc_lookBack) and ExpirationDateTime > now()
| summarize LatestIndicatorTime = arg_max(TimeGenerated, *) by IndicatorId
| where Active == true
// Picking up only IOC's that contain the entities we want
| where isnotempty(Url)
| where TimeGenerated >= ago(ioc_lookBack)
| summarize LatestIndicatorTime = arg_max(TimeGenerated, *) by IndicatorId
| where Active == true and ExpirationDateTime > now()
// using innerunique to keep perf fast and result set low, we only need one match to indicate potential malicious activity that needs to be investigated
| join kind=innerunique (
Syslog
@ -56,5 +56,5 @@ entityMappings:
fieldMappings:
- identifier: Url
columnName: Url
version: 1.2.4
version: 1.2.5
kind: Scheduled

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

@ -0,0 +1,68 @@
id: 23391c84-87d8-452f-a84c-47a62f01e115
name: TI Map URL Entity to UrlClickEvents
description: |
'This query identifies any URL indicators of compromise (IOCs) from threat intelligence (TI) by searching for matches in UrlClickEvents.'
severity: Medium
requiredDataConnectors:
- connectorId: MicrosoftThreatProtection
dataTypes:
- UrlClickEvents
- connectorId: ThreatIntelligence
dataTypes:
- ThreatIntelligenceIndicator
- connectorId: ThreatIntelligenceTaxii
dataTypes:
- ThreatIntelligenceIndicator
- connectorId: MicrosoftDefenderThreatIntelligence
dataTypes:
- ThreatIntelligenceIndicator
queryFrequency: 1h
queryPeriod: 14d
triggerOperator: gt
triggerThreshold: 0
tactics:
- Impact
query: |
let dt_lookBack = 1h;
let ioc_lookBack = 14d;
let UrlClickEvents_ = materialize(UrlClickEvents
| where TimeGenerated >= ago(dt_lookBack)
| extend UrlClickEvents_TimeGenerated = TimeGenerated);
let ChainReportID = UrlClickEvents_
| mv-expand todynamic(UrlChain)
| extend UrlChain = tolower(UrlChain)
| project ReportId, Url, UrlChain;
// Url is not always in UrlChain, so we need to check both
let ClickedUrls =
(union isfuzzy=false (ChainReportID), (ChainReportID | project Url = UrlChain))
| distinct Url
| summarize make_list(Url);
let TI = materialize(ThreatIntelligenceIndicator
| where TimeGenerated >= ago(ioc_lookBack)
| where isnotempty(Url) and tolower(Url) in (ClickedUrls)
| summarize LatestIndicatorTime = arg_max(TimeGenerated, *) by IndicatorId
| where Active == true and ExpirationDateTime > now()
| project-rename TI_Url = Url, TI_Type = Type
);
(union isfuzzy=false (TI | join kind=innerunique (ChainReportID) on $left.TI_Url == $right.UrlChain),
(TI | join kind=innerunique (ChainReportID) on $left.TI_Url == $right.Url))
| project-away UrlChain
| join kind=innerunique (UrlClickEvents_) on ReportId
| where UrlClickEvents_TimeGenerated < ExpirationDateTime
| summarize UrlClickEvents_TimeGenerated = arg_max(UrlClickEvents_TimeGenerated, *) by IndicatorId
| project UrlClickEvents_TimeGenerated, AccountUpn, Description, ActivityGroupNames, IndicatorId, ThreatType, ExpirationDateTime, ConfidenceScore, Url, NetworkMessageId
| extend timestamp = UrlClickEvents_TimeGenerated
| extend timestamp = UrlClickEvents_TimeGenerated, Name = tostring(split(AccountUpn, '@', 0)[0]), UPNSuffix = tostring(split(AccountUpn, '@', 1)[0])
entityMappings:
- entityType: Account
fieldMappings:
- identifier: Name
columnName: Name
- identifier: UPNSuffix
columnName: UPNSuffix
- entityType: URL
fieldMappings:
- identifier: Url
columnName: Url
version: 1.0.0
kind: Scheduled

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

@ -35,7 +35,6 @@ requiredDataConnectors:
- connectorId: CiscoUmbrellaDataConnector
dataTypes:
- Cisco_Umbrella_dns_CL
- connectorId: Corelight
dataTypes:
- Corelight_CL
@ -55,11 +54,11 @@ query: |
let dt_lookBack = 1h;
let ioc_lookBack = 14d;
let DomainTIs= ThreatIntelligenceIndicator
| where TimeGenerated >= ago(ioc_lookBack) and ExpirationDateTime > now()
// Picking up only IOC's that contain the entities we want
| where isnotempty(DomainName)
| where Active == true
| summarize LatestIndicatorTime = arg_max(TimeGenerated, *) by IndicatorId;
| where TimeGenerated >= ago(ioc_lookBack)
| summarize LatestIndicatorTime = arg_max(TimeGenerated, *) by IndicatorId
| where Active == true and ExpirationDateTime > now();
let Domains = DomainTIs | where isnotempty(DomainName) |summarize NDomains=dcount(DomainName), DomainsList=make_set(DomainName)
| project DomainList = iff(NDomains > HAS_ANY_MAX, dynamic([]), DomainsList) ;
DomainTIs
@ -70,7 +69,6 @@ query: |
| where DNS_TimeGenerated < ExpirationDateTime
| project LatestIndicatorTime, Description, ActivityGroupNames, IndicatorId, ThreatType, ExpirationDateTime, ConfidenceScore, Url, DNS_TimeGenerated, Dvc, SrcIpAddr, DnsQuery, DnsQueryType
| extend timestamp = DNS_TimeGenerated, HostCustomEntity = Dvc, IPCustomEntity = SrcIpAddr, URLCustomEntity = Url
entityMappings:
- entityType: Host
fieldMappings:
@ -96,5 +94,5 @@ customDetails:
SourceIPAddress: SrcIpAddr
DnsQuery: DnsQuery
QueryType: DnsQueryType
version: 1.1.4
version: 1.1.5
kind: Scheduled

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

@ -38,7 +38,6 @@ requiredDataConnectors:
- connectorId: Corelight
dataTypes:
- Corelight_CL
queryFrequency: 1h
queryPeriod: 14d
triggerOperator: gt
@ -55,12 +54,11 @@ query: |
let ioc_lookBack = 14d;
let IP_TI =
ThreatIntelligenceIndicator
| where TimeGenerated >= ago(ioc_lookBack) and ExpirationDateTime > now()
| summarize LatestIndicatorTime = arg_max(TimeGenerated, *) by IndicatorId
| where Active == true
| where TimeGenerated >= ago(ioc_lookBack)
| extend IoC = coalesce(NetworkIP, NetworkDestinationIP, NetworkSourceIP,EmailSourceIpAddress,"NO_IP")
| where IoC != "NO_IP"
;
| summarize LatestIndicatorTime = arg_max(TimeGenerated, *) by IndicatorId
| where Active == true and ExpirationDateTime > now();
IP_TI
| join kind=innerunique // using innerunique to keep perf fast and result set low, we only need one match to indicate potential malicious activity that needs to be investigated
(
@ -73,7 +71,6 @@ query: |
on IoC
| where imDns_mintime < ExpirationDateTime
| project imDns_mintime, imDns_maxtime, Description, ActivityGroupNames, IndicatorId, ThreatType, LatestIndicatorTime, ExpirationDateTime, ConfidenceScore, SrcIpAddr, IoC, Dvc, EventVendor, EventProduct, DnsQuery, DnsResponseName
entityMappings:
- entityType: Host
fieldMappings:
@ -87,7 +84,6 @@ entityMappings:
fieldMappings:
- identifier: Address
columnName: SrcIpAddr
customDetails:
LatestIndicatorTime: LatestIndicatorTime
Description: Description
@ -99,10 +95,8 @@ customDetails:
DNSRequestTime: imDns_mintime
SourceIPAddress: SrcIpAddr
DnsQuery: DnsQuery
alertDetailsOverride:
alertDisplayNameFormat: The response {{IoC}} to DNS query matched an IoC
alertDescriptionFormat: The response address {{IoC}} to a DNS query matched a known indicator of compromise of {{ThreatType}}. Consult the threat intelligence blade for more information on the indicator.
version: 1.2.2
version: 1.2.3
kind: Scheduled

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

@ -22,11 +22,13 @@
"Analytic Rules": [
"Analytic Rules/DomainEntity_CommonSecurityLog.yaml",
"Analytic Rules/DomainEntity_DnsEvents.yaml",
"Analytic Rules/DomainEntity_EmailEvents.yaml",
"Analytic Rules/DomainEntity_imWebSession.yaml",
"Analytic Rules/DomainEntity_PaloAlto.yaml",
"Analytic Rules/DomainEntity_SecurityAlert.yaml",
"Analytic Rules/DomainEntity_Syslog.yaml",
"Analytic Rules/EmailEntity_AzureActivity.yaml",
"Analytic Rules/EmailEntity_EmailEvents.yaml",
"Analytic Rules/EmailEntity_OfficeActivity.yaml",
"Analytic Rules/EmailEntity_PaloAlto.yaml",
"Analytic Rules/EmailEntity_SecurityAlert.yaml",
@ -49,10 +51,12 @@
"Analytic Rules/IPEntity_VMConnection.yaml",
"Analytic Rules/IPEntity_W3CIISLog.yaml",
"Analytic Rules/URLEntity_AuditLogs.yaml",
"Analytic Rules/URLEntity_EmailUrlInfo.yaml",
"Analytic Rules/URLEntity_OfficeActivity.yaml",
"Analytic Rules/URLEntity_PaloAlto.yaml",
"Analytic Rules/URLEntity_SecurityAlerts.yaml",
"Analytic Rules/URLEntity_Syslog.yaml",
"Analytic Rules/URLEntity_UrlClickEvents.yaml",
"Analytic Rules/IPEntity_DuoSecurity.yaml",
"Analytic Rules/imDns_DomainEntity_DnsEvents.yaml",
"Analytic Rules/imDns_IPEntity_DnsEvents.yaml",
@ -61,7 +65,7 @@
],
"Metadata": "SolutionMetadata.json",
"BasePath": "C:\\GitHub\\Azure-Sentinel\\Solutions\\Threat Intelligence\\",
"Version": "3.0.1",
"Version": "3.0.2",
"TemplateSpec": true,
"Is1PConnector": true
}

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

@ -6,7 +6,7 @@
"config": {
"isWizard": false,
"basics": {
"description": "<img src=\"https://raw.githubusercontent.com/Azure/Azure-Sentinel/master/Logos/Azure_Sentinel.svg\"width=\"75px\" height=\"75px\">\n\n**Note:** Please refer to the following before installing the solution: \r \n • Review the solution [Release Notes](https://github.com/Azure/Azure-Sentinel/tree/master/Solutions/Threat Intelligence/ReleaseNotes.md)\r \n • There may be [known issues](https://aka.ms/sentinelsolutionsknownissues) pertaining to this Solution, please refer to them before installing.\n\nThe Threat Intelligence solution contains data connectors for import of threat indicators into Microsoft Sentinel, analytic rules for matching TI data with event data, workbook, and hunting queries. Threat indicators can be malicious IP's, URL's, filehashes, domains, email addresses etc.\n\n**Data Connectors:** 4, **Workbooks:** 1, **Analytic Rules:** 38, **Hunting Queries:** 5\n\n[Learn more about Microsoft Sentinel](https://aka.ms/azuresentinel) | [Learn more about Solutions](https://aka.ms/azuresentinelsolutionsdoc)",
"description": "<img src=\"https://raw.githubusercontent.com/Azure/Azure-Sentinel/master/Logos/Azure_Sentinel.svg\"width=\"75px\" height=\"75px\">\n\n**Note:** _There may be [known issues](https://aka.ms/sentinelsolutionsknownissues) pertaining to this Solution, please refer to them before installing._\n\nThe Threat Intelligence solution contains data connectors for import of threat indicators into Microsoft Sentinel, analytic rules for matching TI data with event data, workbook, and hunting queries. Threat indicators can be malicious IP's, URL's, filehashes, domains, email addresses etc.\n\n**Data Connectors:** 4, **Workbooks:** 1, **Analytic Rules:** 42, **Hunting Queries:** 5\n\n[Learn more about Microsoft Sentinel](https://aka.ms/azuresentinel) | [Learn more about Solutions](https://aka.ms/azuresentinelsolutionsdoc)",
"subscription": {
"resourceProviders": [
"Microsoft.OperationsManagement/solutions",
@ -51,7 +51,7 @@
}
],
"steps": [
{
{
"name": "dataconnectors",
"label": "Data Connectors",
"bladeTitle": "Data Connectors",
@ -60,77 +60,28 @@
"name": "dataconnectors1-text",
"type": "Microsoft.Common.TextBlock",
"options": {
"text": "This solution installs four (4) data connectors for ingesting threat indicators (IP addresses, domains, URLs and file hashes) into Microsoft Sentinel. The ingested threat indicators can be used for correlation to enable monitoring, alerting, and hunting using your threat intelligence."
"text": "This Solution installs the data connector for Threat Intelligence. You can get Threat Intelligence custom log data in your Microsoft Sentinel workspace. After installing the solution, configure and enable this data connector by following guidance in Manage solution view."
}
},
{
"name": "dataconnectors2-text",
"type": "Microsoft.Common.TextBlock",
"options": {
"text": "The data connectors installed are:"
"text": "This Solution installs the data connector for Threat Intelligence. You can get Threat Intelligence custom log data in your Microsoft Sentinel workspace. After installing the solution, configure and enable this data connector by following guidance in Manage solution view."
}
},
{
"name": "DC1",
"type": "Microsoft.Common.Section",
"label": "(1)\t\tThreat Intelligence Platforms",
"elements": [
{
"name": "DC1-text",
"type": "Microsoft.Common.TextBlock",
"options": {
"text": "Use this connector to send threat indicators to Microsoft Sentinel from your Threat Intelligence Platform (TIP), such as Threat Connect, Palo Alto Networks MindMeld, MISP, or other integrated applications."
}
}
]
},
{
"name": "DC2",
"type": "Microsoft.Common.Section",
"label": "(2)\t\tThreat Intelligence - TAXII",
"elements": [
{
"name": "DC1-text",
"type": "Microsoft.Common.TextBlock",
"options": {
"text": "Use this connector to bring in threat intelligence to Microsoft Sentinel from a TAXII 2.0 or 2.1 server."
}
}
]
},
{
"name": "DC3",
"type": "Microsoft.Common.Section",
"label": "(3)\t\tThreat Intelligence Upload Indicators API",
"elements": [
{
"name": "DC1-text",
"type": "Microsoft.Common.TextBlock",
"options": {
"text": "Microsoft Sentinel offer a data plane API to bring in threat intelligence from your Threat Intelligence Platform (TIP), such as Threat Connect, Palo Alto Networks MineMeld, MISP, or other integrated applications. Threat indicators can include IP addresses, domains, URLs, file hashes and email addresses."
}
}
]
},
{
"name": "DC4",
"type": "Microsoft.Common.Section",
"label": "(4)\t\tMicrosoft Defender Threat Intelligence",
"elements": [
{
"name": "DC1-text",
"type": "Microsoft.Common.TextBlock",
"options": {
"text": "Microsoft Sentinel provides you the capability to import threat intelligence generated by Microsoft to enable monitoring, alerting and hunting. Use this data connector to import Indicators of Compromise (IOCs) from Microsoft Defender Threat Intelligence (MDTI) into Microsoft Sentinel. Threat indicators can include IP addresses, domains, URLs, and file hashes, etc."
}
}
]
},
{
"name": "dataconnectors3-text",
"type": "Microsoft.Common.TextBlock",
"options": {
"text": "After installing the solution, configure and enable these data connectors by following guidance in Manage solution view."
"text": "This Solution installs the data connector for Threat Intelligence. You can get Threat Intelligence custom log data in your Microsoft Sentinel workspace. After installing the solution, configure and enable this data connector by following guidance in Manage solution view."
}
},
{
"name": "dataconnectors4-text",
"type": "Microsoft.Common.TextBlock",
"options": {
"text": "This Solution installs the data connector for Threat Intelligence. You can get Threat Intelligence custom log data in your Microsoft Sentinel workspace. After installing the solution, configure and enable this data connector by following guidance in Manage solution view."
}
},
{
@ -216,13 +167,13 @@
{
"name": "analytic1",
"type": "Microsoft.Common.Section",
"label": "TI map Domain entity to CommonSecurityLog",
"label": "TI map Domain entity to PaloAlto CommonSecurityLog",
"elements": [
{
"name": "analytic1-text",
"type": "Microsoft.Common.TextBlock",
"options": {
"text": "Identifies a match in CommonSecurityLog table from any Domain IOC from TI"
"text": "Identifies a match in PaloAlto CommonSecurityLog table from any Domain IOC from TI"
}
}
]
@ -244,13 +195,13 @@
{
"name": "analytic3",
"type": "Microsoft.Common.Section",
"label": "TI map Domain entity to Web Session Events (ASIM Web Session schema)",
"label": "TI map Domain entity to EmailEvents",
"elements": [
{
"name": "analytic3-text",
"type": "Microsoft.Common.TextBlock",
"options": {
"text": "This rule identifies Web Sessions for which the target URL hostname is a known IoC. This rule uses the [Advanced Security Information Model (ASIM)](https:/aka.ms/AboutASIM) and supports any web session source that complies with ASIM."
"text": "Identifies a match in EmailEvents table from any Domain IOC from TI"
}
}
]
@ -258,11 +209,25 @@
{
"name": "analytic4",
"type": "Microsoft.Common.Section",
"label": "TI map Domain entity to PaloAlto",
"label": "TI map Domain entity to Web Session Events (ASIM Web Session schema)",
"elements": [
{
"name": "analytic4-text",
"type": "Microsoft.Common.TextBlock",
"options": {
"text": "This rule identifies Web Sessions for which the target URL hostname is a known IoC. <br><br>This rule uses the [Advanced Security Information Model (ASIM)](https:/aka.ms/AboutASIM) and supports any web session source that complies with ASIM."
}
}
]
},
{
"name": "analytic5",
"type": "Microsoft.Common.Section",
"label": "TI map Domain entity to PaloAlto",
"elements": [
{
"name": "analytic5-text",
"type": "Microsoft.Common.TextBlock",
"options": {
"text": "Identifies a match in Palo Alto data in CommonSecurityLog table from any Domain IOC from TI"
}
@ -270,12 +235,12 @@
]
},
{
"name": "analytic5",
"name": "analytic6",
"type": "Microsoft.Common.Section",
"label": "TI map Domain entity to SecurityAlert",
"elements": [
{
"name": "analytic5-text",
"name": "analytic6-text",
"type": "Microsoft.Common.TextBlock",
"options": {
"text": "Identifies a match in SecurityAlert table from any Domain IOC from TI"
@ -284,12 +249,12 @@
]
},
{
"name": "analytic6",
"name": "analytic7",
"type": "Microsoft.Common.Section",
"label": "TI map Domain entity to Syslog",
"elements": [
{
"name": "analytic6-text",
"name": "analytic7-text",
"type": "Microsoft.Common.TextBlock",
"options": {
"text": "Identifies a match in Syslog table from any Domain IOC from TI"
@ -298,12 +263,12 @@
]
},
{
"name": "analytic7",
"name": "analytic8",
"type": "Microsoft.Common.Section",
"label": "TI map Email entity to AzureActivity",
"elements": [
{
"name": "analytic7-text",
"name": "analytic8-text",
"type": "Microsoft.Common.TextBlock",
"options": {
"text": "Identifies a match in AzureActivity table from any Email IOC from TI"
@ -312,12 +277,26 @@
]
},
{
"name": "analytic8",
"name": "analytic9",
"type": "Microsoft.Common.Section",
"label": "TI map Email entity to EmailEvents",
"elements": [
{
"name": "analytic9-text",
"type": "Microsoft.Common.TextBlock",
"options": {
"text": "Identifies a match in EmailEvents table from any Email IOC from TI"
}
}
]
},
{
"name": "analytic10",
"type": "Microsoft.Common.Section",
"label": "TI map Email entity to OfficeActivity",
"elements": [
{
"name": "analytic8-text",
"name": "analytic10-text",
"type": "Microsoft.Common.TextBlock",
"options": {
"text": "Identifies a match in OfficeActivity table from any Email IOC from TI"
@ -326,12 +305,12 @@
]
},
{
"name": "analytic9",
"name": "analytic11",
"type": "Microsoft.Common.Section",
"label": "TI map Email entity to PaloAlto CommonSecurityLog",
"elements": [
{
"name": "analytic9-text",
"name": "analytic11-text",
"type": "Microsoft.Common.TextBlock",
"options": {
"text": "Identifies a match in CommonSecurityLog table from any Email IOC from TI"
@ -340,12 +319,12 @@
]
},
{
"name": "analytic10",
"name": "analytic12",
"type": "Microsoft.Common.Section",
"label": "TI map Email entity to SecurityAlert",
"elements": [
{
"name": "analytic10-text",
"name": "analytic12-text",
"type": "Microsoft.Common.TextBlock",
"options": {
"text": "Identifies a match in SecurityAlert table from any Email IOC from TI which will extend coverage to datatypes such as MCAS, StorageThreatProtection and many others"
@ -354,12 +333,12 @@
]
},
{
"name": "analytic11",
"name": "analytic13",
"type": "Microsoft.Common.Section",
"label": "TI map Email entity to SecurityEvent",
"elements": [
{
"name": "analytic11-text",
"name": "analytic13-text",
"type": "Microsoft.Common.TextBlock",
"options": {
"text": "Identifies a match in SecurityEvent table from any Email IOC from TI"
@ -368,12 +347,12 @@
]
},
{
"name": "analytic12",
"name": "analytic14",
"type": "Microsoft.Common.Section",
"label": "TI map Email entity to SigninLogs",
"elements": [
{
"name": "analytic12-text",
"name": "analytic14-text",
"type": "Microsoft.Common.TextBlock",
"options": {
"text": "Identifies a match in SigninLogs table from any Email IOC from TI"
@ -382,12 +361,12 @@
]
},
{
"name": "analytic13",
"name": "analytic15",
"type": "Microsoft.Common.Section",
"label": "TI map File Hash to CommonSecurityLog Event",
"elements": [
{
"name": "analytic13-text",
"name": "analytic15-text",
"type": "Microsoft.Common.TextBlock",
"options": {
"text": "Identifies a match in CommonSecurityLog Event data from any FileHash IOC from TI"
@ -396,12 +375,12 @@
]
},
{
"name": "analytic14",
"name": "analytic16",
"type": "Microsoft.Common.Section",
"label": "TI map File Hash to Security Event",
"elements": [
{
"name": "analytic14-text",
"name": "analytic16-text",
"type": "Microsoft.Common.TextBlock",
"options": {
"text": "Identifies a match in Security Event data from any File Hash IOC from TI"
@ -410,12 +389,12 @@
]
},
{
"name": "analytic15",
"name": "analytic17",
"type": "Microsoft.Common.Section",
"label": "TI map IP entity to AppServiceHTTPLogs",
"elements": [
{
"name": "analytic15-text",
"name": "analytic17-text",
"type": "Microsoft.Common.TextBlock",
"options": {
"text": "Identifies a match in AppServiceHTTPLogs from any IP IOC from TI"
@ -424,12 +403,12 @@
]
},
{
"name": "analytic16",
"name": "analytic18",
"type": "Microsoft.Common.Section",
"label": "TI map IP entity to AWSCloudTrail",
"elements": [
{
"name": "analytic16-text",
"name": "analytic18-text",
"type": "Microsoft.Common.TextBlock",
"options": {
"text": "Identifies a match in AWSCloudTrail from any IP IOC from TI"
@ -438,12 +417,12 @@
]
},
{
"name": "analytic17",
"name": "analytic19",
"type": "Microsoft.Common.Section",
"label": "TI Map IP Entity to AzureActivity",
"elements": [
{
"name": "analytic17-text",
"name": "analytic19-text",
"type": "Microsoft.Common.TextBlock",
"options": {
"text": "This query maps any IP indicators of compromise (IOCs) from threat intelligence (TI), by searching for matches in AzureActivity."
@ -452,12 +431,12 @@
]
},
{
"name": "analytic18",
"name": "analytic20",
"type": "Microsoft.Common.Section",
"label": "TI map IP entity to AzureFirewall",
"elements": [
{
"name": "analytic18-text",
"name": "analytic20-text",
"type": "Microsoft.Common.TextBlock",
"options": {
"text": "Identifies a match in AzureFirewall (NetworkRule & ApplicationRule Logs) from any IP IOC from TI"
@ -466,12 +445,12 @@
]
},
{
"name": "analytic19",
"name": "analytic21",
"type": "Microsoft.Common.Section",
"label": "TI map IP entity to Azure Key Vault logs",
"elements": [
{
"name": "analytic19-text",
"name": "analytic21-text",
"type": "Microsoft.Common.TextBlock",
"options": {
"text": "Identifies a match in Azure Key Vault logs from any IP IOC from TI"
@ -480,12 +459,12 @@
]
},
{
"name": "analytic20",
"name": "analytic22",
"type": "Microsoft.Common.Section",
"label": "TI map IP entity to AzureNetworkAnalytics_CL (NSG Flow Logs)",
"elements": [
{
"name": "analytic20-text",
"name": "analytic22-text",
"type": "Microsoft.Common.TextBlock",
"options": {
"text": "Identifies a match in AzureNetworkAnalytics_CL (NSG Flow Logs) from any IP IOC from TI that was Allowed"
@ -494,12 +473,12 @@
]
},
{
"name": "analytic21",
"name": "analytic23",
"type": "Microsoft.Common.Section",
"label": "TI Map IP Entity to Azure SQL Security Audit Events",
"elements": [
{
"name": "analytic21-text",
"name": "analytic23-text",
"type": "Microsoft.Common.TextBlock",
"options": {
"text": "This query maps any IP indicators of compromise (IOCs) from threat intelligence (TI), by searching for matches in SQL Security Audit Events."
@ -508,12 +487,12 @@
]
},
{
"name": "analytic22",
"name": "analytic24",
"type": "Microsoft.Common.Section",
"label": "TI Map IP Entity to CommonSecurityLog",
"elements": [
{
"name": "analytic22-text",
"name": "analytic24-text",
"type": "Microsoft.Common.TextBlock",
"options": {
"text": "This query maps any IP indicators of compromise (IOCs) from threat intelligence (TI), by searching for matches in CommonSecurityLog."
@ -522,12 +501,12 @@
]
},
{
"name": "analytic23",
"name": "analytic25",
"type": "Microsoft.Common.Section",
"label": "TI Map IP Entity to DnsEvents",
"elements": [
{
"name": "analytic23-text",
"name": "analytic25-text",
"type": "Microsoft.Common.TextBlock",
"options": {
"text": "This query maps any IP indicators of compromise (IOCs) from threat intelligence (TI), by searching for matches in DnsEvents."
@ -536,26 +515,26 @@
]
},
{
"name": "analytic24",
"name": "analytic26",
"type": "Microsoft.Common.Section",
"label": "TI map IP entity to Web Session Events (ASIM Web Session schema)",
"elements": [
{
"name": "analytic24-text",
"name": "analytic26-text",
"type": "Microsoft.Common.TextBlock",
"options": {
"text": "This rule identifies Web Sessions for which the source IP address is a known IoC. This rule uses the [Advanced Security Information Model (ASIM)](https://aka.ms/AboutASIM) and supports any web session source that complies with ASIM."
"text": "This rule identifies Web Sessions for which the source IP address is a known IoC. <br><br>This rule uses the [Advanced Security Information Model (ASIM)](https://aka.ms/AboutASIM) and supports any web session source that complies with ASIM."
}
}
]
},
{
"name": "analytic25",
"name": "analytic27",
"type": "Microsoft.Common.Section",
"label": "TI map IP entity to OfficeActivity",
"elements": [
{
"name": "analytic25-text",
"name": "analytic27-text",
"type": "Microsoft.Common.TextBlock",
"options": {
"text": "This query maps any IP indicators of compromise (IOCs) from threat intelligence (TI), by searching for matches in OfficeActivity."
@ -564,12 +543,12 @@
]
},
{
"name": "analytic26",
"name": "analytic28",
"type": "Microsoft.Common.Section",
"label": "TI Map IP Entity to SigninLogs",
"elements": [
{
"name": "analytic26-text",
"name": "analytic28-text",
"type": "Microsoft.Common.TextBlock",
"options": {
"text": "This query maps any IP indicators of compromise (IOCs) from threat intelligence (TI), by searching for matches in SigninLogs."
@ -578,12 +557,12 @@
]
},
{
"name": "analytic27",
"name": "analytic29",
"type": "Microsoft.Common.Section",
"label": "TI Map IP Entity to VMConnection",
"elements": [
{
"name": "analytic27-text",
"name": "analytic29-text",
"type": "Microsoft.Common.TextBlock",
"options": {
"text": "This query maps any IP indicators of compromise (IOCs) from threat intelligence (TI), by searching for matches in VMConnection."
@ -592,12 +571,12 @@
]
},
{
"name": "analytic28",
"name": "analytic30",
"type": "Microsoft.Common.Section",
"label": "TI Map IP Entity to W3CIISLog",
"elements": [
{
"name": "analytic28-text",
"name": "analytic30-text",
"type": "Microsoft.Common.TextBlock",
"options": {
"text": "This query maps any IP indicators of compromise (IOCs) from threat intelligence (TI), by searching for matches in W3CIISLog."
@ -606,12 +585,12 @@
]
},
{
"name": "analytic29",
"name": "analytic31",
"type": "Microsoft.Common.Section",
"label": "TI Map URL Entity to AuditLogs",
"elements": [
{
"name": "analytic29-text",
"name": "analytic31-text",
"type": "Microsoft.Common.TextBlock",
"options": {
"text": "This query identifies any URL indicators of compromise (IOCs) from threat intelligence (TI) by searching for matches in AuditLogs."
@ -620,26 +599,40 @@
]
},
{
"name": "analytic30",
"name": "analytic32",
"type": "Microsoft.Common.Section",
"label": "TI Map URL Entity to OfficeActivity Data",
"label": "TI Map URL Entity to EmailUrlInfo",
"elements": [
{
"name": "analytic30-text",
"name": "analytic32-text",
"type": "Microsoft.Common.TextBlock",
"options": {
"text": "This query identifies any URL indicators of compromise (IOCs) from threat intelligence (TI) by searching for matches in OfficeActivity data."
"text": "This query identifies any URL indicators of compromise (IOCs) from threat intelligence (TI) by searching for matches in EmailUrlInfo."
}
}
]
},
{
"name": "analytic31",
"name": "analytic33",
"type": "Microsoft.Common.Section",
"label": "TI Map URL Entity to OfficeActivity Data [Deprecated]",
"elements": [
{
"name": "analytic33-text",
"type": "Microsoft.Common.TextBlock",
"options": {
"text": "This query is Deprecated as its filter conditions will never yield results. This query identifies any URL indicators of compromise (IOCs) from threat intelligence (TI) by searching for matches in OfficeActivity data."
}
}
]
},
{
"name": "analytic34",
"type": "Microsoft.Common.Section",
"label": "TI Map URL Entity to PaloAlto Data",
"elements": [
{
"name": "analytic31-text",
"name": "analytic34-text",
"type": "Microsoft.Common.TextBlock",
"options": {
"text": "This query identifies any URL indicators of compromise (IOCs) from threat intelligence (TI) by searching for matches in PaloAlto Data."
@ -648,12 +641,12 @@
]
},
{
"name": "analytic32",
"name": "analytic35",
"type": "Microsoft.Common.Section",
"label": "TI Map URL Entity to SecurityAlert Data",
"elements": [
{
"name": "analytic32-text",
"name": "analytic35-text",
"type": "Microsoft.Common.TextBlock",
"options": {
"text": "This query identifies any URL indicators of compromise (IOCs) from threat intelligence (TI) by searching for matches in SecurityAlert data."
@ -662,12 +655,12 @@
]
},
{
"name": "analytic33",
"name": "analytic36",
"type": "Microsoft.Common.Section",
"label": "TI Map URL Entity to Syslog Data",
"elements": [
{
"name": "analytic33-text",
"name": "analytic36-text",
"type": "Microsoft.Common.TextBlock",
"options": {
"text": "This query identifies any URL indicators of compromise (IOCs) from threat intelligence (TI) by searching for matches in Syslog data."
@ -676,12 +669,26 @@
]
},
{
"name": "analytic34",
"name": "analytic37",
"type": "Microsoft.Common.Section",
"label": "TI Map URL Entity to UrlClickEvents",
"elements": [
{
"name": "analytic37-text",
"type": "Microsoft.Common.TextBlock",
"options": {
"text": "This query identifies any URL indicators of compromise (IOCs) from threat intelligence (TI) by searching for matches in UrlClickEvents."
}
}
]
},
{
"name": "analytic38",
"type": "Microsoft.Common.Section",
"label": "TI Map IP Entity to Duo Security",
"elements": [
{
"name": "analytic34-text",
"name": "analytic38-text",
"type": "Microsoft.Common.TextBlock",
"options": {
"text": "This query maps any IP indicators of compromise (IOCs) from threat intelligence (TI), by searching for matches in DuoSecurity."
@ -690,12 +697,12 @@
]
},
{
"name": "analytic35",
"name": "analytic39",
"type": "Microsoft.Common.Section",
"label": "TI map Domain entity to Dns Events (ASIM DNS Schema)",
"elements": [
{
"name": "analytic35-text",
"name": "analytic39-text",
"type": "Microsoft.Common.TextBlock",
"options": {
"text": "Identifies a match in DNS events from any Domain IOC from TI\nThis analytic rule uses [ASIM](https://aka.ms/AboutASIM) and supports any built-in or custom source that supports the ASIM DNS schema'"
@ -704,40 +711,40 @@
]
},
{
"name": "analytic36",
"name": "analytic40",
"type": "Microsoft.Common.Section",
"label": "TI map IP entity to DNS Events (ASIM DNS schema)",
"elements": [
{
"name": "analytic36-text",
"name": "analytic40-text",
"type": "Microsoft.Common.TextBlock",
"options": {
"text": "This rule identifies DNS requests for which response IP address is a known IoC. This analytic rule uses [ASIM](https://aka.ms/AboutASIM) and supports any built-in or custom source that supports the ASIM DNS schema."
"text": "This rule identifies DNS requests for which response IP address is a known IoC. <br><br>\nThis analytic rule uses [ASIM](https://aka.ms/AboutASIM) and supports any built-in or custom source that supports the ASIM DNS schema."
}
}
]
},
{
"name": "analytic37",
"name": "analytic41",
"type": "Microsoft.Common.Section",
"label": "TI map IP entity to Network Session Events (ASIM Network Session schema)",
"elements": [
{
"name": "analytic37-text",
"name": "analytic41-text",
"type": "Microsoft.Common.TextBlock",
"options": {
"text": "This rule identifies a match Network Sessions for which the source or destination IP address is a known IoC. This analytic rule uses [ASIM](https://aka.ms/AboutASIM) and supports any built-in or custom source that supports the ASIM NetworkSession schema"
"text": "This rule identifies a match Network Sessions for which the source or destination IP address is a known IoC. <br><br>\nThis analytic rule uses [ASIM](https://aka.ms/AboutASIM) and supports any built-in or custom source that supports the ASIM NetworkSession schema"
}
}
]
},
{
"name": "analytic38",
"name": "analytic42",
"type": "Microsoft.Common.Section",
"label": "TI map IP entity to GitHub_CL",
"elements": [
{
"name": "analytic38-text",
"name": "analytic42-text",
"type": "Microsoft.Common.TextBlock",
"options": {
"text": "Identifies a match in GitHub_CL table from any IP IOC from TI"

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

@ -1,5 +1,6 @@
| **Version** | **Date Modified (DD-MM-YYYY)** | **Change History** |
|-------------|--------------------------------|---------------------------------------------|
|-------------|--------------------------------|---------------------------------------------|]
| 3.0.2 | 23-10-2023 | Updated KQL of analytic rules to improve performance in large datasets |
| 3.0.1 | 22-08-2023 | Removed (Preview) from Name field in **Analytical Rules** |
| 3.0.0 | 14-08-2023 | Modified **Analytical Rule** (TI map Domain entity to SecurityAlert). Updated dynamic([1]) to dynamic([1,1]) so as to make result array of array consistent. |
| | | Updated **Hunting Queries** to have descriptions that meet the 255 characters limit. |