Cloud migrations often involve moving data, workloads, and applications from an on-premise datacenter to a private or public cloud provider. While cloud migrations can offer significant cost savings, faster product deployments, and improved security controls, there are many common pitfalls to avoid during migration, along with best practices that should be followed to maximize cloud platform benefits.
This article is focused on the security risks involved in a cloud migration and provides a compilation of common security anti-patterns and best practices for architects only familiar with traditional on-premise data centers to follow. The following were based on reviews of multiple client Azure cloud environments of varying sizes and maturity.
Common Misconfigurations and Anti-Patterns
Praetorian has observed the following recurring issues in Azure environments. Many of these issues are caused by a paradigm shift in thought from conventional on-premise data centers to cloud deployments.
1. Solely Relying on Azure Portal and Not Consulting Azure Documentation
Azure has limited space available on the Azure portal. Therefore, Azure often simplifies and shortens descriptions to improve the user experience. This has the unintended side effect of misrepresenting certain settings. Praetorian often finds that misconfigurations were due to administrators misunderstanding certain switches and mismatched expectations. For example, there is an “Allow Azure services and resources to access this server” switch for SQL databases. Praetorian often sees companies turn that on with the intention of connecting the SQL databases to other Azure services that the company owns.
However, this toggle would expose the database to any Azure services in any subscription. An attacker could spin up an Azure VM within their subscription and attempt to connect to the database. This is actually documented and highlighted by Azure within the documentation.
Therefore, it is important to not solely rely on the Azure portal description. Praetorian advises organizations to read the documentation and understand the implications of each configuration before toggling it.
2. Accidental Public Exposure of Services Due to Insecure Defaults
Praetorian has commonly observed configurations enabling public access because people often assume that the default settings are secure. Overall, Azure has done a good job of ensuring secure defaults but certain services might have settings that were, by service design or otherwise, left insecure. For example, Azure App Services and CosmosDB are accessible to the public Internet if no manual intervention was performed before deployment.
If a user fills in the basic information during CosmosDB creation, without going through the rest of the tabs, and proceeds to “review + create”. This would deploy a resource that might be unintentionally exposed.
Praetorian recommends going through each tab and each option carefully when deploying resources. A wrong toggle of a particular configuration switch might introduce a large amount of risk.
When deploying applications on Azure, organizations should be mindful of what risks will be introduced by default configurations. Always click through every tab of the deployment and review final configurations before creating a service. Never depend on default configurations. Solutions to prevent public exposure depend on use cases and limitations. For example, Network Security Groups may be used to limit access based on IP address or private endpoints can be used for Azure services.
3. Insecure Secrets Management Practices
Secrets are often found in VM run scripts that perform start-up operations such as joining AD domains or connecting to databases. Additionally, Praetorian often finds credentials in runbooks that are accessible from the Azure portal. Files used by automated deployment tools such as Terraform or Azure Functions may be backed by Storage Accounts and often have high privilege credentials in cleartext. This often provides an attacker with a privilege escalation path from Viewer or Contributor to Owner. Azure Key Vault or another suitable secrets management service should always be used to protect secrets from read-only privileged principals. Managed services that support managed identities should utilize the feature to ensure secure secret retrieval from Azure Key Vault or other reputable secrets management platforms.
4. Authorizing Azure CIDR / Azure Services
A common misconfiguration Praetorian has seen involves authorizing the entire public Azure CIDR range, rather than a specific intended IP address range. Unlike traditional on-premise IP address ranges which are owned by the organization, Azure uses a shared public CIDR range. Additionally, public IP addresses for services like Virtual Machines will change every reboot unless otherwise specified.
Allowing the public Azure CIDR range would permit connectivity with any machine within the Azure network. An attacker could easily bypass the allowlist by launching an Azure VM from their own subscription. Praetorian recommends using Private Endpoints and Private Link to securely expose assets to select internal or an appropriate bastion host solution that can provide developer access.
Additionally, Praetorian often sees the “Allow Azure services and resources to access this server” option enabled for SQL databases with the intention to only allow other Azure services from within the tenant to access the database. However, this option has the unintentional effect of allowing connections from all Azure subscriptions, effectively disabling the allowlist as attackers can spin up VMs in their own subscription and reach the SQL database. See above for further details.
5. Using Subscriptions as a Hard Security Boundary
Companies often use subscriptions as a hard security boundary between production, staging, development, and testing environments. In theory, this might allow segregation of resources and users by providing subscription-level access as needed. However, least privilege is difficult to manage and Praetorian often sees multiple Azure accounts having access to multiple environments which provides a pivot between the environments. For example, developers often require cloud administrator privileges during the development and testing of new cloud services. The main issue is that multiple subscriptions within the same Azure account will still share the same Azure Active Directory tenant. For a clear logical separation and easier management, Praetorian would recommend a Business-to-Business (B2B) approach. Production and staging could be a single B2B environment while development and testing could be another B2B environment. Developers requiring administrator access to the development and testing environments would not increase the risk of the production and staging environments.
Using subscriptions as security boundaries is prone to misconfigurations and make it hard to enforce least privilege while minimizing the impact on developer productivity. Praetorian has seen multiple clients use B2B and Business-to-Consumer (B2C) Azure AD collaboration effectively to manage the trust relationships cleanly.
For example, for a company with lots of applications and a large number of developer teams the convention now would be to have a large Azure Account with an Azure AD tenant and multiple subscriptions for each application.
Since B2B users must be explicitly invited to the Azure Active Directory (AAD) tenant, this model has distinct advantages when it comes to limiting access and ensuring that only current developers or administrators have access to the application. If an employee is moved from one application to another, it would be logically simple to remove their B2B guest user from one application and invite them to the new application.
The same could be done with production, staging, development, and testing environments. Production and staging could be a single B2B AAD tenant while development and testing could be its separate B2B AAD tenant. This ensures that developers who do not need production access would be in a separate AAD tenant from the production one and it would be difficult to have misconfigured access as an explicit invite would have to be sent out. Developers may require cloud administrator access to perform their testing of new cloud services and they could be provided that access without worrying about violating least privilege within the production environment.
6. Failing to Effectively Utilize Azure Native Security Services
Azure Security Center (ASC) provides a “single pane of glass” to help security & operations teams understand their current security posture across all of their cloud workloads. Azure Defender integrates nicely into Security Center and provides endpoint and runtime protections for many common Azure services. Both ASC and Defender play a critical role in informing customers about insecure deployments and potential threats to their environment, and their native integration with Azure’s services provides seamless integration and setup. Based on our clients’ experiences, Praetorian recommends utilizing ASC Standard Tier which flags configuration issues, makes recommendations for remediation, and calculates a security score.
ASC also provides integrations with most major SIEMs. Each subscription should have a security owner responsible for remediating ASC alerts and documenting accepted risks and exceptions. ASC standard tier has extremely useful features such as adaptive network hardening, adaptive application hardening, vulnerability assessment, and automated compliance checks which simplify management of large enterprise cloud deployments.
However, Praetorian would like to stress that a tool is only useful when used and maintained. Processes need to be developed to remediate issues or flag issues as accepted risks. Praetorian often sees ASC and Defender alerts ignored.
Finally, corporate security policies are hard to enforce and have been traditionally based on trust and procedure. Non-compliant resources would often be overlooked. Azure policies allow companies to define and enforce machine-readable security policies using code to prevent misconfigurations on the cloud. A large library of policies is provided by Azure. For example, “ensure resources have an owner tag” which forces a user to include an owner tag on all resources created or “resources should not have public IPs” to prevent unintentional service exposure. Companies could define their own Azure policies based on evolving needs. Azure policies could also be used to ensure compliance (e.g. PCI DSS).
7. Lack of Protections and Awareness About Subdomain Takeovers
Subdomain takeovers involve an attacker gaining control of a subdomain associated with a victim’s domain. This often occurs when a subdomain has a stale DNS entry (often a canonical name, or CNAME) to an external resource that the victim no longer controls. While subdomain takeovers can occur in on-premise deployments, they are particularly common for cloud-native organizations, since cloud platforms often provide custom subdomains for deployed cloud assets. Attackers often target these subdomain-supporting cloud services, as anyone can request the custom subdomain once it’s released. Similarly, service names for storage accounts, Azure SQL, CosmosDB, and many other Azure services can be crafted in domain-squatting or phishing attacks. Engineering teams need to take extra precautions to keep DNS records up to date, and to ensure that proper asset management and monitoring solutions are in place to avoid subdomain takeovers.
8. Lack of a Teardown Process and Asset Management
Praetorian has found that processes are as important as technologies utilized. Attackers will attempt to gain an initial foothold through the path of least resistance. Praetorian often finds exposed development resources and staging environments with relaxed security requirements. As cloud services are tightly integrated and difficult to segregate into separate environments, attackers may abuse the trust relationship of traffic flowing from developer environments to production environments in order to compromise protected production resources. Therefore, it is important to have a proper asset management and teardown process in place to ensure that temporary development and testing resources are removed at the earliest convenience.
9. Not Establishing a Tagging Strategy and Enforce it with Policy
It is extremely easy to spin up cloud resources but hard to pin ownership or purpose to a resource. This leads to a situation where unused resources are left up as no one knows who owns the resource and is afraid of causing service disruption by removing the resource. Unused resources add an additional amount of risk to the cloud environment.
Praetorian recommends tags for data and resources that identify the sensitivity of data stored or processed, resource owner, date to be decommissioned, environment, and any other tags which will aid in maintenance. The name can be obscured so that it isn’t a boon to attackers, such as data_flavor instead of security_level if that is desired. It can be significantly harder to attribute cost to teams in the cloud without tagging, but this also applies to clean-up and visibility into shadow ops and remediations. Do note that enforcing a tagging policy retroactively is significantly more difficult than enforcing one during environment inception.
10. Not Utilizing Dedicated and Clearly Labelled Administrative Accounts
Maintaining a clean Azure Active Directory tenant that adheres to the principle of least privilege is an uphill task for large organizations with tens of thousands of users, constant employee rotations, and employee churn. Additionally, some developers may double up as cloud administrators who require cloud administrator privileges occasionally.
Praetorian has found that having separate accounts for administrator privileges that are clearly labeled has reduced the number of misconfigurations in client environments. For example, if developer A requires reader access on a daily basis and owner access when an incident occurs then Praetorian recommends having two accounts for the developer: firstname.lastname@example.org and email@example.com.
This has a number of benefits:
- Allows different security requirements and higher levels of scrutiny/logging on admin accounts
- Clear logical segregation that is easy to filter allows easy maintenance of the AAD tenant
- The developer would not need to use an overprivileged account to perform daily tasks
- Developers would have to go through the steps of logging out of the developer account and logging into the admin account. This provides a psychological break to the user that they are crossing security boundaries and should be more attentive with the actions they perform on the admin account
There are many benefits to cloud migration, including cost optimization, flexibility, scalability, and even the opportunity for enhanced security. These 10 security issues do not represent an exhaustive list, but rather an introduction into the most common misconfigurations and anti-patterns we experience during engagements with real Azure environments of varying sizes. We hope you find these recommendations valuable to your migration efforts, and as always Praetorian is here to help ensure your cloud implementations are secure.