Author: Chad Cox (Microsoft)
Created: January 2023
Updated: June 2023
Disclaimer This Sample Code is provided for the purpose of illustration only and is not intended to be used in a production environment. THIS SAMPLE CODE AND ANY RELATED INFORMATION ARE PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE. We grant You a nonexclusive, royalty-free right to use and modify the Sample Code and to reproduce and distribute the object code form of the Sample Code, provided that You agree: (i) to not use Our name, logo, or trademarks to market Your software product in which the Sample Code is embedded; (ii) to include a valid copyright notice on Your software product in which the Sample Code is embedded; and (iii) to indemnify, hold harmless, and defend Us and Our suppliers from and against any claims or lawsuits, including attorneys` fees, that arise or result from the use or distribution of the Sample Code..
Deploy the query pack that contains all the queries from this solution into the Log Analytics Workspace that contains the Azure AD Audit / Signin logs
Updates to Microsoft Management Endpoints to include Microsoft Admin Portals
Table of content
- Best Practices
- Persona's
- How to run a Log Analytics Query
- Create list of privileged users for the kql designed to search for privileged user impact
- Find IPAddress not defined as trusted
- Applications not being protected by Conditional Access Policies
- Base Protection - Conditional Access Policies
- Identity Protection - Conditional Access Policies
- Data Protection - Conditional Access Policies
- Attack Surface Reduction - Conditional Access Policies
- Minimize the use of location based policies
- Most companies do not have compliance around MacOS or Linux, In the event you do not, focus those policies on Windows. Something is better than nothing.
- Group based policies are great for one off requirements. Most holes exist because groups are poorly maintain and do not include all the accounts. Base policies should be focus'd on all users.
- All Users = All Users
- Internal Users = All Users Exclude Guest
- Privileged Role Members = Directory Roles (Application Administrator,Authentication Administrator,Cloud Application Administrator,Conditional Access Administrator,Exchange Administrator,Global Administrator,Helpdesk Administrator,Hybrid Identity Administrator,Password Administrator,Privileged Authentication Administrator,Privileged Role Administrator,Security Administrator,SharePoint Administrator,User Administrator)
- Directory Sync Account = Directory Role (Directory Sync Account)
- Break Glass Account = Emergency Account that needs to be excluded from all policies
- Accounts Excluded = Usually Service accounts or vault accounts that present an issue because MFA cannot be used.
- Azure Subscription Owners = These are actual owners of Azure Subscriptions.
- If not specified All Cloud Apps is required for the conditional access policies.
Users | Cloud Apps or Actions | Conditions | Grant | Session |
---|---|---|---|---|
Include: All users Exclude: BreakGlass |
User actions: register security information | Require Hybrid Azure AD joined device, Require device to be marked as compliant, Require one of the selected controls |
Prereq: NA
Comment: This conditional access policy will require a user to be on a compliant device in order for them to be able to register MFA settings. This could easily be swapped to require trusted location. More than likely this will require an exclusion to make sure new users have a way to set up mfa for the first time. Only apply this to operating systems that are actually sending compliant status to Intune / Azure AD
Log Analytics Queries (KQL) against AAD Signin Logs
- No query put together yet.
Users | Cloud Apps or Actions | Conditions | Grant | Session |
---|---|---|---|---|
Include: All users Exclude: BreakGlass |
Include: Microsoft Intune enrollment | Require multifactor authentication |
Prereq: NA
Comment: This conditional access policy requires users registering a device to Intune will be prompted for a MFA.
Log Analytics Queries (KQL) against AAD Signin Logs
Users | Cloud Apps or Actions | Conditions | Grant | Session |
---|---|---|---|---|
Include: All users Exclude: BreakGlass |
User actions: Register or join device | Require multifactor authentication |
Prereq: NA
Comment: This condition access policy requires user's to provide mfa when registering devices to Azure AD.
Log Analytics Queries (KQL) against AAD Signin Logs
Users | Cloud Apps or Actions | Conditions | Grant | Session |
---|---|---|---|---|
Include: Guest Exclude: BreakGlass |
Include: All Cloud Apps | Require multifactor authentication |
Prereq: NA
Comment: This conditional access policy requires guest to MFA when accessing resources.
Log Analytics Queries (KQL) against AAD Signin Logs
Users | Cloud Apps or Actions | Conditions | Grant | Session |
---|---|---|---|---|
Include: Role - all administrator roles Exclude: BreakGlass |
Include: All Cloud Apps | Require multifactor authentication |
Prereq: Run the following script to retrieve a list of admin accounts to put into the query. RetrieveAdminsforKQL.ps1
Comment: This conditional access policy requires members of highly privileged roles to provide MFA.
Log Analytics Queries (KQL) against AAD Signin Logs
- Find possible impact if privileged role members are required to MFA
- Using PIM activates find possible impact if privileged role members are require to mfa
- Using Sentinel UEMA Logs find possible impact if privileged role members are required to mfa
Users | Cloud Apps or Actions | Conditions | Grant | Session |
---|---|---|---|---|
Include: Role - privileged roles Exclude: BreakGlass |
Include: All Cloud Apps | Require multifactor authentication stregth / Passwordless MFA or Phishing-resistant MFA |
Prereq: Run the following script to retrieve a list of admin accounts to put into the query. RetrieveAdminsforKQL.ps1
Comment: This conditional access policy requires members of highly privileged roles to provide MFA.
Log Analytics Queries (KQL) against AAD Signin Logs
- Find possible impact if privileged role members are required to MFA
- Using PIM activates find possible impact if privileged role members are require to mfa
- Using Sentinel UEMA Logs find possible impact if privileged role members are required to mfa
Users | Cloud Apps or Actions | Conditions | Grant | Session |
---|---|---|---|---|
Include: All users Exclude: Guest,BreakGlass |
Include: Office 365 | Require Hybrid Azure AD joined device, Require device to be marked as compliant, Require one of the selected controls |
Prereq:
Comment: This conditional access policy requires users accessing office 365 to be using a compliant device.
Log Analytics Queries (KQL) against AAD Signin Logs
Users | Cloud Apps or Actions | Conditions | Grant | Session |
---|---|---|---|---|
Include: All users Exclude: Guest,BreakGlass |
Include: All Cloud Apps | Include: Any location Excluded: All trusted locations |
Require multifactor authentication |
Prereq: Requires all known internet egresses to be defined as a trusted network. Get list of potential trusted ips
Comment: This conditional access policy will require users accessing application from a non trusted location to require MFA.
Log Analytics Queries (KQL) against AAD Signin Logs
Users | Cloud Apps or Actions | Conditions | Grant | Session |
---|---|---|---|---|
Include: Role - privileged roles Exclude: BreakGlass |
Include: All Cloud Apps | Require device to be marked as compliant |
Prereq: Run the following PowerShell script to retrieve a list of admin accounts to put into the query. RetrieveAdminsforKQL.ps1
Comment: This policy will require privileged role members to sign-in from a trusted device. Hopefully they are using a protected admin workstation.
Log Analytics Queries (KQL) against AAD Signin Logs
- Find possible impact if privileged role member is required to use compliant device
- Using PIM activates find possible impact if privileged role member was required to use a compliant device
- Using Sentinel UEBA Logs find possible impact if privileged role member was required to use a compliant device
Users | Cloud Apps or Actions | Conditions | Grant | Session |
---|---|---|---|---|
Include: Subscription Owner Group Exclude: BreakGlass |
Include: All Cloud Apps | Require multifactor authentication |
Prereq: need to get list of all subscription owners put in a group. This PowerShell script can be used to retrieve a list of sub owners. link to script
Comment: Azure Subscription owners should require additional protection. This policy will make sure all azure role owners will be required to MFA.
Log Analytics Queries (KQL) against AAD Signin Logs
- No query put together yet.
Users | Cloud Apps or Actions | Conditions | Grant | Session |
---|---|---|---|---|
Include: All Users Exclude: BreakGlass |
Include: Microsoft Admin Portals, Microsoft Azure Management |
Require multifactor authentication | Sign-in frequency = 8 Hours |
Prereq:
Comment: This conditional access policy makes sure each endpoint that can be used for management is protected by requiring mfa.
Log Analytics Queries (KQL) against AAD Signin Logs
The policies can now be found here Recommended risk based conditional access policies
Users | Cloud Apps or Actions | Conditions | Grant | Session |
---|---|---|---|---|
Include: Guest Exclude: BreakGlass |
Include: All Cloud Apps | Sign-in frequency = 8 Hour |
Prereq:
Comment: This conditional access policy will make sure guest will need to reauthenticate every 8 hours.
Log Analytics Queries (KQL) against AAD Signin Logs
- No query put together yet.
Users | Cloud Apps or Actions | Conditions | Grant | Session |
---|---|---|---|---|
Include: Role - privileged roles Exclude: BreakGlass |
Include: All Cloud Apps | Sign-in frequency = 8 Hour, Persistent browser session = Never persistent |
Prereq:
Comment: This conditional access policy will make sure guest will need to reauthenticate every x hours.
Log Analytics Queries (KQL) against AAD Signin Logs
- No query put together yet.
Users | Cloud Apps or Actions | Conditions | Grant | Session |
---|---|---|---|---|
Include: All Users Exclude: Guest, BreakGlass |
Include: All Cloud Apps | Filter for devices Include: device.isCompliant -ne True -or device.trustType -ne "ServerAD" | Sign-in frequency = 1 Hour |
Prereq:
Comment: This will more than likely affect Linux or Mac users. If Mac is reporting the compliance state then should be Ok to add. Also consider at minimum doing this to devices outside the trusted network. This conditional access policy will require users authenticating from non trusted devices will have to reauthenticate every hour.
Log Analytics Queries (KQL) against AAD Signin Logs
- No query put together yet.
Users | Cloud Apps or Actions | Conditions | Grant | Session |
---|---|---|---|---|
Include: All Users Exclude: Guest, BreakGlass |
Include: All Cloud Apps | Client Apps Include: Browser Filter for devices Include: device.isCompliant -ne True -or device.trustType -ne "ServerAD" |
Persistent browser session = Never persistent |
Prereq:
Comment: This will more than likely affect Linux or Mac users. If Mac is reporting the compliance state then should be Ok to add. Also consider at minimum doing this to devices outside the trusted network. This conditional access policy will make sure that browsers will not stayed signed in.
Log Analytics Queries (KQL) against AAD Signin Logs
Users | Cloud Apps or Actions | Conditions | Grant | Session |
---|---|---|---|---|
Include: Guests Exclude: BreakGlass |
Include: All Cloud Apps | Include: Mobile apps and desktop clients | Block |
Prereq:
Comment: The goal would be to keep guest users from using actual office apps and restrict to browser.
Create a more secure guest sharing environment - Set up web-only access for guests with unmanaged devices
Log Analytics Queries (KQL) against AAD Signin Logs
Users | Cloud Apps or Actions | Conditions | Grant | Session |
---|---|---|---|---|
Include: All Users Exclude: BreakGlass |
Include: All Cloud Apps | Include: Exchange ActiveSync clients,Other clients | Block |
Prereq:
Comment:
Log Analytics Queries (KQL) against AAD Signin Logs
Users | Cloud Apps or Actions | Conditions | Grant | Session |
---|---|---|---|---|
Include: Role - privileged roles Exclude: BreakGlass |
Include: All Cloud Apps | Include: Exchange ActiveSync clients,Other clients | Block |
Prereq:
Comment:
Log Analytics Queries (KQL) against AAD Signin Logs
Users | Cloud Apps or Actions | Conditions | Grant | Session |
---|---|---|---|---|
Include: Role - privileged roles Exclude: BreakGlass |
Include: All Cloud Apps | Include: Linux | Block |
Prereq:
Comment:
Log Analytics Queries (KQL) against AAD Signin Logs
Users | Cloud Apps or Actions | Conditions | Grant | Session |
---|---|---|---|---|
Include: All Users Exclude: BreakGlass |
Include: All Cloud Apps | Include: Tor Nodes | Block |
Prereq: Define all the tor exit nodes and any other set of IP's that need to be blocked. link to Tor IP list
Comment:
Log Analytics Queries (KQL) against AAD Signin Logs
Users | Cloud Apps or Actions | Conditions | Grant | Session |
---|---|---|---|---|
Include: Guest Exclude: BreakGlass |
Include: All Cloud Apps | Include: Unapproved Countries | Block |
Prereq: Country locations should be defined with countries guest users should not be signing in from.
Comment: This Conditional Access Policies are used to block guest from accessing an application from countries for example Russia where Business may not be allowed.
Log Analytics Queries (KQL) against AAD Signin Logs
Users | Cloud Apps or Actions | Conditions | Grant | Session |
---|---|---|---|---|
Include: guest Exclude: BreakGlass |
Include: All Cloud Apps Excluded: Office 365, Other B2B approved apps |
Block |
Prereq:
Comment: This Conditional Access Policy is used to make sure guest (external B2B) are only allowed to access applications they need access to. This examples blocks everything but Office 365 so that teams and sharepoint collaberation can continue to work. Guest should be blocked from things like Microsoft Azure Management, Microsoft Graph PowerShell, Microsoft Graph Explorer, VPNs, and HR Apps.
Log Analytics Queries (KQL) against AAD Signin Logs
- Find possible guest impact by blocking Graph Explorer and MS Graph PowerShell
- Find possible guest impact by blocking Microsoft Azure Management
- Get list of applications guest are successfully logging into
Users | Cloud Apps or Actions | Conditions | Grant | Session |
---|---|---|---|---|
Include: Role - privileged roles Exclude: BreakGlass |
Include: All Cloud Apps | Include: All Networks Exclude: Trusted Countries |
Block |
Prereq: Country locations should be defined with countries privileged roles members are located.
Comment: This Conditional Access Policy is to force the privileged roles to only allow signing in from countries where these users are located in. The goal is to prevent a global admin account from logging in from a country for example Russia where there are more than likely no administrators located.
Log Analytics Queries (KQL) against AAD Signin Logs
Users | Cloud Apps or Actions | Conditions | Grant | Session |
---|---|---|---|---|
Include: Role - directory sync account Exclude: BreakGlass |
Include: All Cloud Apps | Include: All Networks Exclude: Trusted Networks |
Block |
Prereq: Trusted Locations (IP Ranges) should be defined.
Comment: This Conditional Access Policy is used to make sure if the credentials for the directory sync account are stolen that they cannot be accessed outside of the trusted network.
Log Analytics Queries (KQL) against AAD Signin Logs
Users | Cloud Apps or Actions | Conditions | Grant | Session |
---|---|---|---|---|
Include: (Group of excluded users) Exclude: BreakGlass |
Include: All Cloud Apps | Include: All Networks Exclude: Trusted Networks |
Block |
Prereq: Trusted Locations (IP Ranges) should be defined.
Comment: This Conditional Access Policy is used to make sure accounts excluded from requiring MFA should be required to authenticate from trusted locations. Link below contains the script that can be used to scan all the conditional access policy exclusions and return a list of accounts that should be in this list. Do not include the breakglass account.
- Require TOU for Guest
- In the Azure AD Portal
- Navigate to the Log Analytics Tab
- Copy the example code from the section you want to review the possible impact
- Replace the existing text in the query window or open a new query tab and paste in the new one.
- Then select Run and wait for the results.
Or Deploy the query pack that contains all the queries from this solution into the Log Analytics Workspace that contains the Azure AD Audit / Signin logs
- After the query pack is deployed
- In the Azure AD Portal
- Navigate to the Log Analytics Tab
- Select the Queries and change the group by to Label
- Run this in PowerShell
Connect-MgGraph
Select-MgProfile -Name beta
$roles = @("Application Administrator","Authentication Administrator","Cloud Application Administrator","Conditional Access Administrator","Exchange Administrator","Global Administrator","Helpdesk Administrator","Hybrid Identity Administrator","Password Administrator","Privileged Authentication Administrator","Privileged Role Administrator","Security Administrator","SharePoint Administrator","User Administrator")
(Get-MgDirectoryRole -ExpandProperty members -all | where {$_.displayname -In $roles} | select -ExpandProperty members).id -join('","') | out-file .\privuser.txt
- The results of this will be in a file called privuser.txt
- Open the txt file. Should look something like this
8f47d5a6-a36b-4d99-b6bc-c023cf23ae9b","8f47d5a6-a36b-4d99-b6bc-c023cf23ae9b","8f47d5a6-a36b-4d99-b6bc-c023cf23ae9b","8f47d5a6-a36b-4d99-b6bc-c023cf23ae9b","8f47d5a6-a36b-4d99-b6bc-c023cf23ae9b","8f47d5a6-a36b-4d99-b6bc-c023cf23ae9b
- Next in the sections titled Log Analytics AAD SigninLogs Query (KQL) needs results from the PowerShell script from the section you are reviewing. Will want to copy the kql statement, and paste in Log Analytics.
- on line 1 replace the phrase replace this with the results from the privuser.txt found from the powershell cmdlets
let privusers = pack_array("**replace this with the results from the privuser.txt found from the powershell cmdlets**");
- to look like
let privusers = pack_array("8f47d5a6-a36b-4d99-b6bc-c023cf23ae9b","8f47d5a6-a36b-4d99-b6bc-c023cf23ae9b","8f47d5a6-a36b-4d99-b6bc-c023cf23ae9b","8f47d5a6-a36b-4d99-b6bc-c023cf23ae9b","8f47d5a6-a36b-4d99-b6bc-c023cf23ae9b","8f47d5a6-a36b-4d99-b6bc-c023cf23ae9b");
Log Analytics AAD SigninLogs Query (KQL)
SigninLogs
| where TimeGenerated > ago(30d)
| where ResultType == "0"
| where HomeTenantId == ResourceTenantId
| where NetworkLocationDetails !contains "trustedNamedLocation"
| extend TrustedLocation = tostring(iff(NetworkLocationDetails contains 'trustedNamedLocation', 'trustedNamedLocation',''))
| extend isIPv6 = tostring(iff(IPAddress matches regex @"(([\d|\w]{1,4}\:){7}[\d|\w]{1,4})",'Yes','No'))
| distinct IPAddress, TrustedLocation, UserPrincipalName, isIPv6
| summarize uniqueusercountbyip = count() by IPAddress, TrustedLocation, isIPv6
| where uniqueusercountbyip >= 4
| sort by uniqueusercountbyip desc
Comment
This query returns IP addresses where 4 or more unique users have authenticated against Azure AD. You will want to research each IP and determine if they are owned by the organization or if they belong to something like a public proxy cloud solution like zscaler or umbrella. Legit ones will need to be defined as a trusted network in Azure AD to make sure any location filtered policy works correctly and to help remediate false positives in Azure Identity Protection
Instructions on how to create named locations can be viewed here Named locations
The field uniqueusercountbyip is count of unique list of users. It is possible to see ipv6 addresses which usually comes from Azure Networks and will be normal in the near future from the internet.
Log Analytics AAD SigninLogs Query (KQL)
//https://github.com/reprise99/Sentinel-Queries/blob/main/Azure%20Active%20Directory/Identity-Top20AppswithnoCA.kql
//This query shows applications that are not protected by conditional access policies.
let apps=
SigninLogs
| where TimeGenerated > ago (30d)
| project TimeGenerated, ConditionalAccessPolicies, AppDisplayName
//Exclude native Microsoft apps that you can't enforce policy on or that are covered natively in Office 365
| where AppDisplayName !in ("Microsoft Office Web Apps Service", "Microsoft App Access Panel", "Office Online Core SSO", "Microsoft Authentication Broker", "Microsoft Account Controls V2", "Microsoft 365 Support Service","Office Online Maker SSO","My Apps","My Profile")
| mv-expand ConditionalAccessPolicies
| extend CAResult = tostring(ConditionalAccessPolicies.result)
| summarize ResultSet=make_set(CAResult) by AppDisplayName
| where ResultSet !has "success" or ResultSet !has "failure"
| project AppDisplayName;
SigninLogs
| where TimeGenerated > ago(30d)
| where ResultType == 0
| where AppDisplayName in (apps)
| summarize Count=count()by AppDisplayName
| top 20 by Count
Comment
The image below, shows the applications and the logon count of those apps that is not being protected by some sort of Conditional Access Policy. Ideally every application will have a mfa requirement or a trusted/compliant policy requirement.
-
CISA - Microsoft Azure Active Directory M365 Minimum Viable Secure Configuration Baseline
-
DEV-0537 criminal actor targeting organizations for data exfiltration and destruction
-
Advice for incident responders on recovery from systemic identity compromises
-
Token tactics: How to prevent, detect, and respond to cloud token theft
-
Understanding "Solorigate"'s Identity IOCs - for Identity Vendors and their customers.
-
Security roadmap - Top priorities for the first 30 days, 90 days, and beyond
-
Configure Conditional Access in Microsoft Defender for Endpoint
-
Recommended Microsoft Defender for Cloud Apps policies for SaaS apps
-
Policy recommendations for securing SharePoint sites and files
-
Policy recommendations for securing Teams chats, groups, and files
-
Enable Azure multifactor authentication for Azure Virtual Desktop
-
excludes "Azure Windows VM Sign-In" for Windows virtual machine in Azure
-
Recommendations for conditional access and multi-factor authentication in Microsoft Flow