Identifying vulnerabilities in public-facing services
Once your anonymous attack surface has been identified, and confirmed by the resource owner, you can start looking for vulnerabilities. As a very general rule of thumb, vulnerabilities in Azure can be broken down into three main categories: configuration, patching, and code-related.
Configuration-related vulnerabilities
This grouping of vulnerabilities can be broken into multiple sub-categories, but the two that we will be focusing on are Infrastructure as a Service (IaaS) and Platform-as-a-Service (PaaS) misconfigurations. These misconfigurations are typically caused by human error, resulting in sensitive information being exposed or unauthorized access to services.
IaaS configuration-related vulnerabilities
Azure IaaS services can be generalized as services that take the place of traditional infrastructure. The most common resources are virtual machines, virtual machine scale sets and Windows Virtual Desktops (WVDs). These services can be deployed privately within a virtual network, connected to on-premises networks, or exposed to the internet using a public IP address, as mentioned earlier in this chapter.
Using the list of public IP addresses that a client has provided to us from the results of the commands in the Azure public IP address ranges section of this chapter, we can scan those IP addresses with common vulnerability scanning tools. Remember to always check the IP that you have been provided with for ownership and authorization.
For virtual machines and WVDs, we will typically be looking for weak or default credentials for available management ports. It should also be noted that any IaaS hosts that have internet-facing services could also have additional service misconfigurations. These vulnerabilities are not limited to the parameters that are managed in Azure. An administrator could misconfigure a service on a VM, expose it to the internet, and create a vulnerability.
PaaS configuration-related vulnerabilities
Using the list of enumerated Azure services from the previous section, we can start anonymously looking for vulnerabilities in those services. For example, we identified a storage account with a base name of azurepentesting
in the previous exercise. Now, we can dig deeper into that resource to find misconfigured containers in that storage account.
Storage accounts
Storage accounts are Azure's way of handling data storage in the cloud. These accounts consist of the following sub-services:
- Blob service: General HTTP/HTTPS file hosting
- Files service: Attached data storage (SMB/NFS)
- Table service: NoSQL semi-structured datasets
- Queue service: HTTP/HTTPS message storage
Given the output from the previous subdomain enumeration task, we know that the azurepentesting
base word yielded a storage account named azurepentesting
.
We can also see that there are DNS records for the following subdomains:
- Blob service:
azurepentesting.blob.core.windows.net
- Files service:
azurepentesting.file.core.windows.net
- Table service:
azurepentesting.table.core.windows.net
- Queue service:
azurepentesting.queue.core.windows.net
By default, these four subdomains are allocated when a storage account is created. This does not necessarily mean that an Azure customer is using all four services for data storage purposes, so it is up to us to identify whether they contain any anonymously available data.
The Files, Table, and Queue services always require some level of authentication to access (we will not be focusing on them in this chapter). Instead, we will focus on the Blob service, which allows administrators/developers to configure anonymous access to files.
Blob storage account permissions overview
The Blob service in a storage account consists of containers. These containers are effectively folders that can be used to store objects/data. You can access these objects through an HTTP/HTTPS endpoint. The URL address is a combination of the storage account name, the container, and the object name.
As shown in the following diagram, if the storage account name is azurepentesting
, the container name is public
, and the file within the container is README.txt
, the URL of the object will be as follows:
https://azurepentesting.blob.core.windows.net/public/README.txt.
For the more visual learners, here's what that structure looks like:

Figure 3.11 – Azure Blob service endpoint URL
A storage account can have multiple containers, with each container having a different public access level configuration. The public access configuration options are as follows:
- Private: Does not allow anonymous access. Access needs to be authenticated.
- Blob: Allows anonymous access to a known object URL.
- Container: Allows the container files to be listed and accessed anonymously.
While the Blob container permissions can expose sensitive data, an attacker would need to know the full filenames of the affected files to access them. In cases where an application programmatically creates a file with a predictable naming format (Report-123.pdf
, Report-124.pdf
, and so on), an attacker may be able to infer the names of other files in the storage account after initially identifying the intended user files. This type of filename enumeration is commonly referred to as insecure direct object references, or IDORs for short. PortSwigger has an excellent overview of this issue on their site: https://portswigger.net/web-security/access-control/idor.
An attacker could also perform a container and object name guessing attack using a tool such as Gobuster to see whether an object is returned. The chances of success are minimal but still possible.
The most concerning public access level is container as it allows anyone to list all the available files and access them. This means that an attacker with knowledge of the storage account and container would be able to enumerate all the available files.
Utilizing our previous example storage account URL, we know that the storage account name is azurepentesting
and that the container is public
. By appending the ?restype=container&comp=list
parameters to the container URL (https://azurepentesting.blob.core.windows.net/public/?restype=container&comp=list
), we can list all the objects stored in that container. This will return XML data about the available files, which we can then use to access the objects!

