New NRT Rules Created
This commit is contained in:
Родитель
ed5ba8cd4b
Коммит
f2c58f181f
|
@ -0,0 +1,37 @@
|
|||
id: 0ee2aafb-4500-4e36-bcb1-e90eec2f0b9b
|
||||
name: NRT Login to AWS Management Console without MFA
|
||||
description: |
|
||||
'Multi-Factor Authentication (MFA) helps you to prevent credential compromise. This alert identifies logins to the AWS Management Console without MFA.
|
||||
You can limit this detection to trigger for adminsitrative accounts if you do not have MFA enabled on all accounts.
|
||||
This is done by looking at the eventName ConsoleLogin and if the AdditionalEventData field indicates MFA was NOT used
|
||||
and the ResponseElements field indicates NOT a Failure. Thereby indicating that a non-MFA login was successful.'
|
||||
severity: Low
|
||||
requiredDataConnectors:
|
||||
- connectorId: AWS
|
||||
dataTypes:
|
||||
- AWSCloudTrail
|
||||
tactics:
|
||||
- DefenseEvasion
|
||||
- PrivilegeEscalation
|
||||
- Persistence
|
||||
- InitialAccess
|
||||
relevantTechniques:
|
||||
- T1078
|
||||
query: |
|
||||
AWSCloudTrail
|
||||
| where EventName =~ "ConsoleLogin"
|
||||
| extend MFAUsed = tostring(parse_json(AdditionalEventData).MFAUsed), LoginResult = tostring(parse_json(ResponseElements).ConsoleLogin)
|
||||
| where MFAUsed !~ "Yes" and LoginResult !~ "Failure"
|
||||
| summarize StartTimeUtc = min(TimeGenerated), EndTimeUtc = max(TimeGenerated) by EventName, EventTypeName, LoginResult, MFAUsed, UserIdentityAccountId, UserIdentityPrincipalid, UserAgent,
|
||||
UserIdentityUserName, SessionMfaAuthenticated, SourceIpAddress, AWSRegion
|
||||
entityMappings:
|
||||
- entityType: Account
|
||||
fieldMappings:
|
||||
- identifier: FullName
|
||||
columnName: UserIdentityUserName
|
||||
- entityType: IP
|
||||
fieldMappings:
|
||||
- identifier: Address
|
||||
columnName: SourceIpAddress
|
||||
version: 1.0.0
|
||||
kind: NRT
|
|
@ -0,0 +1,42 @@
|
|||
id: 8540c842-5bbc-4a24-9fb2-a836c0e55a51
|
||||
name: NRT Modified domain federation trust settings
|
||||
description: |
|
||||
'This will alert when a user or application modifies the federation settings on the domain or Update domain authentication from Managed to Federated.
|
||||
For example, this alert will trigger when a new Active Directory Federated Service (ADFS) TrustedRealm object, such as a signing certificate, is added to the domain.
|
||||
Modification to domain federation settings should be rare. Confirm the added or modified target domain/URL is legitimate administrator behavior.
|
||||
To understand why an authorized user may update settings for a federated domain in Office 365, Azure, or Intune, see: https://docs.microsoft.com/office365/troubleshoot/active-directory/update-federated-domain-office-365.
|
||||
For details on security realms that accept security tokens, see the ADFS Proxy Protocol (MS-ADFSPP) specification: https://docs.microsoft.com/openspecs/windows_protocols/ms-adfspp/e7b9ea73-1980-4318-96a6-da559486664b.
|
||||
For further information on AuditLogs please see https://docs.microsoft.com/azure/active-directory/reports-monitoring/reference-audit-activities.'
|
||||
severity: High
|
||||
requiredDataConnectors:
|
||||
- connectorId: AzureActiveDirectory
|
||||
dataTypes:
|
||||
- AuditLogs
|
||||
tactics:
|
||||
- CredentialAccess
|
||||
query: |
|
||||
AuditLogs
|
||||
| where OperationName =~ "Set federation settings on domain" or OperationName =~ "Set domain authentication"
|
||||
//| where Result =~ "success" // commenting out, as it may be interesting to capture failed attempts
|
||||
| mv-expand TargetResources
|
||||
| extend modifiedProperties = parse_json(TargetResources).modifiedProperties
|
||||
| mv-expand modifiedProperties
|
||||
| extend targetDisplayName = tostring(parse_json(modifiedProperties).displayName), NewDomainValue=tostring(parse_json(modifiedProperties).newValue)
|
||||
| extend Federated = iif(OperationName =~ "Set domain authentication", iif(NewDomainValue has "Federated", True, False), True)
|
||||
| where Federated == True
|
||||
| mv-expand AdditionalDetails
|
||||
| extend UserAgent = iff(AdditionalDetails.key == "User-Agent",tostring(AdditionalDetails.value),"")
|
||||
| extend InitiatingUserOrApp = iff(isnotempty(InitiatedBy.user.userPrincipalName),tostring(InitiatedBy.user.userPrincipalName), tostring(InitiatedBy.app.displayName))
|
||||
| extend InitiatingIpAddress = iff(isnotempty(InitiatedBy.user.ipAddress), tostring(InitiatedBy.user.ipAddress), tostring(InitiatedBy.app.ipAddress))
|
||||
| project-reorder TimeGenerated, OperationName, InitiatingUserOrApp, AADOperationType, targetDisplayName, Result, InitiatingIpAddress, UserAgent, CorrelationId, TenantId, AADTenantId
|
||||
entityMappings:
|
||||
- entityType: Account
|
||||
fieldMappings:
|
||||
- identifier: FullName
|
||||
columnName: InitiatingUserOrApp
|
||||
- entityType: IP
|
||||
fieldMappings:
|
||||
- identifier: Address
|
||||
columnName: InitiatingIpAddress
|
||||
version: 1.0.0
|
||||
kind: NRT
|
|
@ -0,0 +1,56 @@
|
|||
id: e42e889a-caaf-4dbb-aec6-371b37d64298
|
||||
name: NRT New access credential added to Application or Service Principal
|
||||
description: |
|
||||
'This will alert when an admin or app owner account adds a new credential to an Application or Service Principal where a verify KeyCredential was already present for the app.
|
||||
If a threat actor obtains access to an account with sufficient privileges and adds the alternate authentication material triggering this event, the threat actor can now authenticate as the Application or Service Principal using this credential.
|
||||
Additional information on OAuth Credential Grants can be found in RFC 6749 Section 4.4 or https://docs.microsoft.com/azure/active-directory/develop/v2-oauth2-client-creds-grant-flow
|
||||
For further information on AuditLogs please see https://docs.microsoft.com/azure/active-directory/reports-monitoring/reference-audit-activities.'
|
||||
severity: Medium
|
||||
requiredDataConnectors:
|
||||
- connectorId: AzureActiveDirectory
|
||||
dataTypes:
|
||||
- AuditLogs
|
||||
tactics:
|
||||
- DefenseEvasion
|
||||
relevantTechniques:
|
||||
- T1550.001
|
||||
tags:
|
||||
- Solorigate
|
||||
- NOBELIUM
|
||||
query: |
|
||||
AuditLogs
|
||||
| where OperationName has_any ("Add service principal", "Certificates and secrets management")
|
||||
| where Result =~ "success"
|
||||
| mv-expand target = TargetResources
|
||||
| where tostring(InitiatedBy.user.userPrincipalName) has "@" or tostring(InitiatedBy.app.displayName) has "@"
|
||||
| extend targetDisplayName = tostring(TargetResources[0].displayName)
|
||||
| extend targetId = tostring(TargetResources[0].id)
|
||||
| extend targetType = tostring(TargetResources[0].type)
|
||||
| extend keyEvents = TargetResources[0].modifiedProperties
|
||||
| mv-expand keyEvents
|
||||
| where keyEvents.displayName =~ "KeyDescription"
|
||||
| extend new_value_set = parse_json(tostring(keyEvents.newValue))
|
||||
| extend old_value_set = parse_json(tostring(keyEvents.oldValue))
|
||||
| where old_value_set != "[]"
|
||||
| extend diff = set_difference(new_value_set, old_value_set)
|
||||
| where isnotempty(diff)
|
||||
| parse diff with * "KeyIdentifier=" keyIdentifier:string ",KeyType=" keyType:string ",KeyUsage=" keyUsage:string ",DisplayName=" keyDisplayName:string "]" *
|
||||
| where keyUsage == "Verify" or keyUsage == ""
|
||||
| extend UserAgent = iff(AdditionalDetails[0].key == "User-Agent",tostring(AdditionalDetails[0].value),"")
|
||||
| extend InitiatingUserOrApp = iff(isnotempty(InitiatedBy.user.userPrincipalName),tostring(InitiatedBy.user.userPrincipalName), tostring(InitiatedBy.app.displayName))
|
||||
| extend InitiatingIpAddress = iff(isnotempty(InitiatedBy.user.ipAddress), tostring(InitiatedBy.user.ipAddress), tostring(InitiatedBy.app.ipAddress))
|
||||
// The below line is currently commented out but Microsoft Sentinel users can modify this query to show only Application or only Service Principal events in their environment
|
||||
//| where targetType =~ "Application" // or targetType =~ "ServicePrincipal"
|
||||
| project-away diff, new_value_set, old_value_set
|
||||
| project-reorder TimeGenerated, OperationName, InitiatingUserOrApp, InitiatingIpAddress, UserAgent, targetDisplayName, targetId, targetType, keyDisplayName, keyType, keyUsage, keyIdentifier, CorrelationId, TenantId
|
||||
entityMappings:
|
||||
- entityType: Account
|
||||
fieldMappings:
|
||||
- identifier: FullName
|
||||
columnName: InitiatingUserOrApp
|
||||
- entityType: IP
|
||||
fieldMappings:
|
||||
- identifier: Address
|
||||
columnName: InitiatingIpAddress
|
||||
version: 1.0.0
|
||||
kind: NRT
|
|
@ -0,0 +1,40 @@
|
|||
id: 5db427b2-f406-4274-b413-e9fcb29412f8
|
||||
name: NRT PIM Elevation Request Rejected
|
||||
description: |
|
||||
'Identifies when a user is rejected for a privileged role elevation via PIM. Monitor rejections for indicators of attacker compromise of the requesting account.
|
||||
Ref : https://docs.microsoft.com/azure/active-directory/fundamentals/security-operations-privileged-identity-management'
|
||||
severity: High
|
||||
requiredDataConnectors:
|
||||
- connectorId: AzureActiveDirectory
|
||||
dataTypes:
|
||||
- AuditLogs
|
||||
tactics:
|
||||
- Persistence
|
||||
relevantTechniques:
|
||||
- T1078.004
|
||||
tags:
|
||||
- AADSecOpsGuide
|
||||
query: |
|
||||
AuditLogs
|
||||
| where ActivityDisplayName =~'Add member to role completed (PIM activation)'
|
||||
| where Result == "failure"
|
||||
| extend Role = tostring(TargetResources[3].displayName)
|
||||
| extend User = tostring(TargetResources[2].displayName)
|
||||
| project-reorder TimeGenerated, User, Role, OperationName, Result, ResultDescription
|
||||
| extend InitiatingUser = tostring(parse_json(tostring(InitiatedBy.user)).userPrincipalName)
|
||||
| extend IPCustomEntity = tostring(parse_json(tostring(InitiatedBy.user)).ipAddress)
|
||||
entityMappings:
|
||||
- entityType: Account
|
||||
fieldMappings:
|
||||
- identifier: FullName
|
||||
columnName: InitiatingUser
|
||||
- entityType: Account
|
||||
fieldMappings:
|
||||
- identifier: FullName
|
||||
columnName: User
|
||||
- entityType: IP
|
||||
fieldMappings:
|
||||
- identifier: Address
|
||||
columnName: IPCustomEntity
|
||||
version: 1.0.0
|
||||
kind: NRT
|
|
@ -0,0 +1,58 @@
|
|||
id: 70fc7201-f28e-4ba7-b9ea-c04b96701f13
|
||||
name: NRT User added to Azure Active Directory Privileged Groups
|
||||
description: |
|
||||
'This will alert when a user is added to any of the Privileged Groups.
|
||||
For further information on AuditLogs please see https://docs.microsoft.com/azure/active-directory/reports-monitoring/reference-audit-activities.
|
||||
For Administrator role permissions in Azure Active Directory please see https://docs.microsoft.com/azure/active-directory/users-groups-roles/directory-assign-admin-roles'
|
||||
severity: Medium
|
||||
requiredDataConnectors:
|
||||
- connectorId: AzureActiveDirectory
|
||||
dataTypes:
|
||||
- AuditLogs
|
||||
tactics:
|
||||
- Persistence
|
||||
- PrivilegeEscalation
|
||||
relevantTechniques:
|
||||
- T1098
|
||||
- T1078
|
||||
query: |
|
||||
let OperationList = dynamic(["Add member to role","Add member to role in PIM requested (permanent)"]);
|
||||
let PrivilegedGroups = dynamic(["UserAccountAdmins","PrivilegedRoleAdmins","TenantAdmins"]);
|
||||
AuditLogs
|
||||
//| where LoggedByService =~ "Core Directory"
|
||||
| where Category =~ "RoleManagement"
|
||||
| where OperationName in~ (OperationList)
|
||||
| mv-expand TargetResources
|
||||
| extend modProps = parse_json(TargetResources).modifiedProperties
|
||||
| mv-expand bagexpansion=array modProps
|
||||
| evaluate bag_unpack(modProps)
|
||||
| extend displayName = column_ifexists("displayName", "NotAvailable"), newValue = column_ifexists("newValue", "NotAvailable")
|
||||
| where displayName =~ "Role.WellKnownObjectName"
|
||||
| extend DisplayName = displayName, GroupName = replace('"','',newValue)
|
||||
| extend initByApp = parse_json(InitiatedBy).app, initByUser = parse_json(InitiatedBy).user
|
||||
| extend AppId = initByApp.appId,
|
||||
InitiatedByDisplayName = case(isnotempty(initByApp.displayName), initByApp.displayName, isnotempty(initByUser.displayName), initByUser.displayName, "not available"),
|
||||
ServicePrincipalId = tostring(initByApp.servicePrincipalId),
|
||||
ServicePrincipalName = tostring(initByApp.servicePrincipalName),
|
||||
UserId = initByUser.id,
|
||||
UserIPAddress = initByUser.ipAddress,
|
||||
UserRoles = initByUser.roles,
|
||||
UserPrincipalName = tostring(initByUser.userPrincipalName),
|
||||
TargetUserPrincipalName = tostring(TargetResources.userPrincipalName)
|
||||
| where GroupName in~ (PrivilegedGroups)
|
||||
// If you don't want to alert for operations from PIM, remove below filtering for MS-PIM.
|
||||
//| where InitiatedByDisplayName != "MS-PIM"
|
||||
| project TimeGenerated, AADOperationType, Category, OperationName, AADTenantId, AppId, InitiatedByDisplayName, ServicePrincipalId, ServicePrincipalName, DisplayName, GroupName, UserId, UserIPAddress, UserRoles, UserPrincipalName, TargetUserPrincipalName
|
||||
| extend AccountCustomEntity = case(isnotempty(ServicePrincipalName), ServicePrincipalName, isnotempty(ServicePrincipalId), ServicePrincipalId, isnotempty(UserPrincipalName), UserPrincipalName, "not available")
|
||||
entityMappings:
|
||||
entityMappings:
|
||||
- entityType: Account
|
||||
fieldMappings:
|
||||
- identifier: FullName
|
||||
columnName: AccountCustomEntity
|
||||
- entityType: Account
|
||||
fieldMappings:
|
||||
- identifier: FullName
|
||||
columnName: TargetUserPrincipalName
|
||||
version: 1.0.0
|
||||
kind: NRT
|
|
@ -0,0 +1,38 @@
|
|||
id: ec491363-5fe7-4eff-b68e-f42dcb76fcf6
|
||||
name: NRT Azure Active Directory Hybrid Health AD FS New Server
|
||||
description: |
|
||||
'This detection uses AzureActivity logs (Administrative category) to identify the creation or update of a server instance in an Azure AD Hybrid health AD FS service.
|
||||
A threat actor can create a new AD Health ADFS service and create a fake server instance to spoof AD FS signing logs. There is no need to compromise an on-prem AD FS server.
|
||||
This can be done programmatically via HTTP requests to Azure. More information in this blog: https://o365blog.com/post/hybridhealthagent/'
|
||||
severity: Medium
|
||||
requiredDataConnectors:
|
||||
- connectorId: AzureActivity
|
||||
dataTypes:
|
||||
- AzureActivity
|
||||
tactics:
|
||||
- DefenseEvasion
|
||||
relevantTechniques:
|
||||
- T1578
|
||||
tags:
|
||||
- SimuLand
|
||||
query: |
|
||||
AzureActivity
|
||||
| where CategoryValue == 'Administrative'
|
||||
| where ResourceProviderValue =~ 'Microsoft.ADHybridHealthService'
|
||||
| where _ResourceId contains 'AdFederationService'
|
||||
| where OperationNameValue =~ 'Microsoft.ADHybridHealthService/services/servicemembers/action'
|
||||
| extend claimsJson = parse_json(Claims)
|
||||
| extend AppId = tostring(claimsJson.appid)
|
||||
| extend AccountName = tostring(claimsJson.name)
|
||||
| project-away claimsJson
|
||||
entityMappings:
|
||||
- entityType: Account
|
||||
fieldMappings:
|
||||
- identifier: FullName
|
||||
columnName: Caller
|
||||
- entityType: IP
|
||||
fieldMappings:
|
||||
- identifier: Address
|
||||
columnName: CallerIpAddress
|
||||
version: 1.0.0
|
||||
kind: NRT
|
|
@ -0,0 +1,41 @@
|
|||
id: 884ead54-cb3f-4676-a1eb-b26532d6cbfd
|
||||
name: NRT Sensitive Azure Key Vault operations
|
||||
description: |
|
||||
'Identifies when sensitive Azure Key Vault operations are used. This includes: VaultDelete, KeyDelete, SecretDelete, SecretPurge, KeyPurge, SecretBackup, KeyBackup.
|
||||
Any Backup operations should match with expected scheduled backup activity.'
|
||||
severity: Low
|
||||
requiredDataConnectors:
|
||||
- connectorId: AzureKeyVault
|
||||
dataTypes:
|
||||
- KeyVaultData
|
||||
tactics:
|
||||
- Impact
|
||||
relevantTechniques:
|
||||
- T1485
|
||||
query: |
|
||||
let SensitiveOperationList = dynamic(
|
||||
["VaultDelete", "KeyDelete", "SecretDelete", "SecretPurge", "KeyPurge", "SecretBackup", "KeyBackup"]);
|
||||
AzureDiagnostics
|
||||
| extend ResultType = columnifexists("ResultType", "NoResultType")
|
||||
| extend requestUri_s = columnifexists("requestUri_s", "None"), identity_claim_http_schemas_microsoft_com_identity_claims_objectidentifier_g = columnifexists("identity_claim_http_schemas_microsoft_com_identity_claims_objectidentifier_g", "None")
|
||||
| extend id_s = columnifexists("id_s", "None"), CallerIPAddress = columnifexists("CallerIPAddress", "None"), clientInfo_s = columnifexists("clientInfo_s", "None")
|
||||
| where ResultType !~ "None" and isnotempty(ResultType)
|
||||
| where identity_claim_http_schemas_microsoft_com_identity_claims_objectidentifier_g !~ "None" and isnotempty(identity_claim_http_schemas_microsoft_com_identity_claims_objectidentifier_g)
|
||||
| where id_s !~ "None" and isnotempty(id_s)
|
||||
| where CallerIPAddress !~ "None" and isnotempty(CallerIPAddress)
|
||||
| where clientInfo_s !~ "None" and isnotempty(clientInfo_s)
|
||||
| where requestUri_s !~ "None" and isnotempty(requestUri_s)
|
||||
| where ResourceType =~ "VAULTS" and ResultType =~ "Success"
|
||||
| where OperationName in~ (SensitiveOperationList)
|
||||
| summarize EventCount=count(), StartTimeUtc=min(TimeGenerated), EndTimeUtc=max(TimeGenerated), TimeTriggered=makelist(TimeGenerated),OperationNameList=make_set(OperationName), RequestURLList=make_set(requestUri_s), CallerIPList = make_set(CallerIPAddress), CallerIPMax= arg_max(CallerIPAddress,*) by ResourceType, ResultType, Resource, id_s, identity_claim_http_schemas_microsoft_com_identity_claims_objectidentifier_g, clientInfo_s
|
||||
entityMappings:
|
||||
- entityType: Account
|
||||
fieldMappings:
|
||||
- identifier: FullName
|
||||
columnName: identity_claim_http_schemas_microsoft_com_identity_claims_objectidentifier_g
|
||||
- entityType: IP
|
||||
fieldMappings:
|
||||
- identifier: Address
|
||||
columnName: CallerIPMax
|
||||
version: 1.0.0
|
||||
kind: NRT
|
|
@ -0,0 +1,36 @@
|
|||
id: d5b32cd4-2328-43da-ab47-cd289c1f5efc
|
||||
name: NRT DNS events related to mining pools
|
||||
description: |
|
||||
'Identifies IP addresses that may be performing DNS lookups associated with common currency mining pools.'
|
||||
severity: Low
|
||||
requiredDataConnectors:
|
||||
- connectorId: DNS
|
||||
dataTypes:
|
||||
- DnsEvents
|
||||
tactics:
|
||||
- Impact
|
||||
relevantTechniques:
|
||||
- T1496
|
||||
query: |
|
||||
DnsEvents
|
||||
| where Name contains "."
|
||||
| where Name has_any ("monerohash.com", "do-dear.com", "xmrminerpro.com", "secumine.net", "xmrpool.com", "minexmr.org", "hashanywhere.com",
|
||||
"xmrget.com", "mininglottery.eu", "minergate.com", "moriaxmr.com", "multipooler.com", "moneropools.com", "xmrpool.eu", "coolmining.club",
|
||||
"supportxmr.com", "minexmr.com", "hashvault.pro", "xmrpool.net", "crypto-pool.fr", "xmr.pt", "miner.rocks", "walpool.com", "herominers.com",
|
||||
"gntl.co.uk", "semipool.com", "coinfoundry.org", "cryptoknight.cc", "fairhash.org", "baikalmine.com", "tubepool.xyz", "fairpool.xyz", "asiapool.io",
|
||||
"coinpoolit.webhop.me", "nanopool.org", "moneropool.com", "miner.center", "prohash.net", "poolto.be", "cryptoescrow.eu", "monerominers.net", "cryptonotepool.org",
|
||||
"extrmepool.org", "webcoin.me", "kippo.eu", "hashinvest.ws", "monero.farm", "supportxmr.com", "xmrpool.eu", "linux-repository-updates.com", "1gh.com",
|
||||
"dwarfpool.com", "hash-to-coins.com", "hashvault.pro", "pool-proxy.com", "hashfor.cash", "fairpool.cloud", "litecoinpool.org", "mineshaft.ml", "abcxyz.stream",
|
||||
"moneropool.ru", "cryptonotepool.org.uk", "extremepool.org", "extremehash.com", "hashinvest.net", "unipool.pro", "crypto-pools.org", "monero.net",
|
||||
"backup-pool.com", "mooo.com", "freeyy.me", "cryptonight.net", "shscrypto.net")
|
||||
entityMappings:
|
||||
- entityType: Host
|
||||
fieldMappings:
|
||||
- identifier: FullName
|
||||
columnName: Computer
|
||||
- entityType: IP
|
||||
fieldMappings:
|
||||
- identifier: Address
|
||||
columnName: ClientIP
|
||||
version: 1.0.0
|
||||
kind: NRT
|
|
@ -0,0 +1,48 @@
|
|||
id: b79f6190-d104-4691-b7db-823e05980895
|
||||
name: NRT Malicious Inbox Rule
|
||||
description: |
|
||||
'Often times after the initial compromise the attackers create inbox rules to delete emails that contain certain keywords.
|
||||
This is done so as to limit ability to warn compromised users that they've been compromised. Below is a sample query that tries to detect this.
|
||||
Reference: https://www.reddit.com/r/sysadmin/comments/7kyp0a/recent_phishing_attempts_my_experience_and_what/'
|
||||
severity: Medium
|
||||
requiredDataConnectors:
|
||||
- connectorId: Office365
|
||||
dataTypes:
|
||||
- OfficeActivity
|
||||
tactics:
|
||||
- Persistence
|
||||
- DefenseEvasion
|
||||
relevantTechniques:
|
||||
- T1098
|
||||
- T1078
|
||||
query: |
|
||||
let Keywords = dynamic(["helpdesk", " alert", " suspicious", "fake", "malicious", "phishing", "spam", "do not click", "do not open", "hijacked", "Fatal"]);
|
||||
OfficeActivity
|
||||
| where Operation =~ "New-InboxRule"
|
||||
| where Parameters has "Deleted Items" or Parameters has "Junk Email" or Parameters has "DeleteMessage"
|
||||
| extend Events=todynamic(Parameters)
|
||||
| parse Events with * "SubjectContainsWords" SubjectContainsWords '}'*
|
||||
| parse Events with * "BodyContainsWords" BodyContainsWords '}'*
|
||||
| parse Events with * "SubjectOrBodyContainsWords" SubjectOrBodyContainsWords '}'*
|
||||
| where SubjectContainsWords has_any (Keywords)
|
||||
or BodyContainsWords has_any (Keywords)
|
||||
or SubjectOrBodyContainsWords has_any (Keywords)
|
||||
| extend ClientIPAddress = case( ClientIP has ".", tostring(split(ClientIP,":")[0]), ClientIP has "[", tostring(trim_start(@'[[]',tostring(split(ClientIP,"]")[0]))), ClientIP )
|
||||
| extend Keyword = iff(isnotempty(SubjectContainsWords), SubjectContainsWords, (iff(isnotempty(BodyContainsWords),BodyContainsWords,SubjectOrBodyContainsWords )))
|
||||
| extend RuleDetail = case(OfficeObjectId contains '/' , tostring(split(OfficeObjectId, '/')[-1]) , tostring(split(OfficeObjectId, '\\')[-1]))
|
||||
| summarize count(), StartTimeUtc = min(TimeGenerated), EndTimeUtc = max(TimeGenerated) by Operation, UserId, ClientIPAddress, ResultStatus, Keyword, OriginatingServer, OfficeObjectId, RuleDetail
|
||||
entityMappings:
|
||||
- entityType: Account
|
||||
fieldMappings:
|
||||
- identifier: FullName
|
||||
columnName: UserId
|
||||
- entityType: Host
|
||||
fieldMappings:
|
||||
- identifier: FullName
|
||||
columnName: OriginatingServer
|
||||
- entityType: IP
|
||||
fieldMappings:
|
||||
- identifier: Address
|
||||
columnName: ClientIPAddress
|
||||
version: 1.0.0
|
||||
kind: NRT
|
|
@ -0,0 +1,69 @@
|
|||
id: 3b05727d-a8d1-477d-bbdd-d957da96ac7b
|
||||
name: NRT Multiple users email forwarded to same destination
|
||||
description: |
|
||||
'Identifies when multiple (more than one) users mailboxes are configured to forward to the same destination.
|
||||
This could be an attacker-controlled destination mailbox configured to collect mail from multiple compromised user accounts.'
|
||||
severity: Medium
|
||||
requiredDataConnectors:
|
||||
- connectorId: Office365
|
||||
dataTypes:
|
||||
- OfficeActivity
|
||||
tactics:
|
||||
- Collection
|
||||
- Exfiltration
|
||||
relevantTechniques:
|
||||
- T1114
|
||||
- T1020
|
||||
query: |
|
||||
OfficeActivity
|
||||
| where Operation =~ "Set-Mailbox"
|
||||
| where Parameters has "ForwardingSmtpAddress"
|
||||
| extend parsed = parse_json(Parameters)
|
||||
| mv-expand parsed
|
||||
| where parsed.Name == "ForwardingSmtpAddress"
|
||||
| extend parameterName = tostring(parsed.Name), fwdingDestination = tostring(parsed.Value)
|
||||
| where isnotempty(fwdingDestination)
|
||||
| extend ClientIPOnly = case(
|
||||
ClientIP has "." and ClientIP has ':', tostring(split(ClientIP,":")[0]),
|
||||
ClientIP has "." and ClientIP has '-', tostring(split(ClientIP,"-")[0]),
|
||||
ClientIP has ']-', tostring(trim_start(@'[[]',tostring(split(ClientIP,"]")[0]))),
|
||||
ClientIP has ']:', tostring(trim_start(@'[[]',tostring(split(ClientIP,"]")[0]))),
|
||||
isempty(ClientIP) and ClientIP_ has "." and ClientIP_ has ':', tostring(split(ClientIP_,":")[0]),
|
||||
isempty(ClientIP) and ClientIP_ has "." and ClientIP_ has '-', tostring(split(ClientIP_,"-")[0]),
|
||||
isempty(ClientIP) and ClientIP_ has ']-', tostring(trim_start(@'[[]',tostring(split(ClientIP_,"]")[0]))),
|
||||
isempty(ClientIP) and ClientIP_ has ']:', tostring(trim_start(@'[[]',tostring(split(ClientIP_,"]")[0]))),
|
||||
isnotempty(ClientIP), ClientIP,
|
||||
isnotempty(ClientIP_), ClientIP_,
|
||||
"IP Not Available"
|
||||
)
|
||||
| extend Port = case(
|
||||
ClientIP has "." and ClientIP has ':', tostring(split(ClientIP,":")[1]),
|
||||
ClientIP has "." and ClientIP has '-', tostring(split(ClientIP,"-")[1]),
|
||||
ClientIP has ']-', tostring(split(ClientIP,"]-")[1]),
|
||||
ClientIP has ']:', tostring(split(ClientIP,"]:")[1]),
|
||||
isempty(ClientIP) and ClientIP_ has "." and ClientIP_ has ':', tostring(split(ClientIP_,":")[1]),
|
||||
isempty(ClientIP) and ClientIP_ has "." and ClientIP_ has '-', tostring(split(ClientIP_,"-")[1]),
|
||||
isempty(ClientIP) and ClientIP_ has ']-', tostring(split(ClientIP_,"]-")[1]),
|
||||
isempty(ClientIP) and ClientIP_ has ']:', tostring(split(ClientIP_,"]:")[1]),
|
||||
isnotempty(ClientIP), ClientIP,
|
||||
isnotempty(ClientIP_), ClientIP_,
|
||||
"IP Not Available"
|
||||
)
|
||||
| extend UserId = iff(isempty(UserId), UserId_, UserId)
|
||||
| summarize StartTimeUtc = min(TimeGenerated), EndTimeUtc = max(TimeGenerated), DistinctUserCount = dcount(UserId), UserId = make_set(UserId),
|
||||
Ports = make_set(Port), EventCount = count() by fwdingDestination, ClientIP = ClientIPOnly
|
||||
| where DistinctUserCount > 1
|
||||
| mv-expand UserId
|
||||
| extend UserId = tostring(UserId), Ports = tostring(Ports)
|
||||
| distinct StartTimeUtc, EndTimeUtc, UserId, DistinctUserCount, ClientIP, Ports, fwdingDestination, EventCount
|
||||
entityMappings:
|
||||
- entityType: Account
|
||||
fieldMappings:
|
||||
- identifier: FullName
|
||||
columnName: UserId
|
||||
- entityType: IP
|
||||
fieldMappings:
|
||||
- identifier: Address
|
||||
columnName: ClientIP
|
||||
version: 1.0.0
|
||||
kind: NRT
|
|
@ -0,0 +1,32 @@
|
|||
id: 508cef41-2cd8-4d40-a519-b04826a9085f
|
||||
name: NRT Security Event log cleared
|
||||
description: |
|
||||
'Checks for event id 1102 which indicates the security event log was cleared.
|
||||
It uses Event Source Name "Microsoft-Windows-Eventlog" to avoid generating false positives from other sources, like AD FS servers for instance.'
|
||||
severity: Medium
|
||||
requiredDataConnectors:
|
||||
- connectorId: SecurityEvents
|
||||
dataTypes:
|
||||
- SecurityEvent
|
||||
- connectorId: WindowsSecurityEvents
|
||||
dataTypes:
|
||||
- SecurityEvent
|
||||
tactics:
|
||||
- DefenseEvasion
|
||||
relevantTechniques:
|
||||
- T1070
|
||||
query: |
|
||||
SecurityEvent
|
||||
| where EventID == 1102 and EventSourceName == "Microsoft-Windows-Eventlog"
|
||||
| summarize StartTimeUtc = min(TimeGenerated), EndTimeUtc = max(TimeGenerated), EventCount = count() by Computer, Account, EventID, Activity
|
||||
entityMappings:
|
||||
- entityType: Account
|
||||
fieldMappings:
|
||||
- identifier: FullName
|
||||
columnName: Account
|
||||
- entityType: Host
|
||||
fieldMappings:
|
||||
- identifier: FullName
|
||||
columnName: Computer
|
||||
version: 1.0.0
|
||||
kind: NRT
|
|
@ -0,0 +1,32 @@
|
|||
id: c3e5dbaa-a540-408c-8b36-68bdfb3df088
|
||||
name: NRT Base64 encoded Windows process command-lines
|
||||
description: |
|
||||
'Identifies instances of a base64 encoded PE file header seen in the process command line parameter.'
|
||||
severity: Medium
|
||||
requiredDataConnectors:
|
||||
- connectorId: SecurityEvents
|
||||
dataTypes:
|
||||
- SecurityEvent
|
||||
tactics:
|
||||
- Execution
|
||||
- DefenseEvasion
|
||||
relevantTechniques:
|
||||
- T1059
|
||||
- T1027
|
||||
- T1140
|
||||
query: |
|
||||
SecurityEvent
|
||||
| where EventID==4688
|
||||
| where isnotempty(CommandLine)
|
||||
| where CommandLine contains "TVqQAAMAAAAEAAA"
|
||||
entityMappings:
|
||||
- entityType: Account
|
||||
fieldMappings:
|
||||
- identifier: FullName
|
||||
columnName: Account
|
||||
- entityType: Host
|
||||
fieldMappings:
|
||||
- identifier: FullName
|
||||
columnName: Computer
|
||||
version: 1.0.0
|
||||
kind: NRT
|
|
@ -0,0 +1,39 @@
|
|||
id: 7ad4c32b-d0d2-411c-a0e8-b557afa12fce
|
||||
name: NRT Process executed from binary hidden in Base64 encoded file
|
||||
description: |
|
||||
'Encoding malicious software is a technique used to obfuscate files from detection.
|
||||
The first CommandLine component is looking for Python decoding base64.
|
||||
The second CommandLine component is looking for Bash/sh command line base64 decoding.
|
||||
The third one is looking for Ruby decoding base64.'
|
||||
severity: Medium
|
||||
requiredDataConnectors:
|
||||
- connectorId: SecurityEvents
|
||||
dataTypes:
|
||||
- SecurityEvent
|
||||
tactics:
|
||||
- Execution
|
||||
- DefenseEvasion
|
||||
relevantTechniques:
|
||||
- T1059
|
||||
- T1027
|
||||
- T1140
|
||||
query: |
|
||||
SecurityEvent
|
||||
| where EventID==4688
|
||||
| where isnotempty(CommandLine)
|
||||
| project TimeGenerated, Computer, Account = SubjectUserName, AccountDomain = SubjectDomainName, FileName = Process, CommandLine, ParentProcessName;
|
||||
ProcessCreationEvents
|
||||
| where CommandLine contains ".decode('base64')"
|
||||
or CommandLine contains "base64 --decode"
|
||||
or CommandLine contains ".decode64("
|
||||
entityMappings:
|
||||
- entityType: Account
|
||||
fieldMappings:
|
||||
- identifier: FullName
|
||||
columnName: Account
|
||||
- entityType: Host
|
||||
fieldMappings:
|
||||
- identifier: FullName
|
||||
columnName: Computer
|
||||
version: 1.0.0
|
||||
kind: NRT
|
|
@ -0,0 +1,32 @@
|
|||
id: 3617d76d-b15e-4c6f-985e-a1dac73c592d
|
||||
name: NRT MFA Rejected by User
|
||||
description: |
|
||||
'Identifies accurances where a user has rejected an MFA prompt. This could be an indicator that a threat actor has compromised the username and password of this user account and is using it to try and log into the account.
|
||||
Ref : https://docs.microsoft.com/azure/active-directory/fundamentals/security-operations-user-accounts#monitoring-for-failed-unusual-sign-ins'
|
||||
severity: Medium
|
||||
requiredDataConnectors:
|
||||
- connectorId: AzureActiveDirectory
|
||||
dataTypes:
|
||||
- SigninLogs
|
||||
tactics:
|
||||
- InitialAccess
|
||||
relevantTechniques:
|
||||
- T1078.004
|
||||
tags:
|
||||
- AADSecOpsGuide
|
||||
query: |
|
||||
SigninLogs
|
||||
| where ResultType == 500121
|
||||
| extend additionalDetails_ = tostring(Status.additionalDetails)
|
||||
| where additionalDetails_ =~ "MFA denied; user declined the authentication"
|
||||
entityMappings:
|
||||
- entityType: Account
|
||||
fieldMappings:
|
||||
- identifier: FullName
|
||||
columnName: UserPrincipalName
|
||||
- entityType: IP
|
||||
fieldMappings:
|
||||
- identifier: Address
|
||||
columnName: IPAddress
|
||||
version: 1.0.1
|
||||
kind: NRT
|
|
@ -0,0 +1,54 @@
|
|||
id: dd03057e-4347-4853-bf1e-2b2d21eb4e59
|
||||
name: NRT Squid proxy events related to mining pools
|
||||
description: |
|
||||
'Checks for Squid proxy events in Syslog associated with common mining pools .This query presumes the default Squid log format is being used.
|
||||
http://www.squid-cache.org/Doc/config/access_log/'
|
||||
severity: Low
|
||||
requiredDataConnectors:
|
||||
- connectorId: Syslog
|
||||
dataTypes:
|
||||
- Syslog
|
||||
tactics:
|
||||
- CommandAndControl
|
||||
relevantTechniques:
|
||||
- T1102
|
||||
query: |
|
||||
let DomainList = dynamic(["monerohash.com", "do-dear.com", "xmrminerpro.com", "secumine.net", "xmrpool.com", "minexmr.org", "hashanywhere.com", "xmrget.com",
|
||||
"mininglottery.eu", "minergate.com", "moriaxmr.com", "multipooler.com", "moneropools.com", "xmrpool.eu", "coolmining.club", "supportxmr.com",
|
||||
"minexmr.com", "hashvault.pro", "xmrpool.net", "crypto-pool.fr", "xmr.pt", "miner.rocks", "walpool.com", "herominers.com", "gntl.co.uk", "semipool.com",
|
||||
"coinfoundry.org", "cryptoknight.cc", "fairhash.org", "baikalmine.com", "tubepool.xyz", "fairpool.xyz", "asiapool.io", "coinpoolit.webhop.me", "nanopool.org",
|
||||
"moneropool.com", "miner.center", "prohash.net", "poolto.be", "cryptoescrow.eu", "monerominers.net", "cryptonotepool.org", "extrmepool.org", "webcoin.me",
|
||||
"kippo.eu", "hashinvest.ws", "monero.farm", "supportxmr.com", "xmrpool.eu", "linux-repository-updates.com", "1gh.com", "dwarfpool.com", "hash-to-coins.com",
|
||||
"hashvault.pro", "pool-proxy.com", "hashfor.cash", "fairpool.cloud", "litecoinpool.org", "mineshaft.ml", "abcxyz.stream", "moneropool.ru", "cryptonotepool.org.uk",
|
||||
"extremepool.org", "extremehash.com", "hashinvest.net", "unipool.pro", "crypto-pools.org", "monero.net", "backup-pool.com", "mooo.com", "freeyy.me", "cryptonight.net",
|
||||
"shscrypto.net"]);
|
||||
Syslog
|
||||
| where ProcessName contains "squid"
|
||||
| extend URL = extract("(([A-Z]+ [a-z]{4,5}:\\/\\/)|[A-Z]+ )([^ :]*)",3,SyslogMessage),
|
||||
SourceIP = extract("([0-9]+ )(([0-9]{1,3})\\.([0-9]{1,3})\\.([0-9]{1,3})\\.([0-9]{1,3}))",2,SyslogMessage),
|
||||
Status = extract("(TCP_(([A-Z]+)(_[A-Z]+)*)|UDP_(([A-Z]+)(_[A-Z]+)*))",1,SyslogMessage),
|
||||
HTTP_Status_Code = extract("(TCP_(([A-Z]+)(_[A-Z]+)*)|UDP_(([A-Z]+)(_[A-Z]+)*))/([0-9]{3})",8,SyslogMessage),
|
||||
User = extract("(CONNECT |GET )([^ ]* )([^ ]+)",3,SyslogMessage),
|
||||
RemotePort = extract("(CONNECT |GET )([^ ]*)(:)([0-9]*)",4,SyslogMessage),
|
||||
Domain = extract("(([A-Z]+ [a-z]{4,5}:\\/\\/)|[A-Z]+ )([^ :\\/]*)",3,SyslogMessage),
|
||||
Bytes = toint(extract("([A-Z]+\\/[0-9]{3} )([0-9]+)",2,SyslogMessage)),
|
||||
contentType = extract("([a-z/]+$)",1,SyslogMessage)
|
||||
| extend TLD = extract("\\.[a-z]*$",0,Domain)
|
||||
| where HTTP_Status_Code == '200'
|
||||
| where Domain contains "."
|
||||
| where Domain has_any (DomainList)
|
||||
entityMappings:
|
||||
- entityType: Account
|
||||
fieldMappings:
|
||||
- identifier: FullName
|
||||
columnName: User
|
||||
- entityType: IP
|
||||
fieldMappings:
|
||||
- identifier: Address
|
||||
columnName: SourceIP
|
||||
- entityType: URL
|
||||
fieldMappings:
|
||||
- identifier: Url
|
||||
columnName: URL
|
||||
version: 1.0.0
|
||||
kind: NRT
|
Загрузка…
Ссылка в новой задаче