id: azure-mfa-not-enabled-privileged-users
info:
  name: Azure MFA Not Enabled for All Privileged Users
  author: princechaddha
  severity: high
  description: |
    Ensure that Multi-Factor Authentication (MFA) is enabled for all user credentials that have write access to the cloud resources within your Microsoft Azure account. Multi-Factor Authentication is a simple, yet efficient method of verifying your Azure user identity by requiring an authentication code generated by a virtual or hardware device, also known as passcode, used in addition to your usual access credentials such as user name and password.
  impact: |
    Without MFA enabled for privileged users, there is an increased risk of unauthorized access which can lead to potential breaches and significant impact on cloud resources and data security.
  remediation: |
    Configure Multi-Factor Authentication for all privileged Azure user accounts to enhance security measures and prevent unauthorized access.
  reference:
    - https://docs.microsoft.com/en-us/azure/active-directory/authentication/concept-mfa-howitworks
    - https://learn.microsoft.com/en-us/azure/role-based-access-control/built-in-roles
    - https://docs.microsoft.com/en-us/graph/api/resources/authenticationmethods-overview
    - https://docs.microsoft.com/en-us/azure/active-directory/authentication/howto-mfa-userstates
  tags: cloud,devops,azure,microsoft,azure-cloud-config,graph-api

flow: |
  code(1);
  for (let User of iterate(template.noMfaUsers)) {
    set("userPrincipalName", User);
    code(2);
  }

self-contained: true
code:
  - engine:
      - sh
      - bash
    source: |
      az rest --method GET --uri 'https://graph.microsoft.com/v1.0/reports/authenticationMethods/userRegistrationDetails' --query "value[?isMfaRegistered==\`false\`].userPrincipalName"

    extractors:
      - type: json
        name: noMfaUsers
        internal: true
        json:
          - '.[]'

  - engine:
      - sh
      - bash
    source: |
      az role assignment list --include-classic-administrators true --assignee "$userPrincipalName" --query '[].{roleDefinitionName:roleDefinitionName}' --output json

    matchers:
      - type: word
        words:
          - 'Owner'
          - 'Contributor'
          - 'Administrator'
          - 'Reservations Administrator'
          - 'Role Based Access Control Administrator'
          - 'User Access Administrator'

    extractors:
      - type: dsl
        dsl:
          - 'userPrincipalName + " is a privileged user without MFA registered"'
# digest: 490a0046304402206d892d252940b608a8d53769f5bf92a9e7d8e27b8def2ce6c61ec22771e90cca02200d535c282211d9f17c7d320f585789b370dbc211c6d4a9c6ceb99b3bccbd353c:922c64590222798bb761d5b6d8e72950