Figure 3.12 – Azure Blob service endpoint URL
From an unauthenticated perspective, what can we do if we do not immediately know any containers in a storage account? We can use automated tools to guess the container names, check whether they allow container permissions, and then list the available files from there.
Hands-on exercise – identifying misconfigured blob containers using MicroBurst
In this exercise, we will use the Invoke-EnumerateAzureBlobs
script from MicroBurst to access data in a misconfigured Azure Blob storage service. Here are the tasks that we will complete in this exercise:
- Task 1: Use the
Invoke-EnumerateAzureBlobs MicroBurst
module to anonymously enumerate storage account containers using theazurepentesting
base name and the built-in permutation list. - Task 2: Define a custom container list and use it to enumerate further containers.
Let's begin:
- Within your pentest VM, open a PowerShell console as an administrator.
- Change your directory path to the
MicroBurst
directory and import the PowerShell functions using thefp;;pwomg
commands:cd .\MicroBurst\ Import-Module .\MicroBurst.psm1
Here's what the output looks like:
Figure 3.13 – Importing the MicroBurst PowerShell module
- Use the
Invoke-EnumerateAzureBlobs
function with a base word ofazurepentesting
to identify public storage accounts with containers that have thecontainer
access level configured:Invoke-EnumerateAzureBlobs -Base azurepentesting
- You can see that MicroBurst has identified two containers (
public
andprivate
) and the objects in those containers.Here's what the output looks like:
Figure 3.14 – Using MicroBurst to find public blob containers
- We can then download the contents of the objects directly using the following commands:
Invoke-WebRequest -Uri "https://azurepentesting.blob.core.windows.net/public/README.txt" -OutFile "README.txt" Invoke-WebRequest -Uri "https://azurepentesting.blob.core.windows.net/private/credentials.txt" -OutFile "credentials.txt"
Here is what the output looks like:
Figure 3.15 – Downloading objects using PowerShell
- Read the content of one of the downloaded files using the following command. This will open the file in Notepad:
notepad .\credentials.txt
Figure 3.16 – Accessing the downloaded file
- In the command we used in Step 3, MicroBurst enumerated the storage account using common container names such as
private
andpublic
. Unless otherwise specified in the command, the names used for the container name guesses will come from thepermutations.txt
file in the MicroBurst repository. The full list of names that MicroBurst uses for guessing can be viewed using the following command:Get-Content .\Misc\permutations.txt
- MicroBurst also allows us to specify custom container names using the
Folders
parameter. Create a custom container name list using the following command. ClickYes
when prompted about creating a new file:notepad customcontainer.txt
Figure 3.17 – Creating a custom container name list
- Add the following names to the Notepad file. Save the file and close it:
scripts templates archive 2020 2019 2018
- Back in the PowerShell console, use the following command to enumerate potential public containers using any of the names in our custom name list:
Invoke-EnumerateAzureBlobs -Base azurepentesting -Folders .\customcontainer.txt
- Here, you can see that we have found more public containers and objects than we did when we ran the command earlier:

Figure 3.18 – Creating a custom container name list
As you can see, configuration-related vulnerabilities can cause serious problems for Azure environments. Throughout this book, we will see multiple examples of these issues at the public-facing and "internal" platform configuration levels.
While this is only one example, there are additional service-specific configuration vulnerabilities that we will highlight throughout this book. Next, we will look at some additional vulnerability categories that may apply to our external-facing services.
Patching-related vulnerabilities
While these issues are less commonly found, there are still plenty of new security patches released every week. As a result, there are plenty of forgotten or abandoned services, applications, and virtual machines that miss these patches. For this book, we will be focusing on exploiting Azure configuration-related vulnerabilities, but it's good to know the basics of exploiting patch-related issues.
From an external perspective, we will typically be scanning Azure virtual machines, with public IPs, for internet-facing services. These services can typically be fingerprinted by network scanning tools to identify the specific version of the software hosting the service.
Once the version of the software has been identified, we can either use vulnerability scanners (Nessus, Nexpose, and so on) or some basic Google skills to find potential vulnerabilities in these services.
Since this is not a network penetration testing book, we recommend checking out one of the many penetration testing books from Packt: https://www.packtpub.com/catalogsearch/result/?q=penetration%20testing.
Code-related vulnerabilities
The "cloudification" of existing applications and the drive toward cloud-native development are some of the driving forces bringing organizations into the Azure cloud. By porting existing or legacy applications into a cloud environment, many organizations are just bringing along many of the old vulnerabilities that previously existed in their original applications.
While there are many benefits to moving to the cloud, it is not a magic bullet to fix application vulnerabilities. Some of the existing common application issues can actually become more impactful in a cloud environment, as the platform can then be abused by these issues to escalate access.
While this is not the book to use to learn about web application penetration testing, we can recommend taking a look at Packt Publishing's other books for a more in-depth look at testing applications: https://www.packtpub.com/catalogsearch/result/?q=Web%20application%20Penetration%20Testing.
At a high level, the following vulnerabilities can be very impactful in an Azure environment, so it may be worth prioritizing these while you are testing.
SQL injection (SQLI)
By injecting SQL queries into an application, an attacker may be able to access sensitive information in the database, force the database to authenticate to the attacker, or even achieve command execution on the database server. In an Azure context, an attacker could potentially execute commands on a SQL database virtual machine, which could then be used to pivot to the internal virtual networks.
Local file include and directory traversal
By accessing local files from the web server, an attacker may be able to access configuration files on the hosts. With applications in Azure, many of these configuration files contain access keys for Azure services, such as Storage accounts, so there may be opportunities to pivot from these services.
Command injection
There are many ways for commands to make their way into an application server, but in a cloud environment, these can be abused to access additional resources in the subscription. Additionally, if the application server is utilizing a managed identity, the attacker may be able to execute commands that can generate an authorization token for the managed identity. This token could then be used to assume the identity of the managed identity.
Honorable mention – server-side request forgery (SSRF)
SSRF is an application issue that allows an attacker to force the application server to make outbound requests. This issue has seen some very impactful usage in AWS environments, where it can be used to query the EC2 metadata service to return IAM credentials. Due to the way the Azure metadata service operates, there is a header that is required for making similar requests in Azure. Metadata service credential attacks can be executed via command injection in Azure, but not via SSRF attacks.