Skip to content

Add Azure technique: Retrieve App Service Publishing Credentials#875

Open
arpitjain099 wants to merge 6 commits into
DataDog:mainfrom
arpitjain099:feat/azure-app-service-publishing-credentials
Open

Add Azure technique: Retrieve App Service Publishing Credentials#875
arpitjain099 wants to merge 6 commits into
DataDog:mainfrom
arpitjain099:feat/azure-app-service-publishing-credentials

Conversation

@arpitjain099

Copy link
Copy Markdown

What this does

Adds a new Azure attack technique, azure.credential-access.app-service-publishing-credentials, that retrieves the publishing profile of an Azure App Service (Web App). The publishing profile contains FTP and Web Deploy credentials in cleartext.

An attacker with read-or-higher access to an App Service can call the Microsoft.Web/sites/publishxml/action ARM operation to download these credentials, without needing access to any Key Vault or secret store. The returned XML contains userName and userPWD attributes that grant direct FTP and Web Deploy access to the application host, which can be used for lateral movement or to deploy malicious code to the running application.

Closes #871.

Behavior

  • Warm-up: provisions an App Service plan and a Linux Web App (main.tf).
  • Detonation: calls WebAppsClient.ListPublishingProfileXMLWithSecrets (the publishxml action) via the Azure SDK for Go, reads the returned publishing profile.
  • Idempotent, no revert needed (read-only retrieval).

MITRE ATT&CK

  • Credential Access (the technique maps to the Credential Access tactic, consistent with how other read-the-secret techniques are tagged).

References

Implementation notes

  • Modeled on the existing Azure techniques azure.exfiltration.disk-export (helper client constructor, providers.Azure() credential plumbing) and azure.execution.vm-run-command (SDK client construction and detonation shape).
  • New dependency: github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/appservice/armappservice/v4 (added to v2/go.mod).
  • Registered via the standard go:embed main.tf + init() RegisterAttackTechnique mechanism, and added to the imports in v2/internal/attacktechniques/main.go.
  • Docs regenerated with make docs (new technique page, Azure index, list, coverage matrix, index.yaml).

Validation

Validated locally with go build ./..., go vet ./..., go test ./pkg/... (registry/loader), and make docs, all passing. This was not detonated against live Azure, since that requires a subscription; the API call shape follows the Azure SDK and the documented publishxml operation.

@arpitjain099 arpitjain099 requested review from a team as code owners June 4, 2026 06:59
Adds a new Azure credential-access attack technique that retrieves an App
Service publishing profile via the Microsoft.Web/sites/publishxml/action ARM
operation. The publishing profile contains FTP and Web Deploy credentials in
cleartext, which an attacker with read-or-higher access can use for lateral
movement or to deploy code to the application host.

The technique warms up a Linux Web App and an App Service plan, then calls
WebAppsClient.ListPublishingProfileXMLWithSecrets from the Azure SDK during
detonation. Observed in the STORM-2949 intrusion (Microsoft, May 2026).

Validated with go build, go vet, go test (pkg registry/loader), and make docs.
Not detonated against live Azure.

Closes DataDog#871

Signed-off-by: Arpit Jain <arpitjain099@gmail.com>
Signed-off-by: arpitjain099 <arpitjain099@gmail.com>
@arpitjain099

Copy link
Copy Markdown
Author

Rebased onto main. The only conflict was the generated MITRE coverage matrix; regenerated it with make docs so it includes both the newer techniques on main and this one. The technique builds clean.

@arpitjain099 arpitjain099 force-pushed the feat/azure-app-service-publishing-credentials branch from f708dca to af023df Compare June 24, 2026 01:37
@christophetd christophetd force-pushed the feat/azure-app-service-publishing-credentials branch from de304bc to 6f28a34 Compare June 24, 2026 07:55
@christophetd

Copy link
Copy Markdown
Contributor

Hi @arpitjain099, thanks for the contribution! I pushed a few cosmetic commits. I'll now test the code against a live Azure subscription then get it merged

@christophetd

Copy link
Copy Markdown
Contributor

I'm hitting quota issues on a subscription that usually works with VMs etc., any idea if you've had to make a specific quota increase request to get it to work?


Error: creating Service Plan: (Serverfarm Name "stratus-red-team-asp-cred-plan" / Resource Group "stratus-red-team-asp-cred-rg-p76fb14t"): web.AppServicePlansClient#CreateOrUpdate: Failure sending request: StatusCode=401 -- Original Error: Code="Unauthorized" Message="Operation cannot be completed without additional quota. \r\nAdditional details - Location:  \r\nCurrent Limit (Total VMs): 0 \r\nCurrent Usage: 0\r\nAmount required for this deployment (Total VMs): 1 \r\n(Minimum) New Limit that you should request to enable this deployment: 1. \r\nNote that if you experience multiple scaling operations failing (in addition to this one) and need to accommodate the aggregate quota requirements of these operations, you will need to request a higher quota limit than the one currently displayed." Details=[{"Message":"Operation cannot be completed without additional quota. \r\nAdditional details - Location:  \r\nCurrent Limit (Total VMs): 0 \r\nCurrent Usage: 0\r\nAmount required for this deployment (Total VMs): 1 \r\n(Minimum) New Limit that you should request to enable this deployment: 1. \r\nNote that if you experience multiple scaling operations failing (in addition to this one) and need to accommodate the aggregate quota requirements of these operations, you will need to request a higher quota limit than the one currently displayed."},{"Code":"Unauthorized"},{"ErrorEntity":{"Code":"Unauthorized","ExtendedCode":"70007","Message":"Operation cannot be completed without additional quota. \r\nAdditional details - Location:  \r\nCurrent Limit (Total VMs): 0 \r\nCurrent Usage: 0\r\nAmount required for this deployment (Total VMs): 1 \r\n(Minimum) New Limit that you should request to enable this deployment: 1. \r\nNote that if you experience multiple scaling operations failing (in addition to this one) and need to accommodate the aggregate quota requirements of these operations, you will need to request a higher quota limit than the one currently displayed.","MessageTemplate":"Operation cannot be completed without additional quota. \r\nAdditional details - Location: {0} \r\nCurrent Limit ({1}): {2} \r\nCurrent Usage: {3}\r\nAmount required for this deployment ({1}): {4} \r\n(Minimum) New Limit that you should request to enable this deployment: {5}. \r\nNote that if you experience multiple scaling operations failing (in addition to this one) and need to accommodate the aggregate quota requirements of these operations, you will need to request a higher quota limit than the one currently displayed.","Parameters":["","Total VMs","0","0","1","1"]}}]

  with azurerm_service_plan.plan,
  on main.tf line 25, in resource "azurerm_service_plan" "plan":
  25: resource "azurerm_service_plan" "plan" {

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

New attack technique: Retrieve Azure App Service Publishing Credentials

2 participants