ado queries
This commit is contained in:
Родитель
6095d85039
Коммит
4fd4ccccf7
|
@ -0,0 +1,32 @@
|
|||
id: bf07ca9c-e408-443a-8939-6860a45a929e
|
||||
name: Azure DevOps - New Extension Added
|
||||
description: |
|
||||
'Extensions added additional features to Azure DevOps. An attacker could use a malicious extension to conduct malicious activity. This query looks for new extensions that are not from a configurable list of approved publishers.'
|
||||
severity: Low
|
||||
requiredDataConnectors: []
|
||||
queryFrequency: 1d
|
||||
queryPeriod: 1d
|
||||
triggerOperator: gt
|
||||
triggerThreshold: 0
|
||||
tactics:
|
||||
- Persistence
|
||||
relevantTechniques:
|
||||
- T1505
|
||||
query: |
|
||||
let allowed_publishers = dynamic([]);
|
||||
AzureDevOpsAuditing
|
||||
| where OperationName =~ "Extension.Installed"
|
||||
| extend ExtensionName = tostring(Data.ExtensionName)
|
||||
| extend PublisherName = tostring(Data.PublisherName)
|
||||
| where PublisherName !in (allowed_publishers)
|
||||
| project-reorder TimeGenerated, OperationName, ExtensionName, PublisherName, ActorUPN, IpAddress, UserAgent, ScopeDisplayName, ScopeType, Data
|
||||
| extend timestamp = TimeGenerated, AccountCustomEntity = ActorUPN, IPCustomEntity = IpAddress
|
||||
entityMappings:
|
||||
- entityType: Account
|
||||
fieldMappings:
|
||||
- identifier: FullName
|
||||
columnName: ActorUPN
|
||||
- entityType: IP
|
||||
fieldMappings:
|
||||
- identifier: Address
|
||||
columnName: IpAddress
|
|
@ -0,0 +1,29 @@
|
|||
id: 5f0d80db-3415-4265-9d52-8466b7372e3a
|
||||
name: Azure DevOps - PAT used with Browser.
|
||||
description: |
|
||||
'Personal Access Tokens (PATs) are used as an alternate password to authenticate into Azure DevOps. PATs are intended for programmatic access for use in code or applications. Given this they can be prone to attacker theft if not adequately secured. This queries looks for the use of a PAT in authentication but from a User Agent indicating a browser. This should not be normal activity and could be an indicator of an attacker using a stolen PAT.'
|
||||
severity: Medium
|
||||
requiredDataConnectors: []
|
||||
queryFrequency: 1d
|
||||
queryPeriod: 1d
|
||||
triggerOperator: gt
|
||||
triggerThreshold: 0
|
||||
tactics:
|
||||
- CredentialAccess
|
||||
relevantTechniques:
|
||||
- T1564
|
||||
query: |
|
||||
AzureDevOpsAuditing
|
||||
| where AuthenticationMechanism startswith "PAT"
|
||||
// Look for useragents that include a redenring engine
|
||||
| where UserAgent has_any ("Gecko", "WebKit", "Presto", "Trident", "EdgeHTML", "Blink")
|
||||
| extend timestamp = TimeGenerated, AccountCustomEntity = ActorUPN, IPCustomEntity = IpAddress
|
||||
entityMappings:
|
||||
- entityType: Account
|
||||
fieldMappings:
|
||||
- identifier: FullName
|
||||
columnName: ActorUPN
|
||||
- entityType: IP
|
||||
fieldMappings:
|
||||
- identifier: Address
|
||||
columnName: IpAddress
|
|
@ -0,0 +1,30 @@
|
|||
id: 71d374e0-1cf8-4e50-aecd-ab6c519795c2
|
||||
name: Azure DevOps - Retention Reduced to Zero
|
||||
description: |
|
||||
'AzureDevOps retains items such as run records and produced artifacts for a configurable amount of time. An attacker looking to reduce the footprint left by their malicious activity may look to reduce the retention time for artifacts and runs to 0.'
|
||||
severity: Low
|
||||
requiredDataConnectors: []
|
||||
queryFrequency: 1d
|
||||
queryPeriod: 1d
|
||||
triggerOperator: gt
|
||||
triggerThreshold: 0
|
||||
tactics:
|
||||
- DefenseEvasion
|
||||
relevantTechniques:
|
||||
- T1564
|
||||
query: |
|
||||
AzureDevOpsAuditing
|
||||
| where OperationName =~ "Pipelines.PipelineRetentionSettingChanged"
|
||||
| where Data.SettingName in ("PurgeArtifacts", "PurgeRuns")
|
||||
| where Data.NewValue == 0
|
||||
| project-reorder TimeGenerated, OperationName, ActorUPN, IpAddress, UserAgent, Data
|
||||
| extend timestamp = TimeGenerated, AccountCustomEntity = ActorUPN, IPCustomEntity = IpAddress
|
||||
entityMappings:
|
||||
- entityType: Account
|
||||
fieldMappings:
|
||||
- identifier: FullName
|
||||
columnName: ActorUPN
|
||||
- entityType: IP
|
||||
fieldMappings:
|
||||
- identifier: Address
|
||||
columnName: IpAddress
|
|
@ -0,0 +1,36 @@
|
|||
id: 4ca74dc0-8352-4ac5-893c-73571cc78331
|
||||
name: Azure DevOps - Variable Secret Not Secured
|
||||
description: |
|
||||
'Credentials used in the build process may be stored as Azure DevOps variables. To secure these variables they should be stored in KeyVault or marked as secrets. This detection looks for new variables added with names that suggest they are credentials but where they are not set as Secrets or stored in KeyVault.'
|
||||
severity: Medium
|
||||
requiredDataConnectors: []
|
||||
queryFrequency: 1d
|
||||
queryPeriod: 1d
|
||||
triggerOperator: gt
|
||||
triggerThreshold: 0
|
||||
tactics:
|
||||
- CredentialAccess
|
||||
relevantTechniques:
|
||||
- T1552
|
||||
query: |
|
||||
let keywords = dynamic(["secret", "secrets", "password", "PAT", "passwd", "pswd", "pwd", "cred", "creds", "credentials", "credential", "key"]);
|
||||
AzureDevOpsAuditing
|
||||
| where TimeGenerated > ago(30d)
|
||||
| where OperationName =~ "Library.VariableGroupModified"
|
||||
| extend Type = tostring(Data.Type)
|
||||
| extend VariableGroupId = tostring(Data.VariableGroupId)
|
||||
| extend VariableGroupName = tostring(Data.VariableGroupName)
|
||||
| mv-expand Data.Variables
|
||||
| where VariableGroupName has_any (keywords) or Data_Variables has_any (keywords)
|
||||
| where Type != "AzureKeyVault"
|
||||
| where Data_Variables !has "IsSecret"
|
||||
| extend timestamp = TimeGenerated, AccountCustomEntity = ActorUPN, IPCustomEntity = IpAddress
|
||||
entityMappings:
|
||||
- entityType: Account
|
||||
fieldMappings:
|
||||
- identifier: FullName
|
||||
columnName: ActorUPN
|
||||
- entityType: IP
|
||||
fieldMappings:
|
||||
- identifier: Address
|
||||
columnName: IpAddress
|
|
@ -0,0 +1,34 @@
|
|||
id: 47857f1f-f8e6-470d-b132-03a8a606b3f4
|
||||
name: Azure DevOps - Build Deleted After Pipeline Modification
|
||||
description: |
|
||||
'An attacker altering pipelines may look to delete builds to reduce the footprint they leave on a system. This query looks for a build for a pipline being deleted within 1 hour of a pipeline being modified. This event may produce false positives but should not be so common that it can’t be effectively used as part of hunting.'
|
||||
requiredDataConnectors: []
|
||||
tactics:
|
||||
- Persistence
|
||||
relevantTechniques:
|
||||
- T1053
|
||||
query: |
|
||||
AzureDevOpsAuditing
|
||||
| where OperationName =~ "Release.ReleaseDeleted"
|
||||
| extend PipelineId = tostring(Data.PipelineId)
|
||||
| extend PipelineName = tostring(Data.PipelineName)
|
||||
| extend timekey = bin(TimeGenerated, 1h)
|
||||
| join (AzureDevOpsAuditing
|
||||
| where OperationName =~ 'Release.ReleasePipelineModified'
|
||||
| extend PipelineId = tostring(Data.PipelineId)
|
||||
| extend PipelineName = tostring(Data.PipelineName)
|
||||
| extend timekey = bin(TimeGenerated, 1h)) on timekey, PipelineId, ActorUPN
|
||||
| where TimeGenerated1 < TimeGenerated
|
||||
| extend ReleaseName = tostring(Data.ReleaseName)
|
||||
| project-rename TimeModified = TimeGenerated1, TimeDeleted = TimeGenerated, ModifyOperation = OperationName1, ModifyUser=ActorUPN1, ModifyIP=IpAddress1, ModifyUA= UserAgent1, DeleteOperation=OperationName, DeleteUser=ActorUPN, DeleteIP=IpAddress, DeleteUA=UserAgent
|
||||
| project-reorder TimeModified, ProjectName, PipelineName, ModifyUser, ModifyIP, ModifyUA, TimeDeleted, DeleteOperation, DeleteUser, DeleteIP, DeleteUA,ReleaseName
|
||||
| extend timestamp = TimeGenerated, AccountCustomEntity = ActorUPN, IPCustomEntity = IpAddress
|
||||
entityMappings:
|
||||
- entityType: Account
|
||||
fieldMappings:
|
||||
- identifier: FullName
|
||||
columnName: ActorUPN
|
||||
- entityType: IP
|
||||
fieldMappings:
|
||||
- identifier: Address
|
||||
columnName: IpAddress
|
|
@ -0,0 +1,27 @@
|
|||
id: 76f626e0-4c78-47d4-aeb6-eaa59f4f2ecb
|
||||
name: Azure DevOps - New Agent Pool Created
|
||||
description: |
|
||||
'Agent Pools provide a valuable resource to build processes. Creating and using a compromised agent pool in a pipeline could allow an attacker to compromise a build process. Whilst the creation of an agent pool itself is not malicious it is unlike to occur so often that it cannot be used as a hunting element when focusing on Azure DevOps activity.'
|
||||
requiredDataConnectors: []
|
||||
tactics:
|
||||
- DefenseEvasion
|
||||
relevantTechniques:
|
||||
- T1578
|
||||
query: |
|
||||
AzureDevOpsAuditing
|
||||
| where OperationName =~ "Library.AgentPoolCreated"
|
||||
| extend AgentPoolName = tostring(Data.AgentPoolName)
|
||||
| extend AgentPoolId = tostring(Data.AgentPoolId)
|
||||
| extend IsHosted = tostring(Data.IsHosted)
|
||||
| extend IsLegacy = tostring(Data.IsLegacy)
|
||||
| project-reorder TimeGenerated, ActorUPN, UserAgent, IpAddress, AuthenticationMechanism, OperationName, AgentPoolName, IsHosted, IsLegacy, Data
|
||||
| extend timestamp = TimeGenerated, AccountCustomEntity = ActorUPN, IPCustomEntity = IpAddress
|
||||
entityMappings:
|
||||
- entityType: Account
|
||||
fieldMappings:
|
||||
- identifier: FullName
|
||||
columnName: ActorUPN
|
||||
- entityType: IP
|
||||
fieldMappings:
|
||||
- identifier: Address
|
||||
columnName: IpAddress
|
|
@ -0,0 +1,30 @@
|
|||
id: 5b6ab1d9-018b-46c6-993b-3198626fc54e
|
||||
name: Azure DevOps - New PAT Operation
|
||||
description: |
|
||||
'PATs are typically used for repeated, programmatic tasks. This query looks for PATs based authentication being used with an Operation not previous associated with PAT based authentication. This could indicate an attacker using a stolen PAT to perform malicious actions.'
|
||||
requiredDataConnectors: []
|
||||
tactics:
|
||||
- DefenseEvasion
|
||||
relevantTechniques:
|
||||
- T1078
|
||||
query: |
|
||||
let lookback = 30d;
|
||||
let timeframe = 3d;
|
||||
let PAT_Actions = AzureDevOpsAuditing
|
||||
| where TimeGenerated > ago(lookback) and TimeGenerated < ago(timeframe)
|
||||
| where AuthenticationMechanism startswith "PAT"
|
||||
| summarize by OperationName;
|
||||
AzureDevOpsAuditing
|
||||
| where TimeGenerated > ago(timeframe)
|
||||
| where AuthenticationMechanism startswith "PAT"
|
||||
| where OperationName !in (PAT_Actions)
|
||||
| extend timestamp = TimeGenerated, AccountCustomEntity = ActorUPN, IPCustomEntity = IpAddress
|
||||
entityMappings:
|
||||
- entityType: Account
|
||||
fieldMappings:
|
||||
- identifier: FullName
|
||||
columnName: ActorUPN
|
||||
- entityType: IP
|
||||
fieldMappings:
|
||||
- identifier: Address
|
||||
columnName: IpAddress
|
|
@ -0,0 +1,41 @@
|
|||
id: 0c149cc9-78ba-4be1-9f7b-018288e3a829
|
||||
name: Azure DevOps - New Release Approver
|
||||
description: |
|
||||
'Releases in Azure Pipelines often require a user authorization to perform the release. An attacker that has compromised a build may look to self-approve a release using a compromised account to avoid user focus on that release. This query looks for release approvers in pipelines where they have not approved a release in the last 30 days. This query can have a significant false positive rate so its best suited as a hunting query rather than a detection.'
|
||||
requiredDataConnectors: []
|
||||
tactics:
|
||||
- DefenseEvasion
|
||||
relevantTechniques:
|
||||
- T1078
|
||||
query: |
|
||||
let lookback = 30d;
|
||||
let timeframe = 1d;
|
||||
AzureDevOpsAuditing
|
||||
| where TimeGenerated > ago(lookback) and TimeGenerated < ago(timeframe)
|
||||
| where OperationName in ("Release.ApprovalCompleted", "Release.ApprovalsCompleted")
|
||||
| extend PipelineName = tostring(Data.PipelineName)
|
||||
| extend ApprovalType = tostring(Data.ApprovalType)
|
||||
| extend StageName = tostring(Data.StageName)
|
||||
| extend ReleaseName = tostring(Data.ReleaseName)
|
||||
| summarize by PipelineName, ActorUPN, ApprovalType
|
||||
| join kind=rightanti (
|
||||
AzureDevOpsAuditing
|
||||
| where TimeGenerated > ago(timeframe)
|
||||
| where OperationName in ("Release.ApprovalCompleted", "Release.ApprovalsCompleted")
|
||||
| extend PipelineName = tostring(Data.PipelineName)
|
||||
| extend ApprovalType = tostring(Data.ApprovalType)
|
||||
| extend StageName = tostring(Data.StageName)
|
||||
| extend ReleaseName = tostring(Data.ReleaseName)) on ActorUPN
|
||||
| project-reorder TimeGenerated, PipelineName, ActorUPN, ApprovalType, StageName, ReleaseName, IpAddress, UserAgent, AuthenticationMechanism
|
||||
| extend timestamp = TimeGenerated, AccountCustomEntity = ActorUPN, IPCustomEntity = IpAddress
|
||||
entityMappings:
|
||||
- entityType: Account
|
||||
fieldMappings:
|
||||
- identifier: FullName
|
||||
columnName: ActorUPN
|
||||
- entityType: IP
|
||||
fieldMappings:
|
||||
- identifier: Address
|
||||
columnName: IpAddress
|
||||
|
||||
|
|
@ -0,0 +1,38 @@
|
|||
id: 0fa523de-ce23-49d0-87a4-e890028e1e50
|
||||
name: Azure DevOps - Variable Created and Deleted
|
||||
description: |
|
||||
'Variables can be used at various stages of a pipeline to inject static variables. Depending on the build process these variables could be added by an attacker to get a build process to conduct an unwanted action such as communicating with an attacker-controlled endpoint or injecting values into code. This query looks for variables that are added and then deleted in a short space of time. This is not normal expected behavior and could ben an indicator of attacker creating elements and then covering tracks. If this hunting query produces only a small number of events in an environment it could be promoted to a detection.'
|
||||
requiredDataConnectors: []
|
||||
tactics:
|
||||
- DefenseEvasion
|
||||
relevantTechniques:
|
||||
- T1578
|
||||
query: |
|
||||
let timeframe = 7d;
|
||||
AzureDevOpsAuditing
|
||||
| where TimeGenerated > ago(timeframe)
|
||||
| where OperationName =~ "Library.VariableGroupModified"
|
||||
| extend variables = Data.Variables
|
||||
| extend VariableGroupName = tostring(Data.VariableGroupName)
|
||||
| join (AzureDevOpsAuditing
|
||||
| where TimeGenerated > ago(timeframe)
|
||||
| where OperationName =~ "Library.VariableGroupModified"
|
||||
| extend variables = Data.Variables
|
||||
| extend VariableGroupName = tostring(Data.VariableGroupName)) on VariableGroupName
|
||||
| extend len = array_length(bag_keys(variables))
|
||||
| extend len1 = array_length(bag_keys(variables1))
|
||||
| where (TimeGenerated < TimeGenerated1 and len > len1) or (TimeGenerated1 > TimeGenerated and len1 < len)
|
||||
| project-away len, len1
|
||||
| extend VariablesRemoved = set_difference(bag_keys(variables), bag_keys(variables1))
|
||||
| project-rename TimeCreated=TimeGenerated, TimeDeleted = TimeGenerated1, CreatingUser = ActorUPN, DeletingUser = ActorUPN1, CreatingIP = IpAddress, DeletingIP = IpAddress1, CreatingUA = UserAgent, DeletingUA = UserAgent1
|
||||
| project-reorder VariableGroupName, TimeCreated, TimeDeleted, VariablesRemoved, CreatingUser, CreatingIP, CreatingUA, DeletingUser, DeletingIP, DeletingUA
|
||||
| extend timestamp = TimeGenerated, AccountCustomEntity = ActorUPN, IPCustomEntity = IpAddress
|
||||
entityMappings:
|
||||
- entityType: Account
|
||||
fieldMappings:
|
||||
- identifier: FullName
|
||||
columnName: ActorUPN
|
||||
- entityType: IP
|
||||
fieldMappings:
|
||||
- identifier: Address
|
||||
columnName: IpAddress
|
Загрузка…
Ссылка в новой задаче