Analytic rule catalog
Azure DevOps Variable Secret Not Secured
Back
| Id | 4ca74dc0-8352-4ac5-893c-73571cc78331 |
| Rulename | 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 |
| Tactics | CredentialAccess |
| Techniques | T1552 |
| Kind | Scheduled |
| Query frequency | 1d |
| Query period | 1d |
| Trigger threshold | 0 |
| Trigger operator | gt |
| Source Uri | https://github.com/Azure/Azure-Sentinel/blob/master/Solutions/AzureDevOpsAuditing/Analytic%20Rules/ADOSecretNotSecured.yaml |
| Version | 1.0.4 |
| Arm template | 4ca74dc0-8352-4ac5-893c-73571cc78331.json |
let keywords = dynamic(["secret", "secrets", "password", "PAT", "passwd", "pswd", "pwd", "cred", "creds", "credentials", "credential", "key"]);
ADOAuditLogs
| 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
| extend AccountName = tostring(split(ActorUPN, "@")[0]), AccountUPNSuffix = tostring(split(ActorUPN, "@")[1])
id: 4ca74dc0-8352-4ac5-893c-73571cc78331
entityMappings:
- fieldMappings:
- columnName: ActorUPN
identifier: FullName
- columnName: AccountName
identifier: Name
- columnName: AccountUPNSuffix
identifier: UPNSuffix
entityType: Account
- fieldMappings:
- columnName: IpAddress
identifier: Address
entityType: IP
severity: Medium
status: Available
requiredDataConnectors: []
kind: Scheduled
query: |
let keywords = dynamic(["secret", "secrets", "password", "PAT", "passwd", "pswd", "pwd", "cred", "creds", "credentials", "credential", "key"]);
ADOAuditLogs
| 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
| extend AccountName = tostring(split(ActorUPN, "@")[0]), AccountUPNSuffix = tostring(split(ActorUPN, "@")[1])
name: Azure DevOps Variable Secret Not Secured
queryPeriod: 1d
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.'
tactics:
- CredentialAccess
triggerOperator: gt
triggerThreshold: 0
relevantTechniques:
- T1552
version: 1.0.4
OriginalUri: https://github.com/Azure/Azure-Sentinel/blob/master/Solutions/AzureDevOpsAuditing/Analytic%20Rules/ADOSecretNotSecured.yaml
queryFrequency: 1d
{
"$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"workspace": {
"type": "String"
}
},
"resources": [
{
"apiVersion": "2024-01-01-preview",
"id": "[concat(resourceId('Microsoft.OperationalInsights/workspaces/providers', parameters('workspace'), 'Microsoft.SecurityInsights'),'/alertRules/4ca74dc0-8352-4ac5-893c-73571cc78331')]",
"kind": "Scheduled",
"name": "[concat(parameters('workspace'),'/Microsoft.SecurityInsights/4ca74dc0-8352-4ac5-893c-73571cc78331')]",
"properties": {
"alertRuleTemplateName": "4ca74dc0-8352-4ac5-893c-73571cc78331",
"customDetails": null,
"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. \nThis 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.'\n",
"displayName": "Azure DevOps Variable Secret Not Secured",
"enabled": true,
"entityMappings": [
{
"entityType": "Account",
"fieldMappings": [
{
"columnName": "ActorUPN",
"identifier": "FullName"
},
{
"columnName": "AccountName",
"identifier": "Name"
},
{
"columnName": "AccountUPNSuffix",
"identifier": "UPNSuffix"
}
]
},
{
"entityType": "IP",
"fieldMappings": [
{
"columnName": "IpAddress",
"identifier": "Address"
}
]
}
],
"OriginalUri": "https://github.com/Azure/Azure-Sentinel/blob/master/Solutions/AzureDevOpsAuditing/Analytic%20Rules/ADOSecretNotSecured.yaml",
"query": "let keywords = dynamic([\"secret\", \"secrets\", \"password\", \"PAT\", \"passwd\", \"pswd\", \"pwd\", \"cred\", \"creds\", \"credentials\", \"credential\", \"key\"]);\nADOAuditLogs\n| where OperationName =~ \"Library.VariableGroupModified\"\n| extend Type = tostring(Data.Type)\n| extend VariableGroupId = tostring(Data.VariableGroupId)\n| extend VariableGroupName = tostring(Data.VariableGroupName)\n| mv-expand Data.Variables\n| where VariableGroupName has_any (keywords) or Data_Variables has_any (keywords)\n| where Type != \"AzureKeyVault\"\n| where Data_Variables !has \"IsSecret\"\n| extend timestamp = TimeGenerated\n| extend AccountName = tostring(split(ActorUPN, \"@\")[0]), AccountUPNSuffix = tostring(split(ActorUPN, \"@\")[1])\n",
"queryFrequency": "P1D",
"queryPeriod": "P1D",
"severity": "Medium",
"status": "Available",
"subTechniques": [],
"suppressionDuration": "PT1H",
"suppressionEnabled": false,
"tactics": [
"CredentialAccess"
],
"techniques": [
"T1552"
],
"templateVersion": "1.0.4",
"triggerOperator": "GreaterThan",
"triggerThreshold": 0
},
"type": "Microsoft.OperationalInsights/workspaces/providers/alertRules"
}
]
}