Microsoft Defender for Identity Auditing

Microsoft Defender for Identity Auditing

Microsoft Defender for Identity monitors your domain controllers by capturing and parsing network traffic and leveraging Windows events directly from your domain controllers. Auditing needs to be enabled for the Windows events to appear in the event viewer. Unfortunately, auditing is not on by default. Microsoft created a great docs page on configuring Windows event collection, but it is “a lot” of manual work, so I decided to make life a bit easier. I created an export of the policies needed for Microsoft Defender for Identity to enhance detection using the Windows events for others to import using a single command.

Configuration

Microsoft docs describe five configurations. Ideally, all configurations need to be done for Microsoft Defender for Identity to enable enhanced detection. These are the five configuration settings.

  1. Configure Audit Policies
  2. Event ID 8004 (NTLM)
  3. Event ID 1644 (Active Directory Web Service)
  4. Configure Object Auditing
  5. Auditing for Specific Detections (AD FS and Exchange)

For the first three configuration settings, I created a backup of a GPO, which you can import using a single command.

  1. Download the files by clicking the green “Code” button on top of the repository, followed by “Download ZIP.”
  2. Unpack the files to a location you remember.
  3. Run the PowerShell command shown below.

Import-Gpo -BackupGpoName "Microsoft Defender for Identity Auditing" -TargetName "Microsoft Defender for Identity Auditing" -Path C:\UnpackedFiles -CreateIfNeeded

The command imports the GPO but does not link it to any Organisation Unit. To link the GPO to the Domain Controller OU, use the following command.

New-GPLink -Name "Microsoft Defender for Identity Auditing" -Target "OU=Domain Controllers, DC=domain, DC=local"

Note: While the resource limitation feature can stop the Defender for Identity service if the server runs out of resources, it does not stop the event auditing at the operating system level. Therefore, ensure your servers have sufficient memory, CPU, and disk resources to avoid performance issues.

Configure Object Auditing

For the forth configuration setting, the following script enables auditing on all users, groups, and computers in the Active Directory domain.

$Path = (Get-ADRootDSE).defaultNamingContext
$ACL = Get-Acl "AD:\$Path" -audit
$inheritedobjectguid = new-object Guid bf967aba-0de6-11d0-a285-00aa003049e2
$identity = [Security.Principal.NTAccount]'everyone'
$inheritanceType = [System.DirectoryServices.ActiveDirectorySecurityInheritance]"Descendents"
$ace = new-object System.DirectoryServices.ActiveDirectoryAuditRule($identity, 'CreateChild, DeleteChild, Self, WriteProperty, DeleteTree, ExtendedRight, Delete, WriteDacl, WriteOwner', "success", [guid]'00000000-0000-0000-0000-000000000000', $inheritanceType, $inheritedobjectguid)
$acl.AddAuditRule($ace)
Set-ACL -Path "AD:\$Path" -AclObject $ACL

$inheritedobjectguid = new-object Guid bf967a86-0de6-11d0-a285-00aa003049e2
$ace = new-object System.DirectoryServices.ActiveDirectoryAuditRule($identity, 'CreateChild, DeleteChild, Self, WriteProperty, DeleteTree, ExtendedRight, Delete, WriteDacl, WriteOwner', "success", [guid]'00000000-0000-0000-0000-000000000000', $inheritanceType, $inheritedobjectguid)
$acl.AddAuditRule($ace)
Set-ACL -Path "AD:\$Path" -AclObject $ACL

$inheritedobjectguid = new-object Guid bf967a9c-0de6-11d0-a285-00aa003049e2
$ace = new-object System.DirectoryServices.ActiveDirectoryAuditRule($identity, 'CreateChild, DeleteChild, Self, WriteProperty, DeleteTree, ExtendedRight, Delete, WriteDacl, WriteOwner', "success", [guid]'00000000-0000-0000-0000-000000000000', $inheritanceType, $inheritedobjectguid)
$acl.AddAuditRule($ace)
Set-ACL -Path "AD:\$Path" -AclObject $ACL

Auditing for Specific Detections

Some detections require auditing specific Active Directory objects. For the fifth configuration setting, one detection is for AD FS and requires auditing on an AD FS object, and the other is for Exchange which requires auditing on the configuration container.

To enable auditing for AD FS detections, use this script.

$Path = (Get-ADRootDSE).defaultNamingContext
$ACL = Get-Acl "AD:\CN=ADFS,CN=Microsoft,CN=Program Data,$Path" -audit
$inheritedobjectguid = new-object Guid 00000000-0000-0000-0000-000000000000
$identity = [Security.Principal.NTAccount]'everyone'
$inheritanceType = [System.DirectoryServices.ActiveDirectorySecurityInheritance]"All"
$ace = new-object System.DirectoryServices.ActiveDirectoryAuditRule($identity, 'ReadProperty, WriteProperty', "Success, Failure", [guid]'00000000-0000-0000-0000-000000000000', $inheritanceType, $inheritedobjectguid)
$acl.AddAuditRule($ace)
Set-ACL -Path "AD:\CN=ADFS,CN=Microsoft,CN=Program Data,$Path" -AclObject $ACL

To enable auditing for Exchange detection, use this script.

$Path = (Get-ADRootDSE).defaultNamingContext
$ACL = Get-Acl "AD:\CN=Configuration,$Path" -audit
$inheritedobjectguid = new-object Guid 00000000-0000-0000-0000-000000000000
$identity = [Security.Principal.NTAccount]'everyone'
$inheritanceType = [System.DirectoryServices.ActiveDirectorySecurityInheritance]"All"
$ace = new-object System.DirectoryServices.ActiveDirectoryAuditRule($identity, 'WriteProperty', "Success, Failure", [guid]'00000000-0000-0000-0000-000000000000', $inheritanceType, $inheritedobjectguid)
$acl.AddAuditRule($ace)
Set-ACL -Path "AD:\CN=Configuration,$Path" -AclObject $ACL

Conclusion

Many organizations go through a digital transformation to the cloud. As attackers use the on-premises environment as a stepping-stone to the cloud, as long as you have an on-premises environment, please use Microsoft Defender for Identity to protect your organization. Since Microsoft Defender for Identity leverages on Windows events, always enable auditing to be sure Microsoft Defender for Identity detects all attacks.

Microsoft Workload Identities Leaked Credentials

Microsoft Workload Identities Leaked Credentials

Microsoft announced four new detections in Azure Active Directory Identity Protection last month. One of the four detections is “Workload Identities Leaked Credentials.” During a Microsoft webinar where I demonstrated this new feature in Microsoft Identity Protection, multiple people requested the tool I created, so I decided to release it.

This blog post will briefly explain the new Workload Identities Leaked Credentials detection and link to a tool I created to scan GitHub repositories for leaked credentials, specifically AadSecrets using the GitHub API requested by some people during a webinar.

Workload Identities Leaked Credentials

Azure Active Directory Identity Protection is a risk-based feature to protect identities in the cloud based on many indicators (atypical travel, malware-linked IP address, and many more). Conditional Access uses these detections to prevent an identity from accessing cloud services based on risk classifications. Using Azure Active Directory Identity Protection makes it possible to mitigate an attack within seconds due to an automated response.

Image 1: Conditional Access Workload Identities

Note: Conditional Access policies, at their simplest, are if-then statements. If a user wants to access a resource, they must complete an action. An action is forcing the user to use Multi-Factor Authentication or forced to change their password.

The new feature in Azure Active Directory Identity Protection now supports the detection of leaked credentials for workload identities. A workload identity is an identity used to authenticate and access other services and resources. Think of a Service Principal created when you create an Enterprise Application.

Image 2: Identity Protection Workload Identities

Microsoft scans GitHub, Pastebin, etc., for leaked credentials, and if there is a match with your environment, by comparing the hash of the password, it will trigger an alert and mitigate the risk.

Leaked credentials are a common mistake made by many administrators. GitHub already supported the “Leaked Credentials” feature, but no comparison in any environment occurs. Still, with Azure Active Directory Identity Protection, the hash is compared with the hash in Azure Active Directory to see if there is a match. Suppose there is a match, an alert triggers.

Microsoft GitHub Scanner

For demonstration purposes, I created a tool to scan for leaked credentials on GitHub. The tool uses the GitHub API to get all files in the repository and scans for AadSecrets. As I created it for demonstration purposes only, it is not perfect. PowerShell could be an option, but I decided to use C# core for fun.

The tool is simple. I use an API to list all files in a repository and re-write the URL to get the raw contents. Then I scan for AadSecret in the raw contents for leaked credentials. I do not have to download any repository as some tools do to make it simple, fast, and accessible.

Image 3: Microsoft GitHub Scanner

Conclusion

In my opinion, Azure Active Directory Identity Protection is a must to protect identities in any corporate environment. The combination of Azure Identity Protection and Conditional Access drastically lowers the risk of a compromised identity. Now that workload identities are also protected makes it even more powerful.

Microsoft Defender for Office 365 Safe Links Bypass

Microsoft Defender for Office 365 Safe Links Bypass

In my previous blog post, I mentioned you need a URL shortener instead of the Azure Function URL to send to a mailbox to identify Microsoft Defender for Office 365 Safe Links. The reason to use a shortener is that using the direct Function App URL bypasses Microsoft Defender for Office 365 Safe Links active scanning. This blog post will briefly explain how this bypass works and how an attacker can use it to their advantage.

As a reminder, here is the flow used to identify Microsoft Defender for Office 365 Safe Links.

Image 1: Flow to detect Microsoft Defender for Office 365 Safe Links

To my surprise, when sending the Function App URL, Microsoft Defender for Office 365 Safe Links does not actively scan the URL. So I was thinking, what if I create a URL forwarder using the Function App forwarding the user to a malicious website? Does it “bypass” the active scanning using Microsoft Defender for Office 365 Safe Links?

After some testing, I was surprised Microsoft Defender for Office 365 Safe Links is not actively scanning the URL. Here is the code for the forwarder using an Azure Function App.

#r "Newtonsoft.Json"
 
using Microsoft.AspNetCore.Mvc;
 
public static IActionResult Run(HttpRequest req, ILogger log)
{
    return new RedirectResult("https://malicious.com", true);
}

So sending the Function App URL using a phishing e-mail redirects the user to a malicious website and bypasses Microsoft Defender for Office 365 Safe Links active scanning.

Conclusion

Microsoft Defender for Office 365 is a product that is hard to bypass, mainly because it can be a black box. When using this bypass, layered security should stop a user from visiting malicious websites, like enabling Smartscreen, so using layered security is always a good idea.

Microsoft Defender for Office 365 Identification

Microsoft Defender for Office 365 Identification

A few months ago, I wrote a script that checks if a company uses Microsoft Defender for Identity. I then wondered if there is a way to identify if a company uses Microsoft Defender for Office 365. Safe Links, a Microsoft Defender for Office 365 feature, actively scans incoming URLs. So checking if Microsoft Defender for Office 365 scans the URL to identify Microsoft Defender for office 365 is manageable. This blog post will briefly explain how I identified if a company uses Microsoft Defender for Office 365 Safe Links, possibly without sending a single valid e-mail.

Microsoft Defender for Office 365

I do not want to detail what Microsoft Defender for Office 365 is, but an important feature to understand is Safe Links. Safe Links is a feature in Microsoft Defender for Office 365 that provides malicious URL scanning and time-of-click verification of links in e-mail messages and Microsoft Teams.

So if you sent an e-mail to a mailbox, URL scanning takes place by Microsoft Defender for Office 365 Safe Links. If you can identify if Microsoft performs the scan, you can determine if Microsoft Defender for Office 365 is enabled. So simply running an HTTP listener for incoming requests should do the trick.

Azure Function App

First, I thought running a simple HTTP server was enough, but then I had the idea to use a Function App since that already contains an HTTP trigger that I can use. If I could capture the incoming request, I could validate who is actively scanning the URL. But since I wanted to send myself an e-mail with the information, I thought it would be easier to use a Logic App instead.

Azure Logic App

When an HTTP request is received, the Logic App triggers. So capturing the request would be enough to get all the information I need. Unfortunately, I could not get the IP address of the initial request since the Logic App did not provide me with the correct information.

What I could do, though, is use an Azure Function App to send all the information I need to a Logic App and then send the e-mail.

Image 1: Flow to detect Microsoft Defender for Office 365 Safe Links

Function Code

I ended up with a function using the HTTP trigger template. The HTTP trigger function runs whenever it receives an HTTP request, responding based on data in the body or query string. My function checks if the IP address to scan the URL is from Microsoft and sends a POST request to a Logic App.

using namespace System.Net
 
param($Request, $TriggerMetadata)
 
$IPAddress = $Request.Headers["x-forwarded-for"]
$UserAgent = $Request.Headers["user-agent"]
 
if($IPAddress -like "40.94.*.*") {
    $MDODetected = "Yes"
}
Else {
    $MDODetected = "No"
}
 
$params = @{'IP Address' = "$IPAddress";
'MDO Detected' = "$MDODetected";
'User Agent' = "$UserAgent";
} | ConvertTo-Json
 
Invoke-WebRequest -Uri 'https://prod-165.westeurope.logic.azure.com:443/workflows/<SNIP>' -Method POST -Body $params -ContentType 'application/json'
 
Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{
    StatusCode = [HttpStatusCode]::OK
    Body = $params
})

Note: I identified Microsoft Defender for Office 365 Safe Links using the IP address, but technically you can identify any active scanning based on any header.

Pasting the Function App URL in a browser shows the following information.

Image 2: Output from the Azure Function when accessing using a browser

Sending an e-mail

Now that we identify who is scanning the URL by capturing the GET request, we can forward it to a Logic App and send ourselves an e-mail with the information we need.

We can trigger the Logic App with a POST request, parse it to JSON, and send the information from the JSON parsing using an e-mail. Here is a screenshot of the Logic Apps steps.

Image 3: The Logic App flow

We have to send the Function App URL to an e-mail address and see if Microsoft scans the URL. Sending the Function App URL is enough to get the information needed to identify if Microsoft scans the URL.

Note: To ensure that Microsoft scans the URL, you need to use a URL shortener and send the shortener URL to a mailbox. More information about that in a future blog post.

An e-mail to a non-existing mailbox also does the trick, depending on the configuration. So first, try to send an e-mail to a non-existing mailbox. If it identifies as “Microsoft Defender for Office 365 Identified,” you know Microsoft Defender for Office 365 is running, and you do not have to send an e-mail to an existing mailbox to be more stealthy.

Conclusion

Using this technique makes it possible to also identify other e-mail scanning services, but my main goal was to identify Microsoft Defender for Office 365, and it worked.

Microsoft Azure Subscription Hijacking

Microsoft Azure Subscription Hijacking

Suppose you have a pay-as-you-go subscription in Azure. In that case, you might need to review who owns the Global Administrator role or who has owner permissions on that subscription in your tenant as a malicious user or attacker can hijack the subscription and make high costs at your expense. Since all activity logs are moved to the malicious user or attacker’s tenant, detecting this attack is, let us say, challenging. This blog post will briefly explain how attackers perform this attack.

Payment Information

Only a credit card or debit card is accepted when creating a pay-as-you-go subscription. Once you create the pay-as-you-go subscription, the payment information is attached to that subscription. So, suppose a malicious user or attacker moves the tenant’s subscription to a controlled tenant by the malicious user or attacker. In that case, the payment information is also moved over, including the activity logs. Once the subscription lives in the malicious user or attacker-controlled tenant, deploying resources comes at your costs, and you can not take it back. The result is losing all resources in that subscription, including very high costs if the attacker deploys resources.

Owner Permissions

It is possible to perform the attack if a malicious user or attacker gets owner permissions on a pay-as-you-go subscription. So be careful to give a guest user owner permission on a pay-as-you-go subscription. Since the guest user is out of your control, once the guest user gets compromised, an attacker can change the directory and move the subscription to an attacker controller tenant and deploy resources or mine crypto, which results in high costs.

Once a malicious user with the Global Administrator role or an attacker gets hold of a user with the Global Administrator role, a single click is needed to get owner permissions on all subscriptions within the tenant and perform the attack. The single-click option is the “Access management for Azure resources” within Azure Active Directory, elevating access to all subscriptions and management groups.

Image 1: Moving the subscription, payment info and activity log to the attacker’s tenant.

Once setting the owner permissions, the malicious user or attacker invites a user from the malicious user or attacker-controlled tenant and changes directory to move the subscription, including the payment information of the victim and the activity logs.

Conclusion

For me, it is mind-blown why Microsoft does not validate the payment information when moving the subscription to another directory. The activity logs move along with the subscription, so detection is challenging, but monitoring your identities, limiting the users with the Global Administrator role, and no owner permissions for guest users should lower the risk of a successful attack.