-
Notifications
You must be signed in to change notification settings - Fork 3k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #8996 from BlueCycleOps/solution/Threatconnect-1
Solution/threatconnect1
- Loading branch information
Showing
20 changed files
with
2,408 additions
and
0 deletions.
There are no files selected for viewing
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
87 changes: 87 additions & 0 deletions
87
Solutions/ThreatConnect/Analytic Rules/ThreatConnect_DomainEntity_DnsEvents.yaml
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,87 @@ | ||
id: f8960f1c-07d2-512b-9c41-952772d40c84 | ||
name: Threat Connect TI map Domain entity to DnsEvents | ||
version: 1.0.0 | ||
kind: Scheduled | ||
description: | | ||
Identifies a match in DnsEvents from any ThreatConnect Domain IOC from TI | ||
severity: Medium | ||
requiredDataConnectors: | ||
- connectorId: DNS | ||
dataTypes: | ||
- DnsEvents | ||
- connectorId: ThreatIntelligence | ||
dataTypes: | ||
- ThreatIntelligenceIndicator | ||
- connectorId: ThreatIntelligenceTaxii | ||
dataTypes: | ||
- ThreatIntelligenceIndicator | ||
- connectorId: MicrosoftDefenderThreatIntelligence | ||
dataTypes: | ||
- ThreatIntelligenceIndicator | ||
queryFrequency: 1h | ||
queryPeriod: 7d | ||
triggerOperator: gt | ||
triggerThreshold: 0 | ||
tactics: | ||
- Impact | ||
query: | | ||
// Define the lookback periods for time-based filters | ||
let dt_lookBack = 1h; // Look back 1 hour for DNS events | ||
let ioc_lookBack = 7d; // Look back 7 days for threat intelligence indicators | ||
// Fetch threat intelligence indicators related to domains | ||
let Domain_Indicators = ThreatIntelligenceIndicator | ||
| where TimeGenerated >= ago(ioc_lookBack) | ||
| summarize LatestIndicatorTime = arg_max(TimeGenerated, *) by IndicatorId | ||
| where ExpirationDateTime > now() and Active == true | ||
// Filter out non ThreatConnect TI Sources | ||
| where SourceSystem startswith "ThreatConnect-" | ||
// 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 | ||
let list_tlds = Domain_Indicators | ||
| extend parts = split(DomainName, '.') | ||
| extend tld = parts[(array_length(parts)-1)] | ||
| summarize count() by tostring(tld) | ||
| project tld | ||
| summarize make_list(tld, maxListSize); | ||
// Perform a join between domain indicators and DNS events to identify potential malicious activity | ||
Domain_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 ( | ||
DnsEvents | ||
| where TimeGenerated > ago(dt_lookBack) | ||
// Extract domain patterns from syslog message | ||
| where isnotempty(Name) | ||
| extend parts = split(Name, '.') | ||
| 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) | ||
| extend DNS_TimeGenerated = TimeGenerated | ||
) on $left.TI_DomainEntity==$right.Name | ||
// Filter out DNS events that occurred after the expiration of the corresponding indicator | ||
| where DNS_TimeGenerated < ExpirationDateTime | ||
// Group the results by IndicatorId and Name, and keep the DNS event with the latest timestamp | ||
| summarize DNS_TimeGenerated = arg_max(DNS_TimeGenerated, *) by IndicatorId, Name | ||
// Select the desired output fields | ||
| project DNS_TimeGenerated, Description, ActivityGroupNames, IndicatorId, ThreatType, ExpirationDateTime, ConfidenceScore, Url, Computer, ClientIP, Name, QueryType, Type, TI_DomainEntity | ||
// Extract hostname and DNS domain from the Computer field | ||
| extend HostName = tostring(split(Computer, '.', 0)[0]), DnsDomain = tostring(strcat_array(array_slice(split(Computer, '.'), 1, -1), '.')) | ||
// Rename the timestamp field | ||
| extend timestamp = DNS_TimeGenerated | ||
entityMappings: | ||
- entityType: Host | ||
fieldMappings: | ||
- identifier: HostName | ||
columnName: HostName | ||
- identifier: DnsDomain | ||
columnName: DnsDomain | ||
- entityType: IP | ||
fieldMappings: | ||
- identifier: Address | ||
columnName: ClientIP | ||
- entityType: URL | ||
fieldMappings: | ||
- identifier: Url | ||
columnName: Url |
66 changes: 66 additions & 0 deletions
66
Solutions/ThreatConnect/Analytic Rules/ThreatConnect_EmailEntity_OfficeActivity.yaml
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,66 @@ | ||
id: 4f7ade3e-7121-5274-83ea-d7ed22a01fea | ||
name: ThreatConnect TI map Email entity to OfficeActivity | ||
version: 1.2.4 | ||
kind: Scheduled | ||
description: | | ||
'Identifies a match in OfficeActivity table from any Email IOC from ThreatConnect TI' | ||
severity: Medium | ||
requiredDataConnectors: | ||
- connectorId: Office365 | ||
dataTypes: | ||
- OfficeActivity | ||
- 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 emailregex = @'^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+$'; | ||
ThreatIntelligenceIndicator | ||
| where TimeGenerated >= ago(ioc_lookBack) | ||
| summarize LatestIndicatorTime = arg_max(TimeGenerated, *) by IndicatorId | ||
| where ExpirationDateTime > now() and Active == true | ||
// Filter out non ThreatConnect TI Sources | ||
| where SourceSystem startswith "ThreatConnect-" | ||
//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 ( | ||
OfficeActivity | where TimeGenerated >= ago(dt_lookBack) and isnotempty(UserId) | ||
| where UserId matches regex emailregex | ||
| extend OfficeActivity_TimeGenerated = TimeGenerated | ||
) | ||
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 | ||
| extend Name = tostring(split(UserId, '@', 0)[0]), UPNSuffix = tostring(split(UserId, '@', 1)[0]) | ||
| extend timestamp = OfficeActivity_TimeGenerated | ||
entityMappings: | ||
- entityType: Account | ||
fieldMappings: | ||
- identifier: Name | ||
columnName: Name | ||
- identifier: UPNSuffix | ||
columnName: UPNSuffix | ||
- entityType: IP | ||
fieldMappings: | ||
- identifier: Address | ||
columnName: ClientIP | ||
- entityType: URL | ||
fieldMappings: | ||
- identifier: Url | ||
columnName: Url |
81 changes: 81 additions & 0 deletions
81
Solutions/ThreatConnect/Analytic Rules/ThreatConnect_EmailEntity_SigninLogs.yaml
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,81 @@ | ||
id: ecb68ce7-c309-59a7-a8de-07ccf2a0ea4f | ||
name: ThreatConnect TI map Email entity to SigninLogs | ||
version: 1.2.4 | ||
kind: Scheduled | ||
description: | | ||
'Identifies a match in SigninLogs table from any Email IOC from ThreatConnect TI' | ||
severity: Medium | ||
requiredDataConnectors: | ||
- connectorId: ThreatIntelligence | ||
dataTypes: | ||
- ThreatIntelligenceIndicator | ||
- connectorId: ThreatIntelligenceTaxii | ||
dataTypes: | ||
- ThreatIntelligenceIndicator | ||
- connectorId: AzureActiveDirectory | ||
dataTypes: | ||
- SigninLogs | ||
- connectorId: AzureActiveDirectory | ||
dataTypes: | ||
- AADNonInteractiveUserSignInLogs | ||
- connectorId: MicrosoftDefenderThreatIntelligence | ||
dataTypes: | ||
- ThreatIntelligenceIndicator | ||
queryFrequency: 1h | ||
queryPeriod: 14d | ||
triggerOperator: gt | ||
triggerThreshold: 0 | ||
tactics: | ||
- Impact | ||
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){ | ||
ThreatIntelligenceIndicator | ||
| where TimeGenerated >= ago(ioc_lookBack) | ||
| summarize LatestIndicatorTime = arg_max(TimeGenerated, *) by IndicatorId | ||
| where ExpirationDateTime > now() and Active == true | ||
// Filter out non ThreatConnect TI Sources | ||
| where SourceSystem startswith "ThreatConnect-" | ||
//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 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 | ||
| 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: | ||
- identifier: Name | ||
columnName: Name | ||
- identifier: UPNSuffix | ||
columnName: UPNSuffix | ||
- entityType: IP | ||
fieldMappings: | ||
- identifier: Address | ||
columnName: IPAddress | ||
- entityType: URL | ||
fieldMappings: | ||
- identifier: Url | ||
columnName: Url |
79 changes: 79 additions & 0 deletions
79
Solutions/ThreatConnect/Analytic Rules/ThreatConnect_IPEntity_NetworkSessions.yaml
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,79 @@ | ||
id: ee1fd303-2081-47b7-8f02-e38bfd0868e6 | ||
name: ThreatConnect TI map IP entity to Network Session Events (ASIM Network Session schema) | ||
version: 1.0.0 | ||
kind: Scheduled | ||
description: |- | ||
ThreatConnect Specific: | ||
This rule identifies a match Network Sessions for which the source or destination IP address is a known IoC. <br><br> | ||
This analytic rule uses [ASIM](https://aka.ms/AboutASIM) and supports any built-in or custom source that supports the ASIM NetworkSession schema | ||
severity: Medium | ||
requiredDataConnectors: | ||
- connectorId: ThreatIntelligence | ||
dataTypes: | ||
- ThreatIntelligenceIndicator | ||
queryFrequency: 1h | ||
queryPeriod: 14d | ||
triggerOperator: gt | ||
triggerThreshold: 0 | ||
tactics: | ||
- Impact | ||
query: | | ||
let dt_lookBack = 1h; | ||
let ioc_lookBack = 14d; | ||
let IP_TI = materialize ( | ||
ThreatIntelligenceIndicator | ||
| where TimeGenerated >= ago(ioc_lookBack) | ||
| summarize LatestIndicatorTime = arg_max(TimeGenerated, *) by IndicatorId | ||
| where ExpirationDateTime > now() and Active == true | ||
| where SourceSystem startswith "ThreatConnect-" | ||
| extend TI_ipEntity = coalesce(NetworkIP, NetworkDestinationIP, NetworkSourceIP,EmailSourceIpAddress,"NO_IP") | ||
| where TI_ipEntity != "NO_IP" | ||
); | ||
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 | ||
| join kind=innerunique | ||
( | ||
_Im_NetworkSession (starttime=ago(dt_lookBack)) | ||
| where isnotempty(SrcIpAddr) | ||
| summarize imNWS_mintime=min(TimeGenerated), imNWS_maxtime=max(TimeGenerated) by SrcIpAddr, DstIpAddr, Dvc, EventProduct, EventVendor | ||
| lookup (IP_TI | project TI_ipEntity, Active) on $left.SrcIpAddr == $right.TI_ipEntity | ||
| project-rename SrcMatch = Active | ||
| lookup (IP_TI | project TI_ipEntity, Active) on $left.DstIpAddr == $right.TI_ipEntity | ||
| project-rename DstMatch = Active | ||
| where SrcMatch or DstMatch | ||
| extend | ||
IoCIP = iff(SrcMatch, SrcIpAddr, DstIpAddr), | ||
IoCDirection = iff(SrcMatch, "Source", "Destination") | ||
)on $left.TI_ipEntity == $right.IoCIP | ||
| where imNWS_mintime < ExpirationDateTime | ||
| project imNWS_mintime, imNWS_maxtime, Description, ActivityGroupNames, IndicatorId, ThreatType, ExpirationDateTime, ConfidenceScore, SrcIpAddr, DstIpAddr, IoCDirection, IoCIP, Dvc, EventVendor, EventProduct | ||
suppressionEnabled: false | ||
incidentConfiguration: | ||
createIncident: true | ||
groupingConfiguration: | ||
enabled: true | ||
reopenClosedIncident: false | ||
lookbackDuration: 4h | ||
matchingMethod: AllEntities | ||
eventGroupingSettings: | ||
aggregationKind: SingleAlert | ||
alertDetailsOverride: | ||
alertDisplayNameFormat: A network session {{IoCDirection}} address {{IoCIP}} matched an IoC. | ||
alertDescriptionFormat: The {{IoCDirection}} address {{IoCIP}} of a network session matched a known indicator of compromise of {{ThreatType}}. Consult the threat intelligence blead for more information on the indicator. | ||
customDetails: | ||
IndicatorId: IndicatorId | ||
IoCConfidenceScore: ConfidenceScore | ||
IoCDescription: Description | ||
IoCExpirationTime: ExpirationDateTime | ||
EventEndTime: imNWS_maxtime | ||
ActivityGroupNames: ActivityGroupNames | ||
ThreatType: ThreatType | ||
IoCIPDirection: IoCDirection | ||
EventStartTime: imNWS_mintime | ||
entityMappings: | ||
- entityType: IP | ||
fieldMappings: | ||
- identifier: Address | ||
columnName: IoCIP | ||
suppressionDuration: 1h | ||
|
Oops, something went wrong.