This table is provided for reviewing service authentication and authorization security in Azure – Especially cross-service security. It has been made publicly available so it can be referred in any documentation as URL.
- Azure Service Authentication and Authorization table
- MS references
- Notes regarding non AAD-based authentication options
- Notes regarding AAD-based authentication options
- Service Table
- Notes
- Fetching non-Azure AD based credentials with initial Azure AD authentication
- App Service Deployment Credentials
- SAS KEYS
- App registrations
- API management
- Require user assigment on applications by default and check permissions
- Azure DevOps - Ensure PAT tokens are evaluated with Conditional Access Policy (CAP) validation
- Service connections in Azure Devops
- Certificate option for client credentials
- SQL authentication and 'Allow Azure services and resources to access this server'
- Auditing local authentication with Azure Policy
- Contribution
- Disclaimer
MS recommendations below is just subset of many examples. I picked few ones which are really driving the point of trying to avoid password (string-based) options.
⚠ The emphasis is to highlight the significance of choosing between Azure AD and non-Azure AD authentication options for Azure services.
- IM-2: Manage application identities securely and automatically
- Use Azure AD Authentication instead of SQL server authentication in Azure SQL
- Microsoft recommends using Azure AD with your Azure Service Bus applications when possible
- Azure AD provides superior security and ease of use over Shared Key for authorizing requests to Blob storage.
- Azure Event Hubs supports authorizing to Event Hubs resources using Azure Active Directory (Azure AD). Authorizing users or applications using OAuth 2.0 token returned by Azure AD provides superior security and ease of use over shared access signatures
- Configure your Azure API Management instance to protect your APIs by using the OAuth 2.0 protocol with Azure AD
⚠ MS sources on string-based password auth
- While function keys can provide some mitigation for unwanted access, the only way to truly secure your function endpoints is by implementing positive authentication of clients accessing your functions.
- While it's convenient to use password secrets as a credential, we strongly recommend that you use x509 certificates as the only credential type for getting tokens for your application
- Access key appears in the URL
- Our suggestion is to enable Diagnostic Logging and Azure Defender where available and periodically rotate your keys.
- All string-based authentication methods in table below are considered passwords.
❌Password/String-based authentication is not considered strong in terms of strength, as shown in the table below. Even though security can be increased with password length, and password rotation.
- The table assumes rotation because password can be leaked
❌Bypasses Azure AD logs means that no events are produced for the resource type in Azure AD logs when the authentication mechanism is used.
❌ Susceptible to sharing across multiple targets in the table means that the service allows human defined password (monkey/dog/cat/birthday) creation, thus allowing the admin to re-use passwords across systems
-
Services which generate these passwords, and don't allow admins to input passwords are considered not shareable in the same sense (not all services in the table can be shared across systems, but can be shared across clients still)
Note: Even if the key is system generated, it can be obviously leaked If a SAS is leaked, it can be used by anyone who obtains it, which can potentially compromise resource utilizing SAS scheme
✔ Can be authorized based on Azure RBAC settings on services, and Azure AD roles granted for the API permissions
✔ Are logged in both Azure AD and service specific logs
✔ Can be managed as objects exposed in Azure AD and Azure RBAC (supports listing, filtering, policies and have specific properties which are exposed to configuration plane)
- Column Service logs in table mean that there is logging option outside Azure, which typically includes the authentication information.
Service | Azure AD & RBAC based | Logged in Azure AD | Logged in service specific logs | Rotation needed | Strength | Tied to resource lifecycle |
---|---|---|---|---|---|---|
Managed Identity | ✅ | ✅ | ✅ | ✅ Managed identities do not require rotation | ✅ Strong (Certificate based) | ✅ * When using system assigned managed identity |
Service Principal (Password) | ✅ | ✅ | ✅ | Requires Rotation (supports expiration) | ❌Password based While it's convenient to use password secrets as a credential, we strongly recommend that you use x509 certificates as the only credential type for getting tokens for your application. MS security-best-practices for Credential configuration |
❌ Suspectible to sharing across multiple targets (while not common, Azure AD ServicePrincipals support user created passwords, which can be shared, and can be weak in strength) |
Service Principal (Certificate) | ✅ | ✅ | ✅ | Less need for rotation as the service newer exposes the private key when requesting access tokens from Azure AD, still users or service can leak the key (supports expiration) - The key can additionally be protected by password, before it's allowed to form JWT token | ✅ Strong (Certificate based) cert options | ❌ (Same Private Key could be shared for multiple app registrations) |
Storage Account key | ❌ Bypasses Azure RBAC note ¹ | ❌ No AAD Log | ✅ | Requires Rotation (❌Does not support expiration) | ❌Password based | ✅ |
Table continues
Service | Azure AD & RBAC based | Logged in Azure AD | Logged in service specific logs | Rotation needed | Strength | Tied to resource lifecycle |
---|---|---|---|---|---|---|
SAS Tokens in Logic Apps SAS Tokens in Storage Accounts SAS Tokens in Event Hubs SAS Tokens in Service Bus |
❌ Bypasses Azure RBAC note ¹ | ❌ No AAD Log | ✅ | Requires Rotation ( ¹ supports expiration) | ❌Password based | ✅ |
SSH Keys | ❌ Bypasses Azure RBAC note ¹ | ❌ No AAD Log | ✅ | Can be rotated if needed (with PKI) | ✅ Strong (Certificate based) | ❌ Suspectible to sharing across multiple targets |
SSH Passwords | ❌ Bypasses Azure RBAC note ¹ | ❌ No AAD Log | ✅ | Requires Rotation (Supports user expiration) | ❌Password based | ❌ Suspectible to sharing across multiple targets |
PAT Azure DataBricks PAT in Azure Devops |
❌ Bypasses Azure RBAC note ¹ | ❌ No AAD Log | ✅ | Requires Rotation (supports expiration) | ❌Password based | ✅ |
SQL Authentication | ❌ Bypasses Azure RBAC note ¹ | ❌ No AAD Log | ✅ | Requires Rotation (supports expiration) | ❌Password based | ❌ Suspectible to sharing across multiple targets |
Table continues
Service | Azure AD & RBAC based | Logged in Azure AD | Logged in service specific logs | Rotation needed | Strength | Tied to resource lifecycle |
---|---|---|---|---|---|---|
APIM Subscription Key | ❌ Bypasses Azure RBAC note ¹ | ❌ No AAD Log | ✅ | Requires Rotation | ❌Password based | ✅ |
Function Access Keys | ❌ Bypasses Azure RBAC note ¹ | ❌ Bypasses Azure Azure AD log | ✅ | Requires Rotation | ❌Password based | ✅ |
App Service Webdeploy (Basic Auth) | ❌ Bypasses Azure RBAC note ¹ | ❌ No AAD Log | ✅ | Requires Rotation | ❌Password based | ✅ |
App Service Webdeploy (FTP) | ❌ Bypasses Azure RBAC note ¹ | ❌ No AAD Log | ✅ | Requires Rotation | ❌Password based | ✅ |
AKS management with --admin option |
📑 Initial sign-in is Azure RBAC when Azure RBAC is used | 📑 No AAD log after initial sign-in | ✅ | Requires rotation Rotate certificates in Azure Kubernetes Service (AKS) | ✅ Strong (Certificate based) | 📑 Unlikely to be shared, as the AKS creates it's own CA |
To retrieve most of the credentials in the table you typically have to initially authenticate first with Azure AD. The table regurgitates the same scenario for many other credential types (Initially requires Azure AD but once obtained bypasses the access domain of Azure AD) - Scenarios like this means, that once the credential is fetched, it's issuance and usage are not tracked with Azure AD
To facilitate many of the deployment scenarios Azure App Service uses under the hood something called Deployment Credentials
Essentially these credentials are used for two scenarios Basic auth string in authorization header Authorization: 'Basic YWRtaW5pc3RyYXRvcjpwYXNzd29yZA==
for the SCM web api, and same deployment credentials FTP based, but passed in FTP protocol
⚠ Note: This bypass is based on indirect access. Azure Key Vault itself is not suspectible to non-azure-ad based access, and neither do the secrets exist outside runtime platform anywhere
- Attacker uses Basic Auth (publishingUserName and publishingPassword) to access directly key vault references that are loaded for runtime in the SCM API
POC - Node.js
async function mfaBypassToGetKeyVaultReferences(publishingUserName, publishingPassword, name) {
var base64 = Buffer.from(`${publishingUserName}:${publishingPassword}`).toString('base64')
var {data} = await axios({
url:`https://${name}.scm.azurewebsites.net/api/settings`,
headers: {
"Authorization": "Basic " + base64},
method:"get",
}).catch((error) => console.log('sd')); console.log(data)
}
✅Credentials as Azure Key Vault Reference / Backed by Azure AD
⚠Access Key Vault References with basic auth if SCM endpoint is not secured
Since many of the automations use these credentials, and publishing to app service does not directly support strong authentication supporting authorization mechnisms (Validation of JWT token in authorization header) it's important that once app is deployed you don't leave the endpoints open for exploitation.
✅ Make securing non Azure AD backed endpoint part of your continous integration (If requested, I can add Azure Pipelines example)
Options
-
Disable basic authentication Some organizations need to meet security requirements and would rather disable access via FTP or WebDeploy. This way, the organization's members can only access its App Services through APIs that are controlled by Azure Active Directory (Azure AD).
-
Network restriction on SCM endpoint When you use network isolation to secure your functions, you must also account for this endpoint.
While SAS keys themselves support expiration, they are often derived from key that does not support expiration. Such examples are the keys in the connection string of Event Hub and service hubs under shared access policies.
Read more here https://docs.microsoft.com/en-us/azure/service-bus-messaging/service-bus-sas#shared-access-authorization-policies
App registrations are covered by the service principal scenarios in the table. See Service Principal and types of service principal
Ensure security operations such IP-filtering and authn/z related policies are required in 'All operations' level. This ensures, that newly created operations will inherit the security policies of the API.
- Attack scenario
This attack is possible against API's that don't check claims beyond the audience and issuer value for tokens issued to client credential enabled SPN's. Mitigation is to implement proper checking of claims, and/or requiring user assignment on the API.
- Attacker is any SPN registered in the tenant which has client credentials registered.
- Mitigation by proper claims checking
https://joonasw.net/view/always-check-token-permissions-in-aad-protected-api
- Mitigation by user assignment
Requiring user assignment on Service Principal settings prevents arbitrary client credential enabled apps from being issued tokens with the correct audience for the attacker. The mitigation was originally proposed by Johan Lindroos
If this setting is not enabled arbitrary SPN's registered in the tenant with client credentials(be they single or multi-tenant origin), the spn can request valid tokens for apps that don't do internal ACL for permissions (or require user assigment).
"But what if we did have an identity in the target tenant? If we could somehow trick a user in the organization to consent to our app, could we do the attack as before? Yes, we could. As long as a service principal for your app exists in the target tenant, you can acquire an access token for any API in that tenant."
⚠ Carefully review and evaluate this control in test environment before enabling it on production
MS references Microsoft Documentation
Background
Since the usage of PAT token is essentially basic auth, you might want to limit the usage of long-lived PAT's created for automations running outside Azure Devops. You can to this by enabling Conditional Access for non web-flows ¹
Personal Access Tokens and basic authentication
⚠ Beware that enabling IP-restrictions for PAT tokens affect also GIT clients that use short-lived PAT tokens after initial Azure AD authentication. Based on my testing usage of PAT tokens can't be excluded by advanced conditions like device filtering. Only IP and user exclusion seems to work.
Conditional Acces example Read CA For PAT
Azure AD Conditional Access is applied for the web flow regardless of this policy setting.
- There is also possibility of restricting the lifetime of PAT tokens, but this might require extensive work for long-running automations that do not use the build-agents built-in OAuth2 based flows and are excluded from CA based on 'named location'
MS Documentation on the subject
Enable Azure Active Directory (Azure AD) Conditional Access Policy (CAP) validation
- this policy is set to off by default and only applies to other authentication methods aside from the web flow.
¹ If you have 'all apps' type Conditional Access Policy, web flows are already protected by Conditional Access, regardless of the CAP setting in Azure Devops. Review carefully any PAT token usage, before enabling the policy: example
Security of service connections can be much enhanced by the use of managed identity (self-hosted Devops agent) - and SP (certificate) when MS-hosted pipeline is used.
NodeJS
- Azure AD Client Credentials with Certificate - Code Examples for Node.js
- service-principal and certificate based login by providing an ABSOLUTE file path to the .pem file
Any SP that uses certificate credential in client credential flow can be validated to have used the certificate after token validation by inspecting the appidacr
claim.
https://securecloud.blog/2021/01/15/azure-api-management-enforce-use-of-certificate-in-client-credentials-flow/
“Allow Azure services and resources to access this server” setting for SQL allows a trivial bypass for SQL firewall. Essentially the if attacker gets the SQL connection string, the protection by network rules does very little to protect from compromise, as the attacker can mount the attack from within Azure.
-
Many Azure Services rely on this setting to consume Azure SQL. Consider using this setting only if managed identities / Azure AD based identities are used to consume Azure SQL database.
Using Azure AD based identity based on strong authentcation to consume SQL ensures, that even if the firewall was bypassed, the attacker would need to get access tokens issued for the managed identity to continue the attack.
MS reference
Switching the setting to ON creates an inbound firewall rule for IP 0.0.0.0 - 0.0.0.0 named AllowAllWindowsAzureIps
Documentation az policy set-definition
Following AZ CLI command will deploy the policy initiative
az policy set-definition create -n Audit_Local_Authentication_Audit_Set \
--subscription '3539c2a2-cd25-48c6-b295-14e59334ef1c' \
--definitions https://raw.githubusercontent.com/jsa2/aad-auth-n-z/main/guides/localAuthPolicy/localAuthd.json
After running the Azure CLI command you should see following set displayed in Azure Policy. You can then proceed to assign the policy at scope you deem suitable
Feel free to submit pull request for fixing, or adding anything in this document
The information in this document is provided “AS IS” with no warranties and confers no rights.