Azure AD/Active Directory User Security Evaluation Reporter

During December 2018 – February 2019 Microsoft have run an online Microsoft Graph Security Hackathon on Devpost.

The criteria of the hackathon was;

  • Build or update a functioning Microsoft Graph-powered solution that leverages the Microsoft Graph Security API

Following the announcement of the Hackathon I was encouraged by Kloud management to enter. During the busy month of December I started to formulate a concept for entry in the Hackathon taking learnings from the hackathon I entered in 2018. Over the Xmas holiday period I started working on my entry which continued into January and February at nights and weekends.

Problem

A Security Administrator within an Organisation enables security related configuration options on an Azure Tenant to implement security controls that align an organisation with Microsoft recommendations and best practice.

The Azure Security Score provides an evaluation on the alignment of an organisation with best practice, however to some extent it still requires end users to have the right configuration for security related elements of their profile. But as a Service Desk Operator or Cyber Security Officer there isn’t a single view of a user’s security posture that can give you an individual user security score summary. My solution……

Microsoft User Security Evaluation Reporter (USER)

Microsoft User Security Evaluation Reporter (USER) is an Azure AD and Active Directory tool for use by the Service Desk and Cyber Security Officers to get instant visibility of an organisations Azure Security Score that allows them to then evaluate current risks within an organisation right down to individual users.

When the Microsoft USER loads the current Azure Security Score is retrieved, evaluated and displayed for alignment with Microsoft Recommendations. Also, on load the last 5 Active Security Risk Events are displayed.

Microsoft USER Recent Risk Events and Azure Secure Score.PNG

The Service Desk Operator or Cyber Security Officer can select one of the recent Security Events or search for a user and drill down into the associated identity. They will be quickly able to understand the users’ individual security posture aligned with best practice.

What are the recent Security Risk Events for that user? Does that user;

  • Have MFA enabled? Is MFA enabled with an Authenticator App as the primary method?
  • Is the users Active Directory password in the Pwned Passwords v4 list from Have I Been Pwned?
  • Has the user recently being attempting Azure Password Reset functions?
  • What are the last 10 logins for that user?
  • What is the base user information for that user and what devices are registered to that user? Are they Azure AD Joined?

User Secure Score Summary.PNG

The clip below gives a walk through with more detail of my Microsoft USER tool.

How I built it

The solution is built using;

  • NodeJS and Javascript
  • leveraging Azure Functions to interface with Azure AD, Microsoft Graph, Azure Table Service
  • Lithnet Password Protection for Active Directory that in turn leverages the Have I Been Pwned v4 dataset
  • All secrets are stored in Azure Key Vault.
  • The WebApp is Application Insights enabled.
  • The WebApp is deployed using a Docker Container into Azure App Service

The architecture is shown below.

MS User Security Evaluation Reporter Architecture

The Code

A Repo with the code can be found here. Keep in mind I’m not a developer and this is my first WebApp that was put together late at night and over weekends and only tested in Chrome and Edge. The Readme also contains hopefully everything you should need to deploy it.

 

Azure Self Service Password Reset Reporting using PowerShell

Just over 18 months ago I wrote this post on using PowerShell and oAuth to access the Azure AD Reports API to retrieve MIM Hybrid Report data.  This week I went to re-use that for Azure Password Reset Reporting and found out that the API had been deprecated.

API Deprecated.PNG

Using the error information that actually was informative I proceeded to the new API. Having authenticated as I had in the previous article, I executed the following to retrieve a list of the Audit Reports available.

$TenantDomain = "customer.com.au"
$url = 'https://graph.windows.net/' + $tenantdomain + "/activities/auditActivityTypes?api-version=beta"
# Returns a JSON document for the Audit Activity Types
$auditActivities= (Invoke-WebRequest-Headers $headerParams-Uri $url).Content |ConvertFrom-Json
$auditActivities.activityTypes

Before I go any further it’s a good time to mention you can easily access the Audit log events using the Azure Portal and retrieve the data you maybe looking for and download a report. There is also the Azure Audit logs content pack for PowerBI as detailed here. Those are awesome solutions, but if you want to do something a little more bespoke and programmatic then keep reading.

Azure AD Password Events Audit Log Data

For the record (as at 18 Dec 2018) there are 1023 different Activity Resource Types. The full list is available here. The ones I’m interested in right now though are a subset of the Self-service Password Management category;

SSPR Audit Reports
SSPR Audit Reports
After investigation, the API to get the information I was after is now available on the Microsoft Graph Beta Audit Logs endpoint auditLogs/directoryAudits
https://graph.microsoft.com/beta/auditLogs/directoryAudits 

My Azure AD Registered App needed to be updated to have the additional role (AuditLog.Read.All) which was done via the Registered Applications blade under Azure Active Directory in the Azure Portal;

AuditLog.Read.All

My script then needed to be updated to talk to the Microsoft Graph and the new scope;

$resource = "https://graph.microsoft.com"
$scope = "AuditLog.Read.All; Directory.Read.All"

So to get Azure Password Reset events for the last week the following calls can be made;

# Get Reset Password Events
$DirectoryAuditURL = "https://graph.microsoft.com/beta/auditLogs/directoryAudits"
$passwordMgmtAuditData = Invoke-RestMethod -Method Get -Uri "$($DirectoryAuditURL)?`$filter=category eq `'UserManagement`' and activityDateTime ge 2018-12-11T03:15:10.6837342Z and startswith(activityDisplayName%2C+`'Reset password`')" -Headers @{Authorization = "Bearer $($Global:accesstoken)"}

To retrieve the other events contained in the auditLog we just need to alter the event to retrieve events for and the timeframe of interest. The events from the table above associated with Azure Self Service Password Reset and Azure Change Password are;

Blocked from self-service password reset
Change password (self-service)
Credentials Registered and Password Reset Status of User
Reset password (by admin)
Reset password (self-service)
Security info saved for self-service password reset
Self-serve password reset flow activity progress
Self-service password reset flow activity progress
Unlock user account (self-service)
User completed security info registration for self-service password reset
User registered for self-service password reset
User started security info registration for self-service password reset

The Script

Here is the modified script from my previous post here that uses oAuth to retrieve Azure Password Reset events. As per the other script it enables the scopes required. If you’re not Global Admin get the script run initially by someone who has the Global Admin role or get them to assign the AuditLog.Read.All permission to the Azure AD Application you have created. You can then login and get an Access Token and a Refresh Token.

Update;

  • Line 5 for your Application ClientID
  • Line 6 for your Application Secret
  • Line 18 for where you want to store the Refresh Token
  • Line 97 can be un-remarked after getting a token to use the Refresh Token (and Line 96 commented out). To get a new Access Token using the stored Refresh Token (Line 18) call the Get-NewTokens function

If, due to your time filter you have more than the maximum (1000 events) that can be returned per call, you can use the skiptoken to get the next page. If you have more than 2000 use the subsequent skipToken in additional calls in a do { get data } while ($skipToken) loop with the addition of adding the returned data to a collection.

$skipToken = $passwordMgmtAuditData.'@odata.nextLink'
$results = Invoke-RestMethod -Method Get -Uri $skipToken -Headers @{Authorization = "Bearer $($Global:accesstoken)"}

If you want to automate the time period to retrieve events for then you can use the Get-Date function and set the time window.

# Date Time for the report. Last 14 Days
[string]$strDateTimeNow = Get-Date -Format yyyy-MM-ddThh:mm:ss
[datetime]$dateTimeNow = Get-Date -Format yyyy-MM-ddThh:mm:ss
[datetime]$minus14Days = $dateTimeNow.AddDays(-14)
[string]$14daysAgo = get-date($minus14Days) -Format yyyy-MM-ddThh:mm:ss

so then the call for the last 14 days of events would be

$passwordMgmtAuditData = Invoke-RestMethod -Method Get -Uri "$($DirectoryAuditURL)?`$filter=category eq `'UserManagement`' and activityDateTime ge $($14daysAgo)z and activityDateTime le $($strDateTimeNow)z and startswith(activityDisplayName%2C+`'Reset password`')" -Headers @{Authorization = "Bearer $($Global:accesstoken)"}

Summary

Using the Microsoft Graph auditLog API we can retrieve using PowerShell events of interest for reporting or other requirements.