> For the complete documentation index, see [llms.txt](https://docs.stoik.io/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.stoik.io/cyber-best-practices/vulnerability-remediation-guides/cloud-scan/microsoft-azure-entra-id-microsoft-365.md).

# Microsoft Azure / Entra ID / Microsoft 365

These findings apply to organizations using Microsoft cloud services (Azure subscriptions, Microsoft 365, Entra ID / Azure Active Directory).

## Privileged Users with MFA Disabled

**Severity: High**

### What it means

Multi-Factor Authentication (MFA) adds a second layer of security when logging in, typically a code from a phone app or a hardware key. Without MFA, if an attacker guesses or steals an admin's password (through phishing, a data breach, or brute force), they get full access to your cloud environment with nothing else stopping them.

This finding flags **administrator accounts that do not have MFA enabled**. These are the most sensitive accounts in your organization: a compromised admin account can lead to full control of your email, files, and infrastructure.

### What the scan checks

The scan examines all users with privileged roles (Global Administrator, Application Administrator, Security Administrator, etc.) and checks whether they have registered for MFA. The alert triggers if any privileged user has MFA disabled.

### How to fix

**Option A: Enable Security Defaults (simplest)**

If you don't already have Conditional Access policies, Security Defaults is the quickest way to enforce MFA for all users:

1. Go to [Entra ID](https://entra.microsoft.com) > `Identity` > `Overview` > `Properties`.
2. Click `Manage security defaults`.
3. Set to `Enabled`.

**Option B: Use Conditional Access (recommended for larger organizations)**

1. Go to [Entra ID](https://entra.microsoft.com) > `Protection` > `Conditional Access`.
2. Click `+ New policy`.
3. Name it: "Require MFA for Admins".
4. Under `Users`: select `Directory roles` and pick all admin roles (Global Administrator, Security Administrator, etc.).
5. Under `Grant`: select `Require multifactor authentication`.
6. Set the policy to `On` and save.

After creating the policy, each admin will be prompted to set up MFA on their next login.

## Shadow Admin Users

**Severity: Low**

### What it means

A "Shadow Admin" is a user who has administrative powers without being an obvious administrator. They hold roles like "Password Administrator" or "Helpdesk Administrator" that give them significant permissions (e.g., resetting anyone's password, managing applications), but they might not be subject to the same security controls (MFA, access reviews) as the officially recognized admins.

The risk is that these accounts fly under the radar: they don't show up in the "Global Administrators" list, but an attacker who compromises one of them can still do serious damage, like resetting a Global Admin's password and taking over the entire tenant.

### What the scan checks

The scan identifies users assigned to any of these Entra ID roles:

* Application Administrator
* Authentication Administrator
* Cloud Application Administrator
* Helpdesk Administrator
* Password Administrator
* Privileged Authentication Administrator
* Privileged Role Administrator
* User Account Administrator

Users who also have the Global Administrator role are excluded (they are already visible as full admins).

### How to fix

1. Go to [Entra ID](https://entra.microsoft.com) > `Roles and administrators`.
2. Click on each of the roles listed above.
3. Review the list of assigned users. For each user, ask:
   * **Does this person actually need this role?** If not, remove them.
   * **Is this a permanent assignment?** Consider using [Privileged Identity Management (PIM)](https://learn.microsoft.com/en-us/entra/id-governance/privileged-identity-management/) for just-in-time access instead of permanent role assignments.
   * **Is MFA enabled for this user?** Shadow admins should have the same MFA requirements as full admins.

## High Percentage of Privileged Users

**Severity: Medium**

### What it means

More than **10% of your users** have administrator roles in Entra ID. This is a sign that admin permissions have been granted too broadly, perhaps for convenience, or because temporary access was never revoked.

Every admin account is a potential entry point for an attacker. Reducing the number of admins limits the blast radius if one account is compromised.

### What the scan checks

The scan counts the total number of users with any admin role and compares it to the total number of enabled users. The alert triggers if the ratio exceeds 10%.

### How to fix

1. Go to [Entra ID](https://entra.microsoft.com) > `Roles and administrators`.
2. For each admin role, review who is assigned.
3. Remove users who no longer need admin access.
4. For users who only need admin access occasionally, use **Privileged Identity Management (PIM)** for just-in-time elevation.

## Users with MFA Disabled

**Severity: High**

### What it means

Some users in your organization do not have MFA enabled. Without MFA, a stolen or guessed password is all an attacker needs to access their mailbox, files, and any applications they have access to.

This is how the majority of business email compromise (BEC) attacks happen: an attacker phishes a user's password, logs in without MFA, and then sends fraudulent emails or steals sensitive data.

### What the scan checks

The scan checks the MFA registration status of all enabled users. Any user with `isMfaRegistered = false` triggers the alert.

### How to fix

The most effective approach is to enforce MFA for all users via Conditional Access or Security Defaults (see "Privileged Users with MFA Disabled" above for step-by-step instructions).

To check which users are missing MFA:

1. Go to [Entra ID](https://entra.microsoft.com) > `Protection` > `Authentication methods` > `User registration details`.
2. Filter by "MFA capable = No" to see who hasn't registered.

## No Security Contact Set

**Severity: Medium**

### What it means

Microsoft Defender for Cloud can detect security threats in your Azure environment (suspicious login attempts, malware, exposed services, etc.). But if no email address is configured, these alerts have nowhere to go: nobody gets notified, and attacks can go undetected.

### What the scan checks

The scan checks whether at least one security contact email is configured in Microsoft Defender for Cloud's notification settings.

### How to fix

1. Go to the [Azure Portal](https://portal.azure.com).
2. Navigate to `Microsoft Defender for Cloud` > `Environment settings`.
3. Select your subscription.
4. Click `Email notifications`.
5. Fill in:
   * **Additional email addresses:** add a distribution list (e.g., `security@yourcompany.com`), avoid using a single person's email.
   * **Notification types:** at least "High severity" alerts.
6. Click `Save`.

## No Administering Resource Locks Role

**Severity: Low**

### What it means

Azure **Resource Locks** protect critical resources (databases, virtual networks, storage accounts) from accidental deletion or modification. Even an admin with full permissions cannot delete a locked resource without first removing the lock.

This finding means nobody in your organization has been assigned a role specifically for managing these locks. Without someone in charge, locks may not be used consistently, or critical resources may remain unprotected.

### What the scan checks

The scan looks for a custom RBAC role with permissions to manage resource locks (`Microsoft.Authorization/locks/*`). If no such role exists or nobody is assigned to it, the alert triggers.

### How to fix

1. Go to the [Azure Portal](https://portal.azure.com) > `Subscriptions` > select your subscription.
2. Go to `Access control (IAM)` > `Roles` > `+ Add` > `Add custom role`.
3. Create a role with the following permissions:

```
Microsoft.Authorization/locks/read
Microsoft.Authorization/locks/write
Microsoft.Authorization/locks/delete
```

4. Assign this role to a trusted administrator.
5. Have that administrator apply **Delete locks** on critical resources (databases, storage accounts, key vaults).

## Key Vault Not Recoverable

**Severity: High**

### What it means

Azure Key Vault stores your secrets, encryption keys, and certificates. If someone accidentally (or maliciously) deletes a Key Vault, you lose all of these. Without **soft-delete** and **purge protection** enabled, a deleted Key Vault is gone forever: there is no recovery.

### What the scan checks

The scan checks that both protections are enabled:

* **Soft-delete:** deleted key vaults are kept for a retention period (default 90 days) and can be recovered.
* **Purge protection:** even after soft-delete, the vault cannot be permanently erased during the retention period.

### How to fix

1. Go to the [Azure Portal](https://portal.azure.com) > `Key vaults` > select your vault.
2. Go to `Properties`.
3. Enable `Soft-delete` (note: this is now enabled by default on new vaults and cannot be disabled).
4. Enable `Purge protection`.
5. Click `Save`.

For existing vaults via Azure CLI:

```bash
az keyvault update --name <vault-name> --enable-purge-protection true
```

## HTTPS Not Enforced on App Service

**Severity: High**

### What it means

Your Azure App Service (website or API) accepts unencrypted HTTP traffic. This means data sent between users and your application, including login credentials, personal information, and session tokens, can be intercepted by anyone on the network path.

### What the scan checks

The scan checks the `HTTPS Only` setting on each App Service. If it is set to `Off`, the alert triggers.

### How to fix

1. Go to the [Azure Portal](https://portal.azure.com) > `App Services` > select your app.
2. Go to `Settings` > `Configuration` > `General settings`.
3. Set `HTTPS Only` to `On`.
4. Click `Save`.

## Insecure TLS Version on App Service

**Severity: High**

### What it means

Your App Service accepts connections using TLS 1.0 or 1.1, which are outdated encryption protocols with known vulnerabilities. Modern browsers and security standards require TLS 1.2 or higher.

### What the scan checks

The minimum TLS version configured on the App Service. The alert triggers if it is below 1.2.

### How to fix

1. Go to the [Azure Portal](https://portal.azure.com) > `App Services` > select your app.
2. Go to `Settings` > `Configuration` > `General settings`.
3. Set `Minimum TLS Version` to `1.2`.
4. Click `Save`.

## SQL / PostgreSQL / MySQL: SSL Enforcement Disabled

**Severity: High**

### What it means

Your database server accepts unencrypted connections. Without SSL/TLS enforcement, credentials and data sent between your application and the database can be intercepted on the network.

### How to fix

**For Azure Database for MySQL:**

1. Go to [Azure Portal](https://portal.azure.com) > `Azure Database for MySQL` > select your server.
2. Go to `Connection security`.
3. Set `Enforce SSL connection` to `ENABLED`.
4. Click `Save`.

**For Azure Database for PostgreSQL:**

1. Go to [Azure Portal](https://portal.azure.com) > `Azure Database for PostgreSQL` > select your server.
2. Go to `Connection security`.
3. Set `Enforce SSL connection` to `ENABLED`.
4. Click `Save`.

## Public Blob Container

**Severity: High**

### What it means

One or more of your Azure Storage blob containers is configured for **public access**, meaning anyone on the internet can read the files inside without authentication. This is a common source of data leaks.

### How to fix

1. Go to [Azure Portal](https://portal.azure.com) > `Storage accounts` > select the account.
2. Go to `Configuration`.
3. Set `Allow Blob public access` to `Disabled`.
4. Or, to fix individual containers: go to `Containers`, select the container, and change `Public access level` to `Private`.

## Virtual Machine Disks Not Encrypted

**Severity: High**

### What it means

Your virtual machine's disks are not encrypted. If the underlying physical hardware is compromised, decommissioned, or improperly disposed of, the data on those disks could be read in clear text.

### How to fix

1. Go to [Azure Portal](https://portal.azure.com) > `Virtual machines` > select the VM.
2. Go to `Disks` > `Additional settings`.
3. Enable `Azure Disk Encryption` (ADE) or `Server-Side Encryption with customer-managed keys`.
4. For new VMs, enable encryption at creation time.


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation by asking a question.

Perform an HTTP GET request on the following URL with the `ask` and `goal` query parameters:

```
GET https://docs.stoik.io/cyber-best-practices/vulnerability-remediation-guides/cloud-scan/microsoft-azure-entra-id-microsoft-365.md?ask=<question>&goal=<user_goal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is what the user is ultimately trying to achieve, the reason they need the answer. Sharing it helps GitBook give you a better, more relevant answer. A goal is most helpful when it describes the outcome the user wants rather than restating the question. For example, with `ask=how do I create an API token`, a goal like `automate deployments from our CI pipeline` lets GitBook tailor the answer to that use case.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
