Create an Azure Vulnerable Lab: Part #2 – Environment Variables

This article is part of a blog series where I explain common Azure vulnerabilities, how to create a lab such that it reproduces the issues, and how to exploit it. To follow this tutorial, you’ll need an Azure account and Azure CLI tool installed on your machine both of which you can get for free.

1. Environment Variables

An environment variable is a variable whose value is set outside the program, typically through functionality built into the operating system or microservice. An environment variable is made up of a name/value pair, and any number may be created and available for reference at a point in time.

Storing sensitive information (API keys, passwords, SQL connection strings) in the environment variables is totally fine, unless it’s not. You can read more about Why you shouldn’t use ENV variables for secret data, but to keep things short Azure will protect you as much as it can, but it won’t protect you shoot yourself in the foot.

Imagine a web application that connects to an API using a private key and saves the results in a local database to display it later. You don’t keep the API key and connection string in the source code, because that will be committed to source control (i.e: Github) and you don’t want everyone to see the credentials. Alternatively, you store this information in the environment variables and that’s fine unless your application is vulnerable to command injection for example.

For this tutorial, we will create and deploy a web application to Azure. The application is vulnerable to command injection. We will then store some dummy sensitive information in the environment variables and see how to dump this information and what else is stored there. Let’s begin!

2. Creating a vulnerable web app

Since our application is developed in python, we will need to install python3 locally. If you developed something in python before, you know that most of the time the applications would have some kind of dependency on libraries. When an application is deployed to Azure, these libraries are pushed together with the source code. To keep our local machine python packages “clean”, we will use python’s virtual environment which you can install using something similar to:

python3 -m pip install --user virtualenv

All packages that have to be installed (such as azure-code, Flask, etc) together with their versions are mentioned in the requirements.txt and are installed in a virtual environment dedicated to this project such that other applications that are using the same packages won’t break. Cool, so how do we do that?

    cd .\webapp
    python3 -m venv .venv
    .venv\scripts\activate
    pip install -r requirements.txt
    deactivate
    cd ..

Now that our application has all the dependencies installed, we will login to Azure with azcli, and make sure we start clean by deleting and creating again the resource group. (Note, if you already have the resource group created from previous challenge and you want to keep both challenges, you can skip the deletion and creation of the resource group).

    az login
    az group delete --name $resourceGroupName --yes
    az group create --name $resourceGroupName --location $location

Deploying application to Azure is quite straightforward, and it only takes one command: “az webapp up”. This will create an “App Service” on Azure if it doesn’t exist, pack the source code of our application, upload it, and unpack it. The only thing to be careful about is that we are running the command in the right folder. Pretty cool, right?

    cd ".\webapp"
    az webapp up --sku S1 --name $webappName --resource-group $resourceGroupName --plan $appserviceplanName --location $location
    cd ..

Then, we can create an environment variable that will contain the sensitive information. It could be an API key, password, connection string to database, etc. For the sake of this challenge, we will call it simply “flag”:

az webapp config appsettings set --resource-group $resourceGroupName  --name $webappName --settings "flag=e98bd50154903c87ecce53e1ecd217a9"

Lastly, since this is a web application that gives command execution to anyone, it would be wise to restrict the access and only allow traffic coming from our IP address. Using the “az webapp config access-restriction” we add a firewall rule

$ip = Invoke-RestMethod http://ipinfo.io/json
az webapp config access-restriction add --priority 200 --resource-group $resourceGroupName --name $webappName --rule-name "CTF Only" --action Allow --ip-address $ip.ip

To check if this worked, we can go to Azure portal under our App Service -> Settings -> Networking -> Access Restriction

That will show you that there is one access rule active, the “CTF only” which allows only one IP address to access the application

To triple check this works as intended, you can turn on your VPN and browse to the web app, or use an online proxy such as proxysite.com which in both cases should return a 403 error.

3. Exploiting Azure environment variables

To check if everything went just fine, navigate to the web app and try to see our permissions. In this case we are root:

Since this is a linux server, we will use the “env” command to dump the variable, and there we can see among many other variables our flag:
Check what other details is Azure storing in the environment variables. In the next tutorial we will see how we can use the storage account’s connection strings that we find in the application’s source code to get access to a private container, and recover files that have been already deleted for several days!

6 thoughts on “Create an Azure Vulnerable Lab: Part #2 – Environment Variables

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s