Tracking MFA enable/disable events through MS-graph integration

57 views
Skip to first unread message

wazuh

unread,
Nov 25, 2025, 9:32:48 AM11/25/25
to Wazuh | Mailing List
Hi, is there any known way or rules for monitoring the practice of enforcing MFA through Conditional Access instead of MFA per user?

A client has followed the following guide to enable MFA
Turn off per user MFA in Microsoft Entra ID - Microsoft Entra ID | Microsoft Learn

And now we no longer see the O365 integration events of MFA StrongAuthentication enabling or disabling. (when client did the change we saw hundreds of disabled MFA events and afterwards all the MFA events stopped) rule.id 91539 

As it is Entra ID area i was wondering if the azure-logs wodle for ms-graph monitoring would be able to detect changes to conditional access or is there another known way to monitor Conditional Access policies regarding MFA?
Microsoft Graph - Monitoring Microsoft Azure with Wazuh

Regards,
Dom

Federico Gustavo Galland

unread,
Nov 26, 2025, 7:59:17 AM11/26/25
to Wazuh | Mailing List
Hey Dom,

My prior message was not sent for some reason.

I was saying that you should be able to set up the MS Graph integration with directoryAudits, which will give you access to Entra ID policy changes events.
I'm not 100% sure that these events will trigger rules, though, and I don't have an Azure environment to test this on. But if you set up Graph and hand me over the raw logs, I can help you write custom rules here.

Regards,
Fede

wazuh

unread,
Nov 28, 2025, 4:22:15 AM11/28/25
to Wazuh | Mailing List
I have set it up with directoryAudits, however i am struggling to find the specific event. I do not have an environment myself i could get raw logs from, so was hoping there already was some sort of solution for this Microsoft Change as MFA is quite important to track

Federico Gustavo Galland

unread,
Nov 28, 2025, 6:08:18 AM11/28/25
to Wazuh | Mailing List
Dom,

Wazuh allows you to dump every event in raw form (as received from the data source) if you set <logall_json> to "yes" under /var/ossec/etc/ossec.conf and you restart your manager afterwards.
The raw events will then be output to /var/ossec/logs/archives/archives.json
You would now need to trigger a policy change and if the graph integration is properly set up, you should see the event in archives.json.
You can share a sanitized version of that here so we can work out a rule to match it.

Let me know if you find any issues in this process.

Regards,
Fede

wazuh

unread,
Nov 28, 2025, 8:34:59 AM11/28/25
to Wazuh | Mailing List
hi, yes i do know that however i do not control when a client will change mfa configuration through conditional access policy and the client's o365 is managed by another provider so it is pretty much not possible to get them to send some test events on demand. I will try to find a way to find a way to make a rule for this and will write here once i do. 

Federico Gustavo Galland

unread,
Nov 28, 2025, 9:11:03 AM11/28/25
to Wazuh | Mailing List
Dom,

I was not able to find a sample event either. Let us know as soon as you get hold of one so we can attest it is triggering a rule.

Regards,
Fede

wazuh

unread,
3:15 AM (6 hours ago) 3:15 AM
to Wazuh | Mailing List
Hi again,

i was finally able to get my hands on a test environment for this issue. so now with the most recent Microsoft recommendations to enforce MFA through conditional access the only way to really track the changes is through entra-id wodle integration and to look for conditional access policy change events. (o365 integration also detects changes but lacks information on what was changed in the policy). Whenever a new user is added the policy is automatically applied and that does not generate an event. however what can be observed is whenever someone is added to an exclusion list for the policy (indicating mfa enforcement has been disabled).

There is an issue where readability of the event is quite impractical compared to the old detection of MFA enable/disable events. It relies on finding the difference between the values of the fields data.targetResources.modifiedProperties.oldValue and data.targetResources.modifiedProperties.newValue which a very long hard to read jsons. additionally instead of seeing the email or display name of the user whose MFA enforcement was altered we only get to see the long user ID (Object ID in Entra)

here is an example log, where a user is removed from an exception and enforcement of MFA is enabled. If it were disabled the newValue would have the Object ID of the user in the excludedusers part:

{
  "_index": "wazuh-alerts-4.x-2026.01.13",
  "_id": "eventid",
  "_version": 1,
  "_score": null,
  "_source": {
    "cluster": {
      "node": "worker-node01",
      "name": "wazuh"
    },
    "agent": {
      "name": "test-wazuh-manager-2",
      "id": "000"
    },
    "data": {
      "azure_aad_tag": "microsoft-entra_id",
      "activityDateTime": "2026-01-13T13:44:09.0356648Z",
      "additionalDetails": [
        {
          "value": "Conditional Access",
          "key": "Category"
        }
      ],
      "result": "success",
      "azure_tag": "azure-ad-graph",
      "activityDisplayName": "Update conditional access policy",
      "operationType": "Update",
      "loggedByService": "Conditional Access",
      "correlationId": "correlationid",
      "id": "IPCGraph_fdlongid",
      "targetResources": [
        {
          "groupType": null,
          "displayName": "Require multifactor authentication for all users",
          "modifiedProperties": [
            {
              "newValue": "{\"id\":\"id1\",\"templateId\":\"id2\",\"displayName\":\"Require multifactor authentication for all users\",\"createdDateTime\":\"2026-01-13T13:20:24.8973136+00:00\",\"modifiedDateTime\":\"2026-01-13T13:44:08.4316185+00:00\",\"state\":\"enabled\",\"conditions\":{\"applications\":{\"includeApplications\":[\"All\"],\"excludeApplications\":[],\"includeUserActions\":[],\"includeAuthenticationContextClassReferences\":[],\"applicationFilter\":null},\"users\":{\"includeUsers\":[\"All\"],\"excludeUsers\":[],\"includeGroups\":[],\"excludeGroups\":[],\"includeRoles\":[],\"excludeRoles\":[\"long-role-id\"]},\"userRiskLevels\":[],\"signInRiskLevels\":[],\"clientAppTypes\":[\"all\"],\"servicePrincipalRiskLevels\":[]},\"grantControls\":{\"operator\":\"OR\",\"builtInControls\":[\"mfa\"],\"customAuthenticationFactors\":[],\"termsOfUse\":[]}}",
              "displayName": "ConditionalAccessPolicy",
              "oldValue": "{\"id\":\" id1  \",\"templateId\":\"id2\",\"displayName\":\"Require multifactor authentication for all users\",\"createdDateTime\":\"2026-01-13T13:20:24.8973136+00:00\",\"modifiedDateTime\":\"2026-01-13T13:40:11.6337136+00:00\",\"state\":\"enabled\",\"conditions\":{\"applications\":{\"includeApplications\":[\"All\"],\"excludeApplications\":[],\"includeUserActions\":[],\"includeAuthenticationContextClassReferences\":[],\"applicationFilter\":null},\"users\":{\"includeUsers\":[\"All\"],\"excludeUsers\":[\"id of user (doess not use email, need to cross-reference with entra-id)\"],\"includeGroups\":[],\"excludeGroups\":[],\"includeRoles\":[],\"excludeRoles\":[\"role id\"]},\"userRiskLevels\":[],\"signInRiskLevels\":[],\"clientAppTypes\":[\"all\"],\"servicePrincipalRiskLevels\":[]},\"grantControls\":{\"operator\":\"OR\",\"builtInControls\":[\"mfa\"],\"customAuthenticationFactors\":[],\"termsOfUse\":[]}}"
            }
          ],
          "id": "policy ID",
          "type": "Policy",
          "userPrincipalName": null
        }
      ],
      "category": "Policy",
      "initiatedBy": {
        "app": {
          "servicePrincipalName": "null",
          "displayName": "ADIbizaUX",
          "appId": "aaplication iD",
          "servicePrincipalId": "null"
        },
        "user": {
          "agentType": "notAgentic",
          "homeTenantId": "null",
          "displayName": "Display name of user that made the change",
          "ipAddress": "IP address of the user that made the change",
          "id": "long user ID",
          "userType": "Member",
          "homeTenantName": "null",
          "userPrincipalName": "email of the user that made the change"
        }
      }
    },
    "manager": {
      "name": "test-wazuh-manager-2"
    },
    "log": {
      "file": {
        "path": "/var/ossec/logs/alerts/alerts.json"
      },
      "offset": 250255
    },
    "rule": {
      "firedtimes": 57,
      "mail": false,
      "level": 3,
      "description": "Azure: AD Update conditional access policy",
      "groups": [
        "azure"
      ],
      "id": "87802"
    },
    "decoder": {
      "name": "json"
    },
    "fileset": {
      "name": "alerts"
    },
    "tags": [
      "beats_input_codec_plain_applied"
    ],
    "input": {
      "type": "log"
    },
    "ecs": {
      "version": "1.6.0"
    },
    "service": {
      "type": "wazuh"
    },
    "host": "test-wazuh-manager-2",
    "@version": "1",
    "location": "Azure",
    "id": "1768312267.406583",
    "event": {
      "module": "wazuh",
      "dataset": "wazuh.alerts"
    },
    "fields": {
      "index_prefix": "wazuh-alerts-4.x-"
    },
    "timestamp": "2026-01-13T13:51:07.850+0000"
  },
  "fields": {
    "timestamp": [
      "2026-01-13T13:51:07.850Z"
    ]
  },
  "highlight": {
    "location": [
      "location"
    ]
  },
  "sort": [
    1768312267850
  ]
}
Reply all
Reply to author
Forward
0 new messages