Skip to main content
emnode
Compliance High severity MCSB DP-3

Microsoft Defender for Cloud · Azure App Service

FTPS should be required in web apps

Written and reviewed by Emnode · Last reviewed

What does the recommendation "FTPS should be required in web apps" check?

Flags any App Service web app whose FTP state is left at the default 'All allowed', meaning the platform's built-in FTP deployment endpoint accepts plain FTP as well as FTPS. It looks only at the 'ftpsState' property of the app's site configuration: the check passes when that value is 'FtpsOnly' or 'Disabled', and fails when it is 'AllAllowed'. It is a configuration check on the publishing endpoint, so it does not inspect deployment slots as separate resources, does not check the minimum inbound TLS version that App Service negotiates, and does not look at the application's own HTTPS-only setting. It also says nothing about how you actually push code: Git deployment, ZIP deploy, a container image or a release pipeline can all coexist with an FTP endpoint that is still left open underneath them.

Why does "FTPS should be required in web apps" matter?

Plain FTP sends the deployment username and password across the network in clear text, along with every byte of the files being transferred. Anyone able to observe that traffic, whether on a shared network, through a compromised proxy or via a man-in-the-middle position, reads the publishing credentials directly and can then upload arbitrary files straight into your running site. Because the FTP endpoint is internet-facing by default and uses the same publishing profile as the rest of the app, this is a direct route to defacement, installing a web shell for persistent access, or stealing connection strings and secrets that live in the deployed content. The business consequence is an attacker-controlled production application and a breach that starts from credentials you never had to be tricked into handing over, they simply travelled unencrypted. Requiring FTPS wraps the session in TLS so those credentials and files can no longer be harvested off the wire, and disabling FTP entirely removes the endpoint as an attack surface altogether.

How do I fix "FTPS should be required in web apps"?

  1. In the portal, open the web app, go to Settings then Configuration, open the General settings tab and set 'FTP state' to 'FTPS only' (or 'Disabled' if no FTP workflow exists), then save.
  2. Or run 'az webapp config set --resource-group <rg> --name <app> --ftps-state FtpsOnly', substituting 'Disabled' where FTP deployment is not used; in Bicep set 'siteConfig.ftpsState' to 'FtpsOnly' on the Microsoft.Web/sites resource so new apps ship compliant.
  3. To enforce it across the estate, assign the built-in policy by exact display name rather than a hardcoded GUID: pid=$(az policy definition list --query "[?displayName=='App Service apps should require FTPS only'].name" -o tsv); az policy assignment create --name require-ftps --policy "$pid" --scope <subscription-or-mg-scope>.

Remediation script · bash

# Close the highest-impact plaintext doors first: the Redis non-SSL port,
# then HTTPS-only + a modern TLS floor on every web app.

# Redis: disable the non-SSL port 6379 and require TLS 1.2 (clients use 6380).
for cache in $(az redis list --query "[?enableNonSslPort].name" -o tsv); do
  rg=$(az redis list --query "[?name=='$cache'].resourceGroup" -o tsv)
  az redis update --name "$cache" --resource-group "$rg" \
    --set enableNonSslPort=false minimumTlsVersion=1.2
  echo "$cache: non-SSL port disabled, min TLS 1.2"
done

# Web apps: enforce HTTPS only and raise the TLS floor.
for app in $(az webapp list --query "[?httpsOnly==\`false\`].name" -o tsv); do
  rg=$(az webapp list --query "[?name=='$app'].resourceGroup" -o tsv)
  az webapp update --name "$app" --resource-group "$rg" --https-only true
  az webapp config set --name "$app" --resource-group "$rg" --min-tls-version 1.2
  echo "$app: HTTPS only, min TLS 1.2"
done

# Functions follow the same pattern with az functionapp update --set httpsOnly=true.

# Ratchet it shut: assign the built-in deny policy for web apps over HTTPS only.
az policy assignment create \
  --name require-https-webapp \
  --policy a4af4a39-4135-47fb-b175-47fbdf85311d \
  --scope "/subscriptions/00000000-0000-0000-0000-000000000000"

Full walkthrough (console steps, edge cases and verification) in the lesson Enforce encryption in transit across Azure services.

Is "FTPS should be required in web apps" a false positive?

A web app deliberately set to 'FTPS only' so a legacy build agent can still publish over an encrypted FTP session is correct and should not be forced all the way to 'Disabled'. The control is already satisfied because plain FTP is refused and the credentials travel inside TLS, so the session is no longer interceptable. Tightening further to 'Disabled' would break that deployment path while adding no extra confidentiality, so 'FtpsOnly' is the right resting state for any app that genuinely still relies on FTP-based publishing.