Reviewing Windows 10 Audit Policy Settings

I have spoken about things like Attack Surface Reduction (ASR) for Windows 10 and how easy they are to implement to improve the security of Windows 10:

Attack surface reduction for Windows 10

Another very important aspect of securing Windows 10 environments is to ensure that the audit policy settings are appropriate to capture the right information to help with any investigation. To that end, I have a free scripts available at:

which will show you the current audit policy settings in your environment like so:


As you can see from the above screen gab, many audit settings are not enabled out of the box. Please note, you’ll need to run the script as an administrator for it be able to report the audit policy settings.

You’ll find the best practice recommendations for audit policy settings from Microsoft:

Audit Policy Recommendations

and government departments like the Australian Cyber Security Center:

Hardening Microsoft Windows 10 version 1909 Workstations

Look for the section heading – Audit Event management in the above page.

As always, there are number of different ways to enable these best practice audit policy settings on your Windows 10 devices. To my mind using Microsoft Endpoint Manager that comes with offerings like Microsoft 365 Business Premium is the easiest.


And the quickest way to do this inside Microsoft Endpoint Manager is simply to apply the Windows 10 Security Baseline policies as shown above. To read more about this capability visit:

Use security baselines to configure Windows 10 devices in Intune

In fact, the results from my script are based on the settings found in the Windows 10 Security Baseline policy.

To read more about these security audit policies for Windows 10 I encourage you to take a look at:

Advanced security audit policy settings

and remember, you can configure these settings at the command line if you need to using the:


command, which is exactly what I used in my script to extract the current settings. However, deploying them using Microsoft Manager for Endpoint and baseline policies is going to be far easier across a fleet of devices.

Issues creating Endpoint Security Policies using the Microsoft Graph

I swear it was all working and now BOOM, it doesn’t! Using PowerShell I had been creating Endpoint Security policies but now those same policies were still being created but WITHOUT the configuration settings I had configured.

You can try this for yourself if you wish, without needing to code. Firstly visit the Microsoft Graph Explorer and authenticate.


Change the method to POST, set the API to beta and use the URL =

Then in the Request body use the following:

If you do you’ll find a new Endpoint Security Attack Surface Reduction – ASR rule has been created like so:


If you look at settings for this policy you’ll see:


all the settings are Not configured!

So, no errors during the POST but no settings! Strange.


If however you return to the Request body and change the word value to settingDelta as shown above and then run the same query.


Now, the Endpoint Security policy is created and the settings are configured.

So in summary, don’t use value any more it seems with the request body, use settingsDelta.

PowerShell with Azure Conditional Access

Recently, I did a video demonstrating how PowerShell can be used to automate Endpoint Management:

PowerShell with Endpoint Manager

I’ve now also created a video demonstrating how to automate Azure Conditional Access using PowerShell. As before, I am only making these scripts available via the CIAOPS Paton program.

In this video you’ll see me automatically backup up both Conditional Access locations and policies, then apply best practices locations and policies, finally restore the original policies, all using scripting.

Again, these scripts are not free and part of the CIAOPS Paton program. You’ll find my free stuff at

Use PowerShell with Azure Sentinel

Yes Virginia, it is now possible to use PowerShell with Azure Sentinel. Microsoft has made available the Az.Security insights module that allows you to work with Azure Sentinel. You’ll find the module here:

and you install it in your elevated PowerShell environment via the command:

Install-Module -Name Az.SecurityInsights –AllowClobber

To use the module commands you’ll also need to login to Azure. You can do that by using my connection scripts which are  here:

An easier way to connect using PowerShell

However, what I’ve done to make it even easier for you by creating a complete script here:

You run the script in your environment like so:


You’ll then be prompted to login to your Azure tenant like so:


You’ll then be prompted to select your Azure subscription where Sentinel is configured:


You should see a list of all the subscriptions in your tenant as shown above. Select the one where Azure Sentinel is configured and select OK to continue.


You’ll then be prompted to select which workspace Azure Sentinel is configured with. Again, just select the appropriate workspace and then OK to continue.


The script will now display  a list of all the available Rule Templates in Sentinel as shown above, sorted by most recently added (handy to see what’s new!).


This list is what you see in the Azure Sentinel portal when you select Analytics, then Rule templates as shown above. In effect, this is every analytics rule Sentinel makes available to you.


The next part of the script output will show you every rule in use.


This corresponds with the Active rules area in the web portal as shown above.


The next section of the script output will show you all the available rules and whether they are in use or Active as shown above.


You’ll see something similar if you return to the Rule templates, and note the rules “IN USE”, as shown above.


If you have a close look here, you’ll see rules that have no display name. I’ll cover that a bit further on, as it is still a bit of a mystery to me at this stage.


The last listing in script will show you all the rules that are NOT in use in date order. This is handy as I don’t see anything like this in the web portal.


Finally, the script will give you a summary as shown above.

It is interesting to note that 11 scripts report errors? These seem to be the ones with no names? Still haven’t quite worked that one out yet. You might also see this mismatch in the rules in use as I have above. I need to dig into this a little more. Also a bit strange is the fact that I have 191 scripts reporting in total but if I add the 104 templates in use with the 112 not in use I come to a total of 216! If I then look in the web interface I see:


only 182 templates in total??

This new Azure Sentinel module is only a month old as of writing this article, so early days. Hopefully, these items are minor bugs that will get fixed soon. You can also double check my code to ensure I haven’t something silly. If I have, let me know so I can fix it and share.

However, that considered, I can see this new Azure Sentinel PowerShell module being pretty handy if I’m honest. This script allows me to see when Microsoft adds new rules that I need to go and configure for one. I’ll be spending more time with this PowerShell module to automate how I deploy Azure Sentinel, which I reckon will save me a bucket-load of time.

Looking forward to future updates to this module, but there is no reason you can’t start automating Azure Sentinel yourself today!


PowerShell with Endpoint Manager

Here is video demonstrating what I’ve been working of late. I am only making these scripts available via the CIAOPS Paton program.

The video will show you how I both create and erase policies via script, as well as generate a set of best practice policies and alternatively, importing them from previously saved policies. This saves a huge amount of time when compared creating and assigning policies manually.

Again, these scripts are not free and part of the CIAOPS Paton program. You’ll find my free stuff at

Removing Azure Enterprise app consented permissions


After installing the appropriate PowerShell modules you can connect to  the Microsoft Graph with PowerShell using the command:


as shown above. First thing to remember is that this process can’t be completed in the Power ISE, you’ll need to do it elsewhere (here, using Windows terminal). The second thing to note is that you can specific the scope with which you to connect. Thus, in this case, the scope will be Files.ReadWrite.All and Sites.Readwrite.all. The scope is in effect the permissions the current user will be given when they connect to the Microsoft Graph. This allows you to only provide permissions for exactly what you need.


During the connection process you’ll be asked to consent to the permissions just requested, as shown above. If you simply select Accept here, you are just consenting for the current user. However, if you check the Consent in behalf of your organization option you’ll be providing these permissions to ALL users in your tenant! For now, only consent will be granted for the current user. However, be very, very careful consenting for the whole organization as I will illustrate.

You can now happily go off and perform whatever actions you need to using PowerShell for the Microsoft Graph.


With security in mind, I went to have a look at where these permissions just consented to actually appear. You’ll find them by opening the Azure Portal and navigating to Azure Active Directory as shown above. From here, select Enterprise applications from the menu on the left.


From the screen that appears ensure All applications is select from the menu on the left. Then on the right, locate and select Microsoft Graph PowerShell as shown.


From the screen that now appears, select Permissions from the menu on the left as shown. On the right you’ll then be able to select either Admin consent or User consent.

Because the permissions assigned were only for a single user, the User consent item will show these to us as shown above. This list of permissions matches those consented to when connecting to the Microsoft Graph.

The right hand most column in this display, Grant by, has a hyperlink to show the number of users with this assigned permission.


If you select any of these hyperlinks, you’ll see a list of users, on the right, that have been assigned this permission appear on the right as shown above.

Can you see the problem yet? No? Well…….how do you REMOVE or revoke a permission here?


From what I can determine, you can’t remove the permissions via the portal. If you select Review permissions menu option you’ll see a item displayed from the right as shown above. If you select the option This application has more permissions that I want and basically told to use PowerShell to revoke all permissions for this application as well as being provided with the code to do so.

The issue is that even after you disconnect from the Microsoft Graph, having completed any scripting, those consented permissions remain in place i.e. they are NOT rescinded. This means that if the user account with these permissions to the Graph is compromised then that attacker has access to the Microsoft Graph and potentially lots of sensitive areas in a tenant, especially if the permissions have been added to over time. Imagine how much WORSE it gets if permissions were consented tenant wide, rather than to an individual user?


Selecting that little check box in the above Permissions requested dialog, which I see MANY people do without thinking, can really give you a security headache by opening up your Microsoft Graph permissions for EVERY user in the tenant!

Thus, best security practice is going to be to remove these permissions when they are no longer required as well as limiting who has them initially. Personally, I’d remove them after each interaction so I don’t forget and leave a potential attack vector.

To make doing all that a little easier, I have gone out and created a script that you’ll find in my Github repo:


If you run the script, it will first check whether the Azure AD PowerShell module is loaded. If it is, it will then ask you to login to your tenant. Then it will display a list of all the Azure AD applications in your tenant and allow you to select the ones you want to change (yes, you can select multiple Azure AD apps if you want) as shown above.

In this case, Microsoft Graph PowerShell application is selected.


You’ll then be prompted to select whether you wish to select Admin consent and/or User Consent permissions. You can select both here if you wish by using the CTRL and/or SHIFT key when making selections (i.e. just like when you use Windows Explorer).


If you selected User consent, you’ll then be prompted to select the users you want. Again, multiple selections are available if offered.


You’ll now be prompted to confirm you wish to delete these permissions for these users.


Those permissions will be removed and the script will continue to work through the rest of your selections.

In this case, because there were no Admin consented permissions for this application we receive a notification line as shown in above output.


If you now return and have a look at the permissions for that app in the portal, you should see they have all been removed as shown above.

Leaving users with standing permissions to something as powerful as the Microsoft Graph is not best security practice. It is therefore important to regularly review these and remove what is not required. If you need those permissions again in eth future, after they have been removed, you can always re-consent to them when you next connect to the Microsoft Graph.

Frustrations of using the Microsoft Graph with PowerShell

I’ve spent the past few day wrestling with the using Microsoft Graph with PowerShell, and it hasn’t been fun. Let me explain.


The first issue is that you can’t use the connect-graph command in the PowerShell ISE in Windows 10. if you do, you just get a flashing cursor as shown above that eventually times out.


If you repeat the same process in wither Windows terminal (above) or the PowerShell command you are taken through the standard device login browser process as expected.


After that, if you return to the ISE (above) and repeat the command connect-graph, you receive a message telling you that you are connected by virtue of the token from the previous Windows Terminal session.


If you run the preferred Graph command get-mguser (above) you see that the AssignedLicenses and AssignedPlans attributes are blank.


If you now run my script:

You also get connected to the Microsoft Graph as I highlighted here, but specifically to the Intune portion of the Graph:

New Intune connection PowerShell script

Typically, this type of connection is also designed for device management with PowerShell and work very well. However, because device management also requires access to users, we can also get access to user data via the Graph.


You achieve this by running the following script after connecting to Intune Graph:

$uri = “”
$users = (Invoke-MSGraphRequest -Url $uri -HttpMethod GET).Value

which you see above gives you similar to the user options before but with far more detail as demonstrated by the assignedLicenses and assignedPlans highlighted previously highlight above.


Just to prove there is no smoke and mirrors here, above the output of the command get-mguser used after the connect-graph command (i.e. the non-Intune connection method).

Clearly, the data is in the Graph, but the command get-mguser does not yet seem to support pulling all this down from what I see. I hope someone can point out the error of my ways here but to create the reporting and automation I REALLY want looks like I’m to either have to use the PowerShell Intune module or revert to using the full web based invoke-request to get what I’m after.


What kind of worries me a little is that Intune PowerShell project seen above and at:

that works REALLY well, hasn’t seen any updates in 2 years! There are 57 outstanding issues at the time of writing this blog, including two from me because not all the native wrapper commands work as expected. Are they being attended to at all I wonder?

In summary then, I’m in somewhat of quandary about using PowerShell with the Microsoft Graph. Specific stuff like the Intune SDK works well using the invoke-msgraphrequest command. It is easy to setup and manage the permissions for. On the other hand, the more general Graph commands like get-mguser don’t as yet seem to return as much information as they could. As well as the Intune SDK works I’m kind of afraid that it will not see future development.

So where should I invest my time to continue automating Microsoft 365 administration? Suggestion anyone?