<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:media="http://search.yahoo.com/mrss/"><channel><title>Modern Security</title><link>https://www.modernsecurity.nl/</link><description>Modern Security is offering insights and guides on Microsoft Defender XDR, Sentinel, and other strategies for securing digital landscapes.</description><language>en-us</language><copyright>© 2026 Modern Security</copyright><generator>Hugo</generator><lastBuildDate>Thu, 29 Oct 2026 00:00:00 +0100</lastBuildDate><atom:link href="https://www.modernsecurity.nl/index.xml" rel="self" type="application/rss+xml"/><image><url>https://www.modernsecurity.nl/img/logo-light_hu_98d13a0e48fc51de.png</url><title>Modern Security</title><link>https://www.modernsecurity.nl/</link></image><item><title>Why Modern Security left WordPress: rebuilding the blog with Hugo and Blowfish</title><link>https://www.modernsecurity.nl/modern-security-moved-to-hugo-and-blowfish/</link><guid isPermaLink="true">https://www.modernsecurity.nl/modern-security-moved-to-hugo-and-blowfish/</guid><pubDate>Thu, 29 Oct 2026 00:00:00 +0100</pubDate><dc:creator>Farid Kalaidji</dc:creator><category>Security</category><description>Modern Security moved from WordPress to a static Hugo and Blowfish site on Cloudflare Workers. Why I did it, how the migration worked, and what changed for you.</description><content:encoded><![CDATA[
<h2 class="relative group">Introduction
    <div id="introduction" class="anchor"></div>
    
</h2>
<p>If you&rsquo;re reading this, you&rsquo;re looking at a completely new Modern Security. Same articles, same URLs, same Microsoft security focus. But under the hood almost nothing is left of the old site.</p>
<p>For years this blog ran on WordPress. It worked, but every month I spent more time maintaining the platform than writing about Microsoft security. Plugin updates, a security plugin to protect the other plugins, a cache plugin to make it fast again, a cookie plugin to explain all the other plugins. At some point I asked myself the question I ask customers all the time: why is the attack surface this big for what it actually needs to do?</p>
<p>So I rebuilt it. Modern Security is now a static site built with <a href="https://gohugo.io/"  target="_blank" rel="noreferrer">Hugo</a> and the <a href="https://blowfish.page/"  target="_blank" rel="noreferrer">Blowfish</a> theme, hosted on <a href="https://developers.cloudflare.com/workers/static-assets/"  target="_blank" rel="noreferrer">Cloudflare Workers</a>. In this post I explain why I made the move, how I migrated every article without breaking a single link, what I built on top of Blowfish, and what changed for you as a reader.</p>

<h2 class="relative group">Why leave WordPress?
    <div id="why-leave-wordpress" class="anchor"></div>
    
</h2>
<p>WordPress isn&rsquo;t bad. It runs a huge part of the internet for good reasons. But for a blog like this one, the trade-offs had tipped the wrong way.</p>
<p>Over time the old site needed a long list of plugins: Rank Math Pro for SEO, Wordfence for security, LiteSpeed Cache for performance, Complianz for cookie consent, Google Tag Manager, reCAPTCHA for the contact form, and a newsletter plugin. Each of them is code that runs on every request, needs updates, and can have its own vulnerabilities.</p>
<p>For a security blog that felt wrong for three reasons:</p>
<ul>
<li><strong>Attack surface:</strong> A login page, a database, PHP and a stack of plugins, all reachable from the internet, to serve articles that change a few times a month.</li>
<li><strong>Maintenance:</strong> Updates were never &ldquo;just&rdquo; updates. Something always needed checking afterwards.</li>
<li><strong>Privacy:</strong> The cookie policy listed cookies from WordPress, Wordfence, LiteSpeed, Google, Facebook, Twitter and LinkedIn. That&rsquo;s a lot of third parties for reading an article about Defender XDR.</li>
</ul>
<p>A static site removes most of that by design. There is no database to inject into, no login page to brute-force and no plugins to patch. The server only hands out files.</p>

<h2 class="relative group">The new stack
    <div id="the-new-stack" class="anchor"></div>
    
</h2>

<div class="ms-table" role="region" aria-label="Table" tabindex="0">
  <table>
      <thead>
          <tr>
              <th>Part</th>
              <th>Old site</th>
              <th>New site</th>
          </tr>
      </thead>
    <tbody>
        <tr>
            <td>Platform</td>
            <td>WordPress with PHP and a database</td>
            <td>Hugo static site generator</td>
        </tr>
        <tr>
            <td>Theme</td>
            <td>WordPress theme plus page builder blocks</td>
            <td>Blowfish, with my own layouts on top</td>
        </tr>
        <tr>
            <td>Hosting</td>
            <td>Web hosting with a LiteSpeed server</td>
            <td>Cloudflare Workers (static assets)</td>
        </tr>
        <tr>
            <td>SEO</td>
            <td>Rank Math Pro</td>
            <td>Built into the templates (titles, descriptions, structured data, sitemap)</td>
        </tr>
        <tr>
            <td>Security</td>
            <td>Wordfence</td>
            <td>No login, no database, nothing to log in to</td>
        </tr>
        <tr>
            <td>Contact form</td>
            <td>WordPress form with reCAPTCHA</td>
            <td>A small Cloudflare Worker with Cloudflare Turnstile</td>
        </tr>
        <tr>
            <td>Cookie consent</td>
            <td>Complianz plugin</td>
            <td>A small self-hosted consent banner</td>
        </tr>
        <tr>
            <td>Writing</td>
            <td>WordPress editor</td>
            <td>Markdown files in Git</td>
        </tr>
    </tbody>
  </table>
</div>
<p><strong>Hugo</strong> turns Markdown files into plain HTML pages in seconds. <strong>Blowfish</strong> gives a modern, fast theme with dark mode, search and an accessibility panel. <strong>Cloudflare Workers</strong> builds the site from GitHub on every change and serves it from Cloudflare&rsquo;s network. Pages are plain files; code only runs for the contact form.</p>
<p>One rule I set myself from day one: <strong>never edit the Blowfish theme files.</strong> Blowfish is a Git submodule, pinned to a fixed version, and everything that makes the site look like Modern Security lives in my own layouts and styles. Where I had to replace a Blowfish template, it&rsquo;s documented, so I know exactly what to check when Blowfish releases a new version.</p>

<h2 class="relative group">Migrating every article without breaking a link
    <div id="migrating-without-breaking-a-link" class="anchor"></div>
    
</h2>
<p>The scariest part of any migration is SEO. Years of articles are indexed by Google, linked from LinkedIn posts and bookmarked by readers. If URLs change, all of that turns into 404 errors overnight.</p>
<p>So the migration started with an audit, not with a design. I exported everything from the WordPress REST API: posts, pages, categories, media, and the SEO data Rank Math generated for every page. Then a Python converter turned each WordPress article into a Hugo page bundle: one folder per article with the Markdown text and its images next to it.</p>
<p>A few things the converter had to get right:</p>
<ol>
<li><strong>Identical URLs:</strong> Every article, category and page keeps exactly the same address as on WordPress. One article even had a non-breaking hyphen (U+2011) in its URL, which Hugo silently strips. That one now has its URL set explicitly.</li>
<li><strong>Identical SEO:</strong> Titles, meta descriptions and robots settings are copied exactly as Rank Math had them. A comparison script checks the old and new page headers side by side.</li>
<li><strong>Tables:</strong> Many of my articles are full of tables with KQL queries and settings. The converter checked all 133 tables against the original. That&rsquo;s how I found that a WordPress math plugin had quietly eaten the <code>$</code> signs in a PowerShell command at some point.</li>
<li><strong>Images:</strong> Every screenshot is converted to WebP, and Hugo now creates several sizes of each image, so a phone downloads a small version and a 4K screen a sharp one.</li>
<li><strong>KQL highlighting:</strong> Hugo&rsquo;s code highlighter doesn&rsquo;t know KQL, so the site highlights KQL itself while building. No JavaScript needed in your browser.</li>
</ol>
<p>The old cookie policy pages for different countries will point to one cookie policy, and the remaining old WordPress addresses get permanent redirects. Google sees the same pages, with the same titles, at the same addresses.</p>

<h2 class="relative group">Building the frontend
    <div id="building-the-frontend" class="anchor"></div>
    
</h2>
<p>Blowfish is a great starting point, but I wanted the site to stay recognisably Modern Security: the black top bar, the big logo, black section headings and the photo tiles on the homepage. So most of what you see is built on top of the theme:</p>
<ul>
<li><strong>Homepage:</strong> a mosaic of featured articles, the Security, Identity and Compliance tiles, and every other article with pagination.</li>
<li><strong>Articles:</strong> a table of contents at the top, a featured posts and categories sidebar, a reading progress bar and code blocks with a copy button.</li>
<li><strong>Topic pages:</strong> a photo banner, an introduction per topic, related topics and the articles in that topic.</li>
<li><strong>Dark mode and accessibility:</strong> a dark-mode switch and Blowfish&rsquo;s accessibility panel for text size, link underlines and a distraction-free reading mode.</li>
<li><strong>Sharing without trackers:</strong> share buttons for LinkedIn, X, Bluesky and email are plain links. Nothing from those networks loads until you click.</li>
<li><strong>Mobile:</strong> every page type was checked at phone size, so nothing scrolls sideways and every button is big enough to tap.</li>
</ul>

<h2 class="relative group">Privacy and security by design
    <div id="privacy-and-security-by-design" class="anchor"></div>
    
</h2>
<p>This is the part I&rsquo;m most happy with, because it&rsquo;s where the old site felt most uncomfortable.</p>
<p><strong>Nothing tracks you before you choose:</strong> The site uses Google Analytics and Microsoft Clarity to see which articles are read, but only after you allow it in the cookie banner. Before that choice, no Google or Microsoft script is loaded at all. Rejecting is exactly as easy as accepting, and advertising features are switched off in both tools. You can change your mind at any time via the <em>Cookie settings</em> button on the <a href="https://www.modernsecurity.nl/cookie-policy-eu/" >Cookie Policy</a>, linked at the bottom of every page.</p>
<p><strong>The contact form has no database behind it:</strong> Messages go through a small Cloudflare Worker that checks Cloudflare Turnstile on the server and sends the message by email through an EU mail provider. No form plugin, no stored submissions.</p>
<p><strong>A security.txt file:</strong> If you find a vulnerability, <a href="https://www.modernsecurity.nl/.well-known/security.txt" >/.well-known/security.txt</a> tells you how to report it, following RFC 9116. Fitting for a security blog, and something the old site never had.</p>
<p><strong>Fewer moving parts:</strong> There is no admin login to attack, no database to dump and no plugin to exploit. The most important thing to protect is now the GitHub account that publishes the site, so that&rsquo;s where the security effort goes.</p>

<h2 class="relative group">Writing new articles
    <div id="writing-new-articles" class="anchor"></div>
    
</h2>
<p>Every article is now a Markdown file in a Git repository. I write in VS Code, screenshots go into the same folder as the article, and every change is version-controlled. If I make a mistake, I can roll back. If a reader spots an error, the history shows exactly what changed and when.</p>
<p>For quick fixes away from my laptop, the site is set up for <a href="https://pagescms.org/"  target="_blank" rel="noreferrer">Pages CMS</a>, a simple editor in the browser that commits straight to the repository. When I push a change, Cloudflare builds and publishes the site automatically.</p>

<h2 class="relative group">What I learned
    <div id="what-i-learned" class="anchor"></div>
    
</h2>
<ol>
<li><strong>Audit before you design:</strong> Exporting all URLs and SEO data first made every later decision easier. You can&rsquo;t keep what you never wrote down.</li>
<li><strong>Treat a theme like a dependency:</strong> Pin the version, don&rsquo;t edit it, and keep a list of what you override. Upgrades become a checklist instead of a gamble.</li>
<li><strong>Check the content, not just the pages:</strong> Automated checks on tables and images found problems that had been invisible on the old site for years.</li>
<li><strong>Privacy is a design choice:</strong> Loading nothing before consent was easier to build from scratch than to bolt onto a plugin stack.</li>
<li><strong>Static is a security feature:</strong> The safest login page is the one that doesn&rsquo;t exist.</li>
</ol>
<p>I&rsquo;ll share real performance numbers (Lighthouse and Core Web Vitals) once the new site has been live for a few weeks. If you notice anything that looks broken or a link that no longer works, please <a href="https://www.modernsecurity.nl/contact-form/" >let me know</a>.</p>

<h2 class="relative group">Sources
    <div id="sources" class="anchor"></div>
    
</h2>
<ul>
<li><a href="https://gohugo.io/documentation/"  target="_blank" rel="noreferrer">Hugo documentation</a> (Hugo)</li>
<li><a href="https://blowfish.page/docs/"  target="_blank" rel="noreferrer">Blowfish documentation</a> (Blowfish)</li>
<li><a href="https://developers.cloudflare.com/workers/static-assets/"  target="_blank" rel="noreferrer">Cloudflare Workers static assets</a> (Cloudflare)</li>
<li><a href="https://developers.cloudflare.com/turnstile/"  target="_blank" rel="noreferrer">Cloudflare Turnstile documentation</a> (Cloudflare)</li>
<li><a href="https://learn.microsoft.com/clarity/setup-and-installation/clarity-consent-api-v2"  target="_blank" rel="noreferrer">Clarity Consent API</a> (Microsoft Learn)</li>
<li><a href="https://www.rfc-editor.org/rfc/rfc9116"  target="_blank" rel="noreferrer">RFC 9116: A File Format to Aid in Security Vulnerability Disclosure</a> (RFC Editor)</li>
<li><a href="https://pagescms.org/"  target="_blank" rel="noreferrer">Pages CMS</a> (Pages CMS)</li>
</ul>

<h2 class="relative group">Conclusion
    <div id="conclusion" class="anchor"></div>
    
</h2>
<p>Moving Modern Security from WordPress to Hugo and Blowfish wasn&rsquo;t about chasing a new tool. It was about applying the same principles I write about here to my own site: reduce the attack surface, control what runs, and don&rsquo;t collect more data than you need.</p>
<p>The result is a blog that&rsquo;s faster to maintain, easier to secure and more respectful of your privacy, with every old link still working.</p>
<p>Same content. Same addresses. Far fewer moving parts.</p>
]]></content:encoded><media:content url="https://www.modernsecurity.nl/modern-security-moved-to-hugo-and-blowfish/featured_hu_d9e5466d223133fb.jpg" medium="image" type="image/jpeg" width="1200" height="750"/><enclosure url="https://www.modernsecurity.nl/modern-security-moved-to-hugo-and-blowfish/featured_hu_d9e5466d223133fb.jpg" type="image/jpeg" length="66708"/></item><item><title>Microsoft ISOC explained: what it is, who it is for, and how it compares to Sentinel</title><link>https://www.modernsecurity.nl/microsoft-isoc-defender-vs-sentinel/</link><guid isPermaLink="true">https://www.modernsecurity.nl/microsoft-isoc-defender-vs-sentinel/</guid><pubDate>Fri, 25 Sep 2026 11:42:10 +0100</pubDate><dc:creator>Farid Kalaidji</dc:creator><category>Microsoft Defender XDR</category><category>Microsoft Sentinel</category><description>Microsoft ISOC brings SIEM into Defender as an E5 and E7 benefit. What it is, who it's for, and what Sentinel customers should know.</description><content:encoded><![CDATA[
<h2 class="relative group">ISOC introduction
    <div id="isoc-introduction" class="anchor"></div>
    
</h2>
<p>On September 23, Microsoft announced the Integrated Security Operations Center, or ISOC, in Microsoft Defender. My LinkedIn feed filled up within the hour, and the first question I got was simple: “So is <a href="https://www.modernsecurity.nl/microsoft-sentinel/" >Sentinel</a> dead?”</p>
<p>Short answer: no.</p>
<p>Longer answer: this is the most interesting change to Microsoft’s SOC story since Sentinel moved into the Defender portal, and it changes where many organisations will start. In this post I explain what ISOC is, who it is for, how it compares to Microsoft Sentinel and Defender XDR, and what I would check before using it.</p>

<h2 class="relative group">What is ISOC in Microsoft Defender?
    <div id="what-is-isoc-in-microsoft-defender" class="anchor"></div>
    
</h2>
<p>The key sentence is in Microsoft’s own FAQ: ISOC is not a new product. It is a <strong>benefit</strong> on top of Microsoft Defender Suite, Microsoft 365 E5 and E7 that brings SIEM capabilities from Microsoft Sentinel into the Defender portal.</p>
<p>In practice it does two big things:</p>
<ol>
<li>It turns on SIEM features in Defender for organisations that never deployed Sentinel.</li>
<li>It uses the Defender data you already have, without separate ingestion, and extends retention from 30 to 90 days on November 15, 2026.</li>
</ol>
<p>Until now, E5 gave you excellent XDR, but a SIEM meant a separate Sentinel purchase and project. That is the gap ISOC closes.</p>
<p>Microsoft frames the announcement around attackers: they use AI agents to automate at scale, and every handoff between separate protection and operations systems slows defenders down. Microsoft describes a stack of sensors and signals, context, models, a harness, agents and actuators, with ISOC as the foundation.</p>
<figure><img
    class="my-0 rounded-md"
    loading="lazy"
    decoding="async"
    fetchpriority="auto"
    alt=""
    width="1280"
    height="720"
    src="https://www.modernsecurity.nl/microsoft-isoc-defender-vs-sentinel/image-2_hu_3e69a373767602ad.webp"
   
   
    data-zoom-src="https://www.modernsecurity.nl/microsoft-isoc-defender-vs-sentinel/image-2.webp"></figure><p>It’s worth separating the vision from what ships today. The agents come from Project Perception, introduced in July, which is a limited preview for a small, invitation-only group of customers, with its own consumption-based pricing. ISOC itself doesn’t require Perception. I see it as laying the shared data and workflow foundation that agents will need later, and I think it should be judged on what it delivers without them.</p>

<h2 class="relative group">What you get on day one
    <div id="what-you-get-on-day-one" class="anchor"></div>
    
</h2>
<p>Eligible tenants see these capabilities appear in the Defender portal without extra configuration:</p>
<ul>
<li><strong>Case management.</strong> Incident cases and generic cases, with tasks, templates, SLA policies and activity history. No workspace needed.</li>
<li><strong>Workbooks.</strong> Dashboards built on advanced hunting queries, with example workbooks to get started.</li>
<li><strong>Enhanced automation rules.</strong></li>
<li><strong>Natural-language playbook generation.</strong> Describe the automation you want, and the generator writes a Python playbook for you to review, test and activate.</li>
</ul>
<figure><img
    class="my-0 rounded-md"
    loading="lazy"
    decoding="async"
    fetchpriority="auto"
    alt=""
    width="1871"
    height="840"
    src="https://www.modernsecurity.nl/microsoft-isoc-defender-vs-sentinel/image-8_hu_de6b1d563f040e75.webp"
   
   
    data-zoom-src="https://www.modernsecurity.nl/microsoft-isoc-defender-vs-sentinel/image-8.webp"></figure><figure><img
    class="my-0 rounded-md"
    loading="lazy"
    decoding="async"
    fetchpriority="auto"
    alt=""
    width="1868"
    height="844"
    src="https://www.modernsecurity.nl/microsoft-isoc-defender-vs-sentinel/image-4_hu_345500ae70b4d60a.webp"
   
   
    data-zoom-src="https://www.modernsecurity.nl/microsoft-isoc-defender-vs-sentinel/image-4.webp"></figure><figure><img
    class="my-0 rounded-md"
    loading="lazy"
    decoding="async"
    fetchpriority="auto"
    alt=""
    width="1830"
    height="625"
    src="https://www.modernsecurity.nl/microsoft-isoc-defender-vs-sentinel/image-5_hu_a46c7bbee9725891.webp"
   
   
    data-zoom-src="https://www.modernsecurity.nl/microsoft-isoc-defender-vs-sentinel/image-5.webp"></figure><p>The included data covers Defender for Endpoint, Office 365, Identity, Cloud Apps and Cloud, plus Entra ID Protection logs, and Azure Activity and Office 365 Activity logs through a connector. There is no minimum seat count.</p>

<h2 class="relative group">What requires an ISOC workspace
    <div id="what-requires-an-isoc-workspace" class="anchor"></div>
    
</h2>
<p>When you need more than native Defender data, you create an ISOC workspace linked to an Azure subscription. That unlocks UEBA, Content hub, CI/CD from repositories, threat intelligence, and non-Microsoft data through more than 500 connectors. From October 1, that non-Microsoft data is billed at $2.40 per GB on a pay-as-you-go meter. Regional pricing may vary.</p>
<figure><img
    class="my-0 rounded-md"
    loading="lazy"
    decoding="async"
    fetchpriority="auto"
    alt=""
    width="1010"
    height="947"
    src="https://www.modernsecurity.nl/microsoft-isoc-defender-vs-sentinel/image-6_hu_3e7580be9151a248.webp"
   
   
    data-zoom-src="https://www.modernsecurity.nl/microsoft-isoc-defender-vs-sentinel/image-6.webp"></figure><p>Two details in the documentation are easy to miss:</p>
<ul>
<li><strong>Content hub is connector-only during the preview.</strong> If you install a solution, you get its data connectors, but not its analytics rules, hunting queries or workbooks. So budget time for building or porting detection content for every source you add. A connector without detections is just storage.</li>
<li><strong>UEBA is not part of the licence.</strong> Microsoft describes UEBA as an optional paid Sentinel capability that isn’t included with E5. It can analyse supported Defender tables without ingesting them first, which is a nice improvement, but its output is written to Log Analytics and those charges apply. If you want to know what UEBA brings, I covered the UEBA behaviors layer earlier.</li>
</ul>
<p>One more observation: you create the ISOC workspace under <strong>Settings &gt; Microsoft Sentinel &gt; SIEM workspaces</strong>, and it requires the Microsoft Sentinel Contributor role. My reading is that this is the Sentinel foundation, packaged and licensed differently, rather than a new SIEM engine. Microsoft’s documentation doesn’t state what kind of resource you end up with but I’ll make a guidance on this soon.</p>
<figure><img
    class="my-0 rounded-md"
    loading="lazy"
    decoding="async"
    fetchpriority="auto"
    alt=""
    width="1536"
    height="1024"
    src="https://www.modernsecurity.nl/microsoft-isoc-defender-vs-sentinel/image-7_hu_2657f9f9ddcbaf1e.webp"
   
   
    data-zoom-src="https://www.modernsecurity.nl/microsoft-isoc-defender-vs-sentinel/image-7.webp"></figure>
<h2 class="relative group">Who is ISOC for?
    <div id="who-is-isoc-for" class="anchor"></div>
    
</h2>
<p><strong>Right now:</strong> organisations with Microsoft Defender Suite, Microsoft 365 E5 or E7 that do not have an active Microsoft Sentinel workspace. You need an Azure subscription if you want the workspace.</p>
<p><strong>From November 15, 2026:</strong> existing Sentinel customers who meet the licensing criteria can choose to move to ISOC. Until then, Microsoft’s advice is clear: keep using Sentinel, and don’t disconnect a production workspace to qualify for the preview.</p>
<p>A note on Defender Suite: Microsoft’s documentation lists it as eligible, but the FAQ’s benefit section is written for E5 and E7. If you are on Defender Suite, check that ISOC actually shows up in your tenant, and get the retention and meter confirmed, before you plan around it.</p>

<h2 class="relative group">ISOC vs Microsoft Sentinel vs Defender XDR
    <div id="isoc-vs-microsoft-sentinel-vs-defender-xdr" class="anchor"></div>
    
</h2>
<p>This is how I see the three side by side, based on what is documented today:</p>

<div class="ms-table" role="region" aria-label="Table" tabindex="0">
  <table>
      <thead>
          <tr>
              <th>Aspect</th>
              <th>Defender XDR alone</th>
              <th>Microsoft Sentinel</th>
              <th>ISOC in Defender (preview)</th>
          </tr>
      </thead>
    <tbody>
        <tr>
            <td>What it is</td>
            <td>Product</td>
            <td>Product, separate purchase</td>
            <td>Benefit on Defender Suite, E5, E7</td>
        </tr>
        <tr>
            <td>Who</td>
            <td>Defender licensed tenants</td>
            <td>Any organisation with an Azure subscription</td>
            <td>No active Sentinel workspace now; eligible Sentinel customers from Nov 15, 2026</td>
        </tr>
        <tr>
            <td>Defender data</td>
            <td>30 days in advanced hunting</td>
            <td>Ingested into the workspace; E5 grant covers up to 5 MB per user per day of eligible Microsoft data</td>
            <td>Used in place, 30 days now, 90 days from Nov 15, 2026</td>
        </tr>
        <tr>
            <td>Non-Microsoft data</td>
            <td>Not a SIEM</td>
            <td>Yes, pay-as-you-go or commitment tiers</td>
            <td>Yes, via ISOC workspace, $2.40/GB from Oct 1</td>
        </tr>
        <tr>
            <td>Cases, workbooks, playbooks</td>
            <td>Incidents</td>
            <td>Yes</td>
            <td>Yes, no workspace needed</td>
        </tr>
        <tr>
            <td>Content hub</td>
            <td>Not applicable</td>
            <td>Full solutions: connectors, rules, hunting, workbooks</td>
            <td>Data connectors only in preview</td>
        </tr>
        <tr>
            <td>UEBA</td>
            <td>Not as a SIEM feature</td>
            <td>Optional paid capability</td>
            <td>With workspace, optional paid capability</td>
        </tr>
    </tbody>
  </table>
</div>
<p>My take: <strong>Defender XDR</strong> remains the protection and detection engine. <strong>Sentinel</strong> remains the broad security data platform for organisations with many sources, mature detection content and long retention needs. <strong>ISOC</strong> is the new front door for E5 organisations that want SOC capabilities without first running a SIEM project.</p>
<p>The part I like most is retention. I have seen plenty of designs where Defender data went into Sentinel mainly to keep it longer than 30 days (apart from data lake). Paying to store Microsoft telemetry inside another Microsoft product never felt right. Ninety days included changes that discussion, and it fits the broader trend I wrote about in my post on lake-only ingestion for Defender XDR tables.</p>

<h2 class="relative group">What about existing Sentinel customers?
    <div id="what-about-existing-sentinel-customers" class="anchor"></div>
    
</h2>
<p>My advice: evaluate per customer after November 15. There is no single right answer, because the outcome depends on the licence mix, the data sources and the detection content each environment has built. I’d look at five questions per environment:</p>
<ol>
<li><strong>Licensing.</strong> Is the tenant fully on E5 or E7, or a mix? Defender Suite needs written confirmation.</li>
<li><strong>The E5 grant.</strong> Today, E5 includes a Sentinel data grant of up to 5 MB per user per day for eligible Microsoft data. Microsoft’s ISOC documentation doesn’t say whether that grant still applies once a workspace moves to ISOC. How much of your current ingestion does it cover, and what happens if it goes away?</li>
<li><strong>Identity detections.</strong> Entra sign-in and audit logs aren’t on ISOC’s included list, and they’re core detection data for most SOCs. Defender has its own EntraIdSignInEvents table for interactive and non-interactive sign-ins, and the UEBA documentation even maps it as the “Signin Logs” source. But its schema differs from SigninLogs; conditional access status, for example, is a numeric code instead of text. How many of your analytics rules depend on SigninLogs, and what would porting them cost?</li>
<li><strong>Retention-only ingestion.</strong> Which Defender tables do you ingest mainly to keep them longer than 30 days? Those are where ISOC’s 90 days pays off.</li>
<li><strong>Third-party sources.</strong> What would they cost on the $2.40 meter compared to your current rate, and which of them have detection content that Content hub won’t install for you?</li>
</ol>
<p>Two things Microsoft hasn’t documented yet will also weigh in: what Microsoft data outside the included list costs under ISOC (the billing page only says additional ingestion charges might apply), and what happens to history, retention settings and content when an existing Sentinel workspace moves. Keep in mind that March 31, 2027 is when Sentinel leaves the Azure portal, whether you move to ISOC or not.</p>

<h2 class="relative group">Multi-tenant and MSSP considerations
    <div id="multi-tenant-and-mssp-considerations" class="anchor"></div>
    
</h2>
<p>For anyone managing multiple tenants, the ISOC documentation is still thin:</p>
<ul>
<li>Creating the workspace requires Security Administrator in Entra ID, plus Owner, or User Access Administrator and Sentinel Contributor, on the Azure subscription. Organisations should think carefully before handing that level of access to a third party.</li>
<li>In the Defender multitenant portal, GDAP only covers Defender data. Sentinel data requires Entra B2B, and cross-tenant Sentinel queries still require Azure Lighthouse.</li>
<li>Case management is available in the multitenant portal, but I haven’t found documentation on ISOC workspaces, the benefit or generated playbooks in multi-tenant management.</li>
</ul>

<h2 class="relative group">Limitations and open questions
    <div id="limitations-and-open-questions" class="anchor"></div>
    
</h2>
<ul>
<li><strong>It’s a preview.</strong> Capabilities and availability can change.</li>
<li><strong>Identity logs.</strong> Entra sign-in and audit logs aren’t on the included list, their cost under ISOC isn’t documented, and EntraIdSignInEvents has a different schema than SigninLogs.</li>
<li><strong>The E5 grant.</strong> ISOC documentation doesn’t address whether the E5 Sentinel data grant still applies after moving.</li>
<li><strong>Content hub</strong> installs data connectors only during the preview.</li>
<li><strong>UEBA</strong> is an optional paid capability, and its output incurs Log Analytics charges.</li>
<li><strong>Playbook generator limits.</strong> Python only, no external libraries, no playbook nesting, up to 100 playbooks per tenant, 5,000 lines per playbook, 10 minutes maximum runtime and 8 million AI tokens per day per tenant. Generated code must be reviewed manually.</li>
<li><strong>Enhanced alert trigger rules</strong> don’t support priority ordering, execute one action per rule, and can only run generated playbooks or update alerts.</li>
<li><strong>Multi-tenant guidance</strong> for ISOC is missing.</li>
</ul>

<h2 class="relative group">How I would get started
    <div id="how-i-would-get-started" class="anchor"></div>
    
</h2>
<p>If you’re eligible and don’t run Sentinel, here’s the order I’d follow:</p>
<ol>
<li><strong>Sort out permissions first.</strong> Automation uses Unified RBAC, with separate permissions for automation admin, rules, integrations and playbooks. Decide who can create and who can execute before anyone starts experimenting.</li>
<li><strong>Configure integration profiles.</strong> Generated playbooks can only call Microsoft Graph and Azure Resource Manager once those profiles exist, so set them up with least-privilege access from the start.</li>
<li><strong>Explore the example workbooks.</strong> They’re a quick way to see what your Defender data looks like as dashboards before you build your own.</li>
<li><strong>Treat generated playbooks as code.</strong> Review, test and put them under change control like any other automation. I wrote about the Sentinel AI playbook generator before, and the same rule applies: easy to create should never mean easy to deploy badly.</li>
<li><strong>Add a workspace only with a plan.</strong> For each extra source, know the cost and who will write its detections.</li>
</ol>
<p>I’ll test ISOC hands-on in a lab tenant and follow up with screenshots and findings. If you’re testing it too, I’d love to hear what you run into.</p>

<h2 class="relative group">Sources
    <div id="sources" class="anchor"></div>
    
</h2>
<ul>
<li><a href="https://www.microsoft.com/en-us/security/blog/2026/09/23/reimagining-the-soc-for-the-agentic-era-in-microsoft-defender/"  target="_blank" rel="noreferrer">Reimagining the SOC for the agentic era in Microsoft Defender</a> (Microsoft Security Blog)</li>
<li><a href="https://techcommunity.microsoft.com/blog/microsoftthreatprotectionblog/integrated-security-operations-center-in-microsoft-defender/4559097"  target="_blank" rel="noreferrer">Integrated Security Operations Center in Microsoft Defender</a> (Microsoft Tech Community, incl. FAQ)</li>
<li><a href="https://learn.microsoft.com/en-us/defender-xdr/isoc-overview"  target="_blank" rel="noreferrer">ISOC in Microsoft Defender overview</a> (Microsoft Learn)</li>
<li><a href="https://learn.microsoft.com/en-us/defender-xdr/integrated-security-operations-data-billing-retention"  target="_blank" rel="noreferrer">Data ingestion and billing for ISOC</a> (Microsoft Learn)</li>
<li><a href="https://learn.microsoft.com/en-us/defender-xdr/onboard-isoc-workspace"  target="_blank" rel="noreferrer">Create an ISOC workspace</a> (Microsoft Learn)</li>
<li><a href="https://learn.microsoft.com/en-us/defender-xdr/content-hub-defender"  target="_blank" rel="noreferrer">Use Content hub with ISOC</a> (Microsoft Learn)</li>
<li><a href="https://learn.microsoft.com/en-us/defender-xdr/extend-ueba"  target="_blank" rel="noreferrer">Connect data sources to UEBA with Microsoft 365 E5</a> (Microsoft Learn)</li>
<li><a href="https://learn.microsoft.com/en-us/defender-xdr/siem-defender-automation"  target="_blank" rel="noreferrer">Automation with ISOC</a> (Microsoft Learn)</li>
<li><a href="https://learn.microsoft.com/en-us/defender-xdr/siem-defender-workbooks"  target="_blank" rel="noreferrer">Create and manage workbooks with ISOC</a> (Microsoft Learn)</li>
<li><a href="https://learn.microsoft.com/en-us/defender-xdr/siem-defender-case-management"  target="_blank" rel="noreferrer">Case management in the Microsoft Defender portal</a> (Microsoft Learn)</li>
<li><a href="https://learn.microsoft.com/en-us/defender-xdr/advanced-hunting-entraidsigninevents-table"  target="_blank" rel="noreferrer">EntraIdSignInEvents table</a> (Microsoft Learn)</li>
<li><a href="https://learn.microsoft.com/en-us/unified-secops/mto-requirements"  target="_blank" rel="noreferrer">Set up Microsoft Defender multitenant management</a> (Microsoft Learn)</li>
<li><a href="https://learn.microsoft.com/en-us/security/agentic-security/agentic-security-overview"  target="_blank" rel="noreferrer">What is Project Perception?</a> (Microsoft Learn)</li>
<li><a href="https://learn.microsoft.com/en-us/unified-secops/whats-new"  target="_blank" rel="noreferrer">What’s new for Microsoft’s unified security operations</a> (Microsoft Learn)</li>
</ul>

<h2 class="relative group">Conclusion
    <div id="conclusion" class="anchor"></div>
    
</h2>
<p>ISOC is not the end of Sentinel. It is a new starting point. For E5 and E7 organisations without a SIEM, it removes the biggest barrier: they get case management, workbooks, automation and 90 days of Defender data without a separate purchase or project. That alone makes it worth switching on.</p>
<p>For existing Sentinel customers, the picture is less simple. The benefits are real, but so are the open questions around the E5 grant, identity logs, detection content and migration. That is why I would evaluate per customer after November 15, not move by default.</p>
<p>The bigger shift is where the value of a SOC sits. When the platform comes with the licence, the difference is made by good detections, well-governed automation and people who know what to do with an alert. ISOC makes the platform easier. It doesn’t make security operations easier.</p>
]]></content:encoded><media:content url="https://www.modernsecurity.nl/microsoft-isoc-defender-vs-sentinel/featured_hu_759ed7024d67903c.jpg" medium="image" type="image/jpeg" width="1200" height="675"/><enclosure url="https://www.modernsecurity.nl/microsoft-isoc-defender-vs-sentinel/featured_hu_759ed7024d67903c.jpg" type="image/jpeg" length="47966"/></item><item><title>AI playbook generator in Microsoft Sentinel: turn a sentence into working SOC automation</title><link>https://www.modernsecurity.nl/microsoft-sentinel-ai-playbook-generator/</link><guid isPermaLink="true">https://www.modernsecurity.nl/microsoft-sentinel-ai-playbook-generator/</guid><pubDate>Sat, 22 Aug 2026 22:46:36 +0100</pubDate><dc:creator>Farid Kalaidji</dc:creator><category>Microsoft Defender XDR</category><category>Microsoft Sentinel</category><description>Microsoft Sentinel AI playbook generator: turn a sentence into a working SOC automation, no SCU or Logic Apps needed.</description><content:encoded><![CDATA[<p>Every SOC lead has the same automation backlog problem. There is a long list of response actions everyone agrees would help, and a much shorter list of people who actually know Logic Apps well enough to build them. The playbook generator in <a href="https://www.modernsecurity.nl/microsoft-sentinel/" >Microsoft Sentinel</a> is Microsoft’s answer to that gap: describe what you want in plain language, and get back a working, testable, documented playbook without writing Logic Apps JSON by hand.</p>
<p>I have been through the setup a few times now, both in a lab tenant and in a production Defender portal, and this post walks through the whole process end to end: what the feature is, what changed in August 2026, every prerequisite, the full integration profile setup, and a complete demo where I build a read-only VirusTotal URL enrichment playbook from an empty tenant to a live automation rule.</p>

<h2 class="relative group">What is the playbook generator?
    <div id="what-is-the-playbook-generator" class="anchor"></div>
    
</h2>
<p>The playbook generator is a SOAR authoring experience built on <strong>Cline</strong>, an AI coding agent hosted inside an embedded VS Code environment in the Defender portal. Instead of dragging connectors around a Logic Apps canvas, you describe the automation logic in a chat interface, and the generator produces a validated, code-based playbook in Python, complete with:</p>
<ul>
<li>The complete playbook code</li>
<li>Automatically generated tests, run against a real alert you provide</li>
<li>Documentation and a visual flow diagram</li>
<li>Entity and data mapping based on the alert schema</li>
</ul>
<p>Generated playbooks accept alert data as input and can call out to Microsoft Graph, Azure Resource Manager, or any third-party API you configure through an integration profile. You do not need prior coding experience, though it helps to be comfortable with concepts like VS Code and Entra ID app registrations, since you will touch both.</p>

<h2 class="relative group">Does it cost SCU?
    <div id="does-it-cost-scu" class="anchor"></div>
    
</h2>
<p>No. As of the August 2026 documentation update, Microsoft states it plainly: the playbook generator does not require a separate Microsoft Security Copilot license or Security Compute Units. This used to be more confusing than it needed to be. Earlier in 2026, the feature technically did not bill SCUs, but your tenant still needed Security Copilot enabled with capacity provisioned as a prerequisite, a distinction that tripped up a lot of people, myself included the first time I set this up.</p>
<p>That prerequisite is gone now. There is no dedicated Security Copilot workspace to provision, no capacity to configure, no data sharing sliders to set. If your tenant has a Sentinel workspace onboarded to the Defender portal, you meet the environment requirement, full stop.</p>

<h2 class="relative group">What changed in August 2026
    <div id="what-changed-in-august-2026" class="anchor"></div>
    
</h2>
<p>Microsoft published an update on the Sentinel blog and updated the official documentation on August 7, 2026, confirming that Security Copilot enablement is no longer required to use the playbook generator. The older setup path, provisioning a dedicated Security Copilot workspace purely as a technical gate, has been removed from the documentation entirely, not just deprioritized. The feature is now available to all Microsoft Sentinel customers in the Defender portal out of the box, with no Security Copilot dependency and no additional cost.</p>
<p>The required permissions also simplified as part of this change. The older RBAC requirement (Detection tuning manage, plus Security Copilot read) has been replaced with a single Automation permission, covered in the prerequisites below.</p>
<p>If you went through the old Security Copilot workspace setup before this update, nothing breaks, your existing configuration keeps working. If you never got around to trying the feature because provisioning Security Copilot capacity felt like overkill just to test it, that barrier is gone. The steps below reflect the current, simplified setup.</p>

<h2 class="relative group">Prerequisites at a glance
    <div id="prerequisites-at-a-glance" class="anchor"></div>
    
</h2>
<p>Everything you need before you open the playbook generator for the first time, in one table.</p>

<div class="ms-table" role="region" aria-label="Table" tabindex="0">
  <table>
      <thead>
          <tr>
              <th>Category</th>
              <th>Requirement</th>
              <th>Notes</th>
          </tr>
      </thead>
    <tbody>
        <tr>
            <td>Environment</td>
            <td>Microsoft Sentinel workspace onboarded to the <strong>Microsoft Defender portal</strong></td>
            <td>The Azure portal path does not support the playbook generator. If you are still Azure portal-only, onboard to Defender first.</td>
        </tr>
        <tr>
            <td>License / cost</td>
            <td>None beyond your existing Sentinel workspace</td>
            <td>No Security Copilot license, no SCUs, no additional cost. Confirmed directly in the Microsoft documentation as of August 2026.</td>
        </tr>
        <tr>
            <td>Permission: generate and deploy playbooks</td>
            <td><strong>Automation Playbooks (Read and Write)</strong> in Microsoft Defender unified RBAC</td>
            <td>Assign under the Automation permission group.</td>
        </tr>
        <tr>
            <td>Permission: author automation rules</td>
            <td><strong>Microsoft Sentinel Contributor</strong></td>
            <td>Scoped to the workspace or resource group where the rules will live.</td>
        </tr>
        <tr>
            <td>Identity</td>
            <td>An Entra ID app registration with a client secret</td>
            <td>You create this yourself in step 1, needed for the Graph integration profile.</td>
        </tr>
        <tr>
            <td>Familiarity (not a hard requirement)</td>
            <td>Comfort with VS Code and Entra ID app registration</td>
            <td>No coding experience required, but these two concepts come up constantly.</td>
        </tr>
    </tbody>
  </table>
</div>
<p>One operational note that is easy to miss: RBAC assignments can take up to two hours to propagate. If you are demoing this to a customer or a stakeholder, assign the permissions the day before, not five minutes before the call.</p>

<h2 class="relative group">Step 1: Register an Entra ID app for Graph access
    <div id="step-1-register-an-entra-id-app-for-graph-access" class="anchor"></div>
    
</h2>
<p>Integration profiles are what let a generated playbook actually call out to an API. Almost every playbook touches Microsoft Graph at minimum (to update incidents, disable accounts, send notifications), so this is where you start regardless of what the rest of the playbook does.</p>
<ol>
<li>
<p>Sign in to the <strong>Azure portal</strong> and go to <strong>Microsoft Entra ID &gt; Manage &gt; App registrations</strong>.</p>
</li>
<li>
<p>Select <strong>New registration</strong>.</p>
</li>
<li>
<p>Give it a clear name, for example <code>pb-generator-graph-integration</code>, so it is recognizable later when you are auditing app registrations. Leave the default account type and redirect URI settings unless you have a specific reason to change them.</p>
</li>
</ol>
<figure><img
    class="my-0 rounded-md"
    loading="lazy"
    decoding="async"
    fetchpriority="auto"
    alt="New registration page in Microsoft Entra ID"
    width="1919"
    height="999"
    src="https://www.modernsecurity.nl/microsoft-sentinel-ai-playbook-generator/image-40_hu_7bad97d178ce66ad.webp"
   
   
    data-zoom-src="https://www.modernsecurity.nl/microsoft-sentinel-ai-playbook-generator/image-40.webp"></figure><ol start="4">
<li>Select <strong>Register</strong>.</li>
<li>On the app’s <strong>Overview</strong> page, copy two values and store them somewhere safe for the next step:
<ul>
<li><strong>Application (client) ID</strong></li>
<li><strong>Directory (tenant) ID</strong></li>
</ul>
</li>
<li>Go to <strong>Manage &gt; Certificates &amp; secrets &gt; Client secrets</strong>.</li>
<li>Select <strong>New client secret</strong>, give it a descriptive name (include the expiration date in the name, it saves you a lookup later) and an expiration period, then select <strong>Add</strong></li>
<li>Immediately copy the secret <strong>Value</strong>, not the Secret ID. You cannot retrieve the value again once you leave the page. If you lose it, you will need to generate a new secret.</li>
</ol>
<figure><img
    class="my-0 rounded-md"
    loading="lazy"
    decoding="async"
    fetchpriority="auto"
    alt=""
    width="1919"
    height="997"
    src="https://www.modernsecurity.nl/microsoft-sentinel-ai-playbook-generator/image-48_hu_ebdbf0182226f7.webp"
   
   
    data-zoom-src="https://www.modernsecurity.nl/microsoft-sentinel-ai-playbook-generator/image-48.webp"></figure><ol start="9">
<li>While you are in the app registration, go to <strong>API permissions</strong> and add the Microsoft Graph application permissions your playbook will need. At minimum, add <code>SecurityAlert.Read.All</code>. If your playbook will disable accounts or send notifications, also add the relevant Graph permissions for those actions (<code>User.ReadWrite.All</code>, <code>Mail.Send</code>, and so on), then select <strong>Grant admin consent</strong>.</li>
</ol>
<figure><img
    class="my-0 rounded-md"
    loading="lazy"
    decoding="async"
    fetchpriority="auto"
    alt=""
    width="1919"
    height="997"
    src="https://www.modernsecurity.nl/microsoft-sentinel-ai-playbook-generator/image-43_hu_3ddb37d7191bd1aa.webp"
   
   
    data-zoom-src="https://www.modernsecurity.nl/microsoft-sentinel-ai-playbook-generator/image-43.webp"></figure>
<h2 class="relative group">Step 2: Create the integration profile
    <div id="step-2-create-the-integration-profile" class="anchor"></div>
    
</h2>
<p>With the app registration in place, connect it to Sentinel as an integration profile.</p>
<ol>
<li>In the <strong>Defender portal</strong>, go to <strong>Microsoft Sentinel &gt; Configuration &gt; Automation</strong></li>
<li>Select the <strong>Integration Profiles</strong> tab</li>
</ol>
<figure><img
    class="my-0 rounded-md"
    loading="lazy"
    decoding="async"
    fetchpriority="auto"
    alt=""
    width="1919"
    height="1000"
    src="https://www.modernsecurity.nl/microsoft-sentinel-ai-playbook-generator/image-44_hu_9b53b8218c22022e.webp"
   
   
    data-zoom-src="https://www.modernsecurity.nl/microsoft-sentinel-ai-playbook-generator/image-44.webp"></figure><ol start="3">
<li>Select <strong>Create</strong>. This opens the wizard on the <strong>Provider</strong> step</li>
<li>Under <strong>Select a provider</strong>, leave <strong>Predefined provider integrations</strong> selected and search for or scroll to <strong>Microsoft Graph</strong>, marked as Featured in the list. Select it, then select <strong>Next</strong>.</li>
</ol>
<figure><img
    class="my-0 rounded-md"
    loading="lazy"
    decoding="async"
    fetchpriority="auto"
    alt=""
    width="1919"
    height="998"
    src="https://www.modernsecurity.nl/microsoft-sentinel-ai-playbook-generator/image-46_hu_8506d5123d26304.webp"
   
   
    data-zoom-src="https://www.modernsecurity.nl/microsoft-sentinel-ai-playbook-generator/image-46.webp"></figure><ol start="5">
<li>Fill in the fields below:</li>
</ol>

<div class="ms-table" role="region" aria-label="Table" tabindex="0">
  <table>
      <thead>
          <tr>
              <th>Field</th>
              <th>Value</th>
          </tr>
      </thead>
    <tbody>
        <tr>
            <td>Integration name</td>
            <td>Something descriptive, for example “Graph Integration”</td>
        </tr>
        <tr>
            <td>Description</td>
            <td>Short description, for example “Integration with Microsoft Graph APIs”</td>
        </tr>
        <tr>
            <td>Client ID</td>
            <td>The Application (client) ID from step 1</td>
        </tr>
        <tr>
            <td>Client secret</td>
            <td>The client secret value from step 1</td>
        </tr>
    </tbody>
  </table>
</div>
<figure><img
    class="my-0 rounded-md"
    loading="lazy"
    decoding="async"
    fetchpriority="auto"
    alt=""
    width="1919"
    height="999"
    src="https://www.modernsecurity.nl/microsoft-sentinel-ai-playbook-generator/image-45_hu_d4c9e982b9159897.webp"
   
   
    data-zoom-src="https://www.modernsecurity.nl/microsoft-sentinel-ai-playbook-generator/image-45.webp"></figure><ol start="6">
<li>Select <strong>Next</strong> to reach the <strong>Summary</strong> step, review the details, and select <strong>Create</strong></li>
</ol>
<figure><img
    class="my-0 rounded-md"
    loading="lazy"
    decoding="async"
    fetchpriority="auto"
    alt=""
    width="1919"
    height="1000"
    src="https://www.modernsecurity.nl/microsoft-sentinel-ai-playbook-generator/image-47_hu_783eac5a47934a08.webp"
   
   
    data-zoom-src="https://www.modernsecurity.nl/microsoft-sentinel-ai-playbook-generator/image-47.webp"></figure><p>If your playbook needs to reach beyond Graph, for example a ticketing system, a chat platform, or a threat intel enrichment API, check the predefined provider list first, plenty of common services (AbuseIPDB, AlienVault OTX, and more) are already in there and only ask for a name and credentials, no base URL or auth method to configure.</p>
<p>If you ever need a service that is not in the predefined list, switch to <strong>Create custom integration</strong> instead, that is where you would manually enter a base URL and pick an authentication method from scratch.</p>
<p>Repeat this same wizard for each service before you start generating the playbook. One thing worth planning for either way: you cannot change the API URL or authentication method after a profile is created, only the name and description, so pick the right provider (or double-check a custom base URL) before you finish the wizard.</p>

<h2 class="relative group">Step 3: Start the playbook generator
    <div id="step-3-start-the-playbook-generator" class="anchor"></div>
    
</h2>
<ol>
<li>In the Defender portal, go to <strong>Microsoft Sentinel &gt; Configuration &gt; Automation &gt; Playbooks</strong></li>
<li>Select <strong>Create &gt; Playbook Generator</strong></li>
<li>Give the playbook a clear, descriptive name. I use a naming convention like <code>pb-&lt;trigger&gt;-&lt;action&gt;</code>, for example <code>pb-phishing-disable-account</code>, so the purpose is obvious later in a list of dozens of playbooks</li>
</ol>
<figure><img
    class="my-0 rounded-md"
    loading="lazy"
    decoding="async"
    fetchpriority="auto"
    alt="embedded Visual Studio Code environment opening with the playbook generator and Cline"
    width="1919"
    height="1000"
    src="https://www.modernsecurity.nl/microsoft-sentinel-ai-playbook-generator/image-50_hu_209f1e33c0c08410.webp"
   
   
    data-zoom-src="https://www.modernsecurity.nl/microsoft-sentinel-ai-playbook-generator/image-50.webp"></figure><ol start="4">
<li>Select <strong>Continue</strong> to continue</li>
</ol>
<p>An embedded Visual Studio Code environment opens inside the Defender portal, with Cline ready in the chat pane. This is the whole authoring experience, you never leave the browser tab.</p>
<figure><img
    class="my-0 rounded-md"
    loading="lazy"
    decoding="async"
    fetchpriority="auto"
    alt=""
    width="1918"
    height="999"
    src="https://www.modernsecurity.nl/microsoft-sentinel-ai-playbook-generator/image-51_hu_e5c0bec54bd041be.webp"
   
   
    data-zoom-src="https://www.modernsecurity.nl/microsoft-sentinel-ai-playbook-generator/image-51.webp"></figure>
<h2 class="relative group">Step 4: Work the plan in Plan mode
    <div id="step-4-work-the-plan-in-plan-mode" class="anchor"></div>
    
</h2>
<p>The session always starts in <strong>Plan mode</strong>. This is the most important step to get right, a vague prompt produces a vague plan, and you end up going back and forth far more than necessary.</p>
<ol>
<li>
<p>In the chat interface, describe your playbook requirements in one message. Be explicit about four things:</p>
<ul>
<li><strong>What data to process</strong>: which alert type, which entities on it</li>
<li><strong>What actions to perform</strong>: the actual response steps</li>
<li><strong>What conditions to evaluate</strong>: branching logic, if any</li>
<li><strong>Expected outcomes</strong>: what “done” looks like<br>
I use just a random simple example prompt to the generation in my example showcase: <em>“Create a playbook that triggers on phishing alerts. Extract the sender email address. Check if the user exists in our directory, and if so, temporarily disable their account and notify the security team.”</em></li>
</ul>
</li>
</ol>
<figure><img
    class="my-0 rounded-md"
    loading="lazy"
    decoding="async"
    fetchpriority="auto"
    alt=""
    width="1919"
    height="1000"
    src="https://www.modernsecurity.nl/microsoft-sentinel-ai-playbook-generator/image-52_hu_8f6191f90728afa2.webp"
   
   
    data-zoom-src="https://www.modernsecurity.nl/microsoft-sentinel-ai-playbook-generator/image-52.webp"></figure><ol start="2">
<li>If the generator needs to fetch external API documentation to write accurate code, it asks for approval first. Approve the request, this is how it learns the correct Graph or third-party API call shape rather than guessing.</li>
</ol>
<figure><img
    class="my-0 rounded-md"
    loading="lazy"
    decoding="async"
    fetchpriority="auto"
    alt=""
    width="1919"
    height="999"
    src="https://www.modernsecurity.nl/microsoft-sentinel-ai-playbook-generator/image-53_hu_19343a7396c1d85c.webp"
   
   
    data-zoom-src="https://www.modernsecurity.nl/microsoft-sentinel-ai-playbook-generator/image-53.webp"></figure><ol start="3">
<li>The generator analyzes your prompt and does one or more of the following:
<ul>
<li>Asks clarifying questions if something is ambiguous</li>
<li>Requests API documentation if it cannot resolve the API shape from a web search</li>
<li>Flags missing integration profiles</li>
<li>Produces a preliminary plan and a visual flow diagram</li>
</ul>
</li>
</ol>
<figure><img
    class="my-0 rounded-md"
    loading="lazy"
    decoding="async"
    fetchpriority="auto"
    alt=""
    width="889"
    height="1770"
    src="https://www.modernsecurity.nl/microsoft-sentinel-ai-playbook-generator/image-54_hu_eafda5929749c83.webp"
   
   
    data-zoom-src="https://www.modernsecurity.nl/microsoft-sentinel-ai-playbook-generator/image-54.webp"></figure><ol start="4">
<li>If it flags a missing integration profile:
<ol>
<li>Select <strong>Save</strong> and exit the VS Code environment. This preserves your conversation so far</li>
<li>Go create the missing profile under the <strong>Integration Profiles</strong> tab, exactly as in step 2</li>
<li>Return to the playbook and continue where you left off</li>
</ol>
</li>
<li>Review the plan and flow diagram carefully. This is your last checkpoint before any code gets written. If something is off, describe the change in the chat rather than editing anything manually, the generator revises the plan for you.</li>
<li>When you are satisfied, follow the on-screen instruction to switch to <strong>Act mode</strong></li>
</ol>
<figure><img
    class="my-0 rounded-md"
    loading="lazy"
    decoding="async"
    fetchpriority="auto"
    alt=""
    width="1919"
    height="998"
    src="https://www.modernsecurity.nl/microsoft-sentinel-ai-playbook-generator/image-56_hu_b86c46c06b2ea5ea.webp"
   
   
    data-zoom-src="https://www.modernsecurity.nl/microsoft-sentinel-ai-playbook-generator/image-56.webp"></figure>
<h2 class="relative group">Step 5: Generate the code in Act mode
    <div id="step-5-generate-the-code-in-act-mode" class="anchor"></div>
    
</h2>
<ol>
<li>After switching to Act mode, the generator delivers:
<ul>
<li>The complete playbook code, in Python</li>
<li>Code validation</li>
<li>Comprehensive documentation, including a visual flow diagram and a plain-language description of what the playbook does</li>
</ul>
</li>
</ol>
<figure><img
    class="my-0 rounded-md"
    loading="lazy"
    decoding="async"
    fetchpriority="auto"
    alt=""
    width="1919"
    height="998"
    src="https://www.modernsecurity.nl/microsoft-sentinel-ai-playbook-generator/image-57_hu_3acb03676474bd9b.webp"
   
   
    data-zoom-src="https://www.modernsecurity.nl/microsoft-sentinel-ai-playbook-generator/image-57.webp"></figure><figure><img
    class="my-0 rounded-md"
    loading="lazy"
    decoding="async"
    fetchpriority="auto"
    alt=""
    width="1919"
    height="997"
    src="https://www.modernsecurity.nl/microsoft-sentinel-ai-playbook-generator/image-58_hu_cfc6d921396c4323.webp"
   
   
    data-zoom-src="https://www.modernsecurity.nl/microsoft-sentinel-ai-playbook-generator/image-58.webp"></figure><ol start="4">
<li>It then asks for a real <strong>Alert ID</strong> (get the alert ID from advanced hunting for example – not the Sentinel/XDR alert ID from the portal) to test against. Use an actual alert from your environment, ideally a low-impact one the first time through. Before it runs the test, the generator outlines exactly what changes it is about to apply to your environment and asks for your approval. Read this carefully if the playbook has side effects like disabling an account or blocking an IAM user, this is your chance to catch a misunderstanding before it touches anything real.</li>
</ol>
<figure><img
    class="my-0 rounded-md"
    loading="lazy"
    decoding="async"
    fetchpriority="auto"
    alt=""
    width="1919"
    height="999"
    src="https://www.modernsecurity.nl/microsoft-sentinel-ai-playbook-generator/image-59_hu_159928d12075f789.webp"
   
   
    data-zoom-src="https://www.modernsecurity.nl/microsoft-sentinel-ai-playbook-generator/image-59.webp"></figure><ol start="5">
<li>The generator may request approval at intermediate steps of code generation. To skip repeated approval prompts, select the <strong>Edit</strong> checkbox under <strong>Auto-approve</strong>. I leave auto-approve off for the first run of any new playbook. Once I trust its behavior on a given automation pattern, I turn it on for iteration speed.</li>
</ol>

<h2 class="relative group">Step 6: Validate and save
    <div id="step-6-validate-and-save" class="anchor"></div>
    
</h2>
<ol>
<li>
<p>Manually review the generated code and documentation. The generator does not run automatic code validation beyond the test you just performed, correctness is on you.</p>
</li>
<li>
<p>To preview the generated documentation in Markdown format, press <code>Ctrl+Shift+V</code> on Windows or Linux, <code>Cmd+Shift+V</code> on macOS.</p>
</li>
<li>
<p>Select <strong>Save</strong> at the top left of the editor. One easy mistake here: selecting <strong>Save</strong> inside the chat only saves the current conversational step and confirms your approval for it, it does <strong>not</strong> save the entire playbook. Use the Save button in the editor itself.</p>
</li>
</ol>
<figure><img
    class="my-0 rounded-md"
    loading="lazy"
    decoding="async"
    fetchpriority="auto"
    alt="Playbook editor with the generated files and the Save button at the top right"
    width="1919"
    height="999"
    src="https://www.modernsecurity.nl/microsoft-sentinel-ai-playbook-generator/image-60_hu_774089488eec3c53.webp"
   
   
    data-zoom-src="https://www.modernsecurity.nl/microsoft-sentinel-ai-playbook-generator/image-60.webp"></figure><ol start="4">
<li>The playbook is created in a <strong>disabled</strong> state by default. Close the editor when you are done.</li>
</ol>

<h2 class="relative group">Step 7: Enable the playbook
    <div id="step-7-enable-the-playbook" class="anchor"></div>
    
</h2>
<ol>
<li>On the <strong>Automation</strong> page, go to the <strong>Active Playbooks</strong> tab</li>
<li>Find your newly created playbook in the list</li>
<li>Switch its status to <strong>Activate</strong></li>
</ol>
<figure><img
    class="my-0 rounded-md"
    loading="lazy"
    decoding="async"
    fetchpriority="auto"
    alt=""
    width="1919"
    height="998"
    src="https://www.modernsecurity.nl/microsoft-sentinel-ai-playbook-generator/image-61_hu_265eb1b990b169f3.webp"
   
   
    data-zoom-src="https://www.modernsecurity.nl/microsoft-sentinel-ai-playbook-generator/image-61.webp"></figure><p>Nothing runs automatically yet, even after activation, until you connect it to a trigger in the next step.</p>

<h2 class="relative group">Step 8: Create the enhanced alert trigger
    <div id="step-8-create-the-enhanced-alert-trigger" class="anchor"></div>
    
</h2>
<ol>
<li>Go to the <strong>Automation Rules</strong> tab</li>
<li>Select <strong>Create</strong> to define a new rule using the enhanced trigger</li>
</ol>
<figure><img
    class="my-0 rounded-md"
    loading="lazy"
    decoding="async"
    fetchpriority="auto"
    alt=""
    width="1919"
    height="999"
    src="https://www.modernsecurity.nl/microsoft-sentinel-ai-playbook-generator/image-62_hu_c82696c04dfc41e1.webp"
   
   
    data-zoom-src="https://www.modernsecurity.nl/microsoft-sentinel-ai-playbook-generator/image-62.webp"></figure><ol start="3">
<li>Configure the trigger:</li>
</ol>

<div class="ms-table" role="region" aria-label="Table" tabindex="0">
  <table>
      <thead>
          <tr>
              <th>Setting</th>
              <th>What it does</th>
          </tr>
      </thead>
    <tbody>
        <tr>
            <td>Conditions</td>
            <td>Criteria such as alert title, severity, or provider that decide when the rule fires</td>
        </tr>
        <tr>
            <td>Workspaces</td>
            <td>The workspaces this rule applies to. Ones you lack permission on appear grayed out</td>
        </tr>
        <tr>
            <td>Actions</td>
            <td>Select <strong>Run Generated Playbook</strong> and choose your newly enabled playbook</td>
        </tr>
    </tbody>
  </table>
</div>
<figure><img
    class="my-0 rounded-md"
    loading="lazy"
    decoding="async"
    fetchpriority="auto"
    alt=""
    width="1919"
    height="998"
    src="https://www.modernsecurity.nl/microsoft-sentinel-ai-playbook-generator/image-63_hu_7ef23de4414d7117.webp"
   
   
    data-zoom-src="https://www.modernsecurity.nl/microsoft-sentinel-ai-playbook-generator/image-63.webp"></figure><ol start="4">
<li>Select <strong>Save</strong>.</li>
</ol>
<figure><img
    class="my-0 rounded-md"
    loading="lazy"
    decoding="async"
    fetchpriority="auto"
    alt=""
    width="1919"
    height="998"
    src="https://www.modernsecurity.nl/microsoft-sentinel-ai-playbook-generator/image-64_hu_111b9340acf9485d.webp"
   
   
    data-zoom-src="https://www.modernsecurity.nl/microsoft-sentinel-ai-playbook-generator/image-64.webp"></figure><p>Enhanced Alert Trigger rules run at the tenant level and can cover multiple workspaces and alert sources in a single rule, a meaningful step up from the old alert-triggered playbook model inside analytics rules. These rules live in a separate Automation Rules table from Standard Alert Trigger rules, there is currently no automatic migration between the two, so if you are moving an existing use case over, you rebuild the trigger logic here rather than porting it.</p>

<h2 class="relative group">Step 9: Monitor execution
    <div id="step-9-monitor-execution" class="anchor"></div>
    
</h2>
<ol>
<li>Open the incident that contains the relevant alert</li>
<li>Select the <strong>Activities</strong> tab</li>
<li>Find the row labeled <strong>run playbook</strong> to see execution status and detail</li>
</ol>
<p>One gap worth flagging if you build monitoring dashboards: automation rule run results for generated playbooks show up in the incident Activities tab, but are not written to the Sentinel Health Table. If your existing playbook health reporting depends on that table, generated playbooks will not appear there, and you will want to track them separately or via the incident activity feed instead.</p>

<h2 class="relative group">Demo: building a VirusTotal URL enrichment playbook end to end
    <div id="demo-building-a-virustotal-url-enrichment-playbook-end-to-end" class="anchor"></div>
    
</h2>
<p>To make the steps above concrete, here is the full run I did in my lab tenant, from an empty Automation tab to a live rule enriching alerts with VirusTotal data. This is a good first playbook for anyone trying the generator for the first time: it is read-only, has no side effects on identities or devices, and it is genuinely one of the most common SOC enrichment tasks there is, so the value is obvious the moment you see it work.</p>
<p><strong>Scenario:</strong> when an alert contains a URL entity, look that URL up on VirusTotal and add the verdict as a comment on the incident, so an analyst gets threat context without leaving Sentinel.</p>
<p><strong>Prerequisites specific to this playbook:</strong> a VirusTotal API key (the free public API tier is enough for testing, get one from your VirusTotal account under <strong>API Key</strong>) and a second integration profile for VirusTotal, in addition to the Graph profile from step 2.</p>
<figure><img
    class="my-0 rounded-md"
    loading="lazy"
    decoding="async"
    fetchpriority="auto"
    alt=""
    width="1919"
    height="889"
    src="https://www.modernsecurity.nl/microsoft-sentinel-ai-playbook-generator/image-74_hu_6d3892a05a5c7e80.webp"
   
   
    data-zoom-src="https://www.modernsecurity.nl/microsoft-sentinel-ai-playbook-generator/image-74.webp"></figure><p><strong>Creating the VirusTotal integration profile:</strong></p>
<p>VirusTotal is one of the predefined providers in the wizard, so this is the fastest profile you will set up in this whole guide, just a name and an API key, no base URL or auth method to configure.</p>
<ol>
<li>In the Defender portal, go to <strong>Microsoft Sentinel &gt; Configuration &gt; Automation &gt; Integration Profiles &gt; Create</strong></li>
<li>On the <strong>Provider</strong> step, search for <strong>VirusTotal</strong> in the predefined provider list, select it, and select <strong>Next</strong>.</li>
</ol>
<figure><img
    class="my-0 rounded-md"
    loading="lazy"
    decoding="async"
    fetchpriority="auto"
    alt="Provider step in the integration profile wizard with VirusTotal selected from the predefined list"
    width="1919"
    height="997"
    src="https://www.modernsecurity.nl/microsoft-sentinel-ai-playbook-generator/image-65_hu_a2bad253223a42cc.webp"
   
   
    data-zoom-src="https://www.modernsecurity.nl/microsoft-sentinel-ai-playbook-generator/image-65.webp"></figure><ol start="3">
<li>On the <strong>Name and authentication</strong> step, fill in:</li>
</ol>

<div class="ms-table" role="region" aria-label="Table" tabindex="0">
  <table>
      <thead>
          <tr>
              <th>Field</th>
              <th>Value</th>
          </tr>
      </thead>
    <tbody>
        <tr>
            <td>Integration name</td>
            <td>VirusTotal</td>
        </tr>
        <tr>
            <td>API key</td>
            <td>Your VirusTotal API key</td>
        </tr>
    </tbody>
  </table>
</div>
<figure><img
    class="my-0 rounded-md"
    loading="lazy"
    decoding="async"
    fetchpriority="auto"
    alt=""
    width="1919"
    height="999"
    src="https://www.modernsecurity.nl/microsoft-sentinel-ai-playbook-generator/image-66_hu_9760851d30bab2da.webp"
   
   
    data-zoom-src="https://www.modernsecurity.nl/microsoft-sentinel-ai-playbook-generator/image-66.webp"></figure><ol start="4">
<li>Select <strong>Next</strong>, review the <strong>Summary</strong> step, and select <strong>Create</strong>.</li>
</ol>
<p>Because VirusTotal is predefined, Sentinel already knows the base URL and how to authenticate against it, you only supply the credential. This is worth knowing before you set up any other third-party service: check the predefined list first, since a growing number of common threat intel and enrichment providers only need a name and an API key rather than the full custom integration flow.</p>
<p><strong>Name and start</strong>: I created a new playbook named <code>pb-url-enrichment-virustotal</code> and selected Continue to open the VS Code environment.</p>
<figure><img
    class="my-0 rounded-md"
    loading="lazy"
    decoding="async"
    fetchpriority="auto"
    alt=""
    width="1919"
    height="999"
    src="https://www.modernsecurity.nl/microsoft-sentinel-ai-playbook-generator/image-67_hu_b3d905328463d92.webp"
   
   
    data-zoom-src="https://www.modernsecurity.nl/microsoft-sentinel-ai-playbook-generator/image-67.webp"></figure><p><strong>The Plan mode prompt</strong>:</p>
<blockquote><p><em>“Create a playbook that triggers on alerts containing a URL entity. Look up the URL using the VirusTotal integration and retrieve the analysis stats, including malicious and suspicious detection counts. Add a comment to the related incident summarizing the VirusTotal verdict, including the detection counts and a link to the full VirusTotal report.”</em></p>
</blockquote><p><strong>What came back</strong>: The generator confirmed it found the VirusTotal integration profile and asked one clarifying question, whether to submit the URL for a fresh scan if VirusTotal had no existing analysis on file, or only report on existing data. I chose to check existing analysis first and only trigger a new scan if nothing was on file, since that keeps the playbook fast for URLs VirusTotal already knows about. It then produced a flow diagram: alert trigger, extract URL entity, VirusTotal lookup, conditional branch on analysis availability, incident comment action.</p>
<p><strong>Reviewing the plan</strong>: The proposed flow matched what I asked for, so no revisions needed. I switched to Act mode.</p>
<figure><img
    class="my-0 rounded-md"
    loading="lazy"
    decoding="async"
    fetchpriority="auto"
    alt=""
    width="1919"
    height="999"
    src="https://www.modernsecurity.nl/microsoft-sentinel-ai-playbook-generator/image-70_hu_9cf5c55de444c299.webp"
   
   
    data-zoom-src="https://www.modernsecurity.nl/microsoft-sentinel-ai-playbook-generator/image-70.webp"></figure><p><strong>Act mode and testing</strong>: The generator produced the Python code, ran its own validation pass, and generated documentation with the same flow diagram rendered from the actual code path. It then asked for an Alert ID. I pointed it at a real alert in my lab workspace that had a URL entity attached. Before executing, it listed the exact change it was about to make, posting one incident comment with the VirusTotal verdict, and asked for approval. Since this playbook has no destructive side effects, I approved without hesitation.</p>
<figure><img
    class="my-0 rounded-md"
    loading="lazy"
    decoding="async"
    fetchpriority="auto"
    alt=""
    width="1919"
    height="998"
    src="https://www.modernsecurity.nl/microsoft-sentinel-ai-playbook-generator/image-68_hu_1b2560083307e2ff.webp"
   
   
    data-zoom-src="https://www.modernsecurity.nl/microsoft-sentinel-ai-playbook-generator/image-68.webp"></figure><figure><img
    class="my-0 rounded-md"
    loading="lazy"
    decoding="async"
    fetchpriority="auto"
    alt=""
    width="1919"
    height="999"
    src="https://www.modernsecurity.nl/microsoft-sentinel-ai-playbook-generator/image-69_hu_175ef7774a4ec9e0.webp"
   
   
    data-zoom-src="https://www.modernsecurity.nl/microsoft-sentinel-ai-playbook-generator/image-69.webp"></figure><p><strong>Result:</strong> The test run queried VirusTotal, retrieved the detection stats, and posted a comment on the incident with the malicious and suspicious counts plus a link to the full report. The generator confirmed the test passed. I reviewed the generated Python briefly (the VirusTotal API call, the header-based authentication, the comment formatting) before moving on.</p>
<figure><img
    class="my-0 rounded-md"
    loading="lazy"
    decoding="async"
    fetchpriority="auto"
    alt=""
    width="1917"
    height="999"
    src="https://www.modernsecurity.nl/microsoft-sentinel-ai-playbook-generator/image-71_hu_25665138eaaea689.webp"
   
   
    data-zoom-src="https://www.modernsecurity.nl/microsoft-sentinel-ai-playbook-generator/image-71.webp"></figure><p><strong>Save and enable</strong>: I saved the playbook from the editor’s Save button (not the chat), which left it in a disabled state as expected. I then went to Active Playbooks and switched it to Activate.</p>
<p><strong>The automation rule</strong>: In Automation Rules, I created a new rule with the enhanced trigger: condition set to alert entities contains a URL type, workspace scoped to my lab workspace, action set to Run Playbook targeting <code>pb-url-enrichment-virustotal</code>.</p>
<figure><img
    class="my-0 rounded-md"
    loading="lazy"
    decoding="async"
    fetchpriority="auto"
    alt=""
    width="1919"
    height="999"
    src="https://www.modernsecurity.nl/microsoft-sentinel-ai-playbook-generator/image-73_hu_1e28947d92b9fc4.webp"
   
   
    data-zoom-src="https://www.modernsecurity.nl/microsoft-sentinel-ai-playbook-generator/image-73.webp"></figure><p><strong>Live verification</strong>: I triggered a new test alert containing a known URL entity and confirmed in the incident’s Activities tab that the run playbook entry appeared with a successful status, and the VirusTotal comment was visible on the incident.</p>
<figure><img
    class="my-0 rounded-md"
    loading="lazy"
    decoding="async"
    fetchpriority="auto"
    alt=""
    width="1919"
    height="997"
    src="https://www.modernsecurity.nl/microsoft-sentinel-ai-playbook-generator/image-72_hu_4ffaa45a676ce2b4.webp"
   
   
    data-zoom-src="https://www.modernsecurity.nl/microsoft-sentinel-ai-playbook-generator/image-72.webp"></figure><p>Total time from opening the Automation tab to a live, working rule: around 15 minutes, most of which was creating the VirusTotal API key and the integration profile. If you already have the Graph profile from earlier in this guide, adding a second read-only integration like this one is fast.</p>

<h2 class="relative group">More example prompts to try
    <div id="more-example-prompts-to-try" class="anchor"></div>
    
</h2>
<p>A few prompts that map well to common SOC automation requests, beyond the VirusTotal example above:</p>
<ul>
<li><em>“Create a playbook that triggers on phishing alerts, extracts the sender email address, checks if the user exists in our directory, and if so, temporarily disables their account and notifies the security team.”</em></li>
<li><em>“Create a playbook that blocks an AWS IAM user, assigns the alert to John, and adds a remediation comment when a high severity alert includes an IAM user entity.”</em></li>
<li><em>“Create a playbook that triggers on impossible travel alerts, extracts the affected user, revokes their active sign-in sessions via Graph, and posts a comment with the two sign-in locations and timestamps involved.”</em></li>
<li><em>“Create a playbook that triggers on malware alerts with a device entity, isolates the device, and notifies the on-call channel with the device name, alert severity, and a link to the incident.”</em></li>
</ul>
<p>The pattern that works best is the same across all of them: name the trigger condition, the entity to act on, the action to take, and how to record what happened. The more precisely you name the entity field (sender email, device name, IAM user), the fewer clarifying questions you get back. Note that the phishing, IAM block, and device isolation examples above all involve a real side effect, unlike the VirusTotal demo, so test those against a low-impact alert first and review the approval prompt in Act mode carefully before confirming.</p>

<h2 class="relative group">Limitations to know before you build
    <div id="limitations-to-know-before-you-build" class="anchor"></div>
    
</h2>
<p>Worth reading before you commit a production use case to this feature:</p>
<ul>
<li><strong>Language</strong>: only Python is supported for playbook authoring</li>
<li><strong>Input</strong>: playbooks currently accept alerts as the only input type, no scheduled or manual triggers yet</li>
<li><strong>Editing</strong>: one user can edit a given playbook at a time, though different users can work on different playbooks simultaneously</li>
<li><strong>External libraries</strong>: not currently supported</li>
<li><strong>Code validation</strong>: no automatic validation beyond the test run you perform, review manually</li>
<li><strong>Scale limits per tenant</strong>: up to 100 playbooks, up to 500 integrations, up to 500 active automation rules</li>
<li><strong>Playbook size</strong>: up to 5,000 lines per playbook</li>
<li><strong>Runtime</strong>: 10 minutes maximum per execution</li>
<li><strong>AI interactions</strong>: 8M tokens per day per tenant</li>
<li><strong>Playbook nesting</strong>: not supported. A generated playbook cannot invoke another playbook, so orchestration across multiple playbooks needs a different pattern for now</li>
<li><strong>Graph and ARM integrations</strong>: not enabled by default, you have to create them manually even though they are the most common target</li>
<li><strong>Enhanced Alert Trigger rules</strong>: no priority ordering or expiration dates yet, and only one action per rule</li>
</ul>
<p>None of these are dealbreakers for typical detection-to-response automation, but the 10-minute runtime and single-action-per-rule limits are worth designing around if you are used to building more complex multi-step Logic Apps.</p>

<h2 class="relative group">Why this matters for MSSPs and MDR providers
    <div id="why-this-matters-for-mssps-and-mdr-providers" class="anchor"></div>
    
</h2>
<p>For a multi-tenant MDR operation, the interesting part of this feature is not that it writes code, it is that it lowers the skill floor for building tenant-specific response automation without pulling in a developer every time. A L2 analyst who can clearly describe a response workflow can now get a working, tested playbook without touching Logic Apps designer or writing Python from scratch.</p>
<p>The August 2026 change matters here specifically because it removes a real adoption barrier: provisioning Security Copilot capacity purely to unlock an automation feature was a hard sell across a customer base where Copilot adoption timelines vary a lot. With that dependency gone, this becomes something you can realistically standardize as part of an automation intake process rather than a feature that only shows up in tenants that already invested in Security Copilot.</p>
<p>The generated documentation and flow diagrams are also worth calling out for anyone running a service with change management requirements. Having an auto-generated description and visual flow per playbook makes it much easier to keep an automation runbook current without a separate manual documentation pass every time something changes.</p>

<h2 class="relative group">Resources
    <div id="resources" class="anchor"></div>
    
</h2>
<p><strong>Microsoft documentation</strong></p>
<ul>
<li><a href="https://learn.microsoft.com/en-us/azure/sentinel/automation/generate-playbook"  target="_blank" rel="noreferrer">Generate playbooks using AI in Microsoft Sentinel</a></li>
<li><a href="https://learn.microsoft.com/en-us/azure/sentinel/automation/create-playbooks"  target="_blank" rel="noreferrer">Create and manage Microsoft Sentinel playbooks</a></li>
<li><a href="https://learn.microsoft.com/en-us/azure/sentinel/automation/run-playbooks"  target="_blank" rel="noreferrer">Automate and run Microsoft Sentinel playbooks</a></li>
</ul>
<p><strong>Tech Community blogs</strong></p>
<ul>
<li><a href="https://techcommunity.microsoft.com/blog/microsoftsentinelblog/introducing-the-next-generation-of-soc-automation-sentinel-playbook-generator/4494438"  target="_blank" rel="noreferrer">Introducing the next generation of SOC automation: Sentinel playbook generator</a>, original announcement, June 2026</li>
<li><a href="https://techcommunity.microsoft.com/blog/microsoftsentinelblog/ai-powered-playbook-generator-now-available-to-more-customers/4544385"  target="_blank" rel="noreferrer">AI-powered playbook generator, now available to more customers</a>, Security Copilot requirement removed, August 2026</li>
</ul>

<h2 class="relative group">Final thoughts
    <div id="final-thoughts" class="anchor"></div>
    
</h2>
<p>The playbook generator is one of those features where the interesting part is not the AI, it is what the AI removes from your path: the Logic Apps designer, the connector hunting, the JSON debugging that used to gatekeep SOAR maturity behind whoever on the team happened to know Logic Apps well. Combined with the August 2026 change dropping the Security Copilot dependency, there is very little reason left not to try this in a lab tenant this week.</p>
<p>Start small. Pick one repetitive triage action your analysts do by hand today, describe it precisely in Plan mode, and see what comes out the other side. The limitations around runtime and single actions per rule mean this fits enrichment and single-step response actions best right now, not full incident orchestration, but that is exactly where most automation backlogs live anyway.</p>
<p><em>Got questions about setting this up in a multi-tenant MDR environment, or ran into something not covered here? Leave a comment or reach out via the contact page.</em></p>
]]></content:encoded><media:content url="https://www.modernsecurity.nl/microsoft-sentinel-ai-playbook-generator/featured_hu_ba4f4b2248b72838.jpg" medium="image" type="image/jpeg" width="1200" height="625"/><enclosure url="https://www.modernsecurity.nl/microsoft-sentinel-ai-playbook-generator/featured_hu_ba4f4b2248b72838.jpg" type="image/jpeg" length="94289"/></item><item><title>BYOVD is back: how EDR killers ship inside RaaS kits and how to stop them</title><link>https://www.modernsecurity.nl/byovd-edr-killers-asr-wdac-hvci/</link><guid isPermaLink="true">https://www.modernsecurity.nl/byovd-edr-killers-asr-wdac-hvci/</guid><pubDate>Thu, 20 Aug 2026 09:36:46 +0100</pubDate><dc:creator>Farid Kalaidji</dc:creator><category>Microsoft Defender XDR</category><category>Microsoft Sentinel</category><description>BYOVD-based EDR killers are now offered in ransomware-as-a-service operations. Countermeasures with ASR, vulnerable driver blocklist, HVCI, and WDAC.</description><content:encoded><![CDATA[<p>If you have been reading ransomware incident reports over the past few months, you have probably noticed the same thing I have. Almost every write-up includes some version of the same sentence: the attacker loaded a signed kernel driver and used it to kill the EDR agent before deploying the encryptor.</p>
<p>Bring Your Own Vulnerable Driver, or BYOVD, is not new. But what is new is how reliably it shows up and how professionally it is being packaged and distributed. This post covers what has changed, why your current setup probably has a gap even with tamper protection enabled, and what to actually do about it step by step on the Microsoft stack.</p>

<h2 class="relative group">What changed recently
    <div id="what-changed-recently" class="anchor"></div>
    
</h2>
<p>BYOVD used to require real operational knowledge. You needed to find a suitable driver, understand its IOCTL interface, write code to interact with it, and test it against the target EDR. That kept the barrier high enough that most RaaS affiliates skipped it.</p>
<p>That is no longer the case.</p>
<p>In June 2026, ESET published a detailed investigation into a RaaS operation called Gentlemen. The short version: Gentlemen does not leave EDR evasion up to its affiliates. The operator centrally develops and maintains its own EDR killer framework, named GentleKiller by ESET, and ships it to every affiliate as part of the onboarding package. The framework has at least eight variants, targets more than 400 processes across 48 security products, and is designed to allow fast driver swaps when a new proof-of-concept goes public.</p>
<p>ESET confirmed the gang can operationalise a newly disclosed BYOVD PoC within days of it going public. The affiliate package also bundles three externally sourced tools: HexKiller, ThrottleBlood, and HavocKiller. By the time the ESET report was published, separate ransomware tracking data had linked the group to 478 victims across 66 countries.</p>
<figure><img
    class="my-0 rounded-md"
    loading="lazy"
    decoding="async"
    fetchpriority="auto"
    alt=""
    width="1672"
    height="941"
    src="https://www.modernsecurity.nl/byovd-edr-killers-asr-wdac-hvci/image-9_hu_870e6202e76b3813.webp"
   
   
    data-zoom-src="https://www.modernsecurity.nl/byovd-edr-killers-asr-wdac-hvci/image-9.webp"></figure><p>A separate ESET analysis from earlier in 2026 counted 54 distinct EDR killer tools abusing 35 separately signed vulnerable drivers. Attackers only need one that still works. Defenders need to cover all 35.</p>
<p>Also worth flagging: in February 2026 Huntress documented an intrusion where attackers loaded a revoked EnCase forensic driver from 2006, still loadable due to a legacy exception from 2015. Once running, it called its termination routine every second against 59 hardcoded security processes. Any service that tried to restart was killed immediately. The machine was completely blind before encryption started.</p>
<p>On June 30, 2026, Marcus Hutchins (MalwareTech) published a technical analysis via Expel documenting a zero-day used by the Gentlemen group in an April intrusion: <code>ktapi.sys</code>, a Kontron industrial driver that was not present on any public blocklist at time of publication. The relevant defender takeaway is that <code>ktapi.sys</code> was a legacy cross-signed driver.</p>
<p>Starting with Windows 10 1607, Microsoft tightened kernel-mode driver signing requirements so newly signed drivers generally had to go through Microsoft’s Hardware Dev Center signing process. Previously signed legacy drivers were grandfathered in. Starting from Windows 11 25H2 (kernel build 10.0.26100.32690+), that grandfathering ended. Millions of old, unmaintained drivers that were still loadable on earlier versions are now blocked by default, and <code>ktapi.sys</code> is one of them. If your fleet is already on 25H2, that is a free win with no configuration needed. If it is not, it is worth factoring into your upgrade planning.</p>
<p>That is where we are in 2026. EDR evasion via BYOVD is a feature in an affiliate kit, and the drivers being used are sometimes zero-days that no blocklist covers.</p>

<h2 class="relative group">How BYOVD actually works
    <div id="how-byovd-actually-works" class="anchor"></div>
    
</h2>
<p>By the time BYOVD runs, the attacker already has local admin on the machine. This is post-compromise activity, not initial access. They have usually been in the environment for some time, done their reconnaissance, identified what EDR is running, and are now preparing for the final stage before encryption.</p>
<p>The sequence from that point:</p>
<ol>
<li>The attacker drops a legitimate, signed kernel driver to disk. Often an old anti-cheat driver, an OEM hardware monitoring tool, or a legacy security product component. Not malicious by design, just old and unpatched.</li>
<li>Windows loads it without objection. The signature is valid, the certificate came from a real vendor. The OS trusts it.</li>
<li>The attacker sends crafted IOCTL requests to the loaded driver. Depending on the flaw, this gives ring 0 capability to terminate arbitrary processes, remove kernel callbacks, suppress ETW providers, or patch memory in ways that blind the sensor entirely.</li>
<li>The EDR or AV agent is killed from kernel mode. No alert fires. The thing that would raise the alarm is the thing that just got taken out.</li>
<li>With the security tooling blind or dead, encryption starts. The window between EDR kill and encryption is frequently under an hour.</li>
</ol>
<figure><img
    class="my-0 rounded-md"
    loading="lazy"
    decoding="async"
    fetchpriority="auto"
    alt="BYOVD WDAC ASR HVCI Vulnerable Driver"
    width="1760"
    height="1774"
    src="https://www.modernsecurity.nl/byovd-edr-killers-asr-wdac-hvci/byovd-attack-flow-4_hu_a64385537f871df8.webp"
   
   
    data-zoom-src="https://www.modernsecurity.nl/byovd-edr-killers-asr-wdac-hvci/byovd-attack-flow-4.webp"></figure><p>To make this concrete, look at the actual cases this post is about. The Gentlemen operators specifically choose drivers that are not on any public blocklist. Their GentleKiller variants use custom rootkits and obscure anti-cheat drivers that most defenders have never heard of. When the Expel team investigated the April 2026 intrusion, the attacker used <code>ktapi.sys</code>, a Kontron industrial driver not present on any public blocklist at the time. Gentlemen can operationalise a newly disclosed driver proof-of-concept within days of it going public.</p>
<figure><img
    class="my-0 rounded-md"
    loading="lazy"
    decoding="async"
    fetchpriority="auto"
    alt=""
    width="1595"
    height="713"
    src="https://www.modernsecurity.nl/byovd-edr-killers-asr-wdac-hvci/image-11_hu_d6d898bf8638f621.webp"
   
   
    data-zoom-src="https://www.modernsecurity.nl/byovd-edr-killers-asr-wdac-hvci/image-11.webp"></figure><p>The attacker does not need a well-known, already-blocked driver. They need one driver that works and is not blocked yet. This is why HVCI and App Control are in this post: they do not depend on knowing a driver is bad in advance.</p>

<h2 class="relative group">Why tamper protection does not help here
    <div id="why-tamper-protection-does-not-help-here" class="anchor"></div>
    
</h2>
<p>Tamper protection is designed to prevent unauthorized changes to Defender configuration and common attempts to impair its services and sensor. It is not a driver admission or kernel code-integrity control.</p>
<p>If an attacker succeeds in loading and exploiting a vulnerable kernel driver, the attack has crossed a trust boundary that requires controls such as ASR, the vulnerable driver blocklist, HVCI, and App Control. A kernel driver does not request permission to kill a process. It calls a kernel function directly.</p>

<h2 class="relative group">Prerequisites: BYOVD needs local admin first
    <div id="prerequisites-byovd-needs-local-admin-first" class="anchor"></div>
    
</h2>
<p>Loading a kernel driver via <code>sc.exe create type= kernel</code> requires <code>SeLoadDriverPrivilege</code>, which by default only local administrators hold. This is a post-compromise technique. The attacker has already obtained elevated access before BYOVD runs.</p>
<p>Two things follow from this:</p>
<p>First, local admin hygiene is a meaningful pre-control: remove admin rights from standard users, enforce LAPS, and limit admin role assignments. This raises the cost of reaching BYOVD without making it impossible. Credential Guard protects LSASS credentials from being dumped, limiting the attacker’s ability to use credential theft to move laterally and reach admin on other systems. It is covered in Step 2.</p>
<p>Second, if you detect an EDR kill event, assume the attacker has local admin at minimum. Treat it as a pre-encryption signal, not an isolated incident.</p>

<h2 class="relative group">What drivers are actually being abused: LOLDrivers.io
    <div id="what-drivers-are-actually-being-abused-loldrivers-io" class="anchor"></div>
    
</h2>
<p><a href="https://www.loldrivers.io"  target="_blank" rel="noreferrer">LOLDrivers.io</a> is the community-maintained catalogue of living-off-the-land drivers, signed drivers with known vulnerabilities or malicious uses. Searching by driver name or hash shows what CVEs are linked, what capabilities the flaw exposes, and whether a driver appears in known toolkits. It is a useful baseline check before deployment.</p>
<p>The caveat: sophisticated operators like Gentlemen specifically pick drivers not yet on any blocklist. ktapi.sys was not on LOLDrivers.io at time of discovery. GentleKiller’s variants use obscure anti-cheat and hardware drivers that ESET documented after the fact. The real threat is what is not on the list yet, which is why HVCI and App Control matter. They do not depend on knowing a driver is bad in advance.</p>
<p>Drivers appearing in 2025 and 2026 BYOVD toolkits include Iobitunlocker.sys (IObit Unlocker), revoked forensic drivers from Guidance Software (EnCase), and GentleKiller variants using Safetica ProcessMonitor and Zemana WatchDog drivers. The Microsoft vulnerable driver blocklist is largely derived from LOLDrivers plus Microsoft’s own research.</p>
<figure><img
    class="my-0 rounded-md"
    loading="lazy"
    decoding="async"
    fetchpriority="auto"
    alt=""
    width="1567"
    height="598"
    src="https://www.modernsecurity.nl/byovd-edr-killers-asr-wdac-hvci/image-19_hu_e796b3fc77e0a546.webp"
   
   
    data-zoom-src="https://www.modernsecurity.nl/byovd-edr-killers-asr-wdac-hvci/image-19.webp"></figure>
<h2 class="relative group">What we are going to deploy
    <div id="what-we-are-going-to-deploy" class="anchor"></div>
    
</h2>
<p><strong>Four controls, each intercepting at a different point in the attack chain. None is sufficient alone. They cover different stages and different threat scenarios.</strong></p>
<figure><img
    class="my-0 rounded-md"
    loading="lazy"
    decoding="async"
    fetchpriority="auto"
    alt=""
    width="2000"
    height="621"
    src="https://www.modernsecurity.nl/byovd-edr-killers-asr-wdac-hvci/strategies_hu_765edd1a1b7e706e.webp"
   
   
    data-zoom-src="https://www.modernsecurity.nl/byovd-edr-killers-asr-wdac-hvci/strategies.webp"></figure>
<div class="ms-table" role="region" aria-label="Table" tabindex="0">
  <table>
      <thead>
          <tr>
              <th>Step</th>
              <th>Control</th>
              <th>Primary purpose</th>
          </tr>
      </thead>
    <tbody>
        <tr>
            <td>1</td>
            <td>ASR vulnerable driver rule</td>
            <td>Prevents known vulnerable signed drivers from being written to disk</td>
        </tr>
        <tr>
            <td>2</td>
            <td>HVCI / Memory Integrity</td>
            <td>Hardens kernel execution and constrains exploit techniques. Also enforces Microsoft’s built-in vulnerable driver blocklist automatically</td>
        </tr>
        <tr>
            <td>3</td>
            <td>Microsoft recommended driver blocklist</td>
            <td>Prevents known vulnerable drivers from loading. Most important for devices where HVCI cannot run</td>
        </tr>
        <tr>
            <td>4</td>
            <td>App Control for Business</td>
            <td>Restricts driver loading to explicitly trusted policy rules, covering previously unknown vulnerable drivers</td>
        </tr>
    </tbody>
  </table>
</div>

<h2 class="relative group">Step 1: Enable the ASR rule that blocks the driver from landing on disk
    <div id="step-1-enable-the-asr-rule-that-blocks-the-driver-from-landing-on-disk" class="anchor"></div>
    
</h2>
<p><strong>Important for servers:</strong> ASR rules only enforce when <a href="https://www.modernsecurity.nl/microsoft-defender-for-endpoint/" >Microsoft Defender Antivirus</a> is running in Active mode. If a server has a third-party AV product installed and Defender is running in Passive or EDR-only mode, this rule will not block anything. Verify Defender is in Active mode before relying on this step, especially on Windows Servers where third-party AV is common.</p>
<p>The rule you need is <strong>Block abuse of exploited vulnerable signed drivers</strong>. GUID: <code>56a863a9-875e-4185-98a7-b882c64b5ce5</code>.</p>
<p>This is one of three ASR rules Microsoft explicitly recommends enabling directly in Block mode without an audit period. The others are the LSASS credential theft rule and WMI persistence. The vulnerable driver rule has a low false positive rate in practice.</p>
<p>One thing to understand clearly before deploying: this rule prevents an application from <strong>writing</strong> a vulnerable signed driver <strong>to disk</strong>. It does not prevent a driver that is already sitting on the system from loading. Those are two separate problems and need two separate controls. This step closes the delivery problem. Steps 3 and 4 address the driver-load problem. Step 2 hardens what an exploited driver can do once it has loaded.</p>
<p><strong>Deploy via Intune:</strong></p>
<ol>
<li>Open the Intune admin center (intune.microsoft.com) and sign in with Endpoint Security Manager rights or equivalent.</li>
<li>Navigate to <strong>Endpoint security &gt; Attack surface reduction</strong>.</li>
<li>Click <strong>Create Policy</strong>.</li>
</ol>
<figure><img
    class="my-0 rounded-md"
    loading="lazy"
    decoding="async"
    fetchpriority="auto"
    alt=""
    width="1919"
    height="997"
    src="https://www.modernsecurity.nl/byovd-edr-killers-asr-wdac-hvci/image-12_hu_5ff7350064b28bfa.webp"
   
   
    data-zoom-src="https://www.modernsecurity.nl/byovd-edr-killers-asr-wdac-hvci/image-12.webp"></figure><ol start="4">
<li>Under Platform select <strong>Windows 10, Windows 11, and Windows Server</strong>. Under Profile select <strong>Attack Surface Reduction Rules</strong>. Click Create.</li>
<li>Give the policy a clear name, for example <code>BL-WIN-USR-P-ASR-Attack Surface Reduction rules-v1.0</code>. Click Next.</li>
<li>On the Configuration settings page, find <strong>Block abuse of exploited vulnerable signed drivers</strong> (and all the others if you haven’t configured it yet) and <strong>Block</strong>.</li>
</ol>
<figure><img
    class="my-0 rounded-md"
    loading="lazy"
    decoding="async"
    fetchpriority="auto"
    alt=""
    width="1919"
    height="998"
    src="https://www.modernsecurity.nl/byovd-edr-killers-asr-wdac-hvci/image-13_hu_de678be8ec8df4e7.webp"
   
   
    data-zoom-src="https://www.modernsecurity.nl/byovd-edr-killers-asr-wdac-hvci/image-13.webp"></figure><ol start="7">
<li>Click Next through Scope tags. On Assignments, target your device groups. This rule does not typically generate helpdesk noise, so I would not scope it narrowly for a first deployment.</li>
<li>Review and Create.</li>
</ol>
<p><strong>Verify with Advanced Hunting after deployment:</strong></p>
<p>Give it 24 to 48 hours, then run:</p>
<div class="highlight-wrapper"><div class="highlight"><div class="ms-code-label">KQL</div><pre tabindex="0" class="chroma"><code class="language-kql" data-lang="kql">DeviceEvents
<span class="o">|</span> <span class="k">where</span> Timestamp <span class="o">&gt;</span> <span class="nf">ago</span>(48h)
<span class="o">|</span> <span class="k">where</span> ActionType <span class="o">==</span> <span class="s">&#34;AsrVulnerableSignedDriverBlocked&#34;</span>
<span class="o">|</span> <span class="k">project</span> Timestamp, DeviceName, FileName, FolderPath,
    InitiatingProcessFileName, SHA256
<span class="o">|</span> <span class="k">order by</span> Timestamp <span class="k">desc</span></code></pre></div>
</div>
<p>If this returns results, review each one. If something legitimate in your environment is being blocked, that is the exception to investigate rather than a reason to disable the rule.</p>
<p>You can also review ASR activity in the Defender portal under <strong>Reports &gt; Attack surface reduction rules</strong>. The effective policies can also be checked here:</p>
<figure><img
    class="my-0 rounded-md"
    loading="lazy"
    decoding="async"
    fetchpriority="auto"
    alt=""
    width="1919"
    height="996"
    src="https://www.modernsecurity.nl/byovd-edr-killers-asr-wdac-hvci/image-14_hu_49a56329fee006cd.webp"
   
   
    data-zoom-src="https://www.modernsecurity.nl/byovd-edr-killers-asr-wdac-hvci/image-14.webp"></figure>
<h2 class="relative group">Step 2: Verify and enforce HVCI across your fleet
    <div id="step-2-verify-and-enforce-hvci-across-your-fleet" class="anchor"></div>
    
</h2>
<p>HVCI is a kernel hardening control, not a driver admission control. That distinction matters. A legitimately signed vulnerable driver, including ktapi.sys, satisfies HVCI’s code integrity requirements and can still load. What HVCI does is remove and constrain the exploit primitives that a driver would use to cause harm: it prevents unvalidated executable kernel code, restricts certain memory operations, and protects the code-integrity enforcement mechanism itself. It also enforces the built-in Microsoft vulnerable driver blocklist automatically as a side effect.</p>
<p>Concretely: in the Hutchins/Expel case, kCFG (which HVCI enables) would have stopped the shellcode execution step even after ktapi.sys loaded, because kCFG prevents kernel-mode indirect calls from targeting anything outside a list of valid approved entry points. Expel notes explicitly that a different exploit technique against the same driver could have worked around that. HVCI is not a guarantee. A sufficiently restrictive App Control policy is.</p>
<p>The value of HVCI for BYOVD defence is: it removes or constrains the exploitation chain, it enforces the blocklist automatically, and it makes writing reliable kernel exploits significantly harder. For most RaaS affiliates using off-the-shelf EDR killer toolkits, that is often enough. Against a determined operator writing custom exploits, it is one layer of several.</p>
<p>Most new Windows 11 hardware ships with HVCI enabled by default. The problem I keep running into in practice is that it gets silently disabled during imaging when a hardware vendor supplies a driver that is not HVCI-compatible, and nobody notices afterward.</p>
<p>One additional thing worth knowing: enabling HVCI also activates Kernel Control Flow Guard (kCFG). kCFG enforces that kernel-mode indirect calls can only target valid, approved function entry points. This is specifically what would have stopped the Hutchins/Expel exploit at its shellcode execution step, even if everything else in the chain had succeeded. It is not the headline feature of HVCI but it is part of why enabling memory integrity raises the bar beyond just blocklist enforcement.</p>
<p><strong>Verify on a device via Windows Security:</strong></p>
<p>Open <strong>Windows Security &gt; Device Security &gt; Core isolation</strong>. Memory Integrity should show as On. If the toggle is greyed out and reads “Memory integrity is off. Your device may be vulnerable”, something is blocking it.</p>
<figure><img
    class="my-0 rounded-md"
    loading="lazy"
    decoding="async"
    fetchpriority="auto"
    alt=""
    width="1107"
    height="439"
    src="https://www.modernsecurity.nl/byovd-edr-killers-asr-wdac-hvci/image-22_hu_87106e55c2819094.webp"
   
   
    data-zoom-src="https://www.modernsecurity.nl/byovd-edr-killers-asr-wdac-hvci/image-22.webp"></figure><p><strong>Enable HVCI via Intune (Settings Catalog):</strong></p>
<ol>
<li>Open the Intune admin center and navigate to <strong>Devices &gt; Configuration &gt; Create &gt; New Policy</strong>.</li>
<li>Platform: <strong>Windows 10 and later</strong>. Profile type: <strong>Settings Catalog</strong>. Click Create.</li>
<li>Give the policy a name, for example <code>BL-WIN-USR-P-DEVCONF-MDM Security Baseline version number-SC-DEV-Virtualization Based Technology-v1.0</code>.</li>
<li>Click <strong>Add settings</strong> and search for <strong>Hypervisor Enforced Code Integrity</strong> under the Virtualization Based Technology category.</li>
<li>Add the setting and set <strong>Hypervisor Enforced Code Integrity</strong> to <strong>Enabled with UEFI lock</strong>. The UEFI lock option prevents local disablement without physical UEFI access, which is the right default for managed devices.</li>
</ol>
<figure><img
    class="my-0 rounded-md"
    loading="lazy"
    decoding="async"
    fetchpriority="auto"
    alt=""
    width="1919"
    height="998"
    src="https://www.modernsecurity.nl/byovd-edr-killers-asr-wdac-hvci/image-24_hu_7f0534db929230fb.webp"
   
   
    data-zoom-src="https://www.modernsecurity.nl/byovd-edr-killers-asr-wdac-hvci/image-24.webp"></figure><ol start="6">
<li>Assign to your device groups and deploy.</li>
</ol>
<blockquote><p>Note: HVCI requires a reboot to take effect and some older or OEM drivers are not HVCI-compatible. Run the policy on a pilot group first and check <strong>Windows Security &gt; Core isolation</strong> on affected devices before broad enforcement. If a driver is incompatible, Windows Security will report a specific conflict. You need to update or remove that driver before HVCI can fully activate.</p>
</blockquote><p><strong>Enable Credential Guard alongside HVCI:</strong></p>
<p>Since HVCI and Credential Guard both depend on VBS and share the same hardware prerequisites, deploy them together on endpoint devices. Credential Guard isolates LSASS credentials in the VBS container, preventing tools like Mimikatz from dumping them even when an attacker has kernel-level code execution. Expel specifically calls this out in their ktapi.sys mitigations: if Credential Guard is active, the attacker’s ability to pivot to admin using stolen credentials is significantly limited, which means BYOVD becomes harder to reach in the first place.</p>
<p><strong>Important:</strong> Microsoft does not recommend enabling Credential Guard on domain controllers and explicitly states it provides no additional security benefit on DCs. It is also unsupported on Exchange Server. Apply this to workstations and member servers only. Use a separate scoped policy, not the same policy as your HVCI deployment targeting server OUs.</p>
<ol>
<li>In a Settings Catalog policy scoped to workstations and member servers (not DCs), search for <strong>Credential Guard</strong> under the Device Guard category.</li>
<li>Set <strong>Credential Guard</strong> to <strong>Enabled</strong>. Microsoft’s default enablement is deliberately without UEFI lock to allow remote disablement if needed. Use <strong>Enabled with UEFI lock</strong> only for high-security PAWs where you specifically need to prevent remote disablement and accept that rollback requires physical UEFI access.</li>
<li>Assign and deploy.</li>
</ol>
<p>The same compatibility notes apply: requires VBS, Secure Boot enabled, and virtualization extensions active in UEFI. Run on a pilot group first.</p>

<h2 class="relative group">Step 3: Apply the current vulnerable driver blocklist
    <div id="step-3-apply-the-current-vulnerable-driver-blocklist" class="anchor"></div>
    
</h2>
<p>Since Windows 11 2022 Update, the blocklist ships enabled by default and is automatically enforced when HVCI is active. So if Step 2 (HVCI) is fully deployed, the built-in blocklist is already running on those devices.</p>
<p>Step 3 adds value in two scenarios. For devices where HVCI cannot run, the standalone blocklist gives you driver load protection independently. For devices where HVCI is active, the standalone XML from aka.ms/VulnerableDriverBlockList is slightly more complete than the OS built-in version. Microsoft holds back some entries for compatibility reasons while vendors ship patches.</p>
<p>If HVCI is confirmed active across your entire fleet, this step is a completeness measure. If you have devices where HVCI is not running, it is more important for those specifically.</p>
<p><strong>Deploy via Intune (recommended):</strong></p>
<p>Intune deploys the driver block list as an App Control for Business policy using the XML file published by Microsoft. The XML contains Allow All rules plus specific deny rules for known vulnerable drivers, so it does not block legitimate software and can be deployed directly in enforce mode.</p>
<ol>
<li>Download the driver block rules XML from <a href="https://aka.ms/VulnerableDriverBlockList"  target="_blank" rel="noreferrer">aka.ms/VulnerableDriverBlockList</a>. Save the enforced version locally.</li>
<li>In the Intune admin center, go to <strong>Endpoint security &gt; App Control for Business</strong>.</li>
<li>Select the <strong>App Control for Business</strong> tab and click <strong>Create Policy</strong>.</li>
</ol>
<figure><img
    class="my-0 rounded-md"
    loading="lazy"
    decoding="async"
    fetchpriority="auto"
    alt=""
    width="1919"
    height="998"
    src="https://www.modernsecurity.nl/byovd-edr-killers-asr-wdac-hvci/image-26_hu_596b7a6c1222905c.webp"
   
   
    data-zoom-src="https://www.modernsecurity.nl/byovd-edr-killers-asr-wdac-hvci/image-26.webp"></figure><ol start="4">
<li>Give the policy a name, for example <code>BL-WIN-USR-P-ASR-Driver Block rules-v1.0</code>. Click Next.</li>
<li>On <strong>Configuration settings</strong>, set <strong>Configuration settings format</strong> to <strong>Enter xml data</strong>.</li>
<li>Paste the full XML content from the file you downloaded in step 1.</li>
</ol>
<figure><img
    class="my-0 rounded-md"
    loading="lazy"
    decoding="async"
    fetchpriority="auto"
    alt=""
    width="1919"
    height="997"
    src="https://www.modernsecurity.nl/byovd-edr-killers-asr-wdac-hvci/image-27_hu_97213de2cfce3f9b.webp"
   
   
    data-zoom-src="https://www.modernsecurity.nl/byovd-edr-killers-asr-wdac-hvci/image-27.webp"></figure><ol start="7">
<li>Click Next through Scope tags. On Assignments, assign to your device groups.</li>
<li>Review + create.</li>
</ol>
<blockquote><p>Note: Microsoft recommends deploying this policy alongside any existing App Control policies rather than merging them. If you do plan to merge it with an existing allowlist policy, remove the Allow All rules from the XML before merging.</p>
</blockquote><p><strong>Deploy manually via SiPolicy.p7b (alternative for non-Intune environments):</strong></p>
<p>If you need to deploy outside Intune or want the most current version of the blocklist rather than waiting for the next policy update:</p>
<ol>
<li>Download the <a href="https://aka.ms/refreshpolicy"  target="_blank" rel="noreferrer">App Control policy refresh tool</a>.</li>
<li>Download and extract the <a href="https://aka.ms/VulnerableDriverBlockList"  target="_blank" rel="noreferrer">vulnerable driver blocklist binaries</a>.</li>
</ol>
<figure><img
    class="my-0 rounded-md"
    loading="lazy"
    decoding="async"
    fetchpriority="auto"
    alt=""
    width="1587"
    height="1112"
    src="https://www.modernsecurity.nl/byovd-edr-killers-asr-wdac-hvci/image-29_hu_9696e291ed5a3d8e.webp"
   
   
    data-zoom-src="https://www.modernsecurity.nl/byovd-edr-killers-asr-wdac-hvci/image-29.webp"></figure><ol start="3">
<li>Start with the <strong>audit only</strong> version. Rename the file to <code>SiPolicy.p7b</code>.</li>
<li>Copy <code>SiPolicy.p7b</code> to <code>%windir%\system32\CodeIntegrity</code>.</li>
<li>Run the refresh tool as administrator to activate and apply the policy.</li>
<li>Open Event Viewer. Browse to <strong>Applications and Services Logs &gt; Microsoft &gt; Windows &gt; CodeIntegrity &gt; Operational</strong>. Filter on <strong>Event ID 3099</strong>.</li>
<li>Confirm the PolicyNameBuffer and PolicyIdBuffer match the values in the policy XML you downloaded. If they do, the blocklist is active.</li>
<li>Run in audit mode for a period that covers your normal driver install activity. If nothing legitimate triggers a block, swap in the enforced version and repeat the refresh step.</li>
</ol>
<blockquote><p>Note: if a vulnerable driver is already loaded when you apply the policy, it will not be evicted until reboot. Plan a reboot window into the rollout, especially on servers.</p>
</blockquote><p><strong>For fleet deployment via Intune or ConfigMgr</strong>, deploy <code>SiPolicy.p7b</code> to the CodeIntegrity folder using a Win32 app or a PowerShell remediation script, then run the refresh tool post-copy as a second step. Validate on a representative pilot group across your hardware diversity before broad enforcement.</p>

<h2 class="relative group">Step 4: App Control for Business for your most critical assets
    <div id="step-4-app-control-for-business-for-your-most-critical-assets" class="anchor"></div>
    
</h2>
<p>Steps 1 and 3 are blocklist-based. They stop drivers that are known to be bad. ktapi.sys, the zero-day used in the Gentlemen intrusion, was not on any public blocklist when it was deployed. A sufficiently restrictive App Control for Business policy stops it anyway, not because it knows ktapi.sys is bad, but because it was never on the approved list. With a restrictive policy, an unapproved driver simply does not load.</p>
<p>Most organisations are not here yet. Deployment complexity is real and a misconfigured policy can prevent Windows from booting. Get Steps 1 through 3 in place first, then plan this for your highest-risk assets. App Control lets you allowlist by publisher certificate so new driver versions from the same vendor pass automatically. You can also set a minimum build number to prevent downgrade attacks.</p>
<p>Start with the assets where the driver set is most predictable:</p>
<ul>
<li><strong>Domain controllers</strong>: stable driver set, crown jewel of every ransomware intrusion</li>
<li><strong>Jump boxes and PAWs</strong>: standardised images, minimal variation</li>
<li><strong>File servers</strong>: high-value targets with generally predictable hardware</li>
</ul>
<p><strong>Step-by-step: App Control Wizard</strong></p>
<p>Download the wizard from <code>webapp-wdac-wizard.azurewebsites.net</code> or install via <code>winget install --id Microsoft.AppControlPolicyWizard</code>. The welcome page has three options: Policy Creator, Policy Editor, and Policy Merger.</p>
<figure><img
    class="my-0 rounded-md"
    loading="lazy"
    decoding="async"
    fetchpriority="auto"
    alt=""
    width="1861"
    height="966"
    src="https://www.modernsecurity.nl/byovd-edr-killers-asr-wdac-hvci/image-30_hu_ba6f11217a4acbde.webp"
   
   
    data-zoom-src="https://www.modernsecurity.nl/byovd-edr-killers-asr-wdac-hvci/image-30.webp"></figure><p><strong>1. Create your base policy in audit mode (Policy Creator)</strong></p>
<ol>
<li>Select <strong>Policy Creator</strong>.</li>
<li>On the <strong>Policy Type</strong> screen, select <strong>Multiple Policy Format</strong> and then <strong>Base Policy</strong>. Multiple Policy Format supports Windows 10 1903 and newer, including all modern Windows Server versions. Single Policy Format is for Windows Server 2016 and 2019 only. AppIdTagging is a different feature and not relevant here.</li>
</ol>
<figure><img
    class="my-0 rounded-md"
    loading="lazy"
    decoding="async"
    fetchpriority="auto"
    alt=""
    width="1234"
    height="742"
    src="https://www.modernsecurity.nl/byovd-edr-killers-asr-wdac-hvci/image-33_hu_95a7d85561385d10.webp"
   
   
    data-zoom-src="https://www.modernsecurity.nl/byovd-edr-killers-asr-wdac-hvci/image-33.webp"></figure><ol start="3">
<li>Choose a template. For servers and DCs use <strong>Default Windows Mode</strong>, which allows Windows components, Store apps, and third-party WHQL-compatible drivers. Note: because it trusts WHQL-compatible drivers, an unknown vulnerable driver that passed WHQL could still load. For the tightest driver control, review and restrict the driver signing rules after creating the base policy. For workstations, <strong>Signed and Reputable Mode</strong> is a broader starting point that also trusts reputable signed software.</li>
<li>Name the policy, for example <code>BYOVD Protection - DC Audit</code>, and choose an output folder.</li>
</ol>
<figure><img
    class="my-0 rounded-md"
    loading="lazy"
    decoding="async"
    fetchpriority="auto"
    alt=""
    width="1234"
    height="742"
    src="https://www.modernsecurity.nl/byovd-edr-killers-asr-wdac-hvci/image-34_hu_decd606417f60993.webp"
   
   
    data-zoom-src="https://www.modernsecurity.nl/byovd-edr-killers-asr-wdac-hvci/image-34.webp"></figure><ol start="5">
<li>On the <strong>Policy Rules</strong> page, leave <strong>Audit Mode</strong> enabled. No drivers are blocked yet while you collect data. Two specific toggles worth noting here:
<ul>
<li><strong>Hypervisor-protected Code Integrity</strong> is off by default. Leave it off. HVCI is managed separately through the Intune Settings Catalog policy in Step 2. Enabling it here as well creates a conflict in management scope.</li>
<li><strong>Require WHQL</strong> is off by default. Leaving it off does not introduce a gap. The driver block rules you merge in the next step add explicit deny entries for known-bad WHQL-compatible drivers, which is a more targeted approach than requiring WHQL for everything.</li>
</ul>
</li>
</ol>
<figure><img
    class="my-0 rounded-md"
    loading="lazy"
    decoding="async"
    fetchpriority="auto"
    alt=""
    width="1234"
    height="742"
    src="https://www.modernsecurity.nl/byovd-edr-killers-asr-wdac-hvci/image-35_hu_c36e6eac958a60d0.webp"
   
   
    data-zoom-src="https://www.modernsecurity.nl/byovd-edr-killers-asr-wdac-hvci/image-35.webp"></figure><ol start="6">
<li>On the <strong>File Rules</strong> page, add publisher rules for software you know runs on these assets. A standard DC may need nothing beyond the template defaults.</li>
<li>Click <strong>Next</strong>. The wizard outputs both an <code>.xml</code> file and a <code>.cip</code> binary.</li>
</ol>
<p><strong>2. Merge the driver block rules (Policy Merger)</strong></p>
<ol>
<li>On the welcome page, select <strong>Policy Merger</strong>.</li>
<li>Add your base policy XML from the previous step.</li>
<li>Add the driver block rules XML from aka.ms/VulnerableDriverBlockList.</li>
<li>Set the output path and click <strong>Merge</strong>. The result allows your approved software and explicitly denies known-bad drivers.</li>
</ol>
<p><strong>3. Deploy in audit mode and collect events</strong></p>
<p>DCs, file servers, and jump boxes are domain-joined, not Intune-managed. Deploy the compiled binary via PowerShell, either run directly or packaged as a startup script via Group Policy or SCCM targeting the relevant server OUs.</p>
<p>Convert the XML to binary. The filename must match the PolicyID GUID from inside the XML exactly. Use this snippet to extract it automatically:</p>
<div class="highlight-wrapper"><div class="highlight"><div class="ms-code-label">PowerShell</div><pre tabindex="0" class="chroma"><code class="language-powershell" data-lang="powershell"><span class="line"><span class="cl"><span class="nv">$PolicyId</span> <span class="p">=</span> <span class="p">([</span><span class="no">xml</span><span class="p">](</span><span class="nb">Get-Content</span> <span class="s2">&#34;.\MergedPolicy.xml&#34;</span><span class="p">)).</span><span class="py">SiPolicy</span><span class="p">.</span><span class="py">PolicyID</span>
</span></span><span class="line"><span class="cl"><span class="nb">ConvertFrom-CIPolicy</span> <span class="p">`</span>
</span></span><span class="line"><span class="cl">    <span class="n">-XmlFilePath</span> <span class="s2">&#34;.\MergedPolicy.xml&#34;</span> <span class="p">`</span>
</span></span><span class="line"><span class="cl">    <span class="n">-BinaryFilePath</span> <span class="s2">&#34;.\</span><span class="nv">$PolicyId</span><span class="s2">.cip&#34;</span></span></span></code></pre></div></div>
<p>Copy the binary to the target server and reboot:</p>
<div class="highlight-wrapper"><div class="highlight"><div class="ms-code-label">PowerShell</div><pre tabindex="0" class="chroma"><code class="language-powershell" data-lang="powershell"><span class="line"><span class="cl"><span class="nb">Copy-Item</span> <span class="s2">&#34;.\</span><span class="nv">$PolicyId</span><span class="s2">.cip&#34;</span> <span class="n">-Destination</span> <span class="s2">&#34;C:\Windows\System32\CodeIntegrity\CiPolicies\Active\&#34;</span>
</span></span><span class="line"><span class="cl"><span class="nb">Restart-Computer</span></span></span></code></pre></div></div>
<p>Monitor audit events in Advanced Hunting for two to four weeks:</p>
<div class="highlight-wrapper"><div class="highlight"><div class="ms-code-label">KQL</div><pre tabindex="0" class="chroma"><code class="language-kql" data-lang="kql">DeviceEvents
<span class="o">|</span> <span class="k">where</span> ActionType <span class="o">==</span> <span class="s">&#34;AppControlCodeIntegrityPolicyAudited&#34;</span>
<span class="o">|</span> <span class="k">where</span> FileName <span class="k">endswith</span> <span class="s">&#34;.sys&#34;</span>
<span class="o">|</span> <span class="k">where</span> DeviceName <span class="k">in</span> (<span class="s">&#34;YourDC1&#34;</span>, <span class="s">&#34;YourDC2&#34;</span>)
<span class="o">|</span> <span class="k">project</span> Timestamp, DeviceName, FileName, FolderPath, SHA256
<span class="o">|</span> <span class="k">order by</span> Timestamp <span class="k">desc</span></code></pre></div>
</div>
<p>Review every driver that shows up. If everything is legitimate, proceed to enforcement.</p>
<p><strong>4. Switch to enforcement (Policy Editor)</strong></p>
<ol>
<li>In the wizard, select <strong>Policy Editor</strong> and load your merged policy XML.</li>
<li>On the <strong>Policy Rules</strong> page, toggle <strong>Audit Mode</strong> off.</li>
<li>The wizard saves a new versioned XML file, for example <code>MergedPolicy_v10.0.0.1.xml</code>.</li>
<li>Convert to binary and redeploy using the same PowerShell steps above. The reboot activates enforcement.</li>
</ol>

<h2 class="relative group">Detection: catch the driver event before the kill
    <div id="detection-catch-the-driver-event-before-the-kill" class="anchor"></div>
    
</h2>

<h3 class="relative group">ASR vulnerable-driver activity
    <div id="asr-vulnerable-driver-activity" class="anchor"></div>
    
</h3>
<p>Start with the control itself. This query shows when the <strong>Block abuse of exploited vulnerable signed drivers</strong> ASR rule was triggered in Audit or Block mode.</p>
<div class="highlight-wrapper"><div class="highlight"><div class="ms-code-label">KQL</div><pre tabindex="0" class="chroma"><code class="language-kql" data-lang="kql">DeviceEvents
<span class="o">|</span> <span class="k">where</span> Timestamp <span class="o">&gt;</span> <span class="nf">ago</span>(7d)
<span class="o">|</span> <span class="k">where</span> ActionType <span class="k">in</span> (
    <span class="s">&#34;AsrVulnerableSignedDriverAudited&#34;</span>,
    <span class="s">&#34;AsrVulnerableSignedDriverBlocked&#34;</span>
)
<span class="o">|</span> <span class="k">project</span> Timestamp, DeviceName, ActionType, FileName,
    FolderPath, InitiatingProcessFileName, SHA256
<span class="o">|</span> <span class="k">order by</span> Timestamp <span class="k">desc</span></code></pre></div>
</div>

<h3 class="relative group">Driver file dropped to an unusual location:
    <div id="driver-file-dropped-to-an-unusual-location" class="anchor"></div>
    
</h3>
<p>Legitimate driver installs rarely write .sys files to user-writable paths. This query catches the delivery step before the load.</p>
<div class="highlight-wrapper"><div class="highlight"><div class="ms-code-label">KQL</div><pre tabindex="0" class="chroma"><code class="language-kql" data-lang="kql">DeviceFileEvents
<span class="o">|</span> <span class="k">where</span> Timestamp <span class="o">&gt;</span> <span class="nf">ago</span>(1d)
<span class="o">|</span> <span class="k">where</span> FileName <span class="k">endswith</span> <span class="s">&#34;.sys&#34;</span>
<span class="o">|</span> <span class="k">where</span> FolderPath <span class="k">has_any</span> (
    <span class="s">&#34;\\Temp\\&#34;</span>, <span class="s">&#34;\\AppData\\&#34;</span>, <span class="s">&#34;\\Users\\Public\\&#34;</span>,
    <span class="s">&#34;\\PerfLogs\\&#34;</span>, <span class="s">&#34;\\Downloads\\&#34;</span>, <span class="s">&#34;\\ProgramData\\&#34;</span>
)
<span class="o">|</span> <span class="k">project</span> Timestamp, DeviceName, FileName, FolderPath,
    InitiatingProcessFileName, SHA256
<span class="o">|</span> <span class="k">order by</span> Timestamp <span class="k">desc</span></code></pre></div>
</div>
<figure><img
    class="my-0 rounded-md"
    loading="lazy"
    decoding="async"
    fetchpriority="auto"
    alt=""
    width="1917"
    height="998"
    src="https://www.modernsecurity.nl/byovd-edr-killers-asr-wdac-hvci/image-15_hu_d8392c27419fd3e0.webp"
   
   
    data-zoom-src="https://www.modernsecurity.nl/byovd-edr-killers-asr-wdac-hvci/image-15.webp"></figure>
<h3 class="relative group">Behavioral BYOVD detection: correlate driver drop and load
    <div id="behavioral-byovd-detection-correlate-driver-drop-and-load" class="anchor"></div>
    
</h3>
<p>Known hashes only catch drivers we have already seen. A stronger complementary approach is to correlate an unusual <code>.sys</code> file drop with a driver load shortly afterwards and prioritize drivers that are rare across the environment.</p>
<div class="highlight-wrapper"><div class="highlight"><div class="ms-code-label">KQL</div><pre tabindex="0" class="chroma"><code class="language-kql" data-lang="kql">DeviceFileEvents
<span class="o">|</span> <span class="k">where</span> Timestamp <span class="o">&gt;</span> <span class="nf">ago</span>(7d)
<span class="o">|</span> <span class="k">where</span> FileName <span class="k">endswith</span> <span class="s">&#34;.sys&#34;</span>
<span class="o">|</span> <span class="k">where</span> FolderPath !<span class="k">startswith</span> <span class="s">@&#34;C:\Windows&#34;</span>
<span class="o">|</span> <span class="k">where</span> FolderPath !<span class="k">startswith</span> <span class="s">@&#34;C:\Program Files&#34;</span>
<span class="o">|</span> <span class="k">where</span> <span class="k">isnotempty</span>(SHA1)
<span class="o">|</span> <span class="k">project</span>
    DropTime = Timestamp,
    DeviceId,
    DeviceName,
    SHA1,
    DriverFileName = FileName,
    DriverPath = FolderPath,
    DroppingProcess = InitiatingProcessFileName,
    DroppingProcessCommandLine = InitiatingProcessCommandLine
<span class="o">|</span> <span class="k">join</span> <span class="k">kind</span>=<span class="k">inner</span> (
    DeviceEvents
    <span class="o">|</span> <span class="k">where</span> Timestamp <span class="o">&gt;</span> <span class="nf">ago</span>(7d)
    <span class="o">|</span> <span class="k">where</span> ActionType <span class="o">==</span> <span class="s">&#34;DriverLoad&#34;</span>
    <span class="o">|</span> <span class="k">where</span> <span class="k">isnotempty</span>(SHA1)
    <span class="o">|</span> <span class="k">project</span>
        LoadTime = Timestamp,
        DeviceId,
        SHA1,
        LoadedDriver = FileName,
        LoadedDriverPath = FolderPath
) <span class="k">on</span> DeviceId, SHA1
<span class="o">|</span> <span class="k">where</span> LoadTime <span class="k">between</span> (DropTime .. DropTime + 30s)
<span class="o">|</span> <span class="k">project</span>
    DropTime,
    LoadTime,
    DeviceName,
    DriverFileName,
    DriverPath,
    DroppingProcess,
    DroppingProcessCommandLine,
    LoadedDriver,
    LoadedDriverPath,
    SHA1
<span class="o">|</span> <span class="k">order by</span> DropTime <span class="k">desc</span></code></pre></div>
</div>

<h3 class="relative group">ktapi.sys and was.exe IOCs from the Hutchins/Expel report (June 2026):
    <div id="ktapi-sys-and-was-exe-iocs-from-the-hutchins-expel-report-june-2026" class="anchor"></div>
    
</h3>
<p>The hashes below are published in the Expel investigation. Expel notes that the recovered <code>ktapi.sys</code> sample came from a third-party source and could not be confirmed as the exact copy used during the intrusion. Treat these hashes as hunting pivots rather than relying on hash-only blocking.</p>
<div class="highlight-wrapper"><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="cl">DeviceFileEvents| where Timestamp &gt; ago(30d)| where FileName in~ (&#34;ktapi.sys&#34;, &#34;was.exe&#34;)    or SHA256 in (        &#34;7ee17efef04bb7c9de90d5210263ed6993f867e5a11f86e65e3bb1362c7de237&#34;,        &#34;9ca9432b0d29204cb5420a1a6b01533d4552130c2a8a5ecd7837efadefb4a046&#34;,        &#34;89ba754861e11d9db4440b2b5db61fd5bee16752e4623c4271b8fdd0a666c677&#34;,        &#34;c277ae5a4dd62f51de5278790796cd2700de7f77ea17762e97729f27872d076b&#34;    )| project Timestamp, DeviceName, FileName, FolderPath,    InitiatingProcessFileName, SHA256| order by Timestamp desc</span></span></code></pre></div></div>

<h3 class="relative group">Hunt for known LOLDrivers in MDE
    <div id="hunt-for-known-loldrivers-in-mde" class="anchor"></div>
    
</h3>
<p>LOLDrivers publishes a Microsoft Defender query that compares actual driver-load events against its live catalogue of vulnerable and malicious drivers. The query is credited by LOLDrivers to <strong>Mehmet Ergene (@Cyb3rMonk)</strong>.</p>
<div class="highlight-wrapper"><div class="highlight"><div class="ms-code-label">KQL</div><pre tabindex="0" class="chroma"><code class="language-kql" data-lang="kql"><span class="k">let</span> LOLDrivers = <span class="k">externaldata</span> (Category:string, KnownVulnerableSamples:dynamic, Verified:string ) [h<span class="s">@&#34;https://www.loldrivers.io/api/drivers.json&#34;</span>]
    <span class="k">with</span> (format=multijson, ingestionMapping=<span class="s">&#39;[{&#34;Column&#34;:&#34;Category&#34;,&#34;Properties&#34;:{&#34;Path&#34;:&#34;$.Category&#34;}},{&#34;Column&#34;:&#34;KnownVulnerableSamples&#34;,&#34;Properties&#34;:{&#34;Path&#34;:&#34;$.KnownVulnerableSamples&#34;}},{&#34;Column&#34;:&#34;Verified&#34;,&#34;Properties&#34;:{&#34;Path&#34;:&#34;$.Verified&#34;}}]&#39;</span>)
<span class="o">|</span> <span class="k">mv-expand</span> KnownVulnerableSamples
<span class="o">|</span> <span class="k">extend</span> SHA1 = <span class="nf">tostring</span>(KnownVulnerableSamples.SHA1), SHA256 = <span class="nf">tostring</span>(KnownVulnerableSamples.SHA256)
;
<span class="c1">// you can filter the drivers further based on category or verified status</span>
DeviceEvents
<span class="o">|</span> <span class="k">where</span> ActionType <span class="o">==</span> <span class="s">&#34;DriverLoad&#34;</span>
<span class="o">|</span> <span class="k">join</span> <span class="k">kind</span>=<span class="k">inner</span> (LOLDrivers <span class="o">|</span> <span class="k">where</span> <span class="k">isnotempty</span>(SHA256)) <span class="k">on</span> SHA256
<span class="o">|</span> <span class="k">union</span> (
  DeviceEvents
  <span class="o">|</span> <span class="k">where</span> ActionType <span class="o">==</span> <span class="s">&#34;DriverLoad&#34;</span>
  <span class="o">|</span> <span class="k">join</span> <span class="k">kind</span>=<span class="k">inner</span> (LOLDrivers <span class="o">|</span> <span class="k">where</span> <span class="k">isnotempty</span>(SHA1)) <span class="k">on</span> SHA1
)</code></pre></div>
</div>
<p>This gives you a continuously updated hunt for <strong>known vulnerable or malicious drivers that were actually loaded</strong> in your environment.</p>

<h3 class="relative group">Hunt for rare driver loads
    <div id="hunt-for-rare-driver-loads" class="anchor"></div>
    
</h3>
<p>A newly introduced driver that appears on only one or two systems deserves attention, particularly on servers and other assets with a stable driver baseline. Rarity is also one of the signals used in the Ransom-ISAC behavioral detection methodology.</p>
<div class="highlight-wrapper"><div class="highlight"><div class="ms-code-label">KQL</div><pre tabindex="0" class="chroma"><code class="language-kql" data-lang="kql">DeviceEvents
<span class="o">|</span> <span class="k">where</span> Timestamp <span class="o">&gt;</span> <span class="nf">ago</span>(7d)
<span class="o">|</span> <span class="k">where</span> ActionType <span class="o">==</span> <span class="s">&#34;DriverLoad&#34;</span>
<span class="o">|</span> <span class="k">where</span> FileName <span class="k">endswith</span> <span class="s">&#34;.sys&#34;</span>
<span class="o">|</span> <span class="k">summarize</span>
    FirstSeen=<span class="nf">min</span>(Timestamp),
    LastSeen=<span class="nf">max</span>(Timestamp),
    Devices=<span class="nf">dcount</span>(DeviceId),
    DeviceList=<span class="nf">make_set</span>(DeviceName, 10)
    <span class="k">by</span> SHA1, SHA256, FileName, FolderPath
<span class="o">|</span> <span class="k">where</span> Devices <span class="o">&lt;=</span> 2
<span class="o">|</span> <span class="k">order by</span> FirstSeen <span class="k">desc</span></code></pre></div>
</div>
<figure><img
    class="my-0 rounded-md"
    loading="lazy"
    decoding="async"
    fetchpriority="auto"
    alt=""
    width="1917"
    height="995"
    src="https://www.modernsecurity.nl/byovd-edr-killers-asr-wdac-hvci/image-38_hu_f08080edaba113db.webp"
   
   
    data-zoom-src="https://www.modernsecurity.nl/byovd-edr-killers-asr-wdac-hvci/image-38.webp"></figure><p>A more advanced variation published query by <strong>Bert-JanP</strong> identifies recently created driver files on an endpoint with low global prevalence. It then cross-references these files with Windows Event ID 3004, where Windows Code Integrity validates the digital signature of kernel-mode drivers during memory loading. This detection can potentially highlight BYOVD (Bring Your Own Vulnerable Driver) scenarios.</p>
<div class="highlight-wrapper"><div class="highlight"><div class="ms-code-label">KQL</div><pre tabindex="0" class="chroma"><code class="language-kql" data-lang="kql"><span class="k">let</span> DriverwithLowPrevalence =
DeviceFileEvents
<span class="o">|</span> <span class="k">where</span> ActionType <span class="o">==</span> <span class="s">&#34;FileCreated&#34;</span>
<span class="o">|</span> <span class="k">where</span> FileName <span class="k">endswith</span> <span class="s">&#34;.sys&#34;</span>
<span class="o">|</span> <span class="k">invoke</span> <span class="nf">FileProfile</span>(SHA1,1000)
<span class="o">|</span> <span class="k">where</span> GlobalPrevalence <span class="o">&lt;=</span> 150 <span class="k">or</span> <span class="k">isempty</span>(GlobalPrevalence)
<span class="o">|</span> <span class="k">join</span> <span class="k">kind</span>=<span class="k">leftouter</span> DeviceFileCertificateInfo <span class="k">on</span> SHA1
<span class="o">|</span> <span class="k">project</span> FileName;
DeviceEvents
<span class="c1">// Event ID 3004 - Kernel-mode Driver Validation</span>
<span class="o">|</span> <span class="k">where</span> ReportId <span class="o">==</span> <span class="s">&#34;3004&#34;</span>
<span class="o">|</span> <span class="k">where</span> ActionType <span class="o">==</span> <span class="s">@&#34;DriverLoad&#34;</span>
<span class="o">|</span> <span class="k">where</span> FileName <span class="k">has_any</span>(DriverwithLowPrevalence)</code></pre></div>
</div>

<h3 class="relative group">Kernel driver registration through sc.exe
    <div id="kernel-driver-registration-through-sc-exe" class="anchor"></div>
    
</h3>
<p>Many BYOVD chains register the vulnerable driver as a kernel service before loading it. Hunting for explicit <code>sc.exe create ... type= kernel</code> activity gives you another attack-chain signal that does not depend on a known driver hash.</p>
<div class="highlight-wrapper"><div class="highlight"><div class="ms-code-label">KQL</div><pre tabindex="0" class="chroma"><code class="language-kql" data-lang="kql">DeviceProcessEvents
<span class="o">|</span> <span class="k">where</span> Timestamp <span class="o">&gt;</span> <span class="nf">ago</span>(30d)
<span class="o">|</span> <span class="k">where</span> FileName <span class="o">=~</span> <span class="s">&#34;sc.exe&#34;</span>
<span class="o">|</span> <span class="k">where</span> ProcessCommandLine <span class="k">has</span> <span class="s">&#34;create&#34;</span>
<span class="o">|</span> <span class="k">where</span> ProcessCommandLine <span class="k">has</span> <span class="s">&#34;type= kernel&#34;</span>
<span class="o">|</span> <span class="k">project</span>
    Timestamp,
    DeviceName,
    AccountName,
    ProcessCommandLine,
    InitiatingProcessFileName,
    InitiatingProcessCommandLine
<span class="o">|</span> <span class="k">order by</span> Timestamp <span class="k">desc</span></code></pre></div>
</div>
<figure><img
    class="my-0 rounded-md"
    loading="lazy"
    decoding="async"
    fetchpriority="auto"
    alt=""
    width="1917"
    height="996"
    src="https://www.modernsecurity.nl/byovd-edr-killers-asr-wdac-hvci/image-37_hu_97729a8526f68c88.webp"
   
   
    data-zoom-src="https://www.modernsecurity.nl/byovd-edr-killers-asr-wdac-hvci/image-37.webp"></figure><p>Ransom-ISAC also identifies service/driver loading and the surrounding process chain as useful telemetry when investigating BYOVD activity.</p>

<h3 class="relative group">Low-prevalence driver followed by tampering
    <div id="low-prevalence-driver-followed-by-tampering" class="anchor"></div>
    
</h3>
<p>A particularly interesting correlation is a rare driver being loaded on a device followed by Defender tampering activity. <strong>SlimKQL</strong> published this approach specifically for detecting EDR-killing tooling that uses BYOVD.</p>
<div class="highlight-wrapper"><div class="highlight"><div class="ms-code-label">KQL</div><pre tabindex="0" class="chroma"><code class="language-kql" data-lang="kql"><span class="k">let</span> DriverwithLowPrevalence =
DeviceFileEvents
<span class="o">|</span> <span class="k">where</span> ActionType <span class="o">==</span> <span class="s">&#34;FileCreated&#34;</span>
<span class="o">|</span> <span class="k">where</span> FileName <span class="k">endswith</span> <span class="s">&#34;.sys&#34;</span>
<span class="o">|</span> <span class="k">invoke</span> <span class="nf">FileProfile</span>(SHA1, 1000)
<span class="o">|</span> <span class="k">where</span> GlobalPrevalence <span class="o">&lt;=</span> 150 <span class="k">or</span> <span class="k">isempty</span>(GlobalPrevalence)
<span class="o">|</span> <span class="k">join</span> <span class="k">kind</span>=<span class="k">leftouter</span> DeviceFileCertificateInfo <span class="k">on</span> SHA1
<span class="o">|</span> <span class="k">project</span> FileName;

<span class="k">let</span> DevicewithLPDriverActivated =
DeviceEvents
<span class="o">|</span> <span class="k">where</span> ActionType <span class="o">==</span> <span class="s">&#34;DriverLoad&#34;</span>
<span class="o">|</span> <span class="k">where</span> FileName <span class="k">has_any</span>(DriverwithLowPrevalence)
<span class="o">|</span> <span class="k">distinct</span> DeviceName;

DeviceEvents
<span class="o">|</span> <span class="k">where</span> ActionType <span class="o">==</span> <span class="s">&#34;TamperingAttempt&#34;</span>
<span class="o">|</span> <span class="k">where</span> DeviceName <span class="k">in</span> (DevicewithLPDriverActivated)
<span class="o">|</span> <span class="k">project</span> Timestamp, DeviceName, ActionType, FileName, AdditionalFields
<span class="o">|</span> <span class="k">order by</span> Timestamp <span class="k">desc</span></code></pre></div>
</div>
<p>This is a higher-confidence hunt than rarity alone because it combines a <strong>low-prevalence kernel driver with subsequent security-control tampering</strong>.</p>

<h3 class="relative group">Security-tool termination
    <div id="security-tool-termination" class="anchor"></div>
    
</h3>
<p>BYOVD is often used specifically to disable EDR or antivirus processes. This query looks for common command-line attempts to stop security tooling. Adjust the process names to match the products deployed in your environment.</p>
<div class="highlight-wrapper"><div class="highlight"><div class="ms-code-label">KQL</div><pre tabindex="0" class="chroma"><code class="language-kql" data-lang="kql">DeviceProcessEvents
<span class="o">|</span> <span class="k">where</span> Timestamp <span class="o">&gt;</span> <span class="nf">ago</span>(1d)
<span class="o">|</span> <span class="k">where</span> ProcessCommandLine <span class="k">has_any</span> (
    <span class="s">&#34;sc stop&#34;</span>,
    <span class="s">&#34;taskkill /F&#34;</span>,
    <span class="s">&#34;net stop&#34;</span>
)
<span class="o">|</span> <span class="k">where</span> ProcessCommandLine <span class="k">has_any</span> (
    <span class="s">&#34;MsMpEng&#34;</span>,
    <span class="s">&#34;Sense&#34;</span>,
    <span class="s">&#34;WdNisSvc&#34;</span>,
    <span class="s">&#34;CSFalconService&#34;</span>,
    <span class="s">&#34;SentinelAgent&#34;</span>,
    <span class="s">&#34;SepMasterService&#34;</span>,
    <span class="s">&#34;mbamservice&#34;</span>,
    <span class="s">&#34;Sophos&#34;</span>
)
<span class="o">|</span> <span class="k">project</span>
    Timestamp,
    DeviceName,
    AccountName,
    ProcessCommandLine,
    InitiatingProcessFileName,
    InitiatingProcessCommandLine
<span class="o">|</span> <span class="k">order by</span> Timestamp <span class="k">desc</span></code></pre></div>
</div>
<p>This is not BYOVD-specific, but it is useful as a supporting signal and also catches simpler user-mode EDR-killing attempts.</p>

<h3 class="relative group">Gentlemen-specific hunting
    <div id="gentlemen-specific-hunting" class="anchor"></div>
    
</h3>
<p>Finally, keep one campaign-specific hunt. ESET observed the Gentlemen ransomware operation staging tooling under <code>GentlemenCollection</code>, while the later Expel investigation documented <code>ktapi.sys</code> being used against EDR.</p>
<div class="highlight-wrapper"><div class="highlight"><div class="ms-code-label">KQL</div><pre tabindex="0" class="chroma"><code class="language-kql" data-lang="kql">DeviceFileEvents
<span class="o">|</span> <span class="k">where</span> Timestamp <span class="o">&gt;</span> <span class="nf">ago</span>(30d)
<span class="o">|</span> <span class="k">where</span> FileName <span class="k">in</span>~ (<span class="s">&#34;ktapi.sys&#34;</span>, <span class="s">&#34;was.exe&#34;</span>)
    <span class="k">or</span> FolderPath <span class="k">contains</span> <span class="s">&#34;GentlemenCollection&#34;</span>
    <span class="k">or</span> InitiatingProcessFolderPath <span class="k">contains</span> <span class="s">&#34;GentlemenCollection&#34;</span>
<span class="o">|</span> <span class="k">project</span>
    Timestamp,
    DeviceName,
    FileName,
    FolderPath,
    SHA1,
    SHA256,
    InitiatingProcessFileName,
    InitiatingProcessCommandLine
<span class="o">|</span> <span class="k">order by</span> Timestamp <span class="k">desc</span></code></pre></div>
</div>
<p>One more thing worth mentioning here: if you are streaming telemetry to Microsoft Sentinel, events that have already left the endpoint before the EDR kill are still available in Sentinel even if Advanced Hunting goes dark. Getting telemetry off-box quickly is a meaningful compensating control when the on-box agent is compromised.</p>

<h2 class="relative group">What to do when this fires
    <div id="what-to-do-when-this-fires" class="anchor"></div>
    
</h2>
<p>The detection section above establishes that BYOVD activity is a pre-encryption signal. That changes how you respond. You are not investigating an isolated event. You are racing encryption.</p>
<p>If you see any of the following: an ASR vulnerable driver block, an attempted driver-based tamper alert, an unexplained loss of MDE sensor telemetry, or an EDR process termination event, treat it as a high-severity ransomware precursor and act immediately.</p>
<p><strong>Immediate steps:</strong></p>
<ol>
<li><strong>Isolate the host.</strong> Use MDE device isolation if the sensor is still alive. If the EDR agent has already been killed, device isolation may not be available. Have an out-of-band containment path ready through your network layer, NAC, firewall policy, or virtualisation platform. Do not assume MDE isolation is still functional once a kill event has fired.</li>
<li><strong>Investigate how admin was obtained.</strong> BYOVD requires local admin. Look for credential theft, lateral movement, and privilege escalation activity in the hours before the driver event.</li>
<li><strong>Hunt estate-wide immediately.</strong> Search for the same driver filename, hash, and service name across all enrolled devices. A single detection likely means the attacker has already moved laterally.</li>
<li><strong>Check whether other devices stopped reporting.</strong> If the EDR sensor was killed on one device, look for devices that went silent around the same time.</li>
<li><strong>Revoke compromised credentials.</strong> If the attacker reached local admin via credential theft, assume those credentials are compromised across the environment.</li>
<li><strong>Preserve evidence where it does not delay containment.</strong> Memory, event logs, and the driver binary are valuable. Do not delay isolation of an actively compromised system to collect them. Containment comes first.</li>
</ol>

<h2 class="relative group">What MDE alerts fire when this happens
    <div id="what-mde-alerts-fire-when-this-happens" class="anchor"></div>
    
</h2>
<p>Even when BYOVD is attempted, MDE will raise alerts at the tamper layer before or during the attack if it catches the behavior. Knowing the alert titles helps you recognize them in your queue and triage them appropriately.</p>
<p>Alert titles you may see related to BYOVD and EDR kill attempts:</p>
<ul>
<li><strong>Attempt to bypass Microsoft Defender for Endpoint client protection</strong></li>
<li><strong>Attempt to stop Microsoft Defender for Endpoint sensor</strong></li>
<li><strong>Attempt to tamper with Microsoft Defender on multiple devices</strong></li>
<li><strong>Attempt to turn off Microsoft Defender Antivirus protection</strong></li>
<li><strong>Suspicious driver installation detected</strong></li>
</ul>
<p>For the vulnerable signed driver rule specifically, Microsoft’s ASR reference confirms that the activity is surfaced through the ASR Report and Advanced Hunting rather than as a dedicated EDR alert. Separate Defender tamper and suspicious-driver detections can still generate alerts when related behavior is detected:</p>
<figure><img
    class="my-0 rounded-md"
    loading="lazy"
    decoding="async"
    fetchpriority="auto"
    alt=""
    width="1919"
    height="998"
    src="https://www.modernsecurity.nl/byovd-edr-killers-asr-wdac-hvci/image-17_hu_44b5afd4bed6e701.webp"
   
   
    data-zoom-src="https://www.modernsecurity.nl/byovd-edr-killers-asr-wdac-hvci/image-17.webp"></figure><p>If your Sentinel workspace is connected, these tamper alerts will also appear as SecurityAlert records from the MicrosoftDefenderForEndpoint source, queryable via:</p>
<div class="highlight-wrapper"><div class="highlight"><div class="ms-code-label">KQL</div><pre tabindex="0" class="chroma"><code class="language-kql" data-lang="kql">SecurityAlert
<span class="o">|</span> <span class="k">where</span> ProductName <span class="k">has</span> <span class="s">&#34;Microsoft Defender&#34;</span>
<span class="o">|</span> <span class="k">where</span> AlertName <span class="k">has_any</span> (
    <span class="s">&#34;Attempt to bypass&#34;</span>,
    <span class="s">&#34;Attempt to stop&#34;</span>,
    <span class="s">&#34;tamper with Microsoft Defender&#34;</span>,
    <span class="s">&#34;Suspicious driver&#34;</span>
)
<span class="o">|</span> <span class="k">project</span> TimeGenerated, AlertName, AlertSeverity, Entities, Description
<span class="o">|</span> <span class="k">order by</span> TimeGenerated <span class="k">desc</span></code></pre></div>
</div>
<figure><img
    class="my-0 rounded-md"
    loading="lazy"
    decoding="async"
    fetchpriority="auto"
    alt=""
    width="1919"
    height="997"
    src="https://www.modernsecurity.nl/byovd-edr-killers-asr-wdac-hvci/image-18_hu_54589bc989fdccec.webp"
   
   
    data-zoom-src="https://www.modernsecurity.nl/byovd-edr-killers-asr-wdac-hvci/image-18.webp"></figure>
<h2 class="relative group">Validate your coverage across the fleet
    <div id="validate-your-coverage-across-the-fleet" class="anchor"></div>
    
</h2>
<p>Check your Secure Score in the Defender portal under <strong>Secure Score &gt; Improvement actions</strong>, filtered by Device. It surfaces HVCI and ASR rule gaps as scored improvement actions with implementation guidance.</p>
<figure><img
    class="my-0 rounded-md"
    loading="lazy"
    decoding="async"
    fetchpriority="auto"
    alt=""
    width="2000"
    height="1140"
    src="https://www.modernsecurity.nl/byovd-edr-killers-asr-wdac-hvci/image-32_hu_79dd0040d61efedb.webp"
   
   
    data-zoom-src="https://www.modernsecurity.nl/byovd-edr-killers-asr-wdac-hvci/image-32.webp"></figure><p>Coverage percentages per rule are also visible there. A 95% coverage reading means 5% of devices are not receiving the policy, which is worth understanding before you call it done.</p>
<p><strong>Intune Security Baselines as a shortcut:</strong></p>
<p>The Windows Security Baseline and MDE Baseline in Intune ship with HVCI and several core ASR rules pre-configured. If you are not already using them, check <strong>Endpoint security &gt; Security baselines</strong> before manually configuring everything in this post. Step 3 still needs to be done manually, but the baselines close a lot of ground quickly.</p>

<h2 class="relative group">Non-BYOVD EDR killers: the parallel trend to watch
    <div id="non-byovd-edr-killers-the-parallel-trend-to-watch" class="anchor"></div>
    
</h2>
<p>BYOVD is not the only method in use. Several 2026 reports documented EDR killers that work without loading any kernel driver. Techniques include:</p>
<ul>
<li><strong>Process suspension</strong>: repeatedly suspending EDR agent threads to avoid the process restart watchdog</li>
<li><strong>WFP-based blocking</strong>: using Windows Filtering Platform rules to block the EDR agent’s network traffic, cutting off telemetry without killing the process</li>
<li><strong>Handle manipulation</strong>: obtaining handles to protected processes through indirect means to inject or manipulate memory</li>
</ul>
<p>The service termination query in the detection section catches some of these. HVCI and App Control do not protect against them. They require their own detection logic.</p>

<h2 class="relative group">Troubleshooting
    <div id="troubleshooting" class="anchor"></div>
    
</h2>
<p><strong>ASR rule is not triggering anything after deployment:</strong></p>
<ul>
<li>Confirm Microsoft Defender Antivirus is in active mode. ASR does not function in passive mode.</li>
<li>Confirm cloud-delivered protection is enabled. Several ASR rules depend on it, including this one.</li>
<li>Allow 30 minutes for Intune policy sync after creation. Check rule status under <strong>Endpoint security &gt; Attack surface reduction</strong> in the Intune portal.</li>
<li>Run a test: use a known vulnerable driver hash from LOLDrivers.io in a test environment to confirm the rule fires before declaring production clean.</li>
</ul>
<p><strong>HVCI shows “Not enabled” after policy deployment:</strong></p>
<ul>
<li>The most common cause is an incompatible driver. Check Event Viewer under <strong>System</strong> for Code Integrity or Hyper-V related warnings immediately after the policy applies and the device reboots.</li>
<li>Check that VBS (Virtualization Based Security) itself is running in <code>msinfo32</code> before HVCI. HVCI depends on VBS; if VBS is not active, HVCI cannot start.</li>
<li>Some devices require UEFI settings changes (enable Secure Boot and virtualization extensions) before VBS can activate. Check BIOS/UEFI for Intel VT-x or AMD-V, and for Secure Boot status.</li>
<li>HVCI with UEFI lock requires a reboot to fully activate. Do not check immediately after policy sync, check after reboot.</li>
</ul>
<p><strong>Blocklist policy (SiPolicy.p7b) did not apply:</strong></p>
<ul>
<li>Verify the file is in <code>%windir%\system32\CodeIntegrity</code> on the target machine.</li>
<li>Run the refresh tool as an administrator, not as a standard user.</li>
<li>Check for Event ID 3099 in the CodeIntegrity Operational log. If absent, the policy did not activate. If present but with unexpected policy names, you may have a policy conflict with an existing App Control policy on the machine.</li>
</ul>
<p><strong>A legitimate driver is being blocked by the blocklist:</strong></p>
<ul>
<li>Do not exclude it by adding a hash exception to the ASR rule. The right fix is updating the driver to a version that is not on the blocklist.</li>
<li>Contact the vendor for an updated driver version. If none exists yet, work with the vendor on getting the block lifted from the Microsoft blocklist for patched versions via the Microsoft Security Intelligence Driver Submission portal (link in references).</li>
<li>As a temporary measure, apply the blocklist in audit mode while working through the vendor update.</li>
</ul>

<h2 class="relative group">References
    <div id="references" class="anchor"></div>
    
</h2>
<ul>
<li><a href="https://learn.microsoft.com/en-us/defender-endpoint/attack-surface-reduction-rules-reference"  target="_blank" rel="noreferrer">Attack surface reduction rules reference – Microsoft Learn</a></li>
<li><a href="https://learn.microsoft.com/en-us/windows/security/application-security/application-control/app-control-for-business/design/microsoft-recommended-driver-block-rules"  target="_blank" rel="noreferrer">Microsoft recommended driver block rules – Microsoft Learn</a></li>
<li><a href="https://learn.microsoft.com/en-us/windows/security/hardware-security/enable-virtualization-based-protection-of-code-integrity"  target="_blank" rel="noreferrer">Enable virtualization-based protection of code integrity (HVCI) – Microsoft Learn</a></li>
<li><a href="https://learn.microsoft.com/en-us/windows/security/application-security/application-control/app-control-for-business/"  target="_blank" rel="noreferrer">App Control for Business overview – Microsoft Learn</a></li>
<li><a href="https://learn.microsoft.com/en-us/defender-endpoint/tamper-resiliency"  target="_blank" rel="noreferrer">Tamper resiliency in Microsoft Defender for Endpoint – Microsoft Learn</a></li>
<li><a href="https://learn.microsoft.com/en-us/windows/security/identity-protection/credential-guard/"  target="_blank" rel="noreferrer">Credential Guard overview – Microsoft Learn</a></li>
<li><a href="https://webapp-wdac-wizard.azurewebsites.net"  target="_blank" rel="noreferrer">App Control Wizard (formerly WDAC Wizard)</a></li>
<li><a href="https://www.loldrivers.io"  target="_blank" rel="noreferrer">LOLDrivers.io – living off the land drivers catalogue</a></li>
<li><a href="https://www.welivesecurity.com/en/eset-research/killing-me-gently-inside-gentlemens-edr-killer-framework/"  target="_blank" rel="noreferrer">ESET: Killing me gently – Inside Gentlemen’s EDR killer framework</a> (June 2026)</li>
<li><a href="https://expel.com/blog/not-very-gentlemanly-analyzing-a-zero-day-exploit-used-by-the-gentlemen-ransomware-to-disable-targets-edrs/"  target="_blank" rel="noreferrer">Marcus Hutchins / Expel: Not very gentlemanly – Analyzing a zero-day exploit used by The Gentlemen ransomware to disable targets’ EDRs</a> (June 2026)</li>
<li><a href="https://expel.com/blog/the-feature-that-stops-byovd-bring-your-own-vulnerable-driver/"  target="_blank" rel="noreferrer">Expel: The feature that stops BYOVD – App Control for Business deployed via Active Directory</a></li>
<li><a href="https://www.huntress.com/blog/how-attackers-disable-av-edr"  target="_blank" rel="noreferrer">Huntress: How attackers disable AV and EDR</a> (May 2026)</li>
<li><a href="https://thehackernews.com/2026/03/54-edr-killers-use-byovd-to-exploit-34.html"  target="_blank" rel="noreferrer">The Hacker News: 54 EDR killers use BYOVD to exploit 35 signed vulnerable drivers</a> (March 2026)</li>
<li><a href="https://aka.ms/VulnerableDriverBlockList"  target="_blank" rel="noreferrer">Microsoft Vulnerable Driver Blocklist download</a></li>
<li><a href="https://www.microsoft.com/wdsi/driversubmission"  target="_blank" rel="noreferrer">Microsoft Security Intelligence Driver Submission</a></li>
</ul>

<h2 class="relative group">Conclusion
    <div id="conclusion" class="anchor"></div>
    
</h2>
<p>None of these four controls is enough on its own, and they are not all equal in priority either.</p>
<p>The ASR rule stops a vulnerable driver from being written to disk but not one already sitting on the system. The blocklist stops known-bad drivers from loading, but on devices where HVCI is already active the built-in OS blocklist is already running. The standalone version adds completeness for a small number of additional entries and is most important for devices where HVCI cannot run. HVCI hardens kernel execution, constrains exploit primitives, and enforces the blocklist automatically. It is the most impactful control to deploy for most environments but it does not prevent a legitimately signed vulnerable driver from loading. App Control gives you the strongest guarantee of all, because it controls which drivers are admitted in the first place.</p>
<p>Put together: ASR in Block mode closes the delivery step. HVCI enforced fleet-wide hardens kernel execution and gives you blocklist coverage automatically. The standalone driver block list covers devices where HVCI is not running. App Control for Business on your highest-risk assets removes the dependency on any list entirely, covering even zero-day drivers no blocklist has seen yet.</p>
<p>From an MDR perspective, I treat HVCI status and ASR vulnerable-driver-rule Block coverage as fleet-wide metrics tracked on a dashboard, not one-time onboarding checkboxes. Gentlemen adopted two new BYOVD techniques within days of their public release. The blocklist updates quarterly, with additional entries delivered through monthly Windows Update servicing. That gap is real and it drifts faster than most environments expect if nobody is watching it.</p>
<p><em>Have a question or something to add? Drop it in the comments below.</em></p>
]]></content:encoded><media:content url="https://www.modernsecurity.nl/byovd-edr-killers-asr-wdac-hvci/featured_hu_9d1acd19d5d4cddc.jpg" medium="image" type="image/jpeg" width="1200" height="676"/><enclosure url="https://www.modernsecurity.nl/byovd-edr-killers-asr-wdac-hvci/featured_hu_9d1acd19d5d4cddc.jpg" type="image/jpeg" length="61030"/></item><item><title>MDTI convergence: threat intelligence now built into Defender and Sentinel</title><link>https://www.modernsecurity.nl/mdti-defender-and-sentinel/</link><guid isPermaLink="true">https://www.modernsecurity.nl/mdti-defender-and-sentinel/</guid><pubDate>Sat, 08 Aug 2026 14:18:09 +0100</pubDate><dc:creator>Farid Kalaidji</dc:creator><category>Microsoft Sentinel</category><category>Microsoft Defender XDR</category><description>Microsoft Defender Threat Intelligence (MDTI) convergence reached GA. Step-by-step on the connector, using the Graph API, and what to check before.</description><content:encoded><![CDATA[
<h2 class="relative group">Introduction
    <div id="introduction" class="anchor"></div>
    
</h2>
<p>The final phase of the Microsoft Defender Threat Intelligence (MDTI) convergence went generally available in the Defender portal on 1 August 2026. The legacy standalone portal and the legacy Intel Explorer are retired, and Microsoft threat intelligence now lives in the Threat intelligence section of the Defender portal, in entity pages, in Threat analytics, and in Sentinel through a free connector.</p>
<p>I want to walk through what actually changed, how to enable the connector step by step, how to call the Graph API, and where I would still be careful before calling it done in a tenant. I checked every claim below against Microsoft’s current documentation, and where the documentation disagrees with itself I say so.</p>

<h2 class="relative group">What actually changed
    <div id="what-actually-changed" class="anchor"></div>
    
</h2>
<ul>
<li><strong>The legacy experience is retired.</strong> Microsoft’s Learn documentation states that the legacy standalone Microsoft Threat Intelligence portal and the legacy Intel Explorer experience were retired on 1 August 2026. The Threat intelligence section of the Defender portal now has two primary pages: <strong>Overview</strong> and <strong>Intel explorer</strong>.</li>
<li><strong>The data is delivered through the free connector.</strong> Microsoft’s Message Center notice (<a href="https://mc.merill.net/message/MC1192257"  target="_blank" rel="noreferrer">MC1192257</a>) says all MDTI data has been published via the free connector in Microsoft Sentinel, with new Threat Analytics APIs replacing retired MDTI APIs.</li>
<li><strong>The licensing is simpler.</strong> The same notice says that after 1 August 2026 MDTI capabilities require an active Defender or Sentinel license. Microsoft’s Learn pages add that publicly available Microsoft Threat Intelligence data, including entity enrichments, is available to Defender XDR customers at no additional cost.</li>
</ul>
<p>One thing to do before anything else: if you built something on the old MDTI APIs, read the Message Center notice. It tells you to update your internal documentation for the new Threat Analytics APIs and connector availability, so check older integrations rather than assuming they carried over.</p>

<h2 class="relative group">Intel explorer: searching and managing threat intelligence
    <div id="intel-explorer-searching-and-managing-threat-intelligence" class="anchor"></div>
    
</h2>
<p><a href="https://security.microsoft.com/threatintelligenceexplorer"  target="_blank" rel="noreferrer">Intel explorer</a> is the search and investigation page in the Threat intelligence section (left bar). You search by keyword or value, pick a threat intelligence type, and narrow the results with filters. Per Microsoft’s documentation the types are campaigns, indicators, attack patterns, identities, threat actors, tools, vulnerabilities, and reports, and threat analytics reports are available directly from it.</p>
<figure><img
    class="my-0 rounded-md"
    loading="lazy"
    decoding="async"
    fetchpriority="auto"
    alt="MDTI"
    width="1918"
    height="996"
    src="https://www.modernsecurity.nl/mdti-defender-and-sentinel/image_hu_107bf7132dfccd61.webp"
   
   
    data-zoom-src="https://www.modernsecurity.nl/mdti-defender-and-sentinel/image.webp"></figure><p>Beyond searching, the same page is where Sentinel threat intelligence is managed. Microsoft lists these capabilities for Intel explorer:</p>
<ul>
<li>Create STIX threat intelligence objects.</li>
<li>Manage threat intelligence with ingestion rules.</li>
<li>Manage relationships between objects, and add tags.</li>
<li>Investigate indicators and related infrastructure (DNS, resolutions, WHOIS, subdomains, certificates, services, trackers, components, cookies).</li>
<li>Query threat intelligence with advanced hunting.</li>
<li>Export to TAXII 2.1 destinations.</li>
</ul>
<p>For IP address and domain indicators you can also review <code>GeoLocation</code> and <code>WhoIs</code> enrichment. Microsoft marks that enrichment as preview.</p>
<p>To create or manage Sentinel threat intelligence here you need Microsoft Sentinel Contributor or higher. One practical warning from the documentation: do not paste suspicious indicators into a browser. Search them in Intel explorer instead, and remove the brackets from defanged values like <code>contoso[.]com</code> first.</p>

<h2 class="relative group">Entity pages: reputation, infrastructure, and IoCs in context
    <div id="entity-pages-reputation-infrastructure-and-iocs-in-context" class="anchor"></div>
    
</h2>
<p>Domain, IP address, URL, and file entity pages now carry a <strong>Threat Intelligence Insights</strong> tab. All Defender XDR customers can use it with publicly available Microsoft Threat Intelligence data at no extra cost.</p>
<figure><img
    class="my-0 rounded-md"
    loading="lazy"
    decoding="async"
    fetchpriority="auto"
    alt=""
    width="1919"
    height="997"
    src="https://www.modernsecurity.nl/mdti-defender-and-sentinel/image-1_hu_db761a94b9255160.webp"
   
   
    data-zoom-src="https://www.modernsecurity.nl/mdti-defender-and-sentinel/image-1.webp"></figure><p>What you get depends on the entity type. IP addresses and domains get reputation, attributed threat reports, and infrastructure relationships (DNS records, WHOIS, host pairs, subdomains, TLS/SSL certificates, services, components, trackers, cookies). URLs and files get reputation, attributed threat reports, and sandbox analysis.</p>
<figure><img
    class="my-0 rounded-md"
    loading="lazy"
    decoding="async"
    fetchpriority="auto"
    alt=""
    width="1919"
    height="996"
    src="https://www.modernsecurity.nl/mdti-defender-and-sentinel/image-25_hu_b15ee3a97a75cab0.webp"
   
   
    data-zoom-src="https://www.modernsecurity.nl/mdti-defender-and-sentinel/image-25.webp"></figure><p>The reputation score is worth understanding rather than glancing at, since it is what you will triage against:</p>
<figure><img
    class="my-0 rounded-md"
    loading="lazy"
    decoding="async"
    fetchpriority="auto"
    alt=""
    width="1246"
    height="101"
    src="https://www.modernsecurity.nl/mdti-defender-and-sentinel/image-26_hu_81ff8b04398564d3.webp"
   
   
    data-zoom-src="https://www.modernsecurity.nl/mdti-defender-and-sentinel/image-26.webp"></figure>
<div class="ms-table" role="region" aria-label="Table" tabindex="0">
  <table>
      <thead>
          <tr>
              <th>Score</th>
              <th>Category</th>
              <th>What it means</th>
          </tr>
      </thead>
    <tbody>
        <tr>
            <td>75–100</td>
            <td>Malicious</td>
            <td>Confirmed associations to known malicious infrastructure on Microsoft’s blocklist, with matches to machine learning rules that detect suspicious activity</td>
        </tr>
        <tr>
            <td>50–74</td>
            <td>Suspicious</td>
            <td>Likely associated with suspicious infrastructure, matching three or more machine learning rules</td>
        </tr>
        <tr>
            <td>25–49</td>
            <td>Neutral</td>
            <td>Matches at least two machine learning rules</td>
        </tr>
        <tr>
            <td>0–24</td>
            <td>Unknown</td>
            <td>One or zero rule matches</td>
        </tr>
    </tbody>
  </table>
</div>
<p>Microsoft is explicit that the score should be read holistically. The combination of signals (top-level domain, hosting provider, name server, registrar, TLS certificate characteristics) predicts maliciousness, not any single rule.</p>
<figure><img
    class="my-0 rounded-md"
    loading="lazy"
    decoding="async"
    fetchpriority="auto"
    alt=""
    width="1919"
    height="999"
    src="https://www.modernsecurity.nl/mdti-defender-and-sentinel/image-27_hu_d5fdd05516e6cb4a.webp"
   
   
    data-zoom-src="https://www.modernsecurity.nl/mdti-defender-and-sentinel/image-27.webp"></figure><p>You reach the tab from an incident (select an entity in the evidence or alert details), from global search, from advanced hunting results, or by direct navigation. On the entity page it sits next to the Overview tab.</p>

<h2 class="relative group">Threat analytics: reports and IoCs
    <div id="threat-analytics-reports-and-iocs" class="anchor"></div>
    
</h2>
<p>Threat analytics is Microsoft’s in-product threat reporting. Each report has an Overview, an Analyst report, Related incidents, Impacted assets, Endpoints exposure, Recommended actions, and an Indicators tab.</p>
<p>The Overview gives you the threat at a glance: aliases (names used by other vendors), origin, related intelligence, targeted countries and industries, and observed MITRE ATT&amp;CK techniques. It then shows what the threat means for your organization through related incidents, impacted assets, endpoint exposure, and recommended actions.</p>
<figure><img
    class="my-0 rounded-md"
    loading="lazy"
    decoding="async"
    fetchpriority="auto"
    alt=""
    width="1919"
    height="999"
    src="https://www.modernsecurity.nl/mdti-defender-and-sentinel/image-21_hu_49aeda637dc39000.webp"
   
   
    data-zoom-src="https://www.modernsecurity.nl/mdti-defender-and-sentinel/image-21.webp"></figure><p>The <strong>Indicators</strong> tab lists the IoCs tied to the threat. Microsoft researchers update them in real time, and expired IoCs stay in the list so you can investigate past activity. It is marked preview, and only verified customers can access it.</p>
<figure><img
    class="my-0 rounded-md"
    loading="lazy"
    decoding="async"
    fetchpriority="auto"
    alt=""
    width="1919"
    height="997"
    src="https://www.modernsecurity.nl/mdti-defender-and-sentinel/image-22_hu_89e8f9d74b5d30be.webp"
   
   
    data-zoom-src="https://www.modernsecurity.nl/mdti-defender-and-sentinel/image-22.webp"></figure><p>One licensing detail from the documentation: you need a license for at least one Microsoft Defender product to use Threat analytics, and Sentinel SIEM customers only get certain sections or tabs.</p>

<h2 class="relative group">Step by step: enabling the connector in Sentinel
    <div id="step-by-step-enabling-the-connector-in-sentinel" class="anchor"></div>
    
</h2>
<p>Before you start, you need the Microsoft Sentinel Contributor role at the resource group level to install content, and read and write permissions on the Sentinel workspace to configure the connector. Sentinel in the Azure portal is scheduled to move to the Defender portal only after 31 March 2027, so I use the Defender portal paths below.</p>
<ol>
<li><strong>Go to Microsoft Sentinel &gt; Content management &gt; Content hub.</strong> This is where you install any Sentinel solution, threat intelligence included.</li>
<li><strong>Find the Threat Intelligence solution and select Install/Update.</strong></li>
<li><strong>Go to Microsoft Sentinel &gt; Configuration &gt; Data connectors.</strong> In my tenant the connector is listed as <strong>Threat Intelligence (NEW)</strong>, next to the older Microsoft Defender Threat Intelligence connector. Microsoft’s documentation does not use that name yet, it still refers to the standard and premium Defender Threat Intelligence data connectors.</li>
<li><strong>Open the connector page and select Connect.</strong> It is not connected by default in a new workspace, so nothing syncs until you do this.</li>
<li><strong>Wait for the status to change to Connected.</strong> Once it does, indicators start flowing into your workspace.</li>
</ol>
<figure><img
    class="my-0 rounded-md"
    loading="lazy"
    decoding="async"
    fetchpriority="auto"
    alt=""
    width="1919"
    height="999"
    src="https://www.modernsecurity.nl/mdti-defender-and-sentinel/image-23_hu_fba9f710207f4998.webp"
   
   
    data-zoom-src="https://www.modernsecurity.nl/mdti-defender-and-sentinel/image-23.webp"></figure><ol start="6">
<li><strong>Confirm it is actually working.</strong> Go to Logs and run this:</li>
</ol>
<div class="highlight-wrapper"><div class="highlight"><div class="ms-code-label">KQL</div><pre tabindex="0" class="chroma"><code class="language-kql" data-lang="kql">ThreatIntelIndicators
<span class="o">|</span> <span class="k">where</span> TimeGenerated <span class="o">&gt;</span> <span class="nf">ago</span>(1d)
<span class="o">|</span> <span class="k">summarize</span> <span class="k">count</span>() <span class="k">by</span> SourceSystem</code></pre></div>
</div>
<p>Rows within a few minutes means ingestion is working. The ingested intelligence is then available to the <code>TI map...</code> analytics rule templates and to hunting.</p>
<figure><img
    class="my-0 rounded-md"
    loading="lazy"
    decoding="async"
    fetchpriority="auto"
    alt=""
    width="1465"
    height="773"
    src="https://www.modernsecurity.nl/mdti-defender-and-sentinel/image-77_hu_67d8496d0684612d.webp"
   
   
    data-zoom-src="https://www.modernsecurity.nl/mdti-defender-and-sentinel/image-77.webp"></figure><p><strong>Which table?</strong> Sentinel now stores threat intelligence in the <code>ThreatIntelIndicators</code> and <code>ThreatIntelObjects</code> tables. Microsoft stopped ingesting into the legacy <code>ThreatIntelligenceIndicator</code> table in 2025, so queries, rules, and workbooks that still read from it need migrating. Microsoft’s Learn documentation shows how to rewrite those queries for the new schema.</p>

<h2 class="relative group">The Graph API side
    <div id="the-graph-api-side" class="anchor"></div>
    
</h2>
<p>For enrichment or SOAR automation, the Microsoft Graph Threat Intelligence API is the piece to use. It sits under <code>/security/threatIntelligence</code> and covers hosts, passive DNS, WHOIS, SSL certificates, intelligence profiles, vulnerabilities, and articles. The overview page states that the APIs are available to all customers with a Defender XDR and/or Sentinel license, with no separate license required.</p>
<p>The quickest way to try it is Graph Explorer, Microsoft’s own tool. You sign in with your own account, so there is no app registration, secret, or token to handle. The method reference pages list <code>ThreatIntelligence.Read.All</code> as the least privileged permission, and Graph Explorer uses it as a delegated permission on your signed-in account.</p>
<ol>
<li><strong>Open Graph Explorer.</strong> Go to <code>https://developer.microsoft.com/graph/graph-explorer</code>.</li>
<li><strong>Sign in.</strong> Select <strong>Sign in to Graph Explorer</strong> and use an account from your Defender or Sentinel tenant.</li>
<li><strong>Consent to the permission.</strong> Open the <strong>Modify permissions</strong> tab under the request bar, search for <code>ThreatIntelligence</code>, and select <strong>Consent</strong> next to <code>ThreatIntelligence.Read.All</code>. If consent is blocked, an admin needs to approve it for the tenant.</li>
<li><strong>Enter the request.</strong> Set the method to <strong>GET</strong>, the version to <strong>v1.0</strong>, and paste this URL:</li>
</ol>
<div class="highlight-wrapper"><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="cl">https://graph.microsoft.com/v1.0/security/threatIntelligence/hosts/newsplits.com/reputation</span></span></code></pre></div></div>
<ol start="5">
<li><strong>Select Run query.</strong> The status shows <code>200 OK</code> and the <strong>Response preview</strong> tab shows the JSON.</li>
</ol>
<p><code>newsplits.com</code> is the domain from the entity page screenshots above. It is only a lookup value in the URL, so don’t browse to it. This is the response I got in Graph Explorer:</p>
<figure><img
    class="my-0 rounded-md"
    loading="lazy"
    decoding="async"
    fetchpriority="auto"
    alt=""
    width="1651"
    height="835"
    src="https://www.modernsecurity.nl/mdti-defender-and-sentinel/image-75_hu_56911013abded1a8.webp"
   
   
    data-zoom-src="https://www.modernsecurity.nl/mdti-defender-and-sentinel/image-75.webp"></figure><p>It lines up with the portal view of the same domain: score 100, classification malicious, and one high severity <strong>Cyber Threat Intelligence</strong> rule with the description “Daffodil Gust”. The <code>id</code> is just the host name, base64 encoded. The <code>relatedDetailsUrl</code> is a link into Threat analytics in the Defender portal, which is how you get from a verdict to the research behind it.</p>
<p>The <code>score</code> and <code>classification</code> pair is what I would use as an automation gate: if <code>classification</code> comes back <code>malicious</code> or <code>suspicious</code>, branch the playbook into containment or further enrichment, otherwise keep it as passive context on the incident.</p>
<ol start="6">
<li><strong>Try WHOIS.</strong> Change the URL and run it again:</li>
</ol>
<div class="highlight-wrapper"><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="cl">https://graph.microsoft.com/v1.0/security/threatIntelligence/hosts/newsplits.com/whois</span></span></code></pre></div></div>
<figure><img
    class="my-0 rounded-md"
    loading="lazy"
    decoding="async"
    fetchpriority="auto"
    alt=""
    width="1650"
    height="832"
    src="https://www.modernsecurity.nl/mdti-defender-and-sentinel/image-76_hu_5b74d9a2a00f3cf0.webp"
   
   
    data-zoom-src="https://www.modernsecurity.nl/mdti-defender-and-sentinel/image-76.webp"></figure><p>If something fails:</p>
<ul>
<li><strong>403:</strong> the permission was not consented, or your account lacks the license or role.</li>
<li><strong>401:</strong> sign in again.</li>
<li><strong>A licensing error:</strong> see the inconsistency below.</li>
</ul>
<p>Microsoft’s API overview groups the rest of the surface by use case. These are the ones I would reach for during an investigation:</p>

<div class="ms-table" role="region" aria-label="Table" tabindex="0">
  <table>
      <thead>
          <tr>
              <th>Use case</th>
              <th>REST resource</th>
          </tr>
      </thead>
    <tbody>
        <tr>
            <td>Read articles about threat intelligence</td>
            <td><code>articles</code></td>
        </tr>
        <tr>
            <td>Read intelligence profiles about threat actors and common tools of compromise</td>
            <td><code>intelligenceProfiles</code></td>
        </tr>
        <tr>
            <td>Read information about a host, including reputation, cookies, and passive DNS</td>
            <td><code>hosts/{host}</code></td>
        </tr>
        <tr>
            <td>Read passive DNS records about a host</td>
            <td><code>hosts/{host}/passiveDns</code></td>
        </tr>
        <tr>
            <td>Read WHOIS details for a host</td>
            <td><code>hosts/{host}/whois</code></td>
        </tr>
        <tr>
            <td>Read SSL certificate data observed on a host</td>
            <td><code>hosts/{host}/sslCertificates</code></td>
        </tr>
        <tr>
            <td>Read details about a vulnerability</td>
            <td><code>vulnerabilities/{vulnerabilityId}</code></td>
        </tr>
    </tbody>
  </table>
</div>
<p>Graph Explorer runs as you, with delegated access. For automation you would register an app and use application permissions with a client secret or certificate, which is a different identity and a different setup.</p>
<p>For a quick phishing check: pull the domain from an incident, call <code>reputation</code> for a fast verdict, and fall back to <code>whois</code> or <code>passiveDns</code> if it is inconclusive.</p>
<p><strong>Doc inconsistency to know about:</strong> the <code>hostReputation</code> and <code>host</code> reference pages (and possibly others) still say the API requires an active Defender Threat Intelligence Portal license and API add-on license. That contradicts the API overview and Microsoft’s Message Center notice. If a call fails on licensing, that stale note is likely why.</p>

<h2 class="relative group">What I would still check before calling this done
    <div id="what-i-would-still-check-before-calling-this-done" class="anchor"></div>
    
</h2>
<ul>
<li><strong>Preview labels.</strong> The entity page Insights tab, the Indicators tab on reports, and the GeoLocation and WhoIs enrichment in Intel explorer are all still marked Preview in Microsoft’s docs. Build accordingly.</li>
<li><strong>Table migration.</strong> Anything still reading <code>ThreatIntelligenceIndicator</code> is reading a table that no longer receives new data.</li>
<li><strong>Duplicate connectors.</strong> If you run both the older Microsoft Defender Threat Intelligence connector and the newer one, check <code>SourceSystem</code> on <code>ThreatIntelIndicators</code> for duplicates before assuming this was a free upgrade with zero cost impact.</li>
<li><strong>Old rules and old names.</strong> Detections scoped to a specific connector or source need a check.</li>
<li><strong>Licensing wording.</strong> Some Learn pages still talk about a separate license, including the Graph reference pages above and the premium prerequisite on the connector page. The Message Center notice says an active Defender or Sentinel license is enough. Confirm in your own tenant.</li>
<li><strong>Rollout.</strong> Do not assume every tenant looks the same. Check the Threat intelligence menu per tenant.</li>
</ul>

<h2 class="relative group">Sources
    <div id="sources" class="anchor"></div>
    
</h2>
<ul>
<li><a href="https://techcommunity.microsoft.com/blog/microsoftthreatprotectionblog/mdti-convergence-in-microsoft-sentinel-and-defender-xdr-is-complete/4541279"  target="_blank" rel="noreferrer">Microsoft Tech Community: MDTI convergence in Microsoft Sentinel and Defender XDR is complete</a></li>
<li><a href="https://mc.merill.net/message/MC1192257"  target="_blank" rel="noreferrer">Microsoft Message Center notice MC1192257: Microsoft Defender Threat Intelligence: Convergence with Microsoft Defender and Microsoft Sentinel (mirror)</a></li>
<li><a href="https://learn.microsoft.com/en-us/defender-xdr/defender-threat-intelligence"  target="_blank" rel="noreferrer">Microsoft Learn: Threat intelligence in Microsoft Defender</a></li>
<li><a href="https://learn.microsoft.com/en-us/defender-xdr/threat-intelligence-transition"  target="_blank" rel="noreferrer">Microsoft Learn: Transition to the new Threat intelligence experience</a></li>
<li><a href="https://learn.microsoft.com/en-us/defender-xdr/threat-intelligence-explorer"  target="_blank" rel="noreferrer">Microsoft Learn: Use Intel explorer in Microsoft Defender</a></li>
<li><a href="https://learn.microsoft.com/en-us/defender-xdr/entity-page-threat-intelligence"  target="_blank" rel="noreferrer">Microsoft Learn: View threat intelligence in entity pages</a></li>
<li><a href="https://learn.microsoft.com/en-us/defender-xdr/threat-analytics"  target="_blank" rel="noreferrer">Microsoft Learn: Threat analytics in Microsoft Defender</a></li>
<li><a href="https://learn.microsoft.com/en-us/azure/sentinel/connect-mdti-data-connector"  target="_blank" rel="noreferrer">Microsoft Learn: Enable the Microsoft Defender Threat Intelligence data connector</a></li>
<li><a href="https://learn.microsoft.com/en-us/azure/sentinel/work-with-stix-objects-indicators"  target="_blank" rel="noreferrer">Microsoft Learn: Work with STIX objects and indicators in Microsoft Sentinel</a></li>
<li><a href="https://learn.microsoft.com/en-us/graph/api/resources/security-threatintelligence-overview"  target="_blank" rel="noreferrer">Microsoft Learn: Microsoft Threat Intelligence APIs overview (Microsoft Graph)</a></li>
<li><a href="https://learn.microsoft.com/en-us/graph/api/security-host-get-reputation?view=graph-rest-1.0"  target="_blank" rel="noreferrer">Microsoft Learn: Get hostReputation (Microsoft Graph API reference)</a></li>
</ul>

<h2 class="relative group">Bottom line
    <div id="bottom-line" class="anchor"></div>
    
</h2>
<p>For anyone running <a href="https://www.modernsecurity.nl/wp-admin/edit.php" >Sentinel</a> or Defender XDR, this puts Microsoft threat intelligence inside the tools your analysts already use: entity pages during triage, Intel explorer for pivoting, Threat analytics for reporting, and the Graph API for automation. The catch is not the convergence itself. It is making sure your connectors, tables, analytics rules, and cost baselines do not quietly assume the old setup.</p>
]]></content:encoded><media:content url="https://www.modernsecurity.nl/mdti-defender-and-sentinel/featured_hu_dd324eb8853852b2.jpg" medium="image" type="image/jpeg" width="1200" height="625"/><enclosure url="https://www.modernsecurity.nl/mdti-defender-and-sentinel/featured_hu_dd324eb8853852b2.jpg" type="image/jpeg" length="97480"/></item><item><title>AI agent runtime protection in Microsoft Defender for Endpoint</title><link>https://www.modernsecurity.nl/ai-agent-runtime-protection/</link><guid isPermaLink="true">https://www.modernsecurity.nl/ai-agent-runtime-protection/</guid><pubDate>Sun, 05 Jul 2026 15:07:56 +0100</pubDate><dc:creator>Farid Kalaidji</dc:creator><category>Microsoft Defender for Endpoint</category><category>Microsoft Defender XDR</category><category>Microsoft Sentinel</category><description>How Microsoft Defender for Endpoint's AI agent runtime protection detects and blocks prompt injections before executing (now in preview)</description><content:encoded><![CDATA[<p>Discovery tells you an agent exists. It doesn’t tell you when someone tries to hijack it. That’s the gap <strong>AI agent runtime protection</strong> in <a href="https://www.modernsecurity.nl/microsoft-defender-for-endpoint/" >Microsoft Defender for Endpoint</a> closes, and unlike discovery, this one actually stops things and raises alerts. It’s included with Defender for Endpoint Plan 2, Microsoft 365 E5, Microsoft Agent 365, or Microsoft 365 E7, though licensing scope for preview features like this one can still shift before general availability.</p>
<p>If a coding agent fetches a project’s documentation to answer a question, and that page contains hidden text instructing the agent to read the local <code>.env</code> file and post its contents to an external URL, the agent has no way to tell that instruction apart from the legitimate page content. It just read it. Runtime protection is what catches that moment and blocks it before anything leaves the device.</p>

<h2 class="relative group">What runtime protection detects
    <div id="what-runtime-protection-detects" class="anchor"></div>
    
</h2>
<p>The target is prompt injection: malicious instructions hidden inside otherwise legitimate content that an agent reads and then acts on. Defender inspects the three points where content enters or leaves the agent’s reasoning: the prompt itself, the tool call the agent is about to make, and the tool’s response once it comes back. It doesn’t matter where the injected instruction came from, a file, a web page, a repository, or a tool response, all three surfaces get inspected.</p>

<h2 class="relative group">How AI agent runtime protection works
    <div id="how-ai-agent-runtime-protection-works" class="anchor"></div>
    
</h2>
<p>This runs on agent hooks, defined points in an agent’s execution flow where an external tool can inspect and act before the agent continues. Claude Code and GitHub Copilot CLI both expose these hook points natively, which is what lets Defender plug in without touching the underlying model.</p>
<p>Three stages get inspected:</p>
<ul>
<li><strong>User prompt</strong>: the prompt submitted to the agent</li>
<li><strong>Pre-tool call</strong>: the tool invocation request, before it executes</li>
<li><strong>Post-tool response</strong>: the tool’s response, after it comes back</li>
</ul>
<p>Each of these is a fast inline check at a single point, not continuous monitoring of the whole agent process, so the latency hit is minimal.</p>

<h2 class="relative group">The three modes
    <div id="the-three-modes" class="anchor"></div>
    
</h2>
<ul>
<li><strong>Block</strong>: Defender stops the action, notifies the user in the agent UI and via a Windows toast, records the detection in protection history, and raises a security alert correlated into an incident for the SOC.</li>
<li><strong>Audit</strong>: Defender lets the action continue but still records the detection and raises the alert, just as informational rather than something requiring triage.</li>
<li><strong>Disabled</strong>: no inspection at all.</li>
</ul>
<p>Microsoft’s own recommendation is to start in audit mode, watch what comes in, and only flip to block once you trust the accuracy. Worth noting the setting itself is protected by tamper protection, so it can’t be quietly switched off once you’ve enabled it.</p>

<h2 class="relative group">Prerequisites
    <div id="prerequisites" class="anchor"></div>
    
</h2>

<div class="ms-table" role="region" aria-label="Table" tabindex="0">
  <table>
      <thead>
          <tr>
              <th>Requirement</th>
              <th>Detail</th>
          </tr>
      </thead>
    <tbody>
        <tr>
            <td>Onboarding</td>
            <td>Device onboarded to Microsoft Defender for Endpoint</td>
        </tr>
        <tr>
            <td>Operating system</td>
            <td>Supported version of Windows, with Defender Antivirus on current monthly platform and engine updates</td>
        </tr>
        <tr>
            <td>Update channel</td>
            <td>Devices must be on the <strong>Beta</strong> platform and engine update channel, this is a hard requirement during preview</td>
        </tr>
        <tr>
            <td>Antivirus mode</td>
            <td>Defender Antivirus running in active mode</td>
        </tr>
        <tr>
            <td>Supported agent</td>
            <td>One or more supported local AI agents installed, and the agent must natively support a hooks framework</td>
        </tr>
    </tbody>
  </table>
</div>
<p>Right now the supported agent list is short: <strong>Claude Code</strong> and <strong>GitHub Copilot CLI</strong>. That’s noticeably narrower than the list of agents Defender can merely discover, so don’t assume every agent your discovery inventory picks up is also covered by runtime protection.</p>

<h2 class="relative group">The rollout Microsoft recommends, and I’d actually follow it
    <div id="the-rollout-microsoft-recommends-and-id-actually-follow-it" class="anchor"></div>
    
</h2>
<ol>
<li><strong>Test</strong>: enable runtime protection in audit mode on a small set of devices where the supported agents are actively used.</li>
<li><strong>Review</strong>: watch alerts in the Defender portal for one to two weeks, and submit any false positives to Microsoft.</li>
<li><strong>Deploy</strong>: roll out audit mode to additional device groups.</li>
<li><strong>Enforce</strong>: switch to block mode once you’ve validated the alerts are accurate and actionable.</li>
</ol>
<p>Skipping straight to block mode on a feature that’s still in preview is asking for a frustrated developer at your service desk.</p>

<h2 class="relative group">Enabling it on a single device
    <div id="enabling-it-on-a-single-device" class="anchor"></div>
    
</h2>
<p>For testing or validation, this is a PowerShell job, no Intune policy exists for this yet.</p>
<ol>
<li>Open an elevated PowerShell session.</li>
<li>Put the device on the Beta update channel:</li>
</ol>
<div class="highlight-wrapper"><div class="highlight"><div class="ms-code-label">PowerShell</div><pre tabindex="0" class="chroma"><code class="language-powershell" data-lang="powershell"><span class="line"><span class="cl"><span class="nb">Set-MpPreference</span> <span class="n">-PlatformUpdatesChannel</span> <span class="n">Beta</span>
</span></span><span class="line"><span class="cl"><span class="nb">Set-MpPreference</span> <span class="n">-EngineUpdatesChannel</span> <span class="n">Beta</span></span></span></code></pre></div></div>
<ol start="3">
<li>Force three signature updates. This is required for preview validation, not optional:</li>
</ol>
<div class="highlight-wrapper"><div class="highlight"><div class="ms-code-label">PowerShell</div><pre tabindex="0" class="chroma"><code class="language-powershell" data-lang="powershell"><span class="line"><span class="cl"><span class="nb">Update-MpSignature</span>
</span></span><span class="line"><span class="cl"><span class="nb">Update-MpSignature</span>
</span></span><span class="line"><span class="cl"><span class="nb">Update-MpSignature</span></span></span></code></pre></div></div>
<ol start="4">
<li>Confirm the signature version is <code>1.451.224.0</code> or later:</li>
</ol>
<div class="highlight-wrapper"><div class="highlight"><div class="ms-code-label">PowerShell</div><pre tabindex="0" class="chroma"><code class="language-powershell" data-lang="powershell"><span class="line"><span class="cl"><span class="nb">Get-MpComputerStatus</span> <span class="p">|</span> <span class="nb">Select-Object</span> <span class="n">AntivirusSignatureVersion</span></span></span></code></pre></div></div>
<ol start="5">
<li>Enable runtime protection in your chosen mode:</li>
</ol>
<div class="highlight-wrapper"><div class="highlight"><div class="ms-code-label">PowerShell</div><pre tabindex="0" class="chroma"><code class="language-powershell" data-lang="powershell"><span class="line"><span class="cl"><span class="nb">Set-MpPreference</span> <span class="n">-AiAgentProtection</span> <span class="n">Audit</span></span></span></code></pre></div></div>
<p>Replace <code>Audit</code> with <code>Block</code> or <code>Disabled</code> depending on where you are in the rollout.</p>
<ol start="6">
<li>Verify it’s actually set:</li>
</ol>
<div class="highlight-wrapper"><div class="highlight"><div class="ms-code-label">PowerShell</div><pre tabindex="0" class="chroma"><code class="language-powershell" data-lang="powershell"><span class="line"><span class="cl"><span class="nb">Get-MpPreference</span> <span class="p">|</span> <span class="nb">Select-Object</span> <span class="n">AiAgentProtection</span></span></span></code></pre></div></div>
<figure><img
    class="my-0 rounded-md"
    loading="lazy"
    decoding="async"
    fetchpriority="auto"
    alt=""
    width="1350"
    height="766"
    src="https://www.modernsecurity.nl/ai-agent-runtime-protection/screenshot-2026-07-04-215528_hu_a7b417cb7d7d5061.webp"
   
   
    data-zoom-src="https://www.modernsecurity.nl/ai-agent-runtime-protection/screenshot-2026-07-04-215528.webp"></figure>
<h2 class="relative group">Deploying at scale with Intune
    <div id="deploying-at-scale-with-intune" class="anchor"></div>
    
</h2>
<p>There’s no native Intune policy for this setting, so scale means pushing the same PowerShell command as a script:</p>
<ol>
<li>Create a script containing the mode you want for that rollout phase:</li>
</ol>
<div class="highlight-wrapper"><div class="highlight"><div class="ms-code-label">PowerShell</div><pre tabindex="0" class="chroma"><code class="language-powershell" data-lang="powershell"><span class="line"><span class="cl"><span class="nb">Set-MpPreference</span> <span class="n">-AiAgentProtection</span> <span class="n">Block</span></span></span></code></pre></div></div>
<ol start="2">
<li>Deploy it to target device groups using <a href="https://learn.microsoft.com/en-us/intune/device-management/tools/run-powershell-scripts-windows"  target="_blank" rel="noreferrer">PowerShell scripts in Intune</a>.</li>
</ol>
<p>Same command, same logic as the single-device test, just fanned out to a device group with <code>Audit</code> while you’re still validating and <code>Block</code> once you’re confident.</p>

<h2 class="relative group">What an alert actually looks like
    <div id="what-an-alert-actually-looks-like" class="anchor"></div>
    
</h2>
<p>When runtime protection catches something, Defender raises a <strong>Suspicious AI prompt injection</strong> alert. In block mode the severity lands on Critical, High, Medium, or Low depending on assessed risk. In audit mode it’s Informational, so your analysts aren’t stuck triaging something that never actually ran.</p>
<p>For the end user, a block shows up two ways: a message in the agent’s own terminal explaining what was blocked and why, and a Windows toast notification regardless of whether that terminal window is even focused. They can also check <strong>Windows Security</strong> &gt; <strong>Virus &amp; threat protection</strong> &gt; <strong>Current threats</strong> and <strong>Protection history</strong> for the same detection.</p>
<figure><img
    class="my-0 rounded-md"
    loading="lazy"
    decoding="async"
    fetchpriority="auto"
    alt=""
    width="1804"
    height="1401"
    src="https://www.modernsecurity.nl/ai-agent-runtime-protection/screenshot-2026-07-05-151746_hu_49381936303bdbfa.webp"
   
   
    data-zoom-src="https://www.modernsecurity.nl/ai-agent-runtime-protection/screenshot-2026-07-05-151746.webp"></figure><p>For the SOC, it’s a normal alert in the Defender portal, process tree, detection details, and recommended actions included, and it correlates into incidents the same way any other endpoint detection does. No new investigation workflow to learn.</p>

<h2 class="relative group">Testing it yourself with a benign prompt injection
    <div id="testing-it-yourself-with-a-benign-prompt-injection" class="anchor"></div>
    
</h2>
<p>Before you trust any of this in front of a client, validate it on a throwaway test device. The trick is building a test that’s realistic enough to trigger the hook inspection, but genuinely harmless.</p>
<p>Drop something like this into a folder Claude Code has access to, saved as <code>instructions.txt</code>. Then ask the agent something completely ordinary, “Can you summarize instructions.txt for me?”, and see what happens.</p>
<figure><img
    class="my-0 rounded-md"
    loading="lazy"
    decoding="async"
    fetchpriority="auto"
    alt=""
    width="1734"
    height="927"
    src="https://www.modernsecurity.nl/ai-agent-runtime-protection/image-16_hu_437fe90415fc5012.webp"
   
   
    data-zoom-src="https://www.modernsecurity.nl/ai-agent-runtime-protection/image-16.webp"></figure><p>A few things can happen from there. The model itself might recognize the injected instruction and refuse or flag it, independent of Defender entirely, which is worth noting as defense in depth rather than a failed test.</p>
<p>If the agent does attempt the call, that’s the pre-tool-call hook’s moment to catch it, and in block mode you should see the <strong>Suspicious AI prompt injection</strong> alert land in the portal shortly after.</p>
<figure><img
    class="my-0 rounded-md"
    loading="lazy"
    decoding="async"
    fetchpriority="auto"
    alt=""
    width="1919"
    height="1000"
    src="https://www.modernsecurity.nl/ai-agent-runtime-protection/image-18_hu_5ff7eadc0f5a7556.webp"
   
   
    data-zoom-src="https://www.modernsecurity.nl/ai-agent-runtime-protection/image-18.webp"></figure><figure><img
    class="my-0 rounded-md"
    loading="lazy"
    decoding="async"
    fetchpriority="auto"
    alt=""
    width="1919"
    height="998"
    src="https://www.modernsecurity.nl/ai-agent-runtime-protection/image-19_hu_39c8131cab7972d.webp"
   
   
    data-zoom-src="https://www.modernsecurity.nl/ai-agent-runtime-protection/image-19.webp"></figure>
<h2 class="relative group">Resources
    <div id="resources" class="anchor"></div>
    
</h2>
<ul>
<li><a href="https://learn.microsoft.com/en-us/defender-endpoint/ai-agent-runtime-protection-overview"  target="_blank" rel="noreferrer">AI agent runtime protection with Microsoft Defender for Endpoint (Preview)</a></li>
<li><a href="https://learn.microsoft.com/en-us/defender-endpoint/configure-ai-agent-runtime-protection"  target="_blank" rel="noreferrer">Set up AI agent runtime protection with Microsoft Defender for Endpoint</a></li>
<li><a href="https://learn.microsoft.com/en-us/defender-endpoint/local-agent-discovery-overview"  target="_blank" rel="noreferrer">Local AI agent discovery with Microsoft Defender for Endpoint</a></li>
<li><a href="https://code.claude.com/docs/en/hooks"  target="_blank" rel="noreferrer">Claude Code hooks</a></li>
<li><a href="https://docs.github.com/copilot/how-tos/copilot-cli/customize-copilot/use-hooks"  target="_blank" rel="noreferrer">GitHub Copilot hooks</a></li>
<li><a href="https://learn.microsoft.com/en-us/intune/device-management/tools/run-powershell-scripts-windows"  target="_blank" rel="noreferrer">Use PowerShell scripts on Windows devices in Intune</a></li>
<li><a href="https://learn.microsoft.com/en-us/defender-xdr/security-for-ai/defender-security-for-ai"  target="_blank" rel="noreferrer">Protect AI assets from emerging threats and vulnerabilities using Microsoft Defender</a></li>
</ul>

<h2 class="relative group">Where this fits and what’s still missing
    <div id="where-this-fits-and-whats-still-missing" class="anchor"></div>
    
</h2>
<p>Two supported agents is a real limitation right now, not a minor caveat. If your client’s developers are running Cursor, Windsurf, or any of the desktop apps that discovery already picks up, none of that traffic gets inspected yet. Runtime protection and discovery aren’t the same coverage footprint, and conflating them in a client conversation is an easy way to over promise.</p>
<p>The Beta update channel requirement is the other one to flag internally. That’s not something you want live on a production fleet during preview, and it’s easy to forget you’ve put a device there once the preview period drags on.</p>
<p>What it does solve, cleanly, is the actual attack surface these agents introduce. Prompt injection isn’t hypothetical anymore, and having an inline check at the exact moment an agent is about to act on unverified content is a meaningfully different posture than hoping the model itself resists it.</p>
<p>Start in audit mode, watch it for a couple of weeks, and don’t be surprised if your first alert comes from something completely unintentional rather than a real attack.</p>
<p><em>All feature details, prerequisites, PowerShell commands, and rollout guidance were verified against official Microsoft Learn documentation at time of writing. This is a preview feature and may change before general availability.</em></p>
]]></content:encoded><media:content url="https://www.modernsecurity.nl/ai-agent-runtime-protection/featured_hu_842cafad9806e82.jpg" medium="image" type="image/jpeg" width="1200" height="642"/><enclosure url="https://www.modernsecurity.nl/ai-agent-runtime-protection/featured_hu_842cafad9806e82.jpg" type="image/jpeg" length="110008"/></item><item><title>Defender deployment tool: Easy and simple onboarding for Defender for Endpoint</title><link>https://www.modernsecurity.nl/defender-deployment-tool-mde-onboarding/</link><guid isPermaLink="true">https://www.modernsecurity.nl/defender-deployment-tool-mde-onboarding/</guid><pubDate>Sat, 06 Jun 2026 19:21:41 +0100</pubDate><dc:creator>Farid Kalaidji</dc:creator><category>Microsoft Defender for Endpoint</category><description>Easy Microsoft Defender for Endpoint onboarding with Defender Deployment Tool: setup, command-line use, and rollout considerations.</description><content:encoded><![CDATA[<p>Onboarding devices to <a href="https://www.modernsecurity.nl/microsoft-defender-for-endpoint/" >Microsoft Defender for Endpoint</a> has always been one of those tasks that looks simple on paper and turns messy the moment you touch a real environment. Different scripts per OS, onboarding blobs that expire without warning, and zero visibility into whether a rollout actually succeeded until someone notices a device missing from the portal. Microsoft has been quietly rebuilding this whole flow around the Defender deployment tool, and the latest wave of changes is worth a proper look if you are still relying on the old onboarding package and script approach.</p>
<p>In this post I go through what the deployment tool and deployment packages actually do differently, when it makes sense to use it over your existing onboarding method, how to generate a package, and where I think this still needs work before I would trust it for a large, multi-tenant estate.</p>
<p>One thing worth setting expectations on upfront: as of Microsoft’s most recent update to the documentation, the Windows version of the tool is no longer flagged as preview. The Linux version of the deployment tool still is, so if you run a mixed estate, don’t assume both are at the same maturity level.</p>

<h2 class="relative group">From onboarding scripts to deployment packages
    <div id="from-onboarding-scripts-to-deployment-packages" class="anchor"></div>
    
</h2>
<p>The old model was straightforward but brittle: download an onboarding package (a script or GPO blob) from the Defender portal, push it out through your management tool of choice, and hope the device picked it up correctly. There was no built-in expiry, no central view of which packages were still valid, and if that onboarding file leaked or sat on a file share for two years, it stayed usable.</p>
<p>The Defender deployment tool changes the model in a few concrete ways:</p>
<ul>
<li>The onboarding configuration is now embedded directly into a single executable rather than shipped as a separate blob or script.</li>
<li>Generating a package requires setting an expiration date, up to a year, after which the package stops working.</li>
<li>Running the tool requires an access key generated in the portal at package-creation time, so having the executable alone is not enough to onboard a device.</li>
<li>Onboarding and offboarding events are now visible in the device timeline and in advanced hunting, instead of giving you a bare exit code and nothing else.</li>
<li>The tool skips redundant installation if Defender is already present, and gives UI feedback with error descriptions rather than a bare exit code when something goes wrong.</li>
<li>Onboarding and offboarding can proceed even without connectivity, using offline mode, and resume once connectivity returns.</li>
<li>There is a dedicated deployment packages overview under <strong>Settings &gt; Endpoints &gt; Deployment packages</strong>, where you can filter by active, expired or hidden packages.</li>
</ul>
<p>For anyone managing a multi-tenant or multi-customer estate, that last point alone is a meaningful improvement. Before this, tracking which onboarding packages were still floating around for a customer meant asking them, or trusting documentation that was rarely kept current.</p>

<h2 class="relative group">When this tool actually applies
    <div id="when-this-tool-actually-applies" class="anchor"></div>
    
</h2>
<p>Before switching anything over, it is worth being clear on where the deployment tool fits, because it is not meant to replace every onboarding path you already have running.</p>
<ul>
<li><strong>Windows client devices managed through Intune</strong>: Microsoft’s own Intune connector guidance labels the automatic onboarding option (“auto from connector”) as the recommended path once the service-to-service connection between Intune and Defender for Endpoint is set up. There’s no reason to route Intune-managed devices through the deployment tool instead.</li>
<li><strong>Devices not enrolled in Intune</strong>: this is where the tool is genuinely useful, for devices managed through SCCM, GPO, or another orchestration tool, or not centrally managed at all.</li>
<li><strong>On-premises Windows Servers</strong>: the tool works alongside whatever orchestration you already use to distribute software, since it exposes the same command-line and configuration-file options regardless of how it gets pushed out.</li>
<li><strong>Servers connected through Azure Arc, and Azure virtual machines</strong>: Microsoft’s Defender for Cloud documentation confirms that once the Defender for Servers plan is enabled, onboarding is auto-provisioned through the MDE.Windows or MDE.Linux extension, with no separate onboarding package needed. For new subscriptions this integration is enabled automatically and covers supported Windows Server and Linux machines. That makes the deployment tool mainly relevant for servers that are not (yet) Arc-connected or covered by Defender for Servers.</li>
</ul>
<p>For an operations team managing many devices, that narrows things down to a fairly specific but common gap: non-Intune-managed Windows devices and servers that fall outside Defender for Servers auto-provisioning. That is exactly the group that used to depend on the older onboarding scripts and blobs, so it is a sensible place to start piloting this.</p>
<p>The tool also carries its own legacy-OS story worth knowing about: it’s what installs the Defender endpoint security solution on Windows 7 SP1 and Windows Server 2008 R2 SP1, and that legacy solution itself has now reached general availability. It runs on a different underlying implementation than newer OS versions, though, so don’t assume full feature parity, and check the specific prerequisites first (the SHA-2 code signing update KB4474419, the servicing stack update KB4490628, and .NET 3.5 or later on Server 2008 R2 SP1).</p>

<h2 class="relative group">Generating a deployment package
    <div id="generating-a-deployment-package" class="anchor"></div>
    
</h2>
<p>The workflow for creating a new package sits in the same place onboarding always has, but with an extra step:</p>
<ol>
<li>In the Microsoft Defender portal, go to <strong>System &gt; Settings &gt; Endpoints &gt; Onboarding</strong></li>
<li>Choose <strong>Windows</strong> as the operating system</li>
<li>Under deploying by downloading and applying packages or files, select <strong>Onboard</strong></li>
</ol>
<figure><img
    class="my-0 rounded-md"
    loading="lazy"
    decoding="async"
    fetchpriority="auto"
    alt=""
    width="1919"
    height="999"
    src="https://www.modernsecurity.nl/defender-deployment-tool-mde-onboarding/image_hu_591d7455b0a008e7.webp"
   
   
    data-zoom-src="https://www.modernsecurity.nl/defender-deployment-tool-mde-onboarding/image.webp"></figure><figure><img
    class="my-0 rounded-md"
    loading="lazy"
    decoding="async"
    fetchpriority="auto"
    alt=""
    width="1919"
    height="998"
    src="https://www.modernsecurity.nl/defender-deployment-tool-mde-onboarding/image-1_hu_5759a7f19aa73571.webp"
   
   
    data-zoom-src="https://www.modernsecurity.nl/defender-deployment-tool-mde-onboarding/image-1.webp"></figure><ol start="4">
<li>On the package configuration page, give the package a unique, descriptive name and set an expiration date. Microsoft’s own guidance here is to keep the validity period as short as your rollout realistically allows, which lines up with how I would treat any credential with a long shelf life.</li>
</ol>
<figure><img
    class="my-0 rounded-md"
    loading="lazy"
    decoding="async"
    fetchpriority="auto"
    alt=""
    width="1919"
    height="998"
    src="https://www.modernsecurity.nl/defender-deployment-tool-mde-onboarding/image-2_hu_777bb412e1093ea7.webp"
   
   
    data-zoom-src="https://www.modernsecurity.nl/defender-deployment-tool-mde-onboarding/image-2.webp"></figure><ol start="5">
<li>Select <strong>Generate</strong>. You get an access key on screen, which you need to copy and store somewhere sane, because the tool prompts for it during onboarding.</li>
</ol>
<figure><img
    class="my-0 rounded-md"
    loading="lazy"
    decoding="async"
    fetchpriority="auto"
    alt=""
    width="1919"
    height="999"
    src="https://www.modernsecurity.nl/defender-deployment-tool-mde-onboarding/image-3_hu_7d2c6a72b70afb6.webp"
   
   
    data-zoom-src="https://www.modernsecurity.nl/defender-deployment-tool-mde-onboarding/image-3.webp"></figure><ol start="6">
<li>Download the tool as either a .zip or a standalone .exe.</li>
</ol>
<p>That access key is the part I would flag to anyone building a runbook around this. It behaves like a short-lived secret, not a public download link, so it needs to go through the same handling as any other deployment credential rather than sitting in a shared onboarding folder in plaintext.</p>

<h2 class="relative group">Running the tool: interactive and non-interactive
    <div id="running-the-tool-interactive-and-non-interactive" class="anchor"></div>
    
</h2>
<p>For one-off machines or small pilots, the interactive double-click flow is the quickest option:</p>
<ol>
<li>Double-click the executable to launch it.</li>
<li>Confirm you want to start onboarding when the dialog appears.</li>
</ol>
<figure><img
    class="my-0 rounded-md"
    loading="lazy"
    decoding="async"
    fetchpriority="auto"
    alt=""
    width="1000"
    height="750"
    src="https://www.modernsecurity.nl/defender-deployment-tool-mde-onboarding/image-4_hu_6972b679e3e27e9c.webp"
   
   
    data-zoom-src="https://www.modernsecurity.nl/defender-deployment-tool-mde-onboarding/image-4.webp"></figure><ol start="2">
<li>Enter the access key you copied from the portal and continue</li>
</ol>
<figure><img
    class="my-0 rounded-md"
    loading="lazy"
    decoding="async"
    fetchpriority="auto"
    alt=""
    width="1000"
    height="750"
    src="https://www.modernsecurity.nl/defender-deployment-tool-mde-onboarding/image-5_hu_41eafdc068da3fd4.webp"
   
   
    data-zoom-src="https://www.modernsecurity.nl/defender-deployment-tool-mde-onboarding/image-5.webp"></figure><ol>
<li>Wait for installation to complete. No reboot is required in most cases, and if one is needed the tool tells you clearly rather than leaving you to guess from an exit code.</li>
</ol>
<figure><img
    class="my-0 rounded-md"
    loading="lazy"
    decoding="async"
    fetchpriority="auto"
    alt=""
    width="1200"
    height="900"
    src="https://www.modernsecurity.nl/defender-deployment-tool-mde-onboarding/image-8_hu_322dec7f4339d48c.webp"
   
   
    data-zoom-src="https://www.modernsecurity.nl/defender-deployment-tool-mde-onboarding/image-8.webp"></figure><p>For anything beyond a handful of devices, the command-line interface is where this becomes usable at scale. A few examples straight from the tool’s own help output:</p>
<figure><img
    class="my-0 rounded-md"
    loading="lazy"
    decoding="async"
    fetchpriority="auto"
    alt=""
    width="1103"
    height="639"
    src="https://www.modernsecurity.nl/defender-deployment-tool-mde-onboarding/image-6_hu_e68711a9817487df.webp"
   
   
    data-zoom-src="https://www.modernsecurity.nl/defender-deployment-tool-mde-onboarding/image-6.webp"></figure><div class="highlight-wrapper"><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="cl">DefenderDeploymentTool_Name.exe -PreCheck</span></span></code></pre></div></div>
<p>Checks for prerequisites and logs results but does not proceed with installation or onboarding.</p>
<div class="highlight-wrapper"><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="cl">DefenderDeploymentTool_Name.exe -Quiet</span></span></code></pre></div></div>
<p>Runs onboarding without any prompts, using the onboarding file in the same directory.</p>
<div class="highlight-wrapper"><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="cl">DefenderDeploymentTool_Name.exe -Proxy:192.168.0.255:8080 -AllowReboot -Quiet</span></span></code></pre></div></div>
<p>Onboards through a proxy and allows an automatic reboot if one is required, without showing a console window.</p>
<div class="highlight-wrapper"><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="cl">DefenderDeploymentTool_Name.exe -File:\\server\share\Defender.onboarding -Quiet</span></span></code></pre></div></div>
<p>Points the tool at an onboarding file on a network share, useful if you are not distributing it alongside the executable itself.</p>
<p>One thing the docs don’t spell out: your actual download isn’t literally named <code>DefenderDT.exe</code>, that’s just the generic name Microsoft uses in its examples. After running it, the tool drops a <code>DefenderDT.exe</code> copy into <code>C:\ProgramData\Microsoft\DefenderDeploymentTool</code> alongside its log file, which you can use directly for any follow-up commands.</p>
<p>For repeatable deployments, generating a config file with <code>-MakeConfig</code> and editing the resulting <code>MdeConfig.txt</code> is worth doing early. It saves you from maintaining long command-line strings across GPO, SCCM or whatever orchestration tool you use, and it makes the deployment auditable, since the config file itself documents exactly what was run.</p>
<figure><img
    class="my-0 rounded-md"
    loading="lazy"
    decoding="async"
    fetchpriority="auto"
    alt=""
    width="1426"
    height="823"
    src="https://www.modernsecurity.nl/defender-deployment-tool-mde-onboarding/image-3-2_hu_12e45a424f03efc8.webp"
   
   
    data-zoom-src="https://www.modernsecurity.nl/defender-deployment-tool-mde-onboarding/image-3-2.webp"></figure><p>A couple of the less obvious parameters are worth calling out specifically, since they solve real operational problems rather than just being flags for the sake of flags:</p>
<div class="highlight-wrapper"><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="cl">DefenderDeploymentTool_Name.exe -PreCheck -Verbose -Quiet</span></span></code></pre></div></div>
<p>Runs a full prerequisite check and logs the results without touching the device. I would run this as a standalone step ahead of any bulk rollout, since it turns “why did onboarding fail on these forty machines” into something you can catch beforehand instead of after the fact.</p>
<p>For low-bandwidth sites or staged rollouts, the tool can also pre-download the installation files without onboarding anything yet:</p>
<div class="highlight-wrapper"><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="cl">DefenderDeploymentTool_Name.exe -Stage</span></span></code></pre></div></div>
<p>Documented as downloading updates and installation files to the current directory for later use, this is worth combining with a config file if you are pushing to devices over a slow or unreliable link, so the actual onboarding step doesn’t also have to pull the full package down first.</p>
<p>The <code>-UpdateOnly</code> parameter is documented the same way: it installs the latest updates and platform components without performing onboarding, even if an onboarding file is present, which is useful for keeping already-onboarded fleets current without re-running the full onboarding sequence.</p>
<p>The full set of parameters exposed through the config file, straight from Microsoft’s own reference:</p>

<div class="ms-table" role="region" aria-label="Table" tabindex="0">
  <table>
      <thead>
          <tr>
              <th>Parameter</th>
              <th>What it does</th>
          </tr>
      </thead>
    <tbody>
        <tr>
            <td><code>-Offboard</code></td>
            <td>Configures the tool to perform offboarding (same parameter used as <code>-offboard</code> on the command line; casing doesn’t matter).</td>
        </tr>
        <tr>
            <td><code>-Yes</code></td>
            <td>Used with <code>Offboard</code> and <code>Uninstall</code> to proceed without user approval.</td>
        </tr>
        <tr>
            <td><code>-Stage</code></td>
            <td>Downloads installation files for all supported Windows versions to a location for staging.</td>
        </tr>
        <tr>
            <td><code>-Source</code></td>
            <td>Specifies the path to a folder containing staged installation files.</td>
        </tr>
        <tr>
            <td><code>-File</code></td>
            <td>Specifies the full path to the <code>.onboarding</code> or <code>.offboarding</code> file, if it isn’t in the current folder.</td>
        </tr>
        <tr>
            <td><code>-Proxy</code></td>
            <td>Proxy to use during and after installation.</td>
        </tr>
        <tr>
            <td><code>-Quiet</code></td>
            <td>Prevents any dialogs from displaying.</td>
        </tr>
        <tr>
            <td><code>-AllowReboot</code></td>
            <td>Allows device reboots if needed.</td>
        </tr>
        <tr>
            <td><code>-NoResumeAfterReboot</code></td>
            <td>Prevents the tool from resuming activities after a reboot.</td>
        </tr>
        <tr>
            <td><code>-Passive</code></td>
            <td>Windows Server only. Sets Defender Antivirus to run in passive mode.</td>
        </tr>
        <tr>
            <td><code>-UpdateOnly</code></td>
            <td>Installs updates but does not perform onboarding, even if an onboarding file is present.</td>
        </tr>
        <tr>
            <td><code>-Verbose</code></td>
            <td>Displays detailed information.</td>
        </tr>
        <tr>
            <td><code>-Precheck</code></td>
            <td>Checks for prerequisites and logs results but does not proceed with installation or onboarding.</td>
        </tr>
        <tr>
            <td><code>-Uninstall</code></td>
            <td>Offboards the device and uninstalls components added during onboarding.</td>
        </tr>
        <tr>
            <td><code>-RemoveMMA</code></td>
            <td>Optionally removes the specified workspace connection used by Microsoft Monitoring Agent.</td>
        </tr>
        <tr>
            <td><code>-Offline</code></td>
            <td>Allows offboarding to proceed even without connectivity.</td>
        </tr>
    </tbody>
  </table>
</div>
<p>Run <code>DefenderDeploymentTool_Name.exe -?</code> on your own copy of the tool for the authoritative, up-to-date list, since this is exactly the kind of thing Microsoft tends to extend between releases.</p>
<figure><img
    class="my-0 rounded-md"
    loading="lazy"
    decoding="async"
    fetchpriority="auto"
    alt=""
    width="1103"
    height="639"
    src="https://www.modernsecurity.nl/defender-deployment-tool-mde-onboarding/image-7_hu_5f71d2e5e787655b.webp"
   
   
    data-zoom-src="https://www.modernsecurity.nl/defender-deployment-tool-mde-onboarding/image-7.webp"></figure>
<h2 class="relative group">Where this fits in a GPO or orchestrated rollout
    <div id="where-this-fits-in-a-gpo-or-orchestrated-rollout" class="anchor"></div>
    
</h2>
<p>If you are still using Group Policy for onboarding, the steps look like this:</p>
<ol>
<li>Place the executable and the onboarding file (and a config file, if you generated one) on a network share that the target devices can reach.</li>
<li>In the Group Policy Management Console, create a new Group Policy Object or open an existing one for editing.</li>
<li>Go to <strong>Computer configuration &gt; Preferences &gt; Control panel settings</strong>.</li>
<li>Right-click <strong>Scheduled tasks</strong>, point to <strong>New</strong>, and select <strong>Immediate Task</strong>.</li>
<li>On the <strong>General</strong> tab, set the task to run as the <strong>SYSTEM</strong> account, with <strong>Run whether user is logged on or not</strong> and <strong>Run with highest privileges</strong> both selected.</li>
<li>On the <strong>Actions</strong> tab, point the task at the executable using its full UNC path, and add any command-line parameters you need in the arguments field, for example a <code>-file:</code> pointing at an onboarding file that is not in the tool’s working directory.</li>
<li>Save the GPO and link it to the organizational unit containing your target devices.</li>
</ol>
<p>The difference from the previous approach is mainly what you are pointing the scheduled task at: one self-contained executable with its own onboarding configuration, instead of a script plus a separate onboarding package.</p>
<p>If you are placing the tool behind a firewall or proxy allowlist, note that it downloads and updates itself from the <em>definitionupdates.microsoft.com</em> domain. Since those files are served from a content distribution platform, there is no static or predictable IP range to whitelist instead, so the domain needs to be reachable by name rather than by IP.</p>

<h2 class="relative group">Offboarding a device
    <div id="offboarding-a-device" class="anchor"></div>
    
</h2>
<p>Offboarding follows a similarly short, two-part flow:</p>
<ol>
<li>In the Defender portal, go to <strong>System &gt; Settings &gt; Endpoints &gt; Device management &gt; Offboarding</strong>, select Windows, and download the offboarding package. This gives you a .zip file containing the <code>.offboarding</code> file (at least temporary – I am pretty sure Microsoft will release an easier way).</li>
</ol>
<figure><img
    class="my-0 rounded-md"
    loading="lazy"
    decoding="async"
    fetchpriority="auto"
    alt=""
    width="1919"
    height="998"
    src="https://www.modernsecurity.nl/defender-deployment-tool-mde-onboarding/image-1-2_hu_2107e89e46c456f8.webp"
   
   
    data-zoom-src="https://www.modernsecurity.nl/defender-deployment-tool-mde-onboarding/image-1-2.webp"></figure><figure><img
    class="my-0 rounded-md"
    loading="lazy"
    decoding="async"
    fetchpriority="auto"
    alt=""
    width="1919"
    height="998"
    src="https://www.modernsecurity.nl/defender-deployment-tool-mde-onboarding/image-2-2_hu_7713c1212280eecf.webp"
   
   
    data-zoom-src="https://www.modernsecurity.nl/defender-deployment-tool-mde-onboarding/image-2-2.webp"></figure><ol start="2">
<li>Copy the extracted file to the target machine, open an elevated command prompt, and run the executable with the offboarding switch, for example:</li>
</ol>
<div class="highlight-wrapper"><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="cl">DefenderDT.exe -Offboard -File:WindowsDefenderATP_valid_until_2025-05-06.offboarding</span></span></code></pre></div></div>
<p>When prompted <code>Are you sure you want to offboard? Yes(Y)/No(N)?</code>, type <strong>Y</strong> to proceed. A successful run reports:</p>
<div class="highlight-wrapper"><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="cl">Microsoft Defender deployment tool completed, exit code: 0 [Success]</span></span></code></pre></div></div>
<p>For a fully unattended offboarding, add <code>-Yes -Quiet</code> to the same command to skip the confirmation prompt entirely. As with onboarding packages, the offboarding file itself is time-limited (seven days from download), so this is not something you can generate once and keep on a share indefinitely.</p>

<h2 class="relative group">Tracking packages centrally
    <div id="tracking-packages-centrally" class="anchor"></div>
    
</h2>
<p>For anyone managing many customer tenants, the deployment packages page is where the day-to-day value shows up: it replaces asking a customer what onboarding method they used eighteen months ago with a direct answer. Expired or forgotten onboarding packages are exactly the kind of loose end that shows up in a security review and is hard to explain away, so having them visible and filterable in one place closes a real gap.</p>
<figure><img
    class="my-0 rounded-md"
    loading="lazy"
    decoding="async"
    fetchpriority="auto"
    alt=""
    width="1918"
    height="999"
    src="https://www.modernsecurity.nl/defender-deployment-tool-mde-onboarding/image-10_hu_db370e5d83d9230d.webp"
   
   
    data-zoom-src="https://www.modernsecurity.nl/defender-deployment-tool-mde-onboarding/image-10.webp"></figure>
<h2 class="relative group">Troubleshooting a failed run
    <div id="troubleshooting-a-failed-run" class="anchor"></div>
    
</h2>
<p>Before opening a support case, Microsoft’s own guidance points to a few places worth checking first:</p>
<ul>
<li>The tool’s own log, at <code>C:\ProgramData\Microsoft\DefenderDeploymentTool\DefenderDeploymentTool-&lt;COMPUTERNAME&gt;.log</code>.</li>
<li>The Windows Application event log, under the sources <strong>WDATPOnboarding</strong> and <strong>WDATPOffboarding</strong>.</li>
<li>The services themselves, with <code>sc.exe query sense</code> and <code>sc.exe query windefend</code>. Both should report <code>STATE: 4 RUNNING</code> on a healthy device.</li>
</ul>
<p>The tool also returns a documented exit code on completion, which is worth wiring into whatever orchestration or RMM tool triggers it, rather than only checking the log after the fact:</p>

<div class="ms-table" role="region" aria-label="Table" tabindex="0">
  <table>
      <thead>
          <tr>
              <th>Exit code</th>
              <th>Meaning</th>
          </tr>
      </thead>
    <tbody>
        <tr>
            <td>0</td>
            <td>Sequence completed successfully</td>
        </tr>
        <tr>
            <td>1</td>
            <td>Another instance is already running</td>
        </tr>
        <tr>
            <td>2</td>
            <td>Device is already onboarded: no action required</td>
        </tr>
        <tr>
            <td>3</td>
            <td>Offboarding is only available for onboarded devices</td>
        </tr>
        <tr>
            <td>10</td>
            <td>A reboot is required to continue: the tool resumes automatically unless <code>-NoResumeAfterReboot</code> was specified</td>
        </tr>
        <tr>
            <td>40</td>
            <td>Please run the tool with administrative permissions</td>
        </tr>
        <tr>
            <td>50</td>
            <td>Unsupported operating system</td>
        </tr>
        <tr>
            <td>70</td>
            <td>Configuration file error detected</td>
        </tr>
        <tr>
            <td>90</td>
            <td>Prerequisite check(s) failed</td>
        </tr>
        <tr>
            <td>200</td>
            <td>Onboarding failed: sensor initialization error</td>
        </tr>
        <tr>
            <td>201</td>
            <td>Onboarding file missing or not specified</td>
        </tr>
        <tr>
            <td>300</td>
            <td>Offboarding failed</td>
        </tr>
        <tr>
            <td>301</td>
            <td>Offboarding file missing or not specified</td>
        </tr>
        <tr>
            <td>400</td>
            <td>Download failed: unable to retrieve required component</td>
        </tr>
        <tr>
            <td>500</td>
            <td>Installation failed: unable to install required components</td>
        </tr>
        <tr>
            <td>710</td>
            <td>Failed to enable the Defender Antivirus feature</td>
        </tr>
        <tr>
            <td>730 / 740</td>
            <td>Sovereign cloud signature or registry configuration failure</td>
        </tr>
        <tr>
            <td>1000</td>
            <td>An unspecified error occurred</td>
        </tr>
    </tbody>
  </table>
</div>
<p>This is a trimmed list of the ones I’d actually watch for in day-to-day operations; Microsoft’s reference has the complete set, including several more granular codes for update and uninstall failures.</p>

<h2 class="relative group">Considerations and limitations
    <div id="considerations-and-limitations" class="anchor"></div>
    
</h2>
<p>A few points worth being upfront about, straight from Microsoft’s own documentation, rather than presenting this as a finished, edge-case-free solution:</p>
<ul>
<li>If a reboot is required during the interactive experience, you have to sign back in after the reboot for the sequence to resume. Skipping that step leaves the device only partially onboarded.</li>
<li>On Windows Server 2016 and later, if the Defender Antivirus feature was previously uninstalled or removed, you may hit a documented error during the <em>Enabling Feature ‘Windows-Defender’</em> step (exit code 710, error 14081, <em>“The referenced assembly could not be found”</em>). Microsoft is explicit that this isn’t caused by the Defender Antivirus feature or source files themselves, and recommends opening a support case for Windows Servers if you hit it.</li>
<li>On Windows 7, passive mode is set with the <code>-passive</code> parameter, but there is currently no equivalent to the <code>ForceDefenderPassiveMode</code> registry key that servers use to flip back to active mode afterwards. Switching back means offboarding, uninstalling, and running the tool again without the passive parameter.</li>
<li>No integration with existing onboarding methods yet means you cannot simply layer this on top of an Intune or SCCM-based fleet without deciding how the two coexist; the tool remains its own onboarding methodology for now.</li>
</ul>

<h2 class="relative group">References
    <div id="references" class="anchor"></div>
    
</h2>
<ul>
<li><a href="https://learn.microsoft.com/en-us/defender-endpoint/defender-deployment-tool-windows"  target="_blank" rel="noreferrer">Deploy Microsoft Defender endpoint security to Windows devices using the Defender deployment tool</a>: Microsoft Learn</li>
<li><a href="https://learn.microsoft.com/en-us/defender-endpoint/onboard-downlevel"  target="_blank" rel="noreferrer">Onboard previous versions of Windows on Microsoft Defender for Endpoint</a>: Microsoft Learn</li>
<li><a href="https://learn.microsoft.com/en-us/defender-endpoint/whats-new-in-microsoft-defender-endpoint"  target="_blank" rel="noreferrer">What’s new in Microsoft Defender for Endpoint</a>: Microsoft Learn</li>
</ul>

<h2 class="relative group">Closing thoughts
    <div id="closing-thoughts" class="anchor"></div>
    
</h2>
<p>This is a genuine improvement over the old script-and-blob approach, mainly because it finally gives onboarding a lifecycle: an expiry, an access key, and a place to see what is still active. For teams managing many customer tenants specifically, the centralised deployment packages view is the detail I would point a customer to first, since it directly addresses the “which onboarding package is this device even using” question that used to require manual digging.</p>
<p>If you are planning a migration to this tool across an existing estate, start small, keep expiry windows short, and treat the access key with the same care you would give any other deployment credential.</p>
<p>Worth noting for mixed estates: a Linux version of the deployment tool exists as well, combining installation and onboarding the same way. I have not tested it myself yet, but it is on my list for a follow-up post once I have run it against a real Linux fleet.</p>
]]></content:encoded><media:content url="https://www.modernsecurity.nl/defender-deployment-tool-mde-onboarding/featured_hu_897ddcd9c4d562ac.jpg" medium="image" type="image/jpeg" width="1000" height="750"/><enclosure url="https://www.modernsecurity.nl/defender-deployment-tool-mde-onboarding/featured_hu_897ddcd9c4d562ac.jpg" type="image/jpeg" length="42633"/></item><item><title>Microsoft Defender for Endpoint custom data collection: get the telemetry you need</title><link>https://www.modernsecurity.nl/defender-for-endpoint-custom-data-collection/</link><guid isPermaLink="true">https://www.modernsecurity.nl/defender-for-endpoint-custom-data-collection/</guid><pubDate>Mon, 25 May 2026 07:53:52 +0100</pubDate><dc:creator>Farid Kalaidji</dc:creator><category>Microsoft Defender for Endpoint</category><category>Microsoft Defender XDR</category><category>Microsoft Sentinel</category><description>Learn about how Microsoft Defender for Endpoint Custom Data Collection fixes lack of visibility, and step-by-step instructions to implement it properly.</description><content:encoded><![CDATA[<p>If you’ve been working with <a href="https://www.modernsecurity.nl/microsoft-defender-for-endpoint/" >Microsoft Defender for Endpoint (MDE)</a> for any length of time, you’ve probably run into this situation: you’re hunting for a specific behavior, you know it happened on a device, but when you query Advanced Hunting, there’s nothing. The event simply isn’t there.</p>
<p>This isn’t a bug. It’s by design. Until recently, your only real options were to deploy Sysmon alongside Defender for Endpoint, managing another agent, another configuration, and a completely different schema.</p>
<p>Custom data collection, which reached general availability in May 2026, gives you a way to collect the specific telemetry you need without those workarounds. This guide covers what problem it actually solves, what it costs, and how to configure it end to end.</p>

<h2 class="relative group">The real problem: Defender for Endpoint drops events
    <div id="the-real-problem-defender-for-endpoint-drops-events" class="anchor"></div>
    
</h2>
<p><a href="https://www.linkedin.com/in/olafhartong/"  target="_blank" rel="noreferrer">Olaf Hartong</a> and the team at <a href="https://falconforce.nl/"  target="_blank" rel="noreferrer">FalconForce</a> have done thorough work documenting how Defender for Endpoint works under the hood. Their <a href="https://falconforce.nl/microsoft-defender-for-endpoint-internal-0x06-custom-collection/"  target="_blank" rel="noreferrer">MDE Internals</a> blog series is required reading for anyone doing detection engineering with Defender.</p>
<p>Here’s the short version:</p>
<p>Defender for Endpoint applies caps and sampling to limit how much telemetry gets uploaded to the cloud. For many event types, you’ll only see one event per 24 hours for each unique combination of field values. Run the same process a hundred times with identical parameters you’ll see it once in Advanced Hunting.</p>
<p>The reason is straightforward. Defender for Endpoint is sold at a fixed price per device. If every customer could upload unlimited telemetry, backend costs would be unpredictable. So Microsoft made a trade-off: enough data for most use cases, but capped volume.</p>
<p>For day-to-day security operations, this is generally fine. The alerts fire, incidents get created, you can investigate. But for custom detections or proactive threat hunting, these gaps become a real problem. A concrete example: malware that beacons to a C2 server every 10 minutes. With standard Defender for Endpoint telemetry, you might see only a handful of connections to that server because once Defender for Endpoint logs the first connection with a specific process/destination combination, duplicate connections don’t appear for 24 hours. The beaconing pattern that would make detection trivial? Invisible.</p>
<p>The table that suffers most is <code>DeviceImageLoadEvents</code>. DLL loads are sampled so aggressively that FalconForce describes it as “very unreliable.” No events in the portal genuinely does not mean nothing happened on the machine.</p>

<h2 class="relative group">What custom data collection actually does
    <div id="what-custom-data-collection-actually-does" class="anchor"></div>
    
</h2>
<p>Custom data collection lets you define rules that collect specific events and send them to Microsoft Sentinel without the standard Defender for Endpoint caps. The data lands in separate tables so it doesn’t interfere with your normal Defender for Endpoint data.</p>
<p>There is still a limit: <strong>75,000 events per rule, per device, per day</strong> (raised from 25,000 at GA). This is a protective cap to prevent runaway costs, not a sampling mechanism. A well-scoped rule will never hit it.</p>
<p><strong>Supported tables:</strong></p>

<div class="ms-table" role="region" aria-label="Table" tabindex="0">
  <table>
      <thead>
          <tr>
              <th>Standard MDE table</th>
              <th>Custom data collection table</th>
          </tr>
      </thead>
    <tbody>
        <tr>
            <td>DeviceProcessEvents</td>
            <td>DeviceCustomProcessEvents</td>
        </tr>
        <tr>
            <td>DeviceNetworkEvents</td>
            <td>DeviceCustomNetworkEvents</td>
        </tr>
        <tr>
            <td>DeviceFileEvents</td>
            <td>DeviceCustomFileEvents</td>
        </tr>
        <tr>
            <td>DeviceImageLoadEvents</td>
            <td>DeviceCustomImageLoadEvents</td>
        </tr>
        <tr>
            <td>DeviceScriptEvents</td>
            <td>DeviceCustomScriptEvents</td>
        </tr>
    </tbody>
  </table>
</div>
<p>One thing worth noting on <code>DeviceScriptEvents</code>: AMSI events from that table are not available in standard Advanced Hunting, but custom collection routes them to <code>DeviceCustomScriptEvents</code> in Sentinel. So for script-based attack detection, custom collection gives you visibility you simply cannot get any other way through the MDE stack.</p>
<p>Notice what’s missing: no registry events, no named pipes, no driver loads. If you need those, you still need <a href="https://learn.microsoft.com/nl-nl/sysinternals/downloads/sysmon"  target="_blank" rel="noreferrer">Sysmon</a>. Custom data collection is a targeted solution for specific gaps, not a complete replacement.</p>
<p>The custom tables share the same schema as their standard counterparts, with three additional fields: <code>RuleName</code>, <code>RuleLastModificationTime</code>, and <code>Type</code>. These make it easy to identify which rule needs tuning when you’re reviewing results.</p>

<h2 class="relative group">Which scenarios are worth implementing
    <div id="which-scenarios-are-worth-implementing" class="anchor"></div>
    
</h2>
<p>Custom data collection is included with Defender for Endpoint P2, but every event you collect goes to Microsoft Sentinel and gets billed at Sentinel ingestion rates. Before creating any rules, be clear about what gaps you’re actually filling.</p>
<p><strong>High priority usually worth implementing:</strong></p>

<div class="ms-table" role="region" aria-label="Table" tabindex="0">
  <table>
      <thead>
          <tr>
              <th>Scenario</th>
              <th>Why it matters</th>
              <th>Expected volume</th>
          </tr>
      </thead>
    <tbody>
        <tr>
            <td>LSASS spawning a child lsass process</td>
            <td>Credential dumping technique not logged by default in MDE. Use <code>ProcessCreated</code> filtering on <code>lsass.exe</code> as both parent and child</td>
            <td>Low, very targeted</td>
        </tr>
        <tr>
            <td>AMSI script content collection</td>
            <td>Script events from <code>DeviceScriptEvents</code> are not available in standard Advanced Hunting at all, the clearest gap custom data collection fills</td>
            <td>Medium, scope to specific processes</td>
        </tr>
        <tr>
            <td>Unsigned DLLs from temp folders</td>
            <td><code>DeviceImageLoadEvents</code> is heavily sampled in standard MDE: DLL side-loading attempts are largely invisible without custom collection</td>
            <td>Medium</td>
        </tr>
        <tr>
            <td>Executions from uncommon locations</td>
            <td>Standard MDE deduplicates <code>ProcessCreated</code> after the first unique combination per 24 hours, repeated execution from temp or AppData folders disappears</td>
            <td>Medium, broad path list</td>
        </tr>
        <tr>
            <td>File modifications in sensitive directories</td>
            <td>Config tampering, persistence mechanisms, Mimikatz <code>.kirbi</code> ticket files</td>
            <td>Low if scoped well</td>
        </tr>
    </tbody>
  </table>
</div>
<p><strong>Advanced use cases worth considering:</strong></p>

<div class="ms-table" role="region" aria-label="Table" tabindex="0">
  <table>
      <thead>
          <tr>
              <th>Scenario</th>
              <th>Why it matters</th>
              <th>Implementation tip</th>
          </tr>
      </thead>
    <tbody>
        <tr>
            <td>Web shell detection on web servers</td>
            <td>Monitor wwwroot and inetpub for script file creation</td>
            <td>Scope to web server device group only</td>
        </tr>
        <tr>
            <td>Verbose logging during incidents</td>
            <td>Temporarily enable broader collection on compromised machines</td>
            <td>Use dynamic tags, remove after investigation</td>
        </tr>
        <tr>
            <td>.NET CLR loads outside framework folder</td>
            <td>Detect in-memory .NET execution used by Cobalt Strike and similar</td>
            <td>Filter to clr.dll, clrjit.dll, mscoree.dll outside <code>C:\Windows\Microsoft.NET\</code></td>
        </tr>
    </tbody>
  </table>
</div>
<p><strong>Approach with caution: can get expensive fast:</strong></p>

<div class="ms-table" role="region" aria-label="Table" tabindex="0">
  <table>
      <thead>
          <tr>
              <th>Scenario</th>
              <th>Why it’s risky</th>
          </tr>
      </thead>
    <tbody>
        <tr>
            <td>All process creation events</td>
            <td>Massive volume, duplicates existing data</td>
        </tr>
        <tr>
            <td>All network connections</td>
            <td>Volume will explode costs</td>
        </tr>
        <tr>
            <td>All file operations everywhere</td>
            <td>You’ll hit the 75,000 event cap and pay a fortune</td>
        </tr>
        <tr>
            <td>Broad “just in case” rules</td>
            <td>Data without purpose is waste</td>
        </tr>
    </tbody>
  </table>
</div>

<h2 class="relative group">Prerequisites
    <div id="prerequisites" class="anchor"></div>
    
</h2>

<h3 class="relative group">Licensing
    <div id="licensing" class="anchor"></div>
    
</h3>

<div class="ms-table" role="region" aria-label="Table" tabindex="0">
  <table>
      <thead>
          <tr>
              <th>Component</th>
              <th>Requirement</th>
              <th>Notes</th>
          </tr>
      </thead>
    <tbody>
        <tr>
            <td>Microsoft Defender for Endpoint</td>
            <td>Plan 2 (P2)</td>
            <td>Plan 1 does not include custom data collection</td>
        </tr>
        <tr>
            <td>Microsoft Sentinel</td>
            <td>Active workspace</td>
            <td>Required for data storage</td>
        </tr>
        <tr>
            <td>Microsoft 365 license</td>
            <td>E5, E5 Security, or standalone MDE P2</td>
            <td>A5/G5 variants also work</td>
        </tr>
    </tbody>
  </table>
</div>

<h3 class="relative group">Supported operating systems
    <div id="supported-operating-systems" class="anchor"></div>
    
</h3>

<div class="ms-table" role="region" aria-label="Table" tabindex="0">
  <table>
      <thead>
          <tr>
              <th>Operating system</th>
              <th>Minimum version</th>
              <th>Notes</th>
          </tr>
      </thead>
    <tbody>
        <tr>
            <td>Windows 11</td>
            <td>Any version</td>
            <td>MDE client 10.8805+ required</td>
        </tr>
        <tr>
            <td>Windows 10</td>
            <td>1809 or later</td>
            <td>ESU enrollment required</td>
        </tr>
        <tr>
            <td>Windows Server 2022</td>
            <td>Any version</td>
            <td>MDE client 10.8805+ required</td>
        </tr>
        <tr>
            <td>Windows Server 2019</td>
            <td>Any version</td>
            <td>MDE client 10.8805+ required</td>
        </tr>
        <tr>
            <td>Windows Server 2016</td>
            <td>❌</td>
            <td></td>
        </tr>
        <tr>
            <td>Windows Server 2012 R2</td>
            <td>❌</td>
            <td></td>
        </tr>
        <tr>
            <td>macOS</td>
            <td>❌</td>
            <td></td>
        </tr>
        <tr>
            <td>Linux</td>
            <td>❌</td>
            <td></td>
        </tr>
    </tbody>
  </table>
</div>

<h3 class="relative group">Defender for Endpoint client requirements
    <div id="defender-for-endpoint-client-requirements" class="anchor"></div>
    
</h3>

<div class="ms-table" role="region" aria-label="Table" tabindex="0">
  <table>
      <thead>
          <tr>
              <th>Requirement</th>
              <th>Minimum value</th>
              <th>How to verify</th>
          </tr>
      </thead>
    <tbody>
        <tr>
            <td>Sense client version</td>
            <td>10.8805 or higher</td>
            <td>Query <code>DeviceInfo</code> table. See KQL below</td>
        </tr>
        <tr>
            <td>Real-time protection</td>
            <td>Enabled</td>
            <td>Required for telemetry collection</td>
        </tr>
        <tr>
            <td>Cloud-delivered protection</td>
            <td>Enabled</td>
            <td>Required for backend communication</td>
        </tr>
    </tbody>
  </table>
</div>
<p>Query to check client versions across your environment:</p>
<div class="highlight-wrapper"><div class="highlight"><div class="ms-code-label">KQL</div><pre tabindex="0" class="chroma"><code class="language-kql" data-lang="kql">DeviceInfo
<span class="o">|</span> <span class="k">where</span> Timestamp <span class="o">&gt;</span> <span class="nf">ago</span>(1d)
<span class="o">|</span> <span class="k">summarize</span> <span class="nf">arg_max</span>(Timestamp, *) <span class="k">by</span> DeviceId
<span class="o">|</span> <span class="k">project</span> DeviceName, OSPlatform, OSVersionInfo, ClientVersion
<span class="o">|</span> <span class="k">where</span> ClientVersion <span class="o">&lt;</span> <span class="s">&#34;10.8805&#34;</span>
<span class="o">|</span> <span class="k">order by</span> DeviceName</code></pre></div>
</div>

<h3 class="relative group">Portal and permission requirements
    <div id="portal-and-permission-requirements" class="anchor"></div>
    
</h3>

<div class="ms-table" role="region" aria-label="Table" tabindex="0">
  <table>
      <thead>
          <tr>
              <th>Requirement</th>
              <th>Details</th>
          </tr>
      </thead>
    <tbody>
        <tr>
            <td>Defender portal access</td>
            <td>security.microsoft.com</td>
        </tr>
        <tr>
            <td>Required role</td>
            <td>Security Administrator, Security Operator, or Global Administrator</td>
        </tr>
        <tr>
            <td>Sentinel workspace permissions</td>
            <td>Contributor or higher on the Log Analytics workspace</td>
        </tr>
    </tbody>
  </table>
</div>

<h3 class="relative group">Configuration prerequisites
    <div id="configuration-prerequisites" class="anchor"></div>
    
</h3>

<div class="ms-table" role="region" aria-label="Table" tabindex="0">
  <table>
      <thead>
          <tr>
              <th>Component</th>
              <th>Status needed</th>
              <th>Where to configure</th>
          </tr>
      </thead>
    <tbody>
        <tr>
            <td>Sentinel workspace</td>
            <td>Created and active</td>
            <td>Azure Portal → Microsoft Sentinel</td>
        </tr>
        <tr>
            <td>Defender-Sentinel connection</td>
            <td>Connected</td>
            <td>Defender Portal → Settings → Microsoft Sentinel</td>
        </tr>
        <tr>
            <td>Dynamic tags</td>
            <td>Only required if using tag-based scoping. Must be run at least once before use. Static tags are not supported.</td>
            <td>Defender Portal → Settings → Asset rule management</td>
        </tr>
    </tbody>
  </table>
</div>
<blockquote><p>If you plan to scope rules to specific device groups, configure dynamic tags before creating rules. If you deploy org-wide, you can skip this.</p>
</blockquote>
<h2 class="relative group">Step 1: Connect your Microsoft Sentinel workspace
    <div id="step-1-connect-your-microsoft-sentinel-workspace" class="anchor"></div>
    
</h2>
<p>Even if you already have Sentinel connected to Defender for other features, you need to explicitly select it for custom data collection.</p>
<ol>
<li>Open the Microsoft Defender portal at <a href="https://security.microsoft.com"  target="_blank" rel="noreferrer">security.microsoft.com</a></li>
<li>Click <strong>Settings</strong> in the left navigation</li>
<li>Select <strong>Endpoints</strong></li>
<li>Scroll down to <strong>Rules</strong></li>
<li>Click <strong>Custom Data Collection</strong></li>
</ol>
<figure><img
    class="my-0 rounded-md"
    loading="lazy"
    decoding="async"
    fetchpriority="auto"
    alt=""
    width="1919"
    height="998"
    src="https://www.modernsecurity.nl/defender-for-endpoint-custom-data-collection/image_hu_bd6b10856e52ca62.webp"
   
   
    data-zoom-src="https://www.modernsecurity.nl/defender-for-endpoint-custom-data-collection/image.webp"></figure><p>You’ll see the overview page showing any existing rules.</p>
<p>In the top-right corner, click the Microsoft Sentinel workspace dropdown or link, select your workspace from the list, and click <strong>Save</strong>.</p>
<figure><img
    class="my-0 rounded-md"
    loading="lazy"
    decoding="async"
    fetchpriority="auto"
    alt=""
    width="1919"
    height="998"
    src="https://www.modernsecurity.nl/defender-for-endpoint-custom-data-collection/image-1_hu_22c018ce2a0c812f.webp"
   
   
    data-zoom-src="https://www.modernsecurity.nl/defender-for-endpoint-custom-data-collection/image-1.webp"></figure><figure><img
    class="my-0 rounded-md"
    loading="lazy"
    decoding="async"
    fetchpriority="auto"
    alt=""
    width="1919"
    height="998"
    src="https://www.modernsecurity.nl/defender-for-endpoint-custom-data-collection/image-2_hu_79eed5371d531758.webp"
   
   
    data-zoom-src="https://www.modernsecurity.nl/defender-for-endpoint-custom-data-collection/image-2.webp"></figure><p><strong>Important limitation:</strong> You can only connect one Sentinel workspace per Defender tenant for custom data collection. If you have multiple workspaces, decide which one receives the custom telemetry before you start.</p>

<h2 class="relative group">Step 2: Configure dynamic tags
    <div id="step-2-configure-dynamic-tags" class="anchor"></div>
    
</h2>
<p>Dynamic tags are needed if you want to scope rules to specific device groups rather than deploying to all devices. If you skip this and choose “all applicable client devices” when creating rules, you can come back and configure tags later when you want more targeted deployment.</p>
<p>Dynamic tags are automatically applied to devices based on rules you define in Asset Rule Management. Unlike static tags, they update as your environment changes.</p>

<h3 class="relative group">Create a dynamic tag
    <div id="create-a-dynamic-tag" class="anchor"></div>
    
</h3>
<ol>
<li>In the Defender portal, go to <strong>Settings → Microsoft Defender XDR</strong></li>
<li>Click <strong>Asset rule management</strong></li>
<li>Click <strong>Create rule</strong></li>
</ol>
<figure><img
    class="my-0 rounded-md"
    loading="lazy"
    decoding="async"
    fetchpriority="auto"
    alt=""
    width="1919"
    height="997"
    src="https://www.modernsecurity.nl/defender-for-endpoint-custom-data-collection/image-3_hu_2a66fec267d29e66.webp"
   
   
    data-zoom-src="https://www.modernsecurity.nl/defender-for-endpoint-custom-data-collection/image-3.webp"></figure>
<h3 class="relative group">Configure the tag rule
    <div id="configure-the-tag-rule" class="anchor"></div>
    
</h3>
<ul>
<li><strong>Rule name:</strong> Something descriptive “Custom Data Collection Pilot Group”</li>
<li><strong>Description:</strong> Explain what devices this targets</li>
<li><strong>Conditions:</strong> Define which devices get this tag</li>
</ul>
<figure><img
    class="my-0 rounded-md"
    loading="lazy"
    decoding="async"
    fetchpriority="auto"
    alt=""
    width="1919"
    height="998"
    src="https://www.modernsecurity.nl/defender-for-endpoint-custom-data-collection/image-4_hu_a49efb4af6ee31ef.webp"
   
   
    data-zoom-src="https://www.modernsecurity.nl/defender-for-endpoint-custom-data-collection/image-4.webp"></figure><p>Example conditions:</p>

<div class="ms-table" role="region" aria-label="Table" tabindex="0">
  <table>
      <thead>
          <tr>
              <th>Condition type</th>
              <th>Operator</th>
              <th>Value</th>
          </tr>
      </thead>
    <tbody>
        <tr>
            <td>Device name</td>
            <td>Contains</td>
            <td>“P-“</td>
        </tr>
        <tr>
            <td>OS Platform</td>
            <td>Equals</td>
            <td>“Windows 11”</td>
        </tr>
        <tr>
            <td>Device group</td>
            <td>Equals</td>
            <td>“Personal Devices”</td>
        </tr>
    </tbody>
  </table>
</div>
<ul>
<li><strong>Tag to apply:</strong> Enter the tag name that will be stamped on matching devices e.g., “CustomCollectionPilot”</li>
<li>Click <strong>Submit</strong></li>
</ul>
<figure><img
    class="my-0 rounded-md"
    loading="lazy"
    decoding="async"
    fetchpriority="auto"
    alt=""
    width="1919"
    height="996"
    src="https://www.modernsecurity.nl/defender-for-endpoint-custom-data-collection/image-5_hu_3d376b1bedd355e3.webp"
   
   
    data-zoom-src="https://www.modernsecurity.nl/defender-for-endpoint-custom-data-collection/image-5.webp"></figure><figure><img
    class="my-0 rounded-md"
    loading="lazy"
    decoding="async"
    fetchpriority="auto"
    alt=""
    width="1919"
    height="998"
    src="https://www.modernsecurity.nl/defender-for-endpoint-custom-data-collection/image-6_hu_ddfeb823463a5fbe.webp"
   
   
    data-zoom-src="https://www.modernsecurity.nl/defender-for-endpoint-custom-data-collection/image-6.webp"></figure>
<h3 class="relative group">Wait for propagation
    <div id="wait-for-propagation" class="anchor"></div>
    
</h3>
<p>Dynamic tag rules run approximately every hour. After creating the rule, wait for it to run at least once before using the tag in collection rules. Verify tags are applied by going to <strong>Assets → Devices</strong>, selecting a device, and checking the Tags field.</p>

<h2 class="relative group">Step 3: Create your first custom data collection rule
    <div id="step-3-create-your-first-custom-data-collection-rule" class="anchor"></div>
    
</h2>
<p>With your Sentinel workspace connected and your pilot tag ready, create the following rule:</p>
<p>This example uses <code>DeviceScriptEvents</code> with the <code>AmsiScriptContent</code> action type. AMSI script events are not available in standard Advanced Hunting: <code>DeviceScriptEvents</code> is not queryable in the portal without custom data collection. This is exactly the gap the feature is designed to fill: telemetry that MDE collects on the endpoint but never exposes in Advanced Hunting under normal circumstances.</p>

<h3 class="relative group">Start the rule wizard
    <div id="start-the-rule-wizard" class="anchor"></div>
    
</h3>
<ol>
<li>From the Custom Data Collection page, click <strong>Create rule</strong></li>
</ol>
<figure><img
    class="my-0 rounded-md"
    loading="lazy"
    decoding="async"
    fetchpriority="auto"
    alt=""
    width="1919"
    height="998"
    src="https://www.modernsecurity.nl/defender-for-endpoint-custom-data-collection/image-7_hu_d18a6755e63a8ac7.webp"
   
   
    data-zoom-src="https://www.modernsecurity.nl/defender-for-endpoint-custom-data-collection/image-7.webp"></figure>
<h3 class="relative group">Configure general information
    <div id="configure-general-information" class="anchor"></div>
    
</h3>
<p>Enter the following:</p>
<ul>
<li><strong>Rule name:</strong> AMSI script content collection</li>
<li><strong>Description:</strong> Captures AMSI script content events from PowerShell for script-based attack detection. DeviceScriptEvents is not available in standard Advanced Hunting.</li>
<li><strong>Enabled:</strong> Toggle ON</li>
<li>Click <strong>Next</strong></li>
</ul>
<figure><img
    class="my-0 rounded-md"
    loading="lazy"
    decoding="async"
    fetchpriority="auto"
    alt="Custom Data Collection MDE Detection Engineering"
    width="1919"
    height="1000"
    src="https://www.modernsecurity.nl/defender-for-endpoint-custom-data-collection/image-23_hu_26d59f4329b526c4.webp"
   
   
    data-zoom-src="https://www.modernsecurity.nl/defender-for-endpoint-custom-data-collection/image-23.webp"></figure>
<h3 class="relative group">Define the collection rule
    <div id="define-the-collection-rule" class="anchor"></div>
    
</h3>
<p>Configure as follows:</p>
<ul>
<li><strong>Table:</strong> DeviceScriptEvents</li>
<li><strong>Action type:</strong> AmsiScriptContent</li>
</ul>
<figure><img
    class="my-0 rounded-md"
    loading="lazy"
    decoding="async"
    fetchpriority="auto"
    alt=""
    width="1919"
    height="998"
    src="https://www.modernsecurity.nl/defender-for-endpoint-custom-data-collection/image-24_hu_42d5091115600d51.webp"
   
   
    data-zoom-src="https://www.modernsecurity.nl/defender-for-endpoint-custom-data-collection/image-24.webp"></figure>
<h3 class="relative group">Add filter conditions
    <div id="add-filter-conditions" class="anchor"></div>
    
</h3>
<p>Configure the following conditions. The top-level operator is <strong>AND</strong>, with a subgroup using <strong>OR</strong> for the command line exclusions.</p>
<p><strong>Top level (AND):</strong></p>

<div class="ms-table" role="region" aria-label="Table" tabindex="0">
  <table>
      <thead>
          <tr>
              <th>Source</th>
              <th>Operator</th>
              <th>Value</th>
          </tr>
      </thead>
    <tbody>
        <tr>
            <td>InitiatingProcessSHA1</td>
            <td>Not equals</td>
            <td>1</td>
        </tr>
    </tbody>
  </table>
</div>
<p>This condition is always true: no real SHA1 hash will ever equal “1”. It serves as a catch-all to collect all events while still satisfying the filter requirement.</p>
<p><strong>Add subgroup (OR)</strong>, excludes known MDE-internal scripts:</p>

<div class="ms-table" role="region" aria-label="Table" tabindex="0">
  <table>
      <thead>
          <tr>
              <th>Source</th>
              <th>Operator</th>
              <th>Value</th>
          </tr>
      </thead>
    <tbody>
        <tr>
            <td>InitiatingProcessCommandLine</td>
            <td>Not equals</td>
            <td>“cscript.exe” /nologo “MonitorKnowledgeDiscovery.vbs”</td>
        </tr>
        <tr>
            <td>InitiatingProcessCommandLine</td>
            <td>Does not start with</td>
            <td>powershell.exe -ExecutionPolicy AllSigned -NoProfile -NonInteractive -Command “&amp; {<math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>O</mi><mi>u</mi><mi>t</mi><mi>p</mi><mi>u</mi><mi>t</mi><mi>E</mi><mi>n</mi><mi>c</mi><mi>o</mi><mi>d</mi><mi>i</mi><mi>n</mi><mi>g</mi><mo>=</mo><mo stretchy="false">[</mo><mi>C</mi><mi>o</mi><mi>n</mi><mi>s</mi><mi>o</mi><mi>l</mi><mi>e</mi><mo stretchy="false">]</mo><mo>:</mo><mo>:</mo><mi>O</mi><mi>u</mi><mi>t</mi><mi>p</mi><mi>u</mi><mi>t</mi><mi>E</mi><mi>n</mi><mi>c</mi><mi>o</mi><mi>d</mi><mi>i</mi><mi>n</mi><mi>g</mi><mo>=</mo><mo stretchy="false">[</mo><mi>S</mi><mi>y</mi><mi>s</mi><mi>t</mi><mi>e</mi><mi>m</mi><mi mathvariant="normal">.</mi><mi>T</mi><mi>e</mi><mi>x</mi><mi>t</mi><mi mathvariant="normal">.</mi><mi>E</mi><mi>n</mi><mi>c</mi><mi>o</mi><mi>d</mi><mi>i</mi><mi>n</mi><mi>g</mi><mo stretchy="false">]</mo><mo>:</mo><mo>:</mo><mi>U</mi><mi>T</mi><mi>F</mi><mn>8</mn><mo separator="true">;</mo></mrow><annotation encoding="application/x-tex">OutputEncoding = [Console]::OutputEncoding =[System.Text.Encoding]::UTF8;</annotation></semantics></math>OutputEncoding=[Console]::OutputEncoding=[System.Text.Encoding]::UTF8;scriptFileStream</td>
        </tr>
    </tbody>
  </table>
</div>
<figure><img
    class="my-0 rounded-md"
    loading="lazy"
    decoding="async"
    fetchpriority="auto"
    alt=""
    width="1919"
    height="998"
    src="https://www.modernsecurity.nl/defender-for-endpoint-custom-data-collection/image-25_hu_5d25d1a6b88200a7.webp"
   
   
    data-zoom-src="https://www.modernsecurity.nl/defender-for-endpoint-custom-data-collection/image-25.webp"></figure><p>The OR subgroup excludes two known MDE-native script executions that would otherwise generate noise. Add further exclusions here as you identify other internal processes in your environment.</p>

<h3 class="relative group">Define rule scope
    <div id="define-rule-scope" class="anchor"></div>
    
</h3>
<p>The portal gives you two options:</p>
<p><strong>All applicable client devices</strong>, deploys to every Windows device enrolled in Defender for Endpoint. Corresponds to <code>scope: Organization</code> in TelemetryCollectionManager. Simple to configure but highest potential cost, so only use this for critical rules you genuinely need everywhere.</p>
<p><strong>Specific devices that include dynamic tags</strong>, deploys only to devices with the selected tag. Use this for testing, cost control, or scenario-specific monitoring such as web servers or domain controllers.</p>
<figure><img
    class="my-0 rounded-md"
    loading="lazy"
    decoding="async"
    fetchpriority="auto"
    alt=""
    width="1919"
    height="999"
    src="https://www.modernsecurity.nl/defender-for-endpoint-custom-data-collection/image-20_hu_523907baa726b532.webp"
   
   
    data-zoom-src="https://www.modernsecurity.nl/defender-for-endpoint-custom-data-collection/image-20.webp"></figure><blockquote><p>If you choose tag-based scoping, the tags must be dynamic (configured in Asset Rule Management), not manual static tags.</p>
</blockquote><p>Click <strong>Next</strong>, review your settings, then click <strong>Submit</strong>.</p>
<p><strong>Deployment timeline:</strong> Rules take 20 minutes to 1 hour to propagate to devices.</p>
<figure><img
    class="my-0 rounded-md"
    loading="lazy"
    decoding="async"
    fetchpriority="auto"
    alt=""
    width="1919"
    height="998"
    src="https://www.modernsecurity.nl/defender-for-endpoint-custom-data-collection/image-13_hu_346faa14608407bc.webp"
   
   
    data-zoom-src="https://www.modernsecurity.nl/defender-for-endpoint-custom-data-collection/image-13.webp"></figure>
<h2 class="relative group">Step 4: Verify data is flowing
    <div id="step-4-verify-data-is-flowing" class="anchor"></div>
    
</h2>
<p>After creating rules and waiting for deployment, verify everything works.</p>

<h3 class="relative group">Check rule status
    <div id="check-rule-status" class="anchor"></div>
    
</h3>
<p>Go to <strong>Settings → Endpoints → Rules → Custom Data Collection</strong>, find your rule, and confirm the status column shows <strong>Enabled</strong>.</p>
<figure><img
    class="my-0 rounded-md"
    loading="lazy"
    decoding="async"
    fetchpriority="auto"
    alt=""
    width="1919"
    height="997"
    src="https://www.modernsecurity.nl/defender-for-endpoint-custom-data-collection/image-21_hu_f5a265b5da7e95a1.webp"
   
   
    data-zoom-src="https://www.modernsecurity.nl/defender-for-endpoint-custom-data-collection/image-21.webp"></figure>
<h3 class="relative group">Query custom tables in Advanced Hunting
    <div id="query-custom-tables-in-advanced-hunting" class="anchor"></div>
    
</h3>
<p>Check for any events from your rules:</p>
<div class="highlight-wrapper"><div class="highlight"><div class="ms-code-label">KQL</div><pre tabindex="0" class="chroma"><code class="language-kql" data-lang="kql">DeviceCustomScriptEvents
<span class="o">|</span> <span class="k">where</span> TimeGenerated <span class="o">&gt;</span> <span class="nf">ago</span>(1h)
<span class="o">|</span> <span class="k">where</span> RuleName <span class="o">==</span> <span class="s">&#34;AMSI script content collection&#34;</span>
<span class="o">|</span> <span class="k">take</span> 10</code></pre></div>
</div>
<figure><img
    class="my-0 rounded-md"
    loading="lazy"
    decoding="async"
    fetchpriority="auto"
    alt=""
    width="1919"
    height="998"
    src="https://www.modernsecurity.nl/defender-for-endpoint-custom-data-collection/image-22_hu_966ed4ae77a7b360.webp"
   
   
    data-zoom-src="https://www.modernsecurity.nl/defender-for-endpoint-custom-data-collection/image-22.webp"></figure>
<h3 class="relative group">What if no data appears?
    <div id="what-if-no-data-appears" class="anchor"></div>
    
</h3>
<p>Wait at least 1 hour after rule creation before troubleshooting. If still no data:</p>
<ul>
<li><strong>Verify client version:</strong> Query <code>DeviceInfo</code> for your test devices needs to be 10.8805 or higher</li>
<li><strong>Check tag assignment:</strong> Verify the device has the dynamic tag applied</li>
<li><strong>Broaden your rule temporarily:</strong> Create a rule with minimal filters to see if anything flows at all</li>
<li><strong>Reboot a test device:</strong> Sometimes the Defender for Endpoint service needs a restart to pick up new rules</li>
</ul>

<h2 class="relative group">Step 5: Build detections on custom tables
    <div id="step-5-build-detections-on-custom-tables" class="anchor"></div>
    
</h2>
<p>Now that data is flowing, create an analytics rule in Sentinel to detect suspicious script content.</p>

<h3 class="relative group">Create an analytics rule in Sentinel
    <div id="create-an-analytics-rule-in-sentinel" class="anchor"></div>
    
</h3>
<ol>
<li>In the Microsoft Defender portal at <a href="https://security.microsoft.com"  target="_blank" rel="noreferrer">security.microsoft.com</a></li>
<li>Navigate to <strong>Microsoft Sentinel</strong> in the left navigation</li>
<li>Select your workspace</li>
<li>Go to <strong>Analytics → Create → Scheduled query rule</strong></li>
</ol>

<h3 class="relative group">Configure the rule
    <div id="configure-the-rule" class="anchor"></div>
    
</h3>
<p><strong>General tab:</strong></p>
<ul>
<li><strong>Name:</strong> Suspicious PowerShell script content detected via AMSI</li>
<li><strong>Severity:</strong> High</li>
<li><strong>MITRE ATT&amp;CK:</strong> T1059.001 – PowerShell</li>
</ul>
<figure><img
    class="my-0 rounded-md"
    loading="lazy"
    decoding="async"
    fetchpriority="auto"
    alt=""
    width="1919"
    height="998"
    src="https://www.modernsecurity.nl/defender-for-endpoint-custom-data-collection/image-26_hu_ad0fbb49cb55fac0.webp"
   
   
    data-zoom-src="https://www.modernsecurity.nl/defender-for-endpoint-custom-data-collection/image-26.webp"></figure><p><strong>Rule logic tab:</strong></p>
<div class="highlight-wrapper"><div class="highlight"><div class="ms-code-label">KQL</div><pre tabindex="0" class="chroma"><code class="language-kql" data-lang="kql">DeviceCustomScriptEvents
<span class="o">|</span> <span class="k">where</span> RuleName <span class="o">==</span> <span class="s">&#34;AMSI script content collection&#34;</span>
<span class="o">|</span> <span class="k">where</span> ScriptContent <span class="k">has_any</span> (
    <span class="s">&#34;IEX&#34;</span>,
    <span class="s">&#34;Invoke-Expression&#34;</span>,
    <span class="s">&#34;DownloadString&#34;</span>,
    <span class="s">&#34;DownloadFile&#34;</span>,
    <span class="s">&#34;FromBase64String&#34;</span>,
    <span class="s">&#34;Invoke-Mimikatz&#34;</span>,
    <span class="s">&#34;Invoke-Shellcode&#34;</span>,
    <span class="s">&#34;Invoke-ReflectivePEInjection&#34;</span>,
    <span class="s">&#34;AmsiUtils&#34;</span>,
    <span class="s">&#34;-EncodedCommand&#34;</span>,
    <span class="s">&#34;-enc &#34;</span>
)
<span class="o">|</span> <span class="k">project</span>
    TimeGenerated,
    DeviceName,
    InitiatingProcessFileName,
    InitiatingProcessAccountName,
    InitiatingProcessCommandLine,
    ScriptContent,
    ScriptContentSHA256</code></pre></div>
</div>
<figure><img
    class="my-0 rounded-md"
    loading="lazy"
    decoding="async"
    fetchpriority="auto"
    alt=""
    width="1919"
    height="998"
    src="https://www.modernsecurity.nl/defender-for-endpoint-custom-data-collection/image-27_hu_42d6bcd1108d6f68.webp"
   
   
    data-zoom-src="https://www.modernsecurity.nl/defender-for-endpoint-custom-data-collection/image-27.webp"></figure><p><code>ScriptContent</code> contains the decoded script text captured by AMSI: what the script actually does, regardless of how it was obfuscated on the command line. <code>ScriptContentSHA256</code> lets you pivot to other devices where the same script was executed, which is useful during incident response.</p>
<ul>
<li><strong>Run query every:</strong> 5 minutes</li>
<li><strong>Lookup data from:</strong> Last 5 minutes</li>
<li><strong>Alert threshold:</strong> Greater than 0</li>
</ul>
<p><strong>Incident settings:</strong></p>
<p>Enable incident creation. Group alerts by <strong>DeviceName</strong> so multiple suspicious script executions on the same device create one incident.</p>
<figure><img
    class="my-0 rounded-md"
    loading="lazy"
    decoding="async"
    fetchpriority="auto"
    alt=""
    width="1919"
    height="998"
    src="https://www.modernsecurity.nl/defender-for-endpoint-custom-data-collection/image-28_hu_79896549fc224dfb.webp"
   
   
    data-zoom-src="https://www.modernsecurity.nl/defender-for-endpoint-custom-data-collection/image-28.webp"></figure>
<h2 class="relative group">Managing rules at scale with TelemetryCollectionManager
    <div id="managing-rules-at-scale-with-telemetrycollectionmanager" class="anchor"></div>
    
</h2>
<p>If you followed the walkthrough in Step 3, you already experienced what building a single rule in the portal feels like: click through the wizard, add filter conditions one line at a time, one value per line, no way to paste a list, no validation until you submit. For one rule that’s manageable. For ten rules across five device groups, it becomes a real operational problem.</p>
<p>There is no bulk import, no version history, no way to review what changed between last Tuesday and today, and no way to roll back a misconfigured rule without manually recreating it. If a colleague builds a rule and you need to understand what it does, you open the portal, find the rule, and click through the wizard read-only. There is no export to a readable format.</p>
<p>FalconForce released <a href="https://github.com/FalconForceTeam/TelemetryCollectionManager"  target="_blank" rel="noreferrer">TelemetryCollectionManager</a> to solve exactly this. It is a CLI tool that lets you define rules as YAML files, validate them against the MDE schema locally, and deploy them via the Defender API. Your Git repository becomes the single source of truth: rules are reviewed before deployment, changes are tracked, and rollback is a <code>git revert</code>.</p>
<p><strong>Benefits:</strong></p>

<div class="ms-table" role="region" aria-label="Table" tabindex="0">
  <table>
      <thead>
          <tr>
              <th>Benefit</th>
              <th>Description</th>
          </tr>
      </thead>
    <tbody>
        <tr>
            <td>Version control</td>
            <td>Track changes, roll back mistakes</td>
        </tr>
        <tr>
            <td>Code review</td>
            <td>Review rules before deployment</td>
        </tr>
        <tr>
            <td>Bulk operations</td>
            <td>Deploy multiple rules at once</td>
        </tr>
        <tr>
            <td>Validation</td>
            <td>Catch errors before they hit production</td>
        </tr>
        <tr>
            <td>IntelliSense</td>
            <td>VSCode autocomplete with included schema</td>
        </tr>
    </tbody>
  </table>
</div>

<h3 class="relative group">Installation
    <div id="installation" class="anchor"></div>
    
</h3>
<p>Download from GitHub: <a href="https://github.com/FalconForceTeam/TelemetryCollectionManager"  target="_blank" rel="noreferrer">FalconForceTeam/TelemetryCollectionManager</a>. Releases available for Windows, macOS, and Linux.</p>
<p>All rules in the repository are disabled by default review and enable what’s appropriate for your environment before deploying.</p>

<h3 class="relative group">Basic usage
    <div id="basic-usage" class="anchor"></div>
    
</h3>
<p><strong>Step 1:</strong> Set up your rules directory</p>
<div class="highlight-wrapper"><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="cl">rules/
</span></span><span class="line"><span class="cl">├── lsass-access.yaml
</span></span><span class="line"><span class="cl">├── unsigned-dll-loads.yaml
</span></span><span class="line"><span class="cl">├── non-standard-ports.yaml
</span></span><span class="line"><span class="cl">└── powershell-unusual-location.yaml</span></span></code></pre></div></div>
<p><strong>Step 2:</strong> Validate rules locally</p>
<div class="highlight-wrapper"><div class="highlight"><div class="ms-code-label">Bash</div><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">./TelemetryCollectionManager --validate-only</span></span></code></pre></div></div>
<p><strong>Step 3:</strong> Authenticate</p>
<p>The tool requires a user-based token. There is currently no support for service principals, managed identities, or app registrations. This is an API limitation on Microsoft’s side, not a tool limitation. The two options are:</p>
<p>Option A: Azure CLI (recommended)</p>
<div class="highlight-wrapper"><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="cl">az login
</span></span><span class="line"><span class="cl"># Tool automatically uses your session</span></span></code></pre></div></div>
<p>Option B: Manual bearer token (if Azure CLI is not an option)</p>
<div class="highlight-wrapper"><div class="highlight"><div class="ms-code-label">Bash</div><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="nb">export</span> <span class="nv">AZURE_TOKEN</span><span class="o">=</span><span class="s2">&#34;your-token-here&#34;</span>
</span></span><span class="line"><span class="cl"><span class="c1"># Retrieve via browser developer tools: Defender portal &gt; F12 &gt; Network &gt; filter getToken?resource=MATP</span></span></span></code></pre></div></div>
<p><strong>Step 4:</strong> Deploy rules</p>
<div class="highlight-wrapper"><div class="highlight"><div class="ms-code-label">Bash</div><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">./TelemetryCollectionManager --post-rules</span></span></code></pre></div></div>
<p><strong>Step 5:</strong> List existing rules</p>
<div class="highlight-wrapper"><div class="highlight"><div class="ms-code-label">Bash</div><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">./TelemetryCollectionManager --list-rules</span></span></code></pre></div></div>
<p><strong>Step 6:</strong> Delete rules (use with care)</p>
<div class="highlight-wrapper"><div class="highlight"><div class="ms-code-label">Bash</div><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="c1"># Delete specific rules</span>
</span></span><span class="line"><span class="cl">./TelemetryCollectionManager --delete-rules <span class="s2">&#34;rule-id-1,rule-id-2&#34;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># Delete ALL rules</span>
</span></span><span class="line"><span class="cl">./TelemetryCollectionManager --delete-rules<span class="o">=</span>all</span></span></code></pre></div></div>
<p>TelemetryCollectionManager also supports converting existing portal rules to YAML, useful if you built rules in the portal before adopting the tool. Check the <a href="https://github.com/FalconForceTeam/TelemetryCollectionManager"  target="_blank" rel="noreferrer">README</a> for the exact flag.</p>

<h3 class="relative group">YAML schema reference
    <div id="yaml-schema-reference" class="anchor"></div>
    
</h3>
<p>Basic structure:</p>
<div class="highlight-wrapper"><div class="highlight"><div class="ms-code-label">YAML</div><pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl"><span class="c"># yaml-language-server: $schema=../rule-schema.json</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">Rule name here</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nt">description</span><span class="p">:</span><span class="w"> </span><span class="l">What this rule does and why</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nt">enabled</span><span class="p">:</span><span class="w"> </span><span class="kc">true</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nt">platform</span><span class="p">:</span><span class="w"> </span><span class="l">Windows</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nt">scope</span><span class="p">:</span><span class="w"> </span><span class="l">Organization</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nt">table</span><span class="p">:</span><span class="w"> </span><span class="l">DeviceProcessEvents</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nt">actionType</span><span class="p">:</span><span class="w"> </span><span class="l">ProcessCreated</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nt">filters</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">operator</span><span class="p">:</span><span class="w"> </span><span class="l">And</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">expressions</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span>- <span class="nt">filter</span><span class="p">:</span><span class="w"> </span><span class="l">Equals</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">source</span><span class="p">:</span><span class="w"> </span><span class="l">FileName</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">values</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="s2">&#34;example.exe&#34;</span><span class="p">]</span></span></span></code></pre></div></div>
<p>The <code>scope</code> field accepts <code>Organization</code> to deploy the rule to all applicable client devices, which is the equivalent of the “all applicable client devices” option in the portal wizard. To target a specific device group instead, replace it with the name of your dynamic tag, for example <code>scope: CustomCollectionPilot</code>. Static tags are not supported; if you use tag-based scoping it must be a dynamic tag configured in Asset Rule Management.</p>
<p>Nested logic example: PowerShell from a suspicious location, excluding a known management tool:</p>
<div class="highlight-wrapper"><div class="highlight"><div class="ms-code-label">YAML</div><pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl"><span class="nt">filters</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">operator</span><span class="p">:</span><span class="w"> </span><span class="l">And</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">expressions</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span>- <span class="nt">group</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">operator</span><span class="p">:</span><span class="w"> </span><span class="l">Or</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">expressions</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">          </span>- <span class="nt">filter</span><span class="p">:</span><span class="w"> </span><span class="l">Contains</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="nt">source</span><span class="p">:</span><span class="w"> </span><span class="l">FolderPath</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="nt">values</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="s2">&#34;\\temp\\&#34;</span><span class="p">]</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">          </span>- <span class="nt">filter</span><span class="p">:</span><span class="w"> </span><span class="l">Contains</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="nt">source</span><span class="p">:</span><span class="w"> </span><span class="l">FolderPath</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="nt">values</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="s2">&#34;\\downloads\\&#34;</span><span class="p">]</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span>- <span class="nt">filter</span><span class="p">:</span><span class="w"> </span><span class="l">NotEquals</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">source</span><span class="p">:</span><span class="w"> </span><span class="l">InitiatingProcessFileName</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">values</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="s2">&#34;ManagementTool.exe&#34;</span><span class="p">]</span></span></span></code></pre></div></div>

<h2 class="relative group">Practical rule examples
    <div id="practical-rule-examples" class="anchor"></div>
    
</h2>
<p>The following five rules are taken directly from the TelemetryCollectionManager repository, authored by FalconForce. All ship disabled by default which is really awesome, review and enable what fits your environment 🙂</p>

<h3 class="relative group">Example 1: lsass starting lsass
    <div id="example-1-lsass-starting-lsass" class="anchor"></div>
    
</h3>
<p>An attack technique where <code>lsass.exe</code> forks and spawns another instance of itself, commonly used to dump credentials from memory. This process creation event is not logged by default in MDE, making it a textbook case for custom data collection. Look for <code>InitiatingProcessParentFileName</code> not being <code>werfault.exe</code> when hunting results.</p>
<div class="highlight-wrapper"><div class="highlight"><div class="ms-code-label">YAML</div><pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl"><span class="c"># yaml-language-server: $schema=../rule-schema.json</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">lsass_starting_lsass</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nt">description</span><span class="p">:</span><span class="w"> </span><span class="l">An attack technique where lsass.exe &#39;forks&#39; and spawns another instance of itself, often used to dump credentials. Look for the InitiatingParentProcessFileName not being werfault.exe. This is not logged by default in MDE.</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nt">enabled</span><span class="p">:</span><span class="w"> </span><span class="kc">false</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nt">platform</span><span class="p">:</span><span class="w"> </span><span class="l">Windows</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nt">scope</span><span class="p">:</span><span class="w"> </span><span class="l">Organization</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nt">table</span><span class="p">:</span><span class="w"> </span><span class="l">DeviceProcessEvents</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nt">actionType</span><span class="p">:</span><span class="w"> </span><span class="l">ProcessCreated</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nt">filters</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">operator</span><span class="p">:</span><span class="w"> </span><span class="l">And</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">expressions</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span>- <span class="nt">source</span><span class="p">:</span><span class="w"> </span><span class="l">FileName</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">          </span><span class="nt">filter</span><span class="p">:</span><span class="w"> </span><span class="l">Contains</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">          </span><span class="nt">values</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span>- <span class="l">lsass.exe</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span>- <span class="nt">source</span><span class="p">:</span><span class="w"> </span><span class="l">InitiatingProcessFileName</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">          </span><span class="nt">filter</span><span class="p">:</span><span class="w"> </span><span class="l">Contains</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">          </span><span class="nt">values</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span>- <span class="l">lsass.exe</span></span></span></code></pre></div></div>

<h3 class="relative group">Example 2: Executions from uncommon locations
    <div id="example-2-executions-from-uncommon-locations" class="anchor"></div>
    
</h3>
<p>Malware staging and living-off-the-land attacks frequently execute processes from user-writable locations like temp folders, AppData, Downloads, or Desktop.</p>
<div class="highlight-wrapper"><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="cl"># yaml-language-server: $schema=../rule-schema.json
</span></span><span class="line"><span class="cl">name: executions_from_uncommon_locations
</span></span><span class="line"><span class="cl">description: Processes executing from uncommon locations such as temp folders or user profile paths. MDE logs only 1 attempt per process, so this rule will show the repeated executions of the same process.
</span></span><span class="line"><span class="cl">enabled: false
</span></span><span class="line"><span class="cl">platform: Windows
</span></span><span class="line"><span class="cl">scope: Organization
</span></span><span class="line"><span class="cl">table: DeviceProcessEvents
</span></span><span class="line"><span class="cl">actionType: ProcessCreated
</span></span><span class="line"><span class="cl">filters:
</span></span><span class="line"><span class="cl">    operator: Or
</span></span><span class="line"><span class="cl">    expressions:
</span></span><span class="line"><span class="cl">        - source: FolderPath
</span></span><span class="line"><span class="cl">          filter: Contains
</span></span><span class="line"><span class="cl">          values:
</span></span><span class="line"><span class="cl">            - &#39;C:\PerfLogs\&#39;
</span></span><span class="line"><span class="cl">            - &#39;C:\$Recycle.bin\&#39;
</span></span><span class="line"><span class="cl">            - &#39;C:\Users\Default&#39;
</span></span><span class="line"><span class="cl">            - &#39;C:\Users\Public\&#39;
</span></span><span class="line"><span class="cl">            - &#39;\Temp\&#39;
</span></span><span class="line"><span class="cl">            - &#39;C:\Windows\Prefetch\&#39;
</span></span><span class="line"><span class="cl">            - &#39;\AppData\Local\&#39;
</span></span><span class="line"><span class="cl">            - &#39;\AppData\Roaming\&#39;
</span></span><span class="line"><span class="cl">            - &#39;\Local Settings\Temp\&#39;
</span></span><span class="line"><span class="cl">            - &#39;\Temporary Internet Files\&#39;
</span></span><span class="line"><span class="cl">            - &#39;C:\Windows\Fonts\&#39;
</span></span><span class="line"><span class="cl">            - &#39;C:\Windows\Media\&#39;
</span></span><span class="line"><span class="cl">            - &#39;C:\Windows\Help\&#39;
</span></span><span class="line"><span class="cl">            - &#39;\htdocs\&#39;
</span></span><span class="line"><span class="cl">            - &#39;\wwwroot\&#39;
</span></span><span class="line"><span class="cl">            - &#39;\Downloads\&#39;
</span></span><span class="line"><span class="cl">            - &#39;\Desktop\&#39;</span></span></code></pre></div></div>

<h3 class="relative group">Example 3: .NET CLR loaded outside .NET framework folder
    <div id="example-3-net-clr-loaded-outside-net-framework-folder" class="anchor"></div>
    
</h3>
<p><code>DeviceImageLoadEvents</code> is heavily sampled in standard MDE. Loading .NET CLR DLLs (<code>clr.dll</code>, <code>clrjit.dll</code>, <code>mscoree.dll</code>) from processes outside the .NET framework folder is a strong indicator of in-memory .NET assembly execution: used by Cobalt Strike, execute-assembly techniques, and similar post-exploitation frameworks. Without custom collection, these DLL loads are largely invisible.</p>
<div class="highlight-wrapper"><div class="highlight"><div class="ms-code-label">YAML</div><pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl"><span class="c"># yaml-language-server: $schema=../rule-schema.json</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">dotnet_clr_loaded</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nt">description</span><span class="p">:</span><span class="w"> </span><span class="l">The .NET CLR DLLs being loaded by processes outside of the .NET framework folder, which may indicate assemblyloads into injected processes. Tune based on your environment to reduce noise.</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nt">enabled</span><span class="p">:</span><span class="w"> </span><span class="kc">false</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nt">platform</span><span class="p">:</span><span class="w"> </span><span class="l">Windows</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nt">scope</span><span class="p">:</span><span class="w"> </span><span class="l">Organization</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nt">table</span><span class="p">:</span><span class="w"> </span><span class="l">DeviceImageLoadEvents</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nt">actionType</span><span class="p">:</span><span class="w"> </span><span class="l">ImageLoaded</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nt">filters</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">operator</span><span class="p">:</span><span class="w"> </span><span class="l">And</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">expressions</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span>- <span class="nt">source</span><span class="p">:</span><span class="w"> </span><span class="l">FileName</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">filter</span><span class="p">:</span><span class="w"> </span><span class="l">Contains</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">values</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span>- <span class="l">clr.dll</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span>- <span class="l">clrjit.dll</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span>- <span class="l">mscoreei.dll</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span>- <span class="l">mscoree.dll</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span>- <span class="l">mscorlib.dll</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span>- <span class="l">mscoreeis.dll</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span>- <span class="l">mscorlib.ni.dll</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span>- <span class="nt">source</span><span class="p">:</span><span class="w"> </span><span class="l">InitiatingProcessFolderPath</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">filter</span><span class="p">:</span><span class="w"> </span><span class="l">NotContains</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">values</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span>- <span class="s1">&#39;C:\Windows\Microsoft.NET\&#39;</span></span></span></code></pre></div></div>

<h3 class="relative group">Example 4: Rundll32 loading comsvcs.dll for minidump
    <div id="example-4-rundll32-loading-comsvcs-dll-for-minidump" class="anchor"></div>
    
</h3>
<p><code>rundll32.exe</code> loading <code>comsvcs.dll</code> with <code>MiniDump</code> in the command line is a classic post-exploitation credential dump technique. It creates a memory dump of LSASS without using dedicated tooling. Again, <code>DeviceImageLoadEvents</code> is where standard MDE telemetry fails; this specific DLL load pattern may never appear in standard Advanced Hunting.</p>
<div class="highlight-wrapper"><div class="highlight"><div class="ms-code-label">YAML</div><pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl"><span class="c"># yaml-language-server: $schema=../rule-schema.json</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">rundll32_minidump</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nt">description</span><span class="p">:</span><span class="w"> </span><span class="l">Rundll32 loading comsvcs.dll to create a minidump, often used in post-exploitation activity.</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nt">enabled</span><span class="p">:</span><span class="w"> </span><span class="kc">false</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nt">platform</span><span class="p">:</span><span class="w"> </span><span class="l">Windows</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nt">scope</span><span class="p">:</span><span class="w"> </span><span class="l">Organization</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nt">table</span><span class="p">:</span><span class="w"> </span><span class="l">DeviceImageLoadEvents</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nt">actionType</span><span class="p">:</span><span class="w"> </span><span class="l">ImageLoaded</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nt">filters</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">operator</span><span class="p">:</span><span class="w"> </span><span class="l">And</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">expressions</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span>- <span class="nt">source</span><span class="p">:</span><span class="w"> </span><span class="l">FileName</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">filter</span><span class="p">:</span><span class="w"> </span><span class="l">Contains</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">values</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span>- <span class="l">comsvcs.dll</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span>- <span class="nt">source</span><span class="p">:</span><span class="w"> </span><span class="l">InitiatingProcessFileName</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">filter</span><span class="p">:</span><span class="w"> </span><span class="l">Equals</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">values</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span>- <span class="l">rundll32.exe</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span>- <span class="nt">source</span><span class="p">:</span><span class="w"> </span><span class="l">InitiatingProcessCommandLine</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">filter</span><span class="p">:</span><span class="w"> </span><span class="l">Contains</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">values</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span>- <span class="l">MiniDump</span></span></span></code></pre></div></div>

<h3 class="relative group">Example 5: Kirbi file creation
    <div id="example-5-kirbi-file-creation" class="anchor"></div>
    
</h3>
<p><code>.kirbi</code> files are Kerberos ticket files created by Mimikatz during credential theft operations (<code>sekurlsa::tickets /export</code> or <code>kerberos::list /export</code>). Their presence on disk is essentially unambiguous. There is no legitimate reason for <code>.kirbi</code> files to be created in normal operations.</p>
<div class="highlight-wrapper"><div class="highlight"><div class="ms-code-label">YAML</div><pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl"><span class="c"># yaml-language-server: $schema=../rule-schema.json</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">kirbi_file_creation</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nt">description</span><span class="p">:</span><span class="w"> </span><span class="l">Kirbi file creation detection, often used by Mimikatz for credential dumping.</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nt">enabled</span><span class="p">:</span><span class="w"> </span><span class="kc">true</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nt">platform</span><span class="p">:</span><span class="w"> </span><span class="l">Windows</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nt">scope</span><span class="p">:</span><span class="w"> </span><span class="l">Organization</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nt">table</span><span class="p">:</span><span class="w"> </span><span class="l">DeviceFileEvents</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nt">actionType</span><span class="p">:</span><span class="w"> </span><span class="l">FileCreated</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nt">filters</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">operator</span><span class="p">:</span><span class="w"> </span><span class="l">Or</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">expressions</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span>- <span class="nt">source</span><span class="p">:</span><span class="w"> </span><span class="l">FolderPath</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">          </span><span class="nt">filter</span><span class="p">:</span><span class="w"> </span><span class="l">EndsWith</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">          </span><span class="nt">values</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span>- <span class="l">.kirbi</span></span></span></code></pre></div></div>
<p>See the rest of the rules <a href="https://github.com/FalconForceTeam/TelemetryCollectionManager/tree/main/rules"  target="_blank" rel="noreferrer">here</a></p>

<h2 class="relative group">Understanding the costs
    <div id="understanding-the-costs" class="anchor"></div>
    
</h2>

<h3 class="relative group">What’s included vs extra
    <div id="whats-included-vs-extra" class="anchor"></div>
    
</h3>

<div class="ms-table" role="region" aria-label="Table" tabindex="0">
  <table>
      <thead>
          <tr>
              <th>Component</th>
              <th>Cost</th>
          </tr>
      </thead>
    <tbody>
        <tr>
            <td>Custom data collection feature</td>
            <td>Included with Defender for Endpoint P2</td>
        </tr>
        <tr>
            <td>Data ingestion to Sentinel</td>
            <td>Charged per GB</td>
        </tr>
    </tbody>
  </table>
</div>

<h3 class="relative group">Sentinel pricing (approximate, varies by region)
    <div id="sentinel-pricing-approximate-varies-by-region" class="anchor"></div>
    
</h3>

<div class="ms-table" role="region" aria-label="Table" tabindex="0">
  <table>
      <thead>
          <tr>
              <th>Tier</th>
              <th>Price per GB</th>
          </tr>
      </thead>
    <tbody>
        <tr>
            <td>Pay-as-you-go</td>
            <td>~€4.30–5.20</td>
        </tr>
        <tr>
            <td>100 GB/day commitment</td>
            <td>~€3.40 effective</td>
        </tr>
        <tr>
            <td>500 GB/day commitment</td>
            <td>~€2.96 effective</td>
        </tr>
    </tbody>
  </table>
</div>
<p>Always verify current pricing at <a href="https://azure.microsoft.com/en-us/pricing/details/microsoft-sentinel/"  target="_blank" rel="noreferrer">aka.ms/sentinelpricing</a> these figures shift with regional pricing updates.</p>

<h3 class="relative group">Cost calculation example
    <div id="cost-calculation-example" class="anchor"></div>
    
</h3>

<div class="ms-table" role="region" aria-label="Table" tabindex="0">
  <table>
      <thead>
          <tr>
              <th>Factor</th>
              <th>Value</th>
          </tr>
      </thead>
    <tbody>
        <tr>
            <td>Endpoints</td>
            <td>1,000 devices</td>
        </tr>
        <tr>
            <td>Events per device/day</td>
            <td>500 average</td>
        </tr>
        <tr>
            <td>Event size</td>
            <td>~2 KB each</td>
        </tr>
        <tr>
            <td>Daily volume</td>
            <td>1,000 × 500 × 2 KB = 1 GB/day</td>
        </tr>
        <tr>
            <td>Monthly cost (PAYG)</td>
            <td>30 × €5 = ~€150/month</td>
        </tr>
    </tbody>
  </table>
</div>
<p>That’s manageable. The risk is broad rules:</p>

<div class="ms-table" role="region" aria-label="Table" tabindex="0">
  <table>
      <thead>
          <tr>
              <th>Scenario</th>
              <th>Daily volume</th>
              <th>Monthly cost</th>
          </tr>
      </thead>
    <tbody>
        <tr>
            <td>Targeted rules (500 events/device)</td>
            <td>1 GB</td>
            <td>~€150</td>
        </tr>
        <tr>
            <td>Moderate rules (2,000 events/device)</td>
            <td>4 GB</td>
            <td>~€600</td>
        </tr>
        <tr>
            <td>Broad rules (10,000 events/device)</td>
            <td>20 GB</td>
            <td>~€3,000</td>
        </tr>
    </tbody>
  </table>
</div>

<h3 class="relative group">Cost optimization tips
    <div id="cost-optimization-tips" class="anchor"></div>
    
</h3>
<ul>
<li><strong>Start narrow</strong> begin with specific filters, expand only if needed</li>
<li><strong>Scope to device groups</strong> don’t collect from every device if not necessary</li>
<li><strong>Monitor ingestion:</strong> use Sentinel’s Usage workbook regularly</li>
<li><strong>Remove unused rules</strong> if nobody queries the data, delete the rule</li>
<li><strong>Consider commitment tiers</strong> if collecting &gt;100 GB/day, commit for savings</li>
</ul>

<h2 class="relative group">Custom data collection vs Sysmon
    <div id="custom-data-collection-vs-sysmon" class="anchor"></div>
    
</h2>
<p>For years, Sysmon has been the go-to solution for filling MDE’s telemetry gaps. When MDE didn’t give you DLL loads, you added Sysmon. When you needed registry events for persistence detection, Sysmon. Named pipes, driver loads, WMI events: Sysmon covered what MDE didn’t. The trade-off was always the operational overhead: a separate agent to deploy, a separate XML configuration to maintain, a separate data schema to write detections against, and a log collection agent on top of that to get the events into Sentinel.</p>
<p>Custom data collection changes that trade-off significantly. Process, file, network, and image load events now have a native MDE solution that uses the same schema you already query in Advanced Hunting, deploys without an additional agent, and integrates directly with Sentinel. For many organizations, this is enough to remove Sysmon entirely or at least substantially reduce its scope.</p>
<p>Honestly, you probably still need both.</p>

<h3 class="relative group">Comparison
    <div id="comparison" class="anchor"></div>
    
</h3>

<div class="ms-table" role="region" aria-label="Table" tabindex="0">
  <table>
      <thead>
          <tr>
              <th>Aspect</th>
              <th>Custom data collection</th>
              <th>Sysmon</th>
          </tr>
      </thead>
    <tbody>
        <tr>
            <td>Deployment</td>
            <td>Built into Defender for Endpoint</td>
            <td>Separate agent + config</td>
        </tr>
        <tr>
            <td>Management</td>
            <td>Portal or API</td>
            <td>XML files</td>
        </tr>
        <tr>
            <td>Data schema</td>
            <td>MDE tables</td>
            <td>Sysmon events</td>
        </tr>
        <tr>
            <td>Process events</td>
            <td>✅</td>
            <td>✅</td>
        </tr>
        <tr>
            <td>File events</td>
            <td>✅</td>
            <td>✅</td>
        </tr>
        <tr>
            <td>Network events</td>
            <td>✅</td>
            <td>✅</td>
        </tr>
        <tr>
            <td>Image/DLL loads</td>
            <td>✅</td>
            <td>✅</td>
        </tr>
        <tr>
            <td>Registry events</td>
            <td>❌</td>
            <td>✅</td>
        </tr>
        <tr>
            <td>Named pipes</td>
            <td>❌</td>
            <td>✅</td>
        </tr>
        <tr>
            <td>Driver loads</td>
            <td>❌</td>
            <td>✅</td>
        </tr>
        <tr>
            <td>WMI events</td>
            <td>❌</td>
            <td>✅</td>
        </tr>
    </tbody>
  </table>
</div>

<h3 class="relative group">Recommendation
    <div id="recommendation" class="anchor"></div>
    
</h3>
<p>Use a hybrid approach:</p>
<ul>
<li><strong>Custom data collection</strong> for process, file, network, and DLL events where you need complete visibility</li>
<li><strong>Sysmon</strong> slimmed down to registry, pipe, and driver events only</li>
</ul>
<p>This reduces Sysmon’s footprint while maintaining visibility that custom data collection can’t provide.</p>
<p><strong>Alternative for DLL loads only:</strong></p>
<p>If you only need reliable DLL load telemetry without the full custom data collection setup, consider <a href="https://github.com/olafhartong/WDACme"  target="_blank" rel="noreferrer">WDACme</a> a WDAC audit-mode policy that generates CodeIntegrity events for specified DLLs in the <code>DeviceEvents</code> table. That said, custom data collection is more flexible and easier to manage at scale.</p>

<h2 class="relative group">Troubleshooting common issues
    <div id="troubleshooting-common-issues" class="anchor"></div>
    
</h2>

<h3 class="relative group">No events appearing
    <div id="no-events-appearing" class="anchor"></div>
    
</h3>

<div class="ms-table" role="region" aria-label="Table" tabindex="0">
  <table>
      <thead>
          <tr>
              <th>Check</th>
              <th>Solution</th>
          </tr>
      </thead>
    <tbody>
        <tr>
            <td>Time elapsed</td>
            <td>Wait at least 1 hour after rule creation</td>
        </tr>
        <tr>
            <td>Client version</td>
            <td>Must be 10.8805+ check <code>DeviceInfo</code> table</td>
        </tr>
        <tr>
            <td>Rule enabled</td>
            <td>Verify rule shows “Enabled” in portal</td>
        </tr>
        <tr>
            <td>Device in scope</td>
            <td>Verify device has the dynamic tag applied</td>
        </tr>
        <tr>
            <td>Filters too narrow</td>
            <td>Test with a broader rule temporarily</td>
        </tr>
        <tr>
            <td>Custom collection not initializing</td>
            <td>Check for EDR exclusions on target paths or processes; reboot the device if collection isn’t starting</td>
        </tr>
    </tbody>
  </table>
</div>

<h3 class="relative group">Hitting the 75,000 event cap
    <div id="hitting-the-75000-event-cap" class="anchor"></div>
    
</h3>
<p>Your rule is too broad. Solutions:</p>
<ul>
<li>Add more specific filters</li>
<li>Scope to fewer devices</li>
<li>Split into multiple targeted rules</li>
</ul>

<h3 class="relative group">Events in wrong table
    <div id="events-in-wrong-table" class="anchor"></div>
    
</h3>
<p>Custom data collection uses <code>DeviceCustom*</code> tables, not standard <code>Device*</code> tables:</p>
<div class="highlight-wrapper"><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="cl">// Wrong - standard table
</span></span><span class="line"><span class="cl">DeviceProcessEvents | where ...
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">// Right - custom table
</span></span><span class="line"><span class="cl">DeviceCustomProcessEvents | where ...</span></span></code></pre></div></div>

<h3 class="relative group">Rule not deploying to device
    <div id="rule-not-deploying-to-device" class="anchor"></div>
    
</h3>
<ul>
<li>Verify device meets OS and client version prerequisites</li>
<li>If using dynamic tags, verify the tag is applied to the device and the tag rule has run in Asset Rule Management</li>
<li>Try rebooting the device</li>
</ul>

<h3 class="relative group">Useful diagnostic query
    <div id="useful-diagnostic-query" class="anchor"></div>
    
</h3>
<div class="highlight-wrapper"><div class="highlight"><div class="ms-code-label">KQL</div><pre tabindex="0" class="chroma"><code class="language-kql" data-lang="kql"><span class="k">search</span> <span class="k">in</span> (DeviceCustomProcessEvents, DeviceCustomNetworkEvents, DeviceCustomFileEvents, DeviceCustomImageLoadEvents, DeviceCustomScriptEvents) *
<span class="o">|</span> <span class="k">where</span> DeviceId <span class="o">==</span> <span class="s">&#34;your-device-id&#34;</span>
<span class="o">|</span> <span class="k">where</span> TimeGenerated <span class="o">&gt;</span> <span class="nf">ago</span>(24h)
<span class="o">|</span> <span class="k">summarize</span> EventCount = <span class="k">count</span>() <span class="k">by</span> RuleName, $table
<span class="o">|</span> <span class="k">order by</span> EventCount <span class="k">desc</span></code></pre></div>
</div>

<h2 class="relative group">References
    <div id="references" class="anchor"></div>
    
</h2>
<ul>
<li><a href="https://learn.microsoft.com/en-us/defender-endpoint/custom-data-collection"  target="_blank" rel="noreferrer">Microsoft Learn: Custom data collection in Defender for Endpoint</a></li>
<li><a href="https://learn.microsoft.com/en-us/defender-endpoint/create-custom-data-collection-rules"  target="_blank" rel="noreferrer">Microsoft Learn: Create custom data collection rules</a></li>
<li><a href="https://falconforce.nl/microsoft-defender-for-endpoint-internal-0x06-custom-collection/"  target="_blank" rel="noreferrer">FalconForce: MDE Internals 0x06 – Custom Collection</a></li>
<li><a href="https://falconforce.nl/microsoft-defender-for-endpoint-internals-0x03-mde-telemetry-unreliability-and-log-augmentation/"  target="_blank" rel="noreferrer">FalconForce: MDE Internals 0x03 – Telemetry Unreliability</a></li>
<li><a href="https://falconforce.nl/sysmon-vs-microsoft-defender-for-endpoint-mde-internals-0x01/"  target="_blank" rel="noreferrer">FalconForce: MDE Internals 0x01 – Sysmon vs MDE</a></li>
<li><a href="https://github.com/FalconForceTeam/TelemetryCollectionManager"  target="_blank" rel="noreferrer">GitHub: FalconForce TelemetryCollectionManager</a></li>
<li><a href="https://github.com/olafhartong/WDACme"  target="_blank" rel="noreferrer">GitHub: WDACme – DLL load telemetry workaround</a></li>
<li><a href="https://azure.microsoft.com/en-us/pricing/details/microsoft-sentinel/"  target="_blank" rel="noreferrer">Microsoft Sentinel pricing</a></li>
<li><a href="https://learn.microsoft.com/en-us/defender-xdr/configure-asset-rules"  target="_blank" rel="noreferrer">Configure dynamic rules for devices</a></li>
</ul>

<h2 class="relative group">Conclusion
    <div id="conclusion" class="anchor"></div>
    
</h2>
<p>Custom data collection fills a real gap that detection engineers working with Defender for Endpoint have dealt with for years. The event capping in standard telemetry isn’t going away it’s a structural trade-off in how MDE is priced and operated. This feature gives you a legitimate, supported path to collect the specific events you actually need, without bolting on another agent or working around the schema.</p>
<p>That said, it’s not a fire-and-forget feature. Every rule you create is an ongoing cost, and broad rules will surface that cost quickly. The organizations that get the most value from this are the ones that start from a concrete detection gap a technique they couldn’t detect reliably, a table they knew was being sampled and work backwards to the minimum rule that closes it.</p>
<p>The hybrid approach with Sysmon still makes sense for most environments. Custom data collection covers process, file, network, and DLL events well. Sysmon still wins on registry, pipes, and driver loads. Using both, scoped appropriately, gives you more complete coverage than either alone.</p>
]]></content:encoded><media:content url="https://www.modernsecurity.nl/defender-for-endpoint-custom-data-collection/featured_hu_d5f33b01f18c8f99.jpg" medium="image" type="image/jpeg" width="1200" height="800"/><enclosure url="https://www.modernsecurity.nl/defender-for-endpoint-custom-data-collection/featured_hu_d5f33b01f18c8f99.jpg" type="image/jpeg" length="73915"/></item><item><title>Identity attack graph in Microsoft Sentinel: easy find lateral movement paths</title><link>https://www.modernsecurity.nl/microsoft-sentinel-identity-attack-graph/</link><guid isPermaLink="true">https://www.modernsecurity.nl/microsoft-sentinel-identity-attack-graph/</guid><pubDate>Sat, 09 May 2026 19:17:30 +0100</pubDate><dc:creator>Farid Kalaidji</dc:creator><category>Identity</category><category>Microsoft Entra ID (Azure AD)</category><category>Microsoft Sentinel</category><description>Map lateral movement paths across Entra and Azure. Step-by-step setup guide for the Microsoft Sentinel identity attack graph.</description><content:encoded><![CDATA[<p>Sentinel graph ships with two layers. One is custom graphs, where you build your own schema from any data in the lake, which I will cover in a new blog post later. The other is a set of Microsoft-managed graphs that require no authoring at all.</p>
<p>The identity attack graph is the most useful of those managed graphs. Enable two connectors, turn on the graph, wait for the initial build, and you have a query-able model of how identities in your tenant connect to Azure resources through permissions and group memberships. No notebooks, no schema design, no GQL to write upfront.</p>
<p><strong>The graph is currently in preview</strong></p>

<h2 class="relative group">What it shows you
    <div id="what-it-shows-you" class="anchor"></div>
    
</h2>
<p>The identity attack graph models three things: identities (users, service principals, managed identities, groups), Azure resources (subscriptions, resource groups, VMs, storage accounts, Key Vaults), and the access relationships connecting them via role assignments and group memberships.</p>
<p>The focus is lateral movement paths, not just direct access. A user who is a member of a group that has a role assignment on a subscription containing a Key Vault is three hops from that Key Vault. That chain doesn’t appear in a flat permissions table. It appears in a graph because each of those relationships is modelled as an edge you can traverse.</p>
<p>It’s built to answer questions like:</p>
<ul>
<li>What resources could an attacker reach if this account is compromised?</li>
<li>Which identities have indirect paths to privileged roles?</li>
<li>Which service principals can reach VMs, and via how many hops?</li>
<li>Are there circular group memberships creating unintended privilege inheritance?</li>
</ul>
<p>The predefined queries surface these without any GQL knowledge required. You can also write your own once you’re familiar with the schema.</p>

<h2 class="relative group">Prerequisites
    <div id="prerequisites" class="anchor"></div>
    
</h2>

<div class="ms-table" role="region" aria-label="Table" tabindex="0">
  <table>
      <thead>
          <tr>
              <th>Requirement</th>
              <th>Details</th>
          </tr>
      </thead>
    <tbody>
        <tr>
            <td><strong>Microsoft Sentinel data lake</strong></td>
            <td>Must be enabled. The identity attack graph reads from the data lake tier and won’t work without it.</td>
        </tr>
        <tr>
            <td><strong>Microsoft Entra ID Assets connector</strong></td>
            <td>Required. Provides identity data: users, groups, service principals, managed identities, and the relationships between them.</td>
        </tr>
        <tr>
            <td><strong>Azure Resource Graph connector</strong></td>
            <td>Required. Provides Azure subscription and resource hierarchy.</td>
        </tr>
        <tr>
            <td><strong>Role to create the graph</strong></td>
            <td>Global Administrator or Security Administrator.</td>
        </tr>
    </tbody>
  </table>
</div>
<p>Both connectors are bundled in their respective Sentinel solution packages. If not yet installed, find them in Content Hub under <strong><a href="https://www.modernsecurity.nl/microsoft-sentinel/" >Microsoft Sentinel</a></strong> &gt; <strong>Content Management</strong> &gt; <strong>Content Hub</strong>.</p>
<figure><img
    class="my-0 rounded-md"
    loading="lazy"
    decoding="async"
    fetchpriority="auto"
    alt=""
    width="1919"
    height="998"
    src="https://www.modernsecurity.nl/microsoft-sentinel-identity-attack-graph/image_hu_ba4e51b0f6759177.webp"
   
   
    data-zoom-src="https://www.modernsecurity.nl/microsoft-sentinel-identity-attack-graph/image.webp"></figure><figure><img
    class="my-0 rounded-md"
    loading="lazy"
    decoding="async"
    fetchpriority="auto"
    alt=""
    width="1919"
    height="995"
    src="https://www.modernsecurity.nl/microsoft-sentinel-identity-attack-graph/image-7_hu_d2186a1b06479634.webp"
   
   
    data-zoom-src="https://www.modernsecurity.nl/microsoft-sentinel-identity-attack-graph/image-7.webp"></figure><p>Asset data snapshots are taken once every 24 hours. After enabling a connector, data can take up to 24 hours to arrive in the lake. Initial graph processing after that can take up to 48 hours. Enable this well before you need it for an investigation.</p>

<h2 class="relative group">One thing most guides don’t mention: ARG connector coverage
    <div id="one-thing-most-guides-dont-mention-arg-connector-coverage" class="anchor"></div>
    
</h2>
<p>The Azure Resource Graph connector has a coverage limitation worth understanding before you enable it.</p>
<p>When enabled, its managed identity is automatically granted the Reader role only on subscriptions where <em>you</em> have the Owner role. If you don’t have Owner across your entire Azure estate (most people don’t), the connector ingests a partial view. The graph gets built, but it won’t include resources from subscriptions the managed identity can’t read.</p>
<p>In my case I had the owner permissions and the identity was correctly setup:</p>
<figure><img
    class="my-0 rounded-md"
    loading="lazy"
    decoding="async"
    fetchpriority="auto"
    alt=""
    width="1919"
    height="995"
    src="https://www.modernsecurity.nl/microsoft-sentinel-identity-attack-graph/image-1_hu_ab7e9526545e9bb0.webp"
   
   
    data-zoom-src="https://www.modernsecurity.nl/microsoft-sentinel-identity-attack-graph/image-1.webp"></figure><p>To get full tenant coverage, someone with elevated permissions needs to assign the Reader role to the connector’s managed identity at a broader scope if it failed. The managed identity is named <code>msg-resources-</code> followed by an alphanumeric ID, for example <code>msg-resources-b05e</code>. Reader can be assigned at:</p>
<ul>
<li><strong>Tenant root management group</strong> covers all subscriptions in the tenant</li>
<li>A specific <strong>management group</strong> covers a subset</li>
<li>Individual <strong>subscriptions</strong> covers only those</li>
</ul>
<p>Steps to assign:</p>
<ol>
<li>
<p>Navigate to the scope you want to cover, for example Tenant Root Group &gt; <strong>Access control (IAM)</strong></p>
</li>
<li>
<p>Select <strong>+ Add</strong> &gt; <strong>Add role assignment</strong></p>
</li>
<li>
<p>Assign the <strong>Reader</strong> role to the managed identity</p>
</li>
<li>
<p>Locate the <code>msg-resources-*</code> managed identity and complete the assignment</p>
</li>
</ol>
<figure><img
    class="my-0 rounded-md"
    loading="lazy"
    decoding="async"
    fetchpriority="auto"
    alt=""
    width="1919"
    height="999"
    src="https://www.modernsecurity.nl/microsoft-sentinel-identity-attack-graph/image-2_hu_f4ecacb19df53aaf.webp"
   
   
    data-zoom-src="https://www.modernsecurity.nl/microsoft-sentinel-identity-attack-graph/image-2.webp"></figure><p>After the assignment propagates, the next ingestion cycle picks up the additional resources. Up to 24 hours for the new data to appear in the lake.</p>
<p>If your graph is missing subscriptions or resources you’d expect to find, this is almost certainly the reason.</p>

<h2 class="relative group">Setting up the identity attack graph
    <div id="setting-up-the-identity-attack-graph" class="anchor"></div>
    
</h2>

<h3 class="relative group">Step 1: Navigate to Graphs
    <div id="step-1-navigate-to-graphs" class="anchor"></div>
    
</h3>
<p>In the Microsoft Defender portal, go to <strong>Microsoft Sentinel</strong> &gt; <strong>Graphs</strong>.</p>
<figure><img
    class="my-0 rounded-md"
    loading="lazy"
    decoding="async"
    fetchpriority="auto"
    alt=""
    width="1919"
    height="997"
    src="https://www.modernsecurity.nl/microsoft-sentinel-identity-attack-graph/image-3_hu_9343ac3a3f515db6.webp"
   
   
    data-zoom-src="https://www.modernsecurity.nl/microsoft-sentinel-identity-attack-graph/image-3.webp"></figure>
<h3 class="relative group">Step 2: Set up the graph
    <div id="step-2-set-up-the-graph" class="anchor"></div>
    
</h3>
<p>Find the <strong>identity attack graph</strong> card and select <strong>Set up graph</strong>.</p>
<figure><img
    class="my-0 rounded-md"
    loading="lazy"
    decoding="async"
    fetchpriority="auto"
    alt=""
    width="1919"
    height="997"
    src="https://www.modernsecurity.nl/microsoft-sentinel-identity-attack-graph/image-4_hu_7069c80c24b0c0d9.webp"
   
   
    data-zoom-src="https://www.modernsecurity.nl/microsoft-sentinel-identity-attack-graph/image-4.webp"></figure>
<h3 class="relative group">Step 3: Enable the required connectors
    <div id="step-3-enable-the-required-connectors" class="anchor"></div>
    
</h3>
<p>The setup flow walks you through both connectors:</p>
<ul>
<li><strong>Microsoft Entra ID</strong> <strong>Assets</strong> covers identity data, group memberships, and service principals</li>
<li><strong>Azure Resource Graph</strong> covers Azure subscriptions and resource hierarchy</li>
</ul>
<p>If either is not yet installed, go to Content Hub first and install the relevant solution. Already installed but not enabled, the setup flow will prompt you to turn them on.</p>
<p>This is also the point to think about ARG connector coverage. If full tenant coverage matters for your use case, sort out the managed identity Reader assignment before continuing.</p>

<h3 class="relative group">Step 4: Turn on the graph
    <div id="step-4-turn-on-the-graph" class="anchor"></div>
    
</h3>
<p>Select <strong>Turn on graph</strong>. The graph starts ingesting data and building its relationship model.</p>
<figure><img
    class="my-0 rounded-md"
    loading="lazy"
    decoding="async"
    fetchpriority="auto"
    alt=""
    width="1919"
    height="999"
    src="https://www.modernsecurity.nl/microsoft-sentinel-identity-attack-graph/image-5_hu_3253b8c9213e1e82.webp"
   
   
    data-zoom-src="https://www.modernsecurity.nl/microsoft-sentinel-identity-attack-graph/image-5.webp"></figure><p>Initial processing can take up to 48 hours. The graph is not query-able until the first build completes.</p>
<figure><img
    class="my-0 rounded-md"
    loading="lazy"
    decoding="async"
    fetchpriority="auto"
    alt=""
    width="1919"
    height="997"
    src="https://www.modernsecurity.nl/microsoft-sentinel-identity-attack-graph/image-6_hu_4fa0a751c99a88ee.webp"
   
   
    data-zoom-src="https://www.modernsecurity.nl/microsoft-sentinel-identity-attack-graph/image-6.webp"></figure>
<h3 class="relative group">Step 5: Open the query interface
    <div id="step-5-open-the-query-interface" class="anchor"></div>
    
</h3>
<p>When the graph shows as ready, select <strong>Query graph</strong> on the identity attack graph tile.</p>
<figure><img
    class="my-0 rounded-md"
    loading="lazy"
    decoding="async"
    fetchpriority="auto"
    alt=""
    width="1919"
    height="1000"
    src="https://www.modernsecurity.nl/microsoft-sentinel-identity-attack-graph/image-8_hu_1e5c35974dd47a75.webp"
   
   
    data-zoom-src="https://www.modernsecurity.nl/microsoft-sentinel-identity-attack-graph/image-8.webp"></figure>
<h2 class="relative group">Querying the identity attack graph
    <div id="querying-the-identity-attack-graph" class="anchor"></div>
    
</h2>

<h3 class="relative group">Step 6: Review the schema
    <div id="step-6-review-the-schema" class="anchor"></div>
    
</h3>
<p>Before running anything, open the <strong>Schema</strong> tab.</p>
<figure><img
    class="my-0 rounded-md"
    loading="lazy"
    decoding="async"
    fetchpriority="auto"
    alt=""
    width="1919"
    height="1199"
    src="https://www.modernsecurity.nl/microsoft-sentinel-identity-attack-graph/image-10_hu_26022a4f894b5d6a.webp"
   
   
    data-zoom-src="https://www.modernsecurity.nl/microsoft-sentinel-identity-attack-graph/image-10.webp"></figure><p>The schema defines what you can match in GQL. Node types include Entra users, groups, service principals, managed identities, Azure subscriptions, resource groups, VMs, storage accounts, and Key Vaults. Edge types include group memberships and role assignments. Checking the schema before writing queries saves time.</p>
<figure><img
    class="my-0 rounded-md"
    loading="lazy"
    decoding="async"
    fetchpriority="auto"
    alt=""
    width="1919"
    height="1199"
    src="https://www.modernsecurity.nl/microsoft-sentinel-identity-attack-graph/image-11_hu_6f2344b928ba7ed5.webp"
   
   
    data-zoom-src="https://www.modernsecurity.nl/microsoft-sentinel-identity-attack-graph/image-11.webp"></figure><p>Worth being explicit: the query language here is <strong>GQL (Graph Query Language)</strong>, not KQL. The syntax looks familiar in places but the logic is different. GQL uses <code>MATCH (x)-[y]-&gt;(z)</code> patterns to traverse relationships. You follow edges between nodes rather than joining rows. The predefined queries are a good way to see what working GQL looks like before writing your own.</p>

<h3 class="relative group">Step 7: Start with the predefined queries
    <div id="step-7-start-with-the-predefined-queries" class="anchor"></div>
    
</h3>
<p>Start with the predefined queries before writing custom GQL. They cover the most useful scenarios and show you the query structure.</p>
<figure><img
    class="my-0 rounded-md"
    loading="lazy"
    decoding="async"
    fetchpriority="auto"
    alt=""
    width="1919"
    height="1199"
    src="https://www.modernsecurity.nl/microsoft-sentinel-identity-attack-graph/image-12_hu_6f2344b928ba7ed5.webp"
   
   
    data-zoom-src="https://www.modernsecurity.nl/microsoft-sentinel-identity-attack-graph/image-12.webp"></figure>
<div class="ms-table" role="region" aria-label="Table" tabindex="0">
  <table>
      <thead>
          <tr>
              <th>Query</th>
              <th>What it surfaces</th>
          </tr>
      </thead>
    <tbody>
        <tr>
            <td><strong>Visualize any graph</strong></td>
            <td>All nodes and edges, good starting point for exploration</td>
        </tr>
        <tr>
            <td><strong>Map Azure management structure</strong></td>
            <td>Subscription, resource group, and resource hierarchy</td>
        </tr>
        <tr>
            <td><strong>Identity attack paths: Entra users to Azure Key Vaults</strong></td>
            <td>Users with direct or indirect Key Vault access</td>
        </tr>
        <tr>
            <td><strong>Identity attack paths: service principals to virtual machines</strong></td>
            <td>Service principals that can reach VMs</td>
        </tr>
        <tr>
            <td><strong>Identity attack paths to Azure subscriptions</strong></td>
            <td>Identities with paths to subscription-level access</td>
        </tr>
        <tr>
            <td><strong>Identity attack paths to privileged roles</strong></td>
            <td>Identities that can reach privileged directory roles</td>
        </tr>
        <tr>
            <td><strong>Entra group memberships: detect circular relationships</strong></td>
            <td>Groups that form circular membership chains</td>
        </tr>
    </tbody>
  </table>
</div>
<p>Select <strong>Edit query</strong> on any of these to copy the GQL into the editor, then adjust filters, change the target node type, or add conditions for your specific investigation.</p>

<h3 class="relative group">Step 8: Run and explore
    <div id="step-8-run-and-explore" class="anchor"></div>
    
</h3>
<p>Select <strong>Run GQL query</strong>. Results render as an interactive graph (in this case I used the <strong>Visualize any graph</strong> as base):</p>
<figure><img
    class="my-0 rounded-md"
    loading="lazy"
    decoding="async"
    fetchpriority="auto"
    alt=""
    width="1919"
    height="1199"
    src="https://www.modernsecurity.nl/microsoft-sentinel-identity-attack-graph/image-15_hu_9c026b744093740e.webp"
   
   
    data-zoom-src="https://www.modernsecurity.nl/microsoft-sentinel-identity-attack-graph/image-15.webp"></figure><p>From here:</p>
<ul>
<li>Select any node to open the details pane with account status, department, role assignments, and last password change</li>
<li>Right-click a node and select <strong>Explore connected assets</strong> to traverse one hop further without a new query</li>
<li>Switch to <strong>Table view</strong> to see results in rows and export to CSV</li>
<li>Hover over a node to highlight its direct connections and mute everything else</li>
<li>Use the filters in the top right of the canvas to narrow by node type or edge relationship</li>
</ul>
<figure><img
    class="my-0 rounded-md"
    loading="lazy"
    decoding="async"
    fetchpriority="auto"
    alt=""
    width="1919"
    height="1199"
    src="https://www.modernsecurity.nl/microsoft-sentinel-identity-attack-graph/image-14_hu_b3d99f68c9ffa08a.webp"
   
   
    data-zoom-src="https://www.modernsecurity.nl/microsoft-sentinel-identity-attack-graph/image-14.webp"></figure>
<h2 class="relative group">What to look for
    <div id="what-to-look-for" class="anchor"></div>
    
</h2>
<p><strong>Short paths to privileged roles.</strong> The fewer hops between an identity and a privileged directory role, the more exposed you are. An identity two hops from Global Administrator via a nested group chain and a role assignment is a different risk profile than one eight hops away.</p>
<p><strong>Service principals with unexpected resource access.</strong> Service principals reaching VMs or Key Vaults via indirect role assignments, through inherited group memberships or role assignments higher up the subscription hierarchy, often come from earlier deployments that were never cleaned up.</p>
<p><strong>Circular group memberships.</strong> These create privilege inheritance chains that are invisible from the portal’s flat group membership view. The graph shows them immediately as cycles.</p>
<p><strong>Identities whose access exceeds their apparent role.</strong> Someone in a non-privileged department with indirect access to production Key Vaults via three layers of group nesting. Not malicious activity, just environment drift. The graph surfaces it; the follow-up is a permissions review.</p>

<h2 class="relative group">Billing and data retention
    <div id="billing-and-data-retention" class="anchor"></div>
    
</h2>
<p>The identity attack graph is billed under the Sentinel graph meter. Two cost elements to know about:</p>
<ul>
<li><strong>Asset data ingestion</strong>: charges apply for ingesting data through the Entra ID Assets and Azure Resource Graph connectors</li>
<li><strong>Asset data retention</strong>: default retention is 30 days, expandable up to 12 years, and you pay for whatever period you configure</li>
</ul>
<p>Check the <a href="https://www.microsoft.com/en-us/security/pricing/microsoft-sentinel"  target="_blank" rel="noreferrer">Sentinel pricing page</a> for current rates on the graph meter and asset ingestion.</p>

<h2 class="relative group">Limitations
    <div id="limitations" class="anchor"></div>
    
</h2>
<ul>
<li><strong>Up to 48 hours for initial build</strong>: The graph is not queryable during this window.</li>
<li><strong>ARG connector ingests partial coverage by default</strong>: Only subscriptions where the enabling user has Owner. Expand manually for full tenant coverage (see the ARG section above).</li>
<li><strong>Schema is Microsoft-managed</strong>: You can query what’s there but cannot add custom node or edge types.</li>
<li><strong>Asset data refreshes once every 24 hours</strong>: The graph is a point-in-time snapshot. Recent permission changes may not appear until the next ingestion cycle.</li>
<li><strong>Preview</strong>: Functionality and query behavior are subject to change before GA.</li>
</ul>

<h2 class="relative group">Resources
    <div id="resources" class="anchor"></div>
    
</h2>
<ul>
<li><a href="https://learn.microsoft.com/en-us/azure/sentinel/datalake/identity-attack-graph"  target="_blank" rel="noreferrer">What is the identity attack graph? (preview)</a></li>
<li><a href="https://learn.microsoft.com/en-us/azure/sentinel/datalake/enable-data-connectors"  target="_blank" rel="noreferrer">Asset data ingestion in the Microsoft Sentinel data lake</a></li>
<li><a href="https://learn.microsoft.com/en-us/azure/sentinel/datalake/sentinel-graph-overview"  target="_blank" rel="noreferrer">What is Microsoft Sentinel graph?</a></li>
<li><a href="https://learn.microsoft.com/en-us/azure/sentinel/datalake/graph-visualization"  target="_blank" rel="noreferrer">Visualize graphs in Microsoft Sentinel (preview)</a></li>
<li><a href="https://learn.microsoft.com/en-us/azure/sentinel/datalake/gql-reference-for-sentinel-custom-graph"  target="_blank" rel="noreferrer">GQL reference for Sentinel custom graph</a></li>
</ul>

<h2 class="relative group">Closing
    <div id="closing" class="anchor"></div>
    
</h2>
<p>I find these graphs a pleasant way to investigate identity risk. No query to write, no schema to design. Just enable, wait, and start exploring paths you didn’t know existed. What I appreciate most is that the predefined queries do the heavy lifting. You don’t need to know what you’re looking for; the graph shows you anyway.</p>
<p>What would make this even more powerful is the ability to take action directly based on what you find: trigger a remediation, flag a path for review, kick off a Conditional Access change. That’s the natural next step and I hope Microsoft moves in that direction.</p>
<p>Curious to see which managed graphs Microsoft ships next. The identity attack graph is clearly the first of several and the foundation is solid. I’ll might cover here more as they become available.</p>
]]></content:encoded><media:content url="https://www.modernsecurity.nl/microsoft-sentinel-identity-attack-graph/featured_hu_51e9f696a63b42e7.jpg" medium="image" type="image/jpeg" width="1200" height="675"/><enclosure url="https://www.modernsecurity.nl/microsoft-sentinel-identity-attack-graph/featured_hu_51e9f696a63b42e7.jpg" type="image/jpeg" length="104850"/></item><item><title>Getting started with OpenCTI: threat intelligence connected to Microsoft Sentinel</title><link>https://www.modernsecurity.nl/opencti-threat-intelligence-sentinel/</link><guid isPermaLink="true">https://www.modernsecurity.nl/opencti-threat-intelligence-sentinel/</guid><pubDate>Sat, 18 Apr 2026 22:51:22 +0100</pubDate><dc:creator>Farid Kalaidji</dc:creator><category>Microsoft Sentinel</category><category>Microsoft Defender XDR</category><description>A practical guide to installing OpenCTI, adding threat intelligence feeds and connecting it to Microsoft Sentinel for enriching TI information.</description><content:encoded><![CDATA[<p>For the past few years, <strong>MISP</strong> has been my go-to for threat intelligence. It’s open source, flexible, and does exactly what it says on the tin. But MISP is also showing its age in some areas: the interface is not the most intuitive, and wiring it into a modern SOC stack takes a fair amount of glue code. So when I kept seeing <strong>OpenCTI</strong> come up, I figured it was time to actually spin it up and see what the fuss was about.</p>
<p>OpenCTI is developed by the French company <strong><a href="https://filigran.io/"  target="_blank" rel="noreferrer">Filigran</a></strong> and is built around the <strong>STIX 2.1</strong> data model from the ground up. Where MISP started as an event-sharing platform and grew into something more, OpenCTI was designed from day one as a structured threat intelligence platform: with native support for threat actors, campaigns, TTPs, and kill chains. It is gaining serious ground in the threat intelligence space, and for good reason.</p>
<p>In this post I’ll walk through the full process: installing OpenCTI on a clean Ubuntu server, adding free threat intelligence feeds and then wiring it up to <strong><a href="https://www.modernsecurity.nl/microsoft-sentinel/" >Microsoft Sentinel</a></strong> so your IOCs automatically flow into your SIEM and become usable in analytics rules.</p>

<h2 class="relative group">What is OpenCTI and why does it matter?
    <div id="what-is-opencti-and-why-does-it-matter" class="anchor"></div>
    
</h2>
<p>OpenCTI is an open-source threat intelligence platform that lets you store, organize, visualize, and share knowledge about cyber threats. It uses the STIX 2.1 standard for data representation, which means everything is structured and consistent: threat actors, malware families, attack patterns, indicators, observables, relationships, all connected.</p>
<figure><img
    class="my-0 rounded-md"
    loading="lazy"
    decoding="async"
    fetchpriority="auto"
    alt=""
    width="1853"
    height="962"
    src="https://www.modernsecurity.nl/opencti-threat-intelligence-sentinel/image-62_hu_bff03ade81a37048.webp"
   
   
    data-zoom-src="https://www.modernsecurity.nl/opencti-threat-intelligence-sentinel/image-62.webp"></figure><p>The key difference from MISP is depth of context. In MISP you work with events and attributes. In OpenCTI you work with <strong>entities and relationships</strong>: a SHA-256 hash is connected to a malware family, which is connected to a threat actor, which maps to MITRE ATT&amp;CK techniques. You can visually navigate that graph and understand the full picture around a single IOC.</p>
<p>For an MDR context, this is where OpenCTI starts to shine. When an alert fires in Sentinel and you’re looking at a malicious domain, being able to pull up OpenCTI and immediately see which campaigns have used that domain, which malware family dropped it, and what the associated ATT&amp;CK technique is. That’s real context, not just a score.</p>
<p>Microsoft Sentinel ships with built-in threat intelligence, but in my experience it is always worth layering additional sources on top, especially when you want coverage beyond what Microsoft’s feeds provide.</p>

<h2 class="relative group">Architecture overview
    <div id="architecture-overview" class="anchor"></div>
    
</h2>
<p>This post covers the setup and configuration only, not a deep dive into how to use OpenCTI as a platform. Before we dive in, here is what we are building:</p>
<figure><img
    class="my-0 rounded-md"
    loading="lazy"
    decoding="async"
    fetchpriority="auto"
    alt="OpenCTI Microsoft Sentinel"
    width="2000"
    height="967"
    src="https://www.modernsecurity.nl/opencti-threat-intelligence-sentinel/image-43_hu_3bd661728f4936cb.webp"
   
   
    data-zoom-src="https://www.modernsecurity.nl/opencti-threat-intelligence-sentinel/image-43.webp"></figure><p>OpenCTI runs on Ubuntu via Docker Compose in my demo (for production environments look into splitting resources/roles and use K8s). Threat intel connectors pull data from external sources on a schedule. A Live Stream connector pushes indicators to Microsoft Sentinel in real time using the Graph API tiIndicators endpoint. Sentinel analytics rules then match those indicators against ingested logs.</p>
<figure><img
    class="my-0 rounded-md"
    loading="lazy"
    decoding="async"
    fetchpriority="auto"
    alt=""
    width="2000"
    height="1049"
    src="https://www.modernsecurity.nl/opencti-threat-intelligence-sentinel/image-45_hu_f10b36563a72be51.webp"
   
   
    data-zoom-src="https://www.modernsecurity.nl/opencti-threat-intelligence-sentinel/image-45.webp"></figure>
<h2 class="relative group">Part 1: Installing OpenCTI
    <div id="part-1-installing-opencti" class="anchor"></div>
    
</h2>

<h3 class="relative group">System requirements
    <div id="system-requirements" class="anchor"></div>
    
</h3>

<div class="ms-table" role="region" aria-label="Table" tabindex="0">
  <table>
      <thead>
          <tr>
              <th>Resource</th>
              <th>Minimum</th>
              <th>Recommended</th>
          </tr>
      </thead>
    <tbody>
        <tr>
            <td>Ubuntu</td>
            <td>22.04 LTS</td>
            <td>24.04 LTS</td>
        </tr>
        <tr>
            <td>CPU</td>
            <td>4 vCPU</td>
            <td>8+ vCPU</td>
        </tr>
        <tr>
            <td>RAM</td>
            <td>8 GB</td>
            <td>16 GB</td>
        </tr>
        <tr>
            <td>Disk</td>
            <td>50 GB</td>
            <td>100+ GB SSD</td>
        </tr>
    </tbody>
  </table>
</div>
<blockquote><p><strong>RAM note:</strong> Elasticsearch is the main memory consumer. On an 8 GB server you’ll feel the pressure during the initial sync of all connectors simultaneously. 16 GB is strongly recommended for a production deployment.</p>
</blockquote>
<h3 class="relative group">Install Docker
    <div id="install-docker" class="anchor"></div>
    
</h3>
<p>OpenCTI’s official deployment method is Docker Compose. All dependencies, Elasticsearch, Redis, RabbitMQ, MinIO, run as containers. But again: for production environments cluster all your servers and infrastructure 🙂</p>
<div class="highlight-wrapper"><div class="highlight"><div class="ms-code-label">Bash</div><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="c1"># Remove legacy Docker packages</span>
</span></span><span class="line"><span class="cl">sudo apt remove docker.io docker-compose docker-compose-v2 <span class="se">\
</span></span></span><span class="line"><span class="cl">  docker-doc podman-docker containerd runc 2&gt;/dev/null <span class="o">||</span> <span class="nb">true</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">sudo apt update
</span></span><span class="line"><span class="cl">sudo apt install -y ca-certificates curl
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># Add Docker&#39;s official GPG key</span>
</span></span><span class="line"><span class="cl">sudo install -m <span class="m">0755</span> -d /etc/apt/keyrings
</span></span><span class="line"><span class="cl">sudo curl -fsSL https://download.docker.com/linux/ubuntu/gpg <span class="se">\
</span></span></span><span class="line"><span class="cl">  -o /etc/apt/keyrings/docker.asc
</span></span><span class="line"><span class="cl">sudo chmod a+r /etc/apt/keyrings/docker.asc
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># Add Docker repository</span>
</span></span><span class="line"><span class="cl">sudo tee /etc/apt/sources.list.d/docker.sources <span class="s">&lt;&lt;EOF
</span></span></span><span class="line"><span class="cl"><span class="s">Types: deb
</span></span></span><span class="line"><span class="cl"><span class="s">URIs: https://download.docker.com/linux/ubuntu
</span></span></span><span class="line"><span class="cl"><span class="s">Suites: $(. /etc/os-release &amp;&amp; echo &#34;${UBUNTU_CODENAME:-$VERSION_CODENAME}&#34;)
</span></span></span><span class="line"><span class="cl"><span class="s">Components: stable
</span></span></span><span class="line"><span class="cl"><span class="s">Signed-By: /etc/apt/keyrings/docker.asc
</span></span></span><span class="line"><span class="cl"><span class="s">EOF</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">sudo apt update
</span></span><span class="line"><span class="cl">sudo apt install -y docker-ce docker-ce-cli containerd.io <span class="se">\
</span></span></span><span class="line"><span class="cl">  docker-buildx-plugin docker-compose-plugin
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># Run Docker without sudo</span>
</span></span><span class="line"><span class="cl">sudo usermod -aG docker <span class="nv">$USER</span>
</span></span><span class="line"><span class="cl">newgrp docker</span></span></code></pre></div></div>

<h3 class="relative group">Set vm.max_map_count
    <div id="set-vm-max_map_count" class="anchor"></div>
    
</h3>
<p>Elasticsearch needs this or it will crash on startup. Do not skip this step.</p>
<div class="highlight-wrapper"><div class="highlight"><div class="ms-code-label">Bash</div><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">sudo sysctl -w vm.max_map_count<span class="o">=</span><span class="m">1048575</span>
</span></span><span class="line"><span class="cl"><span class="nb">echo</span> <span class="s1">&#39;vm.max_map_count=1048575&#39;</span> <span class="p">|</span> sudo tee -a /etc/sysctl.conf</span></span></code></pre></div></div>

<h3 class="relative group">Clone the OpenCTI Docker repository
    <div id="clone-the-opencti-docker-repository" class="anchor"></div>
    
</h3>
<div class="highlight-wrapper"><div class="highlight"><div class="ms-code-label">Bash</div><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">git clone https://github.com/OpenCTI-Platform/docker.git /opt/opencti
</span></span><span class="line"><span class="cl"><span class="nb">cd</span> /opt/opencti</span></span></code></pre></div></div>

<h3 class="relative group">Configure .env
    <div id="configure-env" class="anchor"></div>
    
</h3>
<p>Generate the values you’ll need:</p>
<div class="highlight-wrapper"><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="cl"># UUIDs
</span></span><span class="line"><span class="cl">cat /proc/sys/kernel/random/uuid
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"># Encryption key (base64)
</span></span><span class="line"><span class="cl">openssl rand -base64 32
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"># Strong password
</span></span><span class="line"><span class="cl">openssl rand -base64 18 | tr -d &#39;/+=&#39; | cut -c1-20</span></span></code></pre></div></div>
<p>Create <code>/opt/opencti/.env</code>:</p>
<div class="highlight-wrapper"><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="cl">###########################
</span></span><span class="line"><span class="cl"># DEPENDENCIES            #
</span></span><span class="line"><span class="cl">###########################
</span></span><span class="line"><span class="cl">MINIO_ROOT_USER=opencti
</span></span><span class="line"><span class="cl">MINIO_ROOT_PASSWORD=YourStrongPassword
</span></span><span class="line"><span class="cl">RABBITMQ_DEFAULT_USER=opencti
</span></span><span class="line"><span class="cl">RABBITMQ_DEFAULT_PASS=YourStrongPassword
</span></span><span class="line"><span class="cl">SMTP_HOSTNAME=localhost
</span></span><span class="line"><span class="cl">OPENSEARCH_ADMIN_PASSWORD=YourStrongPassword
</span></span><span class="line"><span class="cl">ELASTIC_MEMORY_SIZE=4G
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">###########################
</span></span><span class="line"><span class="cl"># COMMON                  #
</span></span><span class="line"><span class="cl">###########################
</span></span><span class="line"><span class="cl">XTM_COMPOSER_ID=8215614c-7139-422e-b825-b20fd2a13a23
</span></span><span class="line"><span class="cl">COMPOSE_PROJECT_NAME=xtm
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">###########################
</span></span><span class="line"><span class="cl"># OPENCTI                 #
</span></span><span class="line"><span class="cl">###########################
</span></span><span class="line"><span class="cl">OPENCTI_HOST=opencti.yourdomain.com
</span></span><span class="line"><span class="cl">OPENCTI_PORT=8080
</span></span><span class="line"><span class="cl">OPENCTI_EXTERNAL_SCHEME=https
</span></span><span class="line"><span class="cl">OPENCTI_ADMIN_EMAIL=admin@yourdomain.com
</span></span><span class="line"><span class="cl">OPENCTI_ADMIN_PASSWORD=YourAdminPassword
</span></span><span class="line"><span class="cl">OPENCTI_ADMIN_TOKEN=&lt;uuid&gt;
</span></span><span class="line"><span class="cl">OPENCTI_HEALTHCHECK_ACCESS_KEY=&lt;random-string&gt;
</span></span><span class="line"><span class="cl">OPENCTI_ENCRYPTION_KEY=&lt;base64-32-bytes&gt;
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">###########################
</span></span><span class="line"><span class="cl"># OPENCTI CONNECTORS      #
</span></span><span class="line"><span class="cl">###########################
</span></span><span class="line"><span class="cl">CONNECTOR_EXPORT_FILE_STIX_ID=dd817c8b-abae-460a-9ebc-97b1551e70e6
</span></span><span class="line"><span class="cl">CONNECTOR_EXPORT_FILE_CSV_ID=7ba187fb-fde8-4063-92b5-c3da34060dd7
</span></span><span class="line"><span class="cl">CONNECTOR_EXPORT_FILE_TXT_ID=ca715d9c-bd64-4351-91db-33a8d728a58b
</span></span><span class="line"><span class="cl">CONNECTOR_IMPORT_FILE_STIX_ID=72327164-0b35-482b-b5d6-a5a3f76b845f
</span></span><span class="line"><span class="cl">CONNECTOR_IMPORT_DOCUMENT_ID=c3970f8a-ce4b-4497-a381-20b7256f56f0
</span></span><span class="line"><span class="cl">CONNECTOR_IMPORT_FILE_YARA_ID=7eb45b60-069b-4f7f-83a2-df4d6891d5ec
</span></span><span class="line"><span class="cl">CONNECTOR_IMPORT_EXTERNAL_REFERENCE_ID=d52dcbc8-fa06-42c7-bbc2-044948c87024
</span></span><span class="line"><span class="cl">CONNECTOR_ANALYSIS_ID=4dffd77c-ec11-4abe-bca7-fd997f79fa36
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">###########################
</span></span><span class="line"><span class="cl"># OPENCTI DEFAULT DATA    #
</span></span><span class="line"><span class="cl">###########################
</span></span><span class="line"><span class="cl">CONNECTOR_OPENCTI_ID=dd010812-9027-4726-bf7b-4936979955ae
</span></span><span class="line"><span class="cl">CONNECTOR_MITRE_ID=8307ea1e-9356-408c-a510-2d7f8b28a0e2</span></span></code></pre></div></div>
<blockquote><p><strong>ELASTIC_MEMORY_SIZE:</strong> Set to roughly 50% of your total RAM. On 8 GB set <code>2G</code>, on 16 GB set <code>6G</code>.</p>
</blockquote>
<h3 class="relative group">Fix docker-compose.yml
    <div id="fix-docker-compose-yml" class="anchor"></div>
    
</h3>
<p>The default <code>docker-compose.yml</code> needs three corrections before you start.</p>
<p><strong>Fix 1: Bind OpenCTI to localhost:</strong></p>
<p>Find the <code>opencti</code> service ports section and change:</p>
<div class="highlight-wrapper"><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="cl"># Before
</span></span><span class="line"><span class="cl">ports:
</span></span><span class="line"><span class="cl">  - &#34;${OPENCTI_PORT}:8080&#34;
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"># After
</span></span><span class="line"><span class="cl">ports:
</span></span><span class="line"><span class="cl">  - &#34;127.0.0.1:8080:8080&#34;</span></span></code></pre></div></div>
<p><strong>Fix 2: Bind MinIO to localhost:</strong></p>
<p>Find the <code>minio</code> service ports section and change:</p>
<div class="highlight-wrapper"><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="cl"># Before
</span></span><span class="line"><span class="cl">ports:
</span></span><span class="line"><span class="cl">  - &#34;9000:9000&#34;
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"># After
</span></span><span class="line"><span class="cl">ports:
</span></span><span class="line"><span class="cl">  - &#34;127.0.0.1:9000:9000&#34;</span></span></code></pre></div></div>
<p><strong>Fix 3: Remove port from APP__BASE_URL:</strong></p>
<p>Find the <code>opencti</code> service environment and change:</p>
<div class="highlight-wrapper"><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="cl"># Before
</span></span><span class="line"><span class="cl">- APP__BASE_URL=${OPENCTI_EXTERNAL_SCHEME}://${OPENCTI_HOST}:${OPENCTI_PORT}
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"># After
</span></span><span class="line"><span class="cl">- APP__BASE_URL=${OPENCTI_EXTERNAL_SCHEME}://${OPENCTI_HOST}</span></span></code></pre></div></div>
<p>Without this fix, every link inside OpenCTI will have <code>:8080</code> appended, which breaks navigation when you access it through nginx on port 443.</p>

<h3 class="relative group">Install and configure nginx
    <div id="install-and-configure-nginx" class="anchor"></div>
    
</h3>
<div class="highlight-wrapper"><div class="highlight"><div class="ms-code-label">Bash</div><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">sudo apt install -y nginx
</span></span><span class="line"><span class="cl">sudo systemctl <span class="nb">enable</span> nginx</span></span></code></pre></div></div>
<p>Create <code>/etc/nginx/sites-available/opencti</code>:</p>
<div class="highlight-wrapper"><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="cl">server {
</span></span><span class="line"><span class="cl">    listen 80;
</span></span><span class="line"><span class="cl">    server_name opencti.yourdomain.com;
</span></span><span class="line"><span class="cl">    return 301 https://$host$request_uri;
</span></span><span class="line"><span class="cl">}
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">server {
</span></span><span class="line"><span class="cl">    listen 443 ssl;
</span></span><span class="line"><span class="cl">    server_name opencti.yourdomain.com;
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    ssl_certificate     /etc/ssl/opencti/origin.crt;
</span></span><span class="line"><span class="cl">    ssl_certificate_key /etc/ssl/opencti/origin.key;
</span></span><span class="line"><span class="cl">    ssl_protocols       TLSv1.2 TLSv1.3;
</span></span><span class="line"><span class="cl">    ssl_ciphers         HIGH:!aNULL:!MD5;
</span></span><span class="line"><span class="cl">    ssl_prefer_server_ciphers on;
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    location / {
</span></span><span class="line"><span class="cl">        proxy_pass         http://127.0.0.1:8080;
</span></span><span class="line"><span class="cl">        proxy_set_header   Host $host;
</span></span><span class="line"><span class="cl">        proxy_set_header   X-Real-IP $remote_addr;
</span></span><span class="line"><span class="cl">        proxy_set_header   X-Forwarded-For $proxy_add_x_forwarded_for;
</span></span><span class="line"><span class="cl">        proxy_set_header   X-Forwarded-Proto $scheme;
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">        # WebSocket support - required by OpenCTI
</span></span><span class="line"><span class="cl">        proxy_http_version 1.1;
</span></span><span class="line"><span class="cl">        proxy_set_header   Upgrade $http_upgrade;
</span></span><span class="line"><span class="cl">        proxy_set_header   Connection &#34;upgrade&#34;;
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">        proxy_read_timeout 3600s;
</span></span><span class="line"><span class="cl">        proxy_send_timeout 3600s;
</span></span><span class="line"><span class="cl">    }
</span></span><span class="line"><span class="cl">}</span></span></code></pre></div></div>
<blockquote><p><strong>WebSocket support is mandatory.</strong> OpenCTI uses WebSockets for live UI updates. Without the <code>Upgrade</code> headers, the interface will partially break.</p>
</blockquote><p>Enable and start:</p>
<div class="highlight-wrapper"><div class="highlight"><div class="ms-code-label">Bash</div><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">sudo ln -s /etc/nginx/sites-available/opencti /etc/nginx/sites-enabled/
</span></span><span class="line"><span class="cl">sudo nginx -t
</span></span><span class="line"><span class="cl">sudo systemctl start nginx</span></span></code></pre></div></div>

<h3 class="relative group">Configure SSL
    <div id="configure-ssl" class="anchor"></div>
    
</h3>
<p>I’m using Cloudflare for SSL all the way, you can also use LetsEncrypt (bot) to generate SSL certificates. After you obtained a certificate and key:</p>
<ol>
<li>Set hostname to <code>opencti.yourdomain.com</code> for the SSL certificate</li>
<li>Copy the <strong>Origin Certificate</strong> and <strong>Private Key</strong></li>
</ol>
<div class="highlight-wrapper"><div class="highlight"><div class="ms-code-label">Bash</div><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">sudo mkdir -p /etc/ssl/opencti
</span></span><span class="line"><span class="cl">sudo nano /etc/ssl/opencti/origin.crt   <span class="c1"># paste the certificate</span>
</span></span><span class="line"><span class="cl">sudo nano /etc/ssl/opencti/origin.key   <span class="c1"># paste the private key</span>
</span></span><span class="line"><span class="cl">sudo chmod <span class="m">644</span> /etc/ssl/opencti/origin.crt
</span></span><span class="line"><span class="cl">sudo chmod <span class="m">600</span> /etc/ssl/opencti/origin.key</span></span></code></pre></div></div>
<p>Add a DNS A record at your domain registrar:</p>

<div class="ms-table" role="region" aria-label="Table" tabindex="0">
  <table>
      <thead>
          <tr>
              <th>Name</th>
              <th>Type</th>
              <th>Value</th>
              <th>Proxy</th>
          </tr>
      </thead>
    <tbody>
        <tr>
            <td><code>opencti</code></td>
            <td>A</td>
            <td>Your server IP</td>
            <td>Depends on your setup</td>
        </tr>
    </tbody>
  </table>
</div>
<blockquote><p>I would not recommend exposing OpenCTI directly to the internet. If possible, restrict access to specific IP ranges or put it behind a VPN. For an MDR context where multiple analysts need access, a site-to-site VPN or a zero-trust solution is a cleaner approach than opening it up publicly.</p>
</blockquote><p>Reload nginx:</p>
<div class="highlight-wrapper"><div class="highlight"><div class="ms-code-label">Bash</div><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">sudo nginx -t <span class="o">&amp;&amp;</span> sudo systemctl reload nginx</span></span></code></pre></div></div>

<h3 class="relative group">Start OpenCTI
    <div id="start-opencti" class="anchor"></div>
    
</h3>
<div class="highlight-wrapper"><div class="highlight"><div class="ms-code-label">Bash</div><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="nb">cd</span> /opt/opencti
</span></span><span class="line"><span class="cl">docker compose up -d
</span></span><span class="line"><span class="cl">docker compose logs -f opencti</span></span></code></pre></div></div>
<p>Initial startup takes 2–5 minutes. Elasticsearch initializes first, then OpenCTI creates the admin user. Once you see a log entry confirming the admin is ready, navigate to <code>https://opencti.yourdomain.com</code> and log in.</p>
<figure><img
    class="my-0 rounded-md"
    loading="lazy"
    decoding="async"
    fetchpriority="auto"
    alt=""
    width="1919"
    height="998"
    src="https://www.modernsecurity.nl/opencti-threat-intelligence-sentinel/image-46_hu_4e09b0e736339006.webp"
   
   
    data-zoom-src="https://www.modernsecurity.nl/opencti-threat-intelligence-sentinel/image-46.webp"></figure><figure><img
    class="my-0 rounded-md"
    loading="lazy"
    decoding="async"
    fetchpriority="auto"
    alt=""
    width="1919"
    height="999"
    src="https://www.modernsecurity.nl/opencti-threat-intelligence-sentinel/image-47_hu_9aeb881573c8d6b9.webp"
   
   
    data-zoom-src="https://www.modernsecurity.nl/opencti-threat-intelligence-sentinel/image-47.webp"></figure>
<h2 class="relative group">Part 2: Adding threat intelligence feeds
    <div id="part-2-adding-threat-intelligence-feeds" class="anchor"></div>
    
</h2>
<p>This is where OpenCTI starts earning its keep. Out of the box it already pulls in MITRE ATT&amp;CK and OpenCTI’s own datasets (marking definitions, identities, locations). But you want IOCs, and for that you need external connectors.</p>
<p>Here is what I added, just an example of a few free feeds. You can also move onto paid feeds like Recorded Future. For my POC this is just enough to demonstrate:</p>

<div class="ms-table" role="region" aria-label="Table" tabindex="0">
  <table>
      <thead>
          <tr>
              <th>Connector</th>
              <th>Data</th>
              <th>Notes</th>
          </tr>
      </thead>
    <tbody>
        <tr>
            <td>AbuseCH</td>
            <td>SSL blacklist</td>
            <td>IP/domain C2 infrastructure</td>
        </tr>
        <tr>
            <td>URLhaus</td>
            <td>Malware URLs</td>
            <td>Live and recent malicious URLs</td>
        </tr>
        <tr>
            <td>ThreatFox</td>
            <td>IOCs</td>
            <td>IPs, domains, URLs, hashes tagged to malware families</td>
        </tr>
        <tr>
            <td>MalwareBazaar</td>
            <td>File hashes</td>
            <td>Recent malware sample hashes with family tags</td>
        </tr>
        <tr>
            <td>AlienVault OTX</td>
            <td>Pulses</td>
            <td>Broad threat intel, requires free API key</td>
        </tr>
        <tr>
            <td>CISA KEV</td>
            <td>CVEs</td>
            <td>Confirmed exploited vulnerabilities, high confidence</td>
        </tr>
        <tr>
            <td>VirusTotal</td>
            <td>File/URL reputation</td>
            <td>Enrichment on demand, requires free API key</td>
        </tr>
    </tbody>
  </table>
</div>

<h3 class="relative group">Generate UUIDs for each connector
    <div id="generate-uuids-for-each-connector" class="anchor"></div>
    
</h3>
<p>Each connector needs a unique UUIDv4:</p>
<div class="highlight-wrapper"><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="cl">for i in 1 2 3 4 5 6 7; do cat /proc/sys/kernel/random/uuid; done</span></span></code></pre></div></div>

<h3 class="relative group">Update .env
    <div id="update-env" class="anchor"></div>
    
</h3>
<p>Add this section to your <code>.env</code>:</p>
<div class="highlight-wrapper"><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="cl">###########################
</span></span><span class="line"><span class="cl"># THREAT INTEL CONNECTORS #
</span></span><span class="line"><span class="cl">###########################
</span></span><span class="line"><span class="cl">CONNECTOR_ABUSECH_ID=&lt;uuid-1&gt;
</span></span><span class="line"><span class="cl">CONNECTOR_URLHAUS_ID=&lt;uuid-2&gt;
</span></span><span class="line"><span class="cl">CONNECTOR_ALIENVAULT_ID=&lt;uuid-3&gt;
</span></span><span class="line"><span class="cl">ALIENVAULT_API_KEY=&lt;your-alienvault-api-key&gt;
</span></span><span class="line"><span class="cl">CONNECTOR_THREATFOX_ID=&lt;uuid-4&gt;
</span></span><span class="line"><span class="cl">CONNECTOR_MALWAREBAZAAR_ID=&lt;uuid-5&gt;
</span></span><span class="line"><span class="cl">CONNECTOR_CISA_KEV_ID=&lt;uuid-6&gt;
</span></span><span class="line"><span class="cl">CONNECTOR_VIRUSTOTAL_ID=&lt;uuid-7&gt;
</span></span><span class="line"><span class="cl">VIRUSTOTAL_API_KEY=&lt;your-virustotal-api-key&gt;</span></span></code></pre></div></div>
<p>Get your API keys:</p>
<ul>
<li><strong>AlienVault OTX:</strong> <a href="https://otx.alienvault.com"  target="_blank" rel="noreferrer">https://otx.alienvault.com</a> → Settings → API Key</li>
<li><strong>VirusTotal:</strong> <a href="https://www.virustotal.com"  target="_blank" rel="noreferrer">https://www.virustotal.com</a> → Profile → API Key</li>
</ul>

<h3 class="relative group">Add connectors to docker-compose.yml
    <div id="add-connectors-to-docker-compose-yml" class="anchor"></div>
    
</h3>
<p>Add the following services to your <code>docker-compose.yml</code> under the threat intel section:</p>
<div class="highlight-wrapper"><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="cl">  connector-abusech:
</span></span><span class="line"><span class="cl">    image: opencti/connector-abuse-ssl:latest
</span></span><span class="line"><span class="cl">    environment:
</span></span><span class="line"><span class="cl">      - OPENCTI_URL=http://opencti:8080
</span></span><span class="line"><span class="cl">      - OPENCTI_TOKEN=${OPENCTI_ADMIN_TOKEN}
</span></span><span class="line"><span class="cl">      - CONNECTOR_ID=${CONNECTOR_ABUSECH_ID}
</span></span><span class="line"><span class="cl">      - CONNECTOR_NAME=AbuseCH
</span></span><span class="line"><span class="cl">      - CONNECTOR_SCOPE=ipv4-addr,ipv6-addr,domain-name,url,file
</span></span><span class="line"><span class="cl">      - CONNECTOR_AUTO=true
</span></span><span class="line"><span class="cl">      - CONNECTOR_CONFIDENCE_LEVEL=80
</span></span><span class="line"><span class="cl">      - ABUSE_SSL_INTERVAL=43200
</span></span><span class="line"><span class="cl">    restart: always
</span></span><span class="line"><span class="cl">    depends_on:
</span></span><span class="line"><span class="cl">      opencti:
</span></span><span class="line"><span class="cl">        condition: service_healthy
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">  connector-urlhaus:
</span></span><span class="line"><span class="cl">    image: opencti/connector-urlhaus:latest
</span></span><span class="line"><span class="cl">    environment:
</span></span><span class="line"><span class="cl">      - OPENCTI_URL=http://opencti:8080
</span></span><span class="line"><span class="cl">      - OPENCTI_TOKEN=${OPENCTI_ADMIN_TOKEN}
</span></span><span class="line"><span class="cl">      - CONNECTOR_ID=${CONNECTOR_URLHAUS_ID}
</span></span><span class="line"><span class="cl">      - CONNECTOR_NAME=URLhaus
</span></span><span class="line"><span class="cl">      - CONNECTOR_SCOPE=urlhaus
</span></span><span class="line"><span class="cl">      - CONNECTOR_AUTO=true
</span></span><span class="line"><span class="cl">      - CONNECTOR_CONFIDENCE_LEVEL=40
</span></span><span class="line"><span class="cl">      - URLHAUS_CSV_URL=https://urlhaus.abuse.ch/downloads/csv_recent/
</span></span><span class="line"><span class="cl">      - URLHAUS_IMPORT_OFFLINE=true
</span></span><span class="line"><span class="cl">      - URLHAUS_CREATE_INDICATORS=true
</span></span><span class="line"><span class="cl">      - URLHAUS_INTERVAL=3
</span></span><span class="line"><span class="cl">    restart: always
</span></span><span class="line"><span class="cl">    depends_on:
</span></span><span class="line"><span class="cl">      opencti:
</span></span><span class="line"><span class="cl">        condition: service_healthy
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">  connector-alienvault:
</span></span><span class="line"><span class="cl">    image: opencti/connector-alienvault:latest
</span></span><span class="line"><span class="cl">    environment:
</span></span><span class="line"><span class="cl">      - OPENCTI_URL=http://opencti:8080
</span></span><span class="line"><span class="cl">      - OPENCTI_TOKEN=${OPENCTI_ADMIN_TOKEN}
</span></span><span class="line"><span class="cl">      - CONNECTOR_ID=${CONNECTOR_ALIENVAULT_ID}
</span></span><span class="line"><span class="cl">      - CONNECTOR_NAME=AlienVault
</span></span><span class="line"><span class="cl">      - CONNECTOR_SCOPE=alienvault
</span></span><span class="line"><span class="cl">      - CONNECTOR_AUTO=true
</span></span><span class="line"><span class="cl">      - CONNECTOR_CONFIDENCE_LEVEL=80
</span></span><span class="line"><span class="cl">      - ALIENVAULT_BASE_URL=https://otx.alienvault.com
</span></span><span class="line"><span class="cl">      - ALIENVAULT_API_KEY=${ALIENVAULT_API_KEY}
</span></span><span class="line"><span class="cl">      - ALIENVAULT_TLP=White
</span></span><span class="line"><span class="cl">      - ALIENVAULT_CREATE_OBSERVABLES=true
</span></span><span class="line"><span class="cl">      - ALIENVAULT_CREATE_INDICATORS=true
</span></span><span class="line"><span class="cl">      - ALIENVAULT_PULSE_START_TIMESTAMP=2020-01-01T00:00:00
</span></span><span class="line"><span class="cl">      - ALIENVAULT_REPORT_TYPE=threat-report
</span></span><span class="line"><span class="cl">      - ALIENVAULT_REPORT_STATUS=New
</span></span><span class="line"><span class="cl">      - ALIENVAULT_GUESS_MALWARE=false
</span></span><span class="line"><span class="cl">      - ALIENVAULT_GUESS_CVE=false
</span></span><span class="line"><span class="cl">      - ALIENVAULT_EXCLUDED_PULSE_INDICATOR_TYPES=FileHash-MD5,FileHash-SHA1
</span></span><span class="line"><span class="cl">      - ALIENVAULT_ENABLE_RELATIONSHIPS=true
</span></span><span class="line"><span class="cl">      - ALIENVAULT_ENABLE_ATTACK_PATTERNS_INDICATES=false
</span></span><span class="line"><span class="cl">      - ALIENVAULT_INTERVAL_SEC=1800
</span></span><span class="line"><span class="cl">    restart: always
</span></span><span class="line"><span class="cl">    depends_on:
</span></span><span class="line"><span class="cl">      opencti:
</span></span><span class="line"><span class="cl">        condition: service_healthy
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">  connector-threatfox:
</span></span><span class="line"><span class="cl">    image: opencti/connector-threatfox:latest
</span></span><span class="line"><span class="cl">    environment:
</span></span><span class="line"><span class="cl">      - OPENCTI_URL=http://opencti:8080
</span></span><span class="line"><span class="cl">      - OPENCTI_TOKEN=${OPENCTI_ADMIN_TOKEN}
</span></span><span class="line"><span class="cl">      - CONNECTOR_ID=${CONNECTOR_THREATFOX_ID}
</span></span><span class="line"><span class="cl">      - CONNECTOR_NAME=ThreatFox
</span></span><span class="line"><span class="cl">      - CONNECTOR_SCOPE=threatfox
</span></span><span class="line"><span class="cl">      - CONNECTOR_AUTO=true
</span></span><span class="line"><span class="cl">      - CONNECTOR_CONFIDENCE_LEVEL=40
</span></span><span class="line"><span class="cl">      - THREATFOX_API_KEY=
</span></span><span class="line"><span class="cl">      - THREATFOX_CREATE_INDICATORS=true
</span></span><span class="line"><span class="cl">      - THREATFOX_CREATE_OBSERVABLES=true
</span></span><span class="line"><span class="cl">      - THREATFOX_IMPORT_OFFLINE=true
</span></span><span class="line"><span class="cl">      - THREATFOX_INTERVAL=3
</span></span><span class="line"><span class="cl">    restart: always
</span></span><span class="line"><span class="cl">    depends_on:
</span></span><span class="line"><span class="cl">      opencti:
</span></span><span class="line"><span class="cl">        condition: service_healthy
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">  connector-malwarebazaar:
</span></span><span class="line"><span class="cl">    image: opencti/connector-malwarebazaar-recent-additions:latest
</span></span><span class="line"><span class="cl">    environment:
</span></span><span class="line"><span class="cl">      - OPENCTI_URL=http://opencti:8080
</span></span><span class="line"><span class="cl">      - OPENCTI_TOKEN=${OPENCTI_ADMIN_TOKEN}
</span></span><span class="line"><span class="cl">      - CONNECTOR_ID=${CONNECTOR_MALWAREBAZAAR_ID}
</span></span><span class="line"><span class="cl">      - CONNECTOR_NAME=MalwareBazaar
</span></span><span class="line"><span class="cl">      - CONNECTOR_SCOPE=malwarebazaar
</span></span><span class="line"><span class="cl">      - CONNECTOR_AUTO=true
</span></span><span class="line"><span class="cl">      - CONNECTOR_CONFIDENCE_LEVEL=50
</span></span><span class="line"><span class="cl">      - MALWAREBAZAAR_CREATE_INDICATORS=true
</span></span><span class="line"><span class="cl">      - MALWAREBAZAAR_INTERVAL=3
</span></span><span class="line"><span class="cl">    restart: always
</span></span><span class="line"><span class="cl">    depends_on:
</span></span><span class="line"><span class="cl">      opencti:
</span></span><span class="line"><span class="cl">        condition: service_healthy
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">  connector-cisa-kev:
</span></span><span class="line"><span class="cl">    image: opencti/connector-cisa-known-exploited-vulnerabilities:latest
</span></span><span class="line"><span class="cl">    environment:
</span></span><span class="line"><span class="cl">      - OPENCTI_URL=http://opencti:8080
</span></span><span class="line"><span class="cl">      - OPENCTI_TOKEN=${OPENCTI_ADMIN_TOKEN}
</span></span><span class="line"><span class="cl">      - CONNECTOR_ID=${CONNECTOR_CISA_KEV_ID}
</span></span><span class="line"><span class="cl">      - CONNECTOR_NAME=CISA KEV
</span></span><span class="line"><span class="cl">      - CONNECTOR_SCOPE=identity,vulnerability
</span></span><span class="line"><span class="cl">      - CONNECTOR_AUTO=true
</span></span><span class="line"><span class="cl">      - CONNECTOR_CONFIDENCE_LEVEL=100
</span></span><span class="line"><span class="cl">      - CISA_CATALOG_URL=https://www.cisa.gov/sites/default/files/feeds/known_exploited_vulnerabilities.json
</span></span><span class="line"><span class="cl">      - CISA_CREATE_INFRASTRUCTURES=false
</span></span><span class="line"><span class="cl">      - CISA_TLP=TLP:CLEAR
</span></span><span class="line"><span class="cl">      - CISA_INTERVAL=3
</span></span><span class="line"><span class="cl">    restart: always
</span></span><span class="line"><span class="cl">    depends_on:
</span></span><span class="line"><span class="cl">      opencti:
</span></span><span class="line"><span class="cl">        condition: service_healthy
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">  connector-virustotal-livehunt:
</span></span><span class="line"><span class="cl">    image: opencti/connector-virustotal-livehunt-notifications:latest
</span></span><span class="line"><span class="cl">    environment:
</span></span><span class="line"><span class="cl">      - OPENCTI_URL=http://opencti:8080
</span></span><span class="line"><span class="cl">      - OPENCTI_TOKEN=${OPENCTI_ADMIN_TOKEN}
</span></span><span class="line"><span class="cl">      - CONNECTOR_ID=${CONNECTOR_VIRUSTOTAL_ID}
</span></span><span class="line"><span class="cl">      - CONNECTOR_NAME=VirusTotal
</span></span><span class="line"><span class="cl">      - CONNECTOR_SCOPE=StixFile,Artifact
</span></span><span class="line"><span class="cl">      - CONNECTOR_AUTO=true
</span></span><span class="line"><span class="cl">      - CONNECTOR_CONFIDENCE_LEVEL=50
</span></span><span class="line"><span class="cl">      - VIRUSTOTAL_API_KEY=${VIRUSTOTAL_API_KEY}
</span></span><span class="line"><span class="cl">      - VIRUSTOTAL_MAX_TLP=TLP:AMBER
</span></span><span class="line"><span class="cl">      - VIRUSTOTAL_CREATE_INDICATORS=true
</span></span><span class="line"><span class="cl">      - VIRUSTOTAL_CREATE_OBSERVABLES=true
</span></span><span class="line"><span class="cl">      - VIRUSTOTAL_INTERVAL_SEC=300
</span></span><span class="line"><span class="cl">    restart: always
</span></span><span class="line"><span class="cl">    depends_on:
</span></span><span class="line"><span class="cl">      opencti:
</span></span><span class="line"><span class="cl">        condition: service_healthy</span></span></code></pre></div></div>
<p>Apply the changes:</p>
<div class="highlight-wrapper"><div class="highlight"><div class="ms-code-label">Bash</div><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="nb">cd</span> /opt/opencti
</span></span><span class="line"><span class="cl">docker compose down
</span></span><span class="line"><span class="cl">docker compose up -d</span></span></code></pre></div></div>

<h3 class="relative group">Checking connector status
    <div id="checking-connector-status" class="anchor"></div>
    
</h3>
<p>Go to <strong>Data → Ingestion → Connectors</strong>. All connectors should turn green within a few minutes. AlienVault takes the longest on first sync. It pulls historical pulses going back to 2020 in my config, so give it time.</p>
<figure><img
    class="my-0 rounded-md"
    loading="lazy"
    decoding="async"
    fetchpriority="auto"
    alt=""
    width="1491"
    height="977"
    src="https://www.modernsecurity.nl/opencti-threat-intelligence-sentinel/image-61_hu_356d42fb93b63d47.webp"
   
   
    data-zoom-src="https://www.modernsecurity.nl/opencti-threat-intelligence-sentinel/image-61.webp"></figure><p>Once data starts flowing, you can browse it at:</p>
<ul>
<li><strong>Observations → Indicators</strong>: all IOCs with source, type, TLP, and confidence</li>
<li><strong>Threats → Malware</strong>: malware families from MITRE and connectors</li>
<li><strong>Threats → Threat Actors</strong>: APT groups and their associated campaigns</li>
<li><strong>Techniques → Attack Patterns</strong>: MITRE ATT&amp;CK techniques</li>
</ul>
<figure><img
    class="my-0 rounded-md"
    loading="lazy"
    decoding="async"
    fetchpriority="auto"
    alt=""
    width="1919"
    height="997"
    src="https://www.modernsecurity.nl/opencti-threat-intelligence-sentinel/image-49_hu_22962adc815fb28a.webp"
   
   
    data-zoom-src="https://www.modernsecurity.nl/opencti-threat-intelligence-sentinel/image-49.webp"></figure>
<h2 class="relative group">Part 3: Connecting OpenCTI to Microsoft Sentinel
    <div id="part-3-connecting-opencti-to-microsoft-sentinel" class="anchor"></div>
    
</h2>
<p>This is where the integration becomes operationally relevant. We’re going to push OpenCTI indicators into Sentinel’s <strong>Threat Intelligence</strong> blade in real time, so they can be used in analytics rules to match against ingested logs.</p>
<figure><img
    class="my-0 rounded-md"
    loading="lazy"
    decoding="async"
    fetchpriority="auto"
    alt=""
    width="1024"
    height="313"
    src="https://www.modernsecurity.nl/opencti-threat-intelligence-sentinel/image-60_hu_a6874d13a69b12dc.webp"
   
   
    data-zoom-src="https://www.modernsecurity.nl/opencti-threat-intelligence-sentinel/image-60.webp"></figure><p>The connector is <code>opencti/connector-sentinel-intel</code> and it works via OpenCTI’s <strong>Live Stream</strong> feature: a server-sent events stream that pushes indicator create/update/delete events to the connector, which then forwards them to Sentinel via the Microsoft Graph API.</p>

<h3 class="relative group">Azure App Registration
    <div id="azure-app-registration" class="anchor"></div>
    
</h3>
<p>The connector authenticates to Microsoft’s Graph API using an Entra ID app registration. This gives OpenCTI permission to write threat indicators into your Sentinel workspace.</p>
<p><strong>Register the application:</strong></p>
<ol>
<li>Go to <a href="https://portal.azure.com/"  target="_blank" rel="noreferrer">portal.azure.com</a></li>
<li>Navigate to <strong>Microsoft Entra ID</strong> → <strong>App registrations</strong></li>
<li>Click <strong>New registration</strong></li>
<li>Fill in the details:
<ul>
<li><strong>Name:</strong> <code>OpenCTI-Sentinel-Connector</code></li>
<li><strong>Supported account types:</strong> Accounts in this organizational directory only</li>
<li><strong>Redirect URI:</strong> leave empty</li>
</ul>
</li>
<li>Click <strong>Register</strong></li>
</ol>
<figure><img
    class="my-0 rounded-md"
    loading="lazy"
    decoding="async"
    fetchpriority="auto"
    alt=""
    width="1897"
    height="989"
    src="https://www.modernsecurity.nl/opencti-threat-intelligence-sentinel/image-50_hu_6ec3bcb3f65093b8.webp"
   
   
    data-zoom-src="https://www.modernsecurity.nl/opencti-threat-intelligence-sentinel/image-50.webp"></figure><p>You will land on the app overview page. Note down two values. You’ll need both later:</p>
<ul>
<li><strong>Application (client) ID</strong>: this is your <code>CLIENT_ID</code></li>
<li><strong>Directory (tenant) ID</strong>: this is your <code>TENANT_ID</code></li>
</ul>
<figure><img
    class="my-0 rounded-md"
    loading="lazy"
    decoding="async"
    fetchpriority="auto"
    alt=""
    width="1919"
    height="999"
    src="https://www.modernsecurity.nl/opencti-threat-intelligence-sentinel/image-51_hu_6fc42064ca1f821f.webp"
   
   
    data-zoom-src="https://www.modernsecurity.nl/opencti-threat-intelligence-sentinel/image-51.webp"></figure><p><strong>Add API permissions:</strong></p>
<p>The connector needs permission to read and write threat indicators. This permission is on the <strong>Microsoft Threat Intelligence</strong> API, not Microsoft Graph.</p>
<ol>
<li>In the left sidebar click <strong>API permissions</strong></li>
<li>Click <strong>Add a permission</strong></li>
<li>Scroll down and select <strong>Microsoft Threat Intelligence</strong></li>
<li>Select <strong>Application permissions</strong> (not Delegated)</li>
<li>Expand the list and check <code>ThreatIndicators.ReadWrite.OwnedBy</code></li>
<li>Click <strong>Add permissions</strong></li>
</ol>
<figure><img
    class="my-0 rounded-md"
    loading="lazy"
    decoding="async"
    fetchpriority="auto"
    alt=""
    width="1919"
    height="1000"
    src="https://www.modernsecurity.nl/opencti-threat-intelligence-sentinel/image-52_hu_1abc24087b8ef0d4.webp"
   
   
    data-zoom-src="https://www.modernsecurity.nl/opencti-threat-intelligence-sentinel/image-52.webp"></figure><p>After adding the permission, it will show as <strong>Not granted</strong>. You need to grant admin consent:</p>
<ol start="7">
<li>Click <strong>Grant admin consent for [your tenant name]</strong></li>
<li>Confirm by clicking <strong>Yes</strong></li>
</ol>
<p>The permission status should now show a green checkmark and read <strong>Granted for [your tenant]</strong>.</p>
<blockquote><p>This step requires a <strong>Global Administrator</strong> or <strong>Privileged Role Administrator</strong> role in Entra ID. If you don’t have that role, ask your Azure admin to grant consent.</p>
</blockquote><p><strong>Create a client secret:</strong></p>
<p>The connector uses a client secret to authenticate. Think of it as a password for the app registration.</p>
<ol>
<li>In the left sidebar click <strong>Certificates &amp; secrets</strong></li>
<li>Click <strong>Client secrets</strong> tab</li>
<li>Click <strong>New client secret</strong></li>
<li>Set a description (e.g. <code>opencti-connector</code>) and an expiry period</li>
<li>Click <strong>Add</strong></li>
</ol>
<figure><img
    class="my-0 rounded-md"
    loading="lazy"
    decoding="async"
    fetchpriority="auto"
    alt=""
    width="1919"
    height="1000"
    src="https://www.modernsecurity.nl/opencti-threat-intelligence-sentinel/image-53_hu_9beaab5d62752a1c.webp"
   
   
    data-zoom-src="https://www.modernsecurity.nl/opencti-threat-intelligence-sentinel/image-53.webp"></figure><p>Azure will show the secret in the list. It has two columns:</p>

<div class="ms-table" role="region" aria-label="Table" tabindex="0">
  <table>
      <thead>
          <tr>
              <th>Column</th>
              <th>Example</th>
              <th>What it is</th>
          </tr>
      </thead>
    <tbody>
        <tr>
            <td><strong>Secret ID</strong></td>
            <td><code>dd93e053-7a34-4c21-...</code></td>
            <td>A UUID identifier: <strong>not</strong> what you need</td>
        </tr>
        <tr>
            <td><strong>Value</strong></td>
            <td><code>90o8Q~LL_0U0dkHbX...</code></td>
            <td>The actual secret: <strong>this is what you copy</strong></td>
        </tr>
    </tbody>
  </table>
</div>
<ol start="6">
<li>Copy the <strong>Value</strong> column immediately</li>
</ol>

<h3 class="relative group">Enable Threat Intelligence in Sentinel
    <div id="enable-threat-intelligence-in-sentinel" class="anchor"></div>
    
</h3>
<p>Before Sentinel can receive indicators from OpenCTI, you need to enable the Threat Intelligence solution and its data connector.</p>
<p><strong>Install the Threat Intelligence solution:</strong></p>
<ol>
<li>Go to <strong>Microsoft Sentinel</strong> → your workspace</li>
<li>In the left sidebar click <strong>Content Hub</strong></li>
<li>In the search box type <code>Threat Intelligence</code></li>
<li>Click on the <strong>Threat Intelligence</strong> solution by Microsoft</li>
<li>Click <strong>Install</strong> in the right panel</li>
</ol>
<figure><img
    class="my-0 rounded-md"
    loading="lazy"
    decoding="async"
    fetchpriority="auto"
    alt=""
    width="1918"
    height="998"
    src="https://www.modernsecurity.nl/opencti-threat-intelligence-sentinel/image-54_hu_4acf522973e0b97c.webp"
   
   
    data-zoom-src="https://www.modernsecurity.nl/opencti-threat-intelligence-sentinel/image-54.webp"></figure><p>Wait for the installation to complete. It installs the data connector, workbooks, and analytics rule templates.</p>
<p><strong>Enable the Threat Intelligence Platforms data connector:</strong></p>
<ol>
<li>In Microsoft Sentinel → <strong>Data connectors</strong></li>
<li>Search for <code>Threat Intelligence Platforms</code></li>
<li>Click on it and then click <strong>Open connector page</strong></li>
<li>Click <strong>Connect</strong> to enable it</li>
</ol>
<p>This connector is what receives the indicators pushed via the Microsoft Graph API. Without enabling it, no data will flow into Sentinel even if the OpenCTI connector is running correctly.</p>
<p><strong>Verify the connector is active:</strong></p>
<p>After connecting, the status should show as <strong>Connected</strong> with a green indicator. The <strong>Data received</strong> section will show the first data once indicators start flowing from OpenCTI.</p>

<h3 class="relative group">Create a Live Stream in OpenCTI
    <div id="create-a-live-stream-in-opencti" class="anchor"></div>
    
</h3>
<ol>
<li>Go to <strong>Data</strong> → <strong>Data Sharing</strong> → <strong>Live Streams</strong></li>
<li>Click <strong>+</strong>, give it a name (e.g. <code>Sentinel</code>), leave it <strong>private</strong>, click <strong>Create</strong></li>
<li>Copy the generated <strong>Stream ID</strong></li>
</ol>
<figure><img
    class="my-0 rounded-md"
    loading="lazy"
    decoding="async"
    fetchpriority="auto"
    alt=""
    width="1919"
    height="994"
    src="https://www.modernsecurity.nl/opencti-threat-intelligence-sentinel/image-55_hu_ee78f8c7ced65b77.webp"
   
   
    data-zoom-src="https://www.modernsecurity.nl/opencti-threat-intelligence-sentinel/image-55.webp"></figure><figure><img
    class="my-0 rounded-md"
    loading="lazy"
    decoding="async"
    fetchpriority="auto"
    alt=""
    width="1919"
    height="999"
    src="https://www.modernsecurity.nl/opencti-threat-intelligence-sentinel/image-56_hu_4e58c6ced761b7a7.webp"
   
   
    data-zoom-src="https://www.modernsecurity.nl/opencti-threat-intelligence-sentinel/image-56.webp"></figure>
<h3 class="relative group">Get the Sentinel Workspace ID
    <div id="get-the-sentinel-workspace-id" class="anchor"></div>
    
</h3>
<p>In <strong>Microsoft Sentinel</strong> → <strong>Settings</strong> → <strong>Workspace settings</strong>, copy the <strong>Workspace ID</strong></p>
<figure><img
    class="my-0 rounded-md"
    loading="lazy"
    decoding="async"
    fetchpriority="auto"
    alt=""
    width="1919"
    height="996"
    src="https://www.modernsecurity.nl/opencti-threat-intelligence-sentinel/image-59_hu_919ee97c9af997c0.webp"
   
   
    data-zoom-src="https://www.modernsecurity.nl/opencti-threat-intelligence-sentinel/image-59.webp"></figure>
<h3 class="relative group">Add connector to docker-compose.yml
    <div id="add-connector-to-docker-compose-yml" class="anchor"></div>
    
</h3>
<p>Generate a UUID for the connector:</p>
<div class="highlight-wrapper"><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="cl">cat /proc/sys/kernel/random/uuid</span></span></code></pre></div></div>
<p>Add to <code>.env</code>:</p>
<div class="highlight-wrapper"><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="cl">###########################
</span></span><span class="line"><span class="cl"># SENTINEL INTEGRATION    #
</span></span><span class="line"><span class="cl">###########################
</span></span><span class="line"><span class="cl">CONNECTOR_SENTINEL_INTEL_ID=&lt;uuid&gt;
</span></span><span class="line"><span class="cl">SENTINEL_STREAM_ID=&lt;stream-id-from-opencti&gt;
</span></span><span class="line"><span class="cl">SENTINEL_TENANT_ID=&lt;directory-tenant-id&gt;
</span></span><span class="line"><span class="cl">SENTINEL_CLIENT_ID=&lt;application-client-id&gt;
</span></span><span class="line"><span class="cl">SENTINEL_CLIENT_SECRET=&lt;client-secret-value&gt;
</span></span><span class="line"><span class="cl">SENTINEL_WORKSPACE_ID=&lt;sentinel-workspace-id&gt;</span></span></code></pre></div></div>
<p>Add to <code>docker-compose.yml</code>:</p>
<div class="highlight-wrapper"><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="cl">  ###########################
</span></span><span class="line"><span class="cl">  # SENTINEL INTEGRATION    #
</span></span><span class="line"><span class="cl">  ###########################
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">  connector-sentinel-intel:
</span></span><span class="line"><span class="cl">    image: opencti/connector-sentinel-intel:latest
</span></span><span class="line"><span class="cl">    environment:
</span></span><span class="line"><span class="cl">      - OPENCTI_URL=http://opencti:8080
</span></span><span class="line"><span class="cl">      - OPENCTI_TOKEN=${OPENCTI_ADMIN_TOKEN}
</span></span><span class="line"><span class="cl">      - CONNECTOR_ID=${CONNECTOR_SENTINEL_INTEL_ID}
</span></span><span class="line"><span class="cl">      - CONNECTOR_LIVE_STREAM_ID=${SENTINEL_STREAM_ID}
</span></span><span class="line"><span class="cl">      - CONNECTOR_LIVE_STREAM_LISTEN_DELETE=true
</span></span><span class="line"><span class="cl">      - CONNECTOR_LIVE_STREAM_NO_DEPENDENCIES=true
</span></span><span class="line"><span class="cl">      - &#34;CONNECTOR_NAME=Microsoft Sentinel Intel&#34;
</span></span><span class="line"><span class="cl">      - CONNECTOR_SCOPE=sentinel
</span></span><span class="line"><span class="cl">      - CONNECTOR_CONFIDENCE_LEVEL=80
</span></span><span class="line"><span class="cl">      - CONNECTOR_LOG_LEVEL=error
</span></span><span class="line"><span class="cl">      - SENTINEL_INTEL_TENANT_ID=${SENTINEL_TENANT_ID}
</span></span><span class="line"><span class="cl">      - SENTINEL_INTEL_CLIENT_ID=${SENTINEL_CLIENT_ID}
</span></span><span class="line"><span class="cl">      - SENTINEL_INTEL_CLIENT_SECRET=${SENTINEL_CLIENT_SECRET}
</span></span><span class="line"><span class="cl">      - SENTINEL_WORKSPACE_ID=${SENTINEL_WORKSPACE_ID}
</span></span><span class="line"><span class="cl">      - &#34;SENTINEL_INTEL_TARGET_PRODUCT=Azure Sentinel&#34;
</span></span><span class="line"><span class="cl">      - SENTINEL_INTEL_LOGIN_URL=https://login.microsoftonline.com
</span></span><span class="line"><span class="cl">      - SENTINEL_INTEL_BASE_URL=https://graph.microsoft.com
</span></span><span class="line"><span class="cl">      - SENTINEL_INTEL_RESOURCE_PATH=/beta/security/tiIndicators
</span></span><span class="line"><span class="cl">      - SENTINEL_INTEL_EXPIRE_TIME=30
</span></span><span class="line"><span class="cl">      - SENTINEL_INTEL_ACTION=alert
</span></span><span class="line"><span class="cl">    restart: always
</span></span><span class="line"><span class="cl">    depends_on:
</span></span><span class="line"><span class="cl">      opencti:
</span></span><span class="line"><span class="cl">        condition: service_healthy</span></span></code></pre></div></div>
<p>Apply:</p>
<div class="highlight-wrapper"><div class="highlight"><div class="ms-code-label">Bash</div><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="nb">cd</span> /opt/opencti
</span></span><span class="line"><span class="cl">docker compose up -d connector-sentinel-intel
</span></span><span class="line"><span class="cl">docker compose logs -f connector-sentinel-intel</span></span></code></pre></div></div>
<p>The connector will show <code>KeyError: 'data'</code> errors on stream heartbeat messages. This is a known bug in the connector and does not affect functionality. What you should <strong>not</strong> see is authentication errors or <code>Invalid URL 'NoneNone'</code>.</p>
<figure><img
    class="my-0 rounded-md"
    loading="lazy"
    decoding="async"
    fetchpriority="auto"
    alt=""
    width="1920"
    height="1140"
    src="https://www.modernsecurity.nl/opencti-threat-intelligence-sentinel/image-57_hu_76eb50cde33d1ecc.webp"
   
   
    data-zoom-src="https://www.modernsecurity.nl/opencti-threat-intelligence-sentinel/image-57.webp"></figure>
<h3 class="relative group">Verifying indicators in Sentinel
    <div id="verifying-indicators-in-sentinel" class="anchor"></div>
    
</h3>
<p>Go to <strong>Microsoft Sentinel → Threat Intelligence</strong>. Indicators should start appearing within a few minutes:</p>
<figure><img
    class="my-0 rounded-md"
    loading="lazy"
    decoding="async"
    fetchpriority="auto"
    alt=""
    width="1919"
    height="998"
    src="https://www.modernsecurity.nl/opencti-threat-intelligence-sentinel/image-58_hu_1af568845bb0b91.webp"
   
   
    data-zoom-src="https://www.modernsecurity.nl/opencti-threat-intelligence-sentinel/image-58.webp"></figure><p><strong>Once indicators are in Sentinel you can query them in KQL:</strong></p>
<div class="highlight-wrapper"><div class="highlight"><div class="ms-code-label">KQL</div><pre tabindex="0" class="chroma"><code class="language-kql" data-lang="kql">ThreatIntelIndicators
<span class="o">|</span> <span class="k">where</span> TimeGenerated <span class="o">&gt;</span> <span class="nf">ago</span>(24h)
<span class="o">|</span> <span class="k">where</span> <span class="k">isnotempty</span>(ObservableKey)
<span class="o">|</span> <span class="k">extend</span> IndicatorType = <span class="nf">tostring</span>(<span class="nf">split</span>(ObservableKey, <span class="s">&#34;:&#34;</span>, 0)[0])
<span class="o">|</span> <span class="k">summarize</span> Count = <span class="k">count</span>() <span class="k">by</span> IndicatorType
<span class="o">|</span> <span class="k">order by</span> Count <span class="k">desc</span></code></pre></div>
</div>
<p><strong>Match IP indicators against CommonSecurityLog (firewalls, proxies):</strong></p>
<div class="highlight-wrapper"><div class="highlight"><div class="ms-code-label">KQL</div><pre tabindex="0" class="chroma"><code class="language-kql" data-lang="kql"><span class="k">let</span> dt_lookBack = 1h;
<span class="k">let</span> ioc_lookBack = 14d;
<span class="k">let</span> IP_Indicators = ThreatIntelIndicators
    <span class="o">|</span> <span class="k">extend</span> IndicatorType = <span class="nf">replace</span>(<span class="s">@&#34;\[|\]|\&#34;</span><span class="s">&#34;&#34;</span>, <span class="s">&#34;&#34;</span>, <span class="nf">tostring</span>(<span class="nf">split</span>(ObservableKey, <span class="s">&#34;:&#34;</span>, 0)))
    <span class="o">|</span> <span class="k">where</span> IndicatorType <span class="k">in</span> (<span class="s">&#34;ipv4-addr&#34;</span>, <span class="s">&#34;ipv6-addr&#34;</span>, <span class="s">&#34;network-traffic&#34;</span>)
    <span class="o">|</span> <span class="k">extend</span> TI_ipEntity = <span class="nf">toupper</span>(ObservableValue)
    <span class="o">|</span> <span class="k">where</span> TimeGenerated <span class="o">&gt;=</span> <span class="nf">ago</span>(ioc_lookBack)
    <span class="o">|</span> <span class="k">where</span> <span class="nf">ipv4_is_private</span>(TI_ipEntity) <span class="o">==</span> <span class="k">false</span>
    <span class="o">|</span> <span class="k">where</span> <span class="k">isnotempty</span>(TI_ipEntity)
    <span class="o">|</span> <span class="k">summarize</span> <span class="nf">arg_max</span>(TimeGenerated, *) <span class="k">by</span> TI_ipEntity;
IP_Indicators
<span class="o">|</span> <span class="k">join</span> <span class="k">kind</span>=<span class="k">innerunique</span> (
    CommonSecurityLog
    <span class="o">|</span> <span class="k">where</span> TimeGenerated <span class="o">&gt;=</span> <span class="nf">ago</span>(dt_lookBack)
    <span class="o">|</span> <span class="k">extend</span> CS_ipEntity = <span class="nf">toupper</span>(DestinationIP)
    <span class="o">|</span> <span class="k">where</span> <span class="k">isnotempty</span>(CS_ipEntity)
) <span class="k">on</span> $left.TI_ipEntity <span class="o">==</span> $right.CS_ipEntity
<span class="o">|</span> <span class="k">project</span>
    TimeGenerated,
    TI_ipEntity,
    SourceIP,
    DestinationIP,
    DeviceVendor,
    Activity,
    Confidence,
    Tags
<span class="o">|</span> <span class="k">order by</span> TimeGenerated <span class="k">desc</span></code></pre></div>
</div>
<p><strong>Match domain indicators against DNS events:</strong></p>
<div class="highlight-wrapper"><div class="highlight"><div class="ms-code-label">KQL</div><pre tabindex="0" class="chroma"><code class="language-kql" data-lang="kql"><span class="k">let</span> dt_lookBack = 1h;
<span class="k">let</span> ioc_lookBack = 14d;
<span class="k">let</span> Domain_Indicators = ThreatIntelIndicators
    <span class="o">|</span> <span class="k">where</span> ObservableKey <span class="o">==</span> <span class="s">&#34;domain-name:value&#34;</span>
    <span class="o">|</span> <span class="k">extend</span> TI_domainEntity = <span class="nf">tolower</span>(ObservableValue)
    <span class="o">|</span> <span class="k">where</span> TimeGenerated <span class="o">&gt;=</span> <span class="nf">ago</span>(ioc_lookBack)
    <span class="o">|</span> <span class="k">where</span> <span class="k">isnotempty</span>(TI_domainEntity)
    <span class="o">|</span> <span class="k">summarize</span> <span class="nf">arg_max</span>(TimeGenerated, *) <span class="k">by</span> TI_domainEntity;
Domain_Indicators
<span class="o">|</span> <span class="k">join</span> <span class="k">kind</span>=<span class="k">innerunique</span> (
    DnsEvents
    <span class="o">|</span> <span class="k">where</span> TimeGenerated <span class="o">&gt;=</span> <span class="nf">ago</span>(dt_lookBack)
    <span class="o">|</span> <span class="k">extend</span> DNS_Name = <span class="nf">tolower</span>(Name)
    <span class="o">|</span> <span class="k">where</span> <span class="k">isnotempty</span>(DNS_Name)
) <span class="k">on</span> $left.TI_domainEntity <span class="o">==</span> $right.DNS_Name
<span class="o">|</span> <span class="k">project</span>
    TimeGenerated,
    TI_domainEntity,
    ClientIP,
    Confidence,
    Tags
<span class="o">|</span> <span class="k">order by</span> TimeGenerated <span class="k">desc</span></code></pre></div>
</div>
<p><strong>Match file hash indicators against Defender for Endpoint:</strong></p>
<div class="highlight-wrapper"><div class="highlight"><div class="ms-code-label">KQL</div><pre tabindex="0" class="chroma"><code class="language-kql" data-lang="kql"><span class="k">let</span> dt_lookBack = 1h;
<span class="k">let</span> ioc_lookBack = 14d;
<span class="k">let</span> Hash_Indicators = ThreatIntelIndicators
    <span class="o">|</span> <span class="k">where</span> ObservableKey <span class="k">has</span> <span class="s">&#34;file:hashes&#34;</span>
    <span class="o">|</span> <span class="k">extend</span> TI_hashEntity = <span class="nf">toupper</span>(ObservableValue)
    <span class="o">|</span> <span class="k">where</span> TimeGenerated <span class="o">&gt;=</span> <span class="nf">ago</span>(ioc_lookBack)
    <span class="o">|</span> <span class="k">where</span> <span class="k">isnotempty</span>(TI_hashEntity)
    <span class="o">|</span> <span class="k">summarize</span> <span class="nf">arg_max</span>(TimeGenerated, *) <span class="k">by</span> TI_hashEntity;
Hash_Indicators
<span class="o">|</span> <span class="k">join</span> <span class="k">kind</span>=<span class="k">innerunique</span> (
    DeviceFileEvents
    <span class="o">|</span> <span class="k">where</span> TimeGenerated <span class="o">&gt;=</span> <span class="nf">ago</span>(dt_lookBack)
    <span class="o">|</span> <span class="k">extend</span> File_SHA256 = <span class="nf">toupper</span>(SHA256)
    <span class="o">|</span> <span class="k">where</span> <span class="k">isnotempty</span>(File_SHA256)
) <span class="k">on</span> $left.TI_hashEntity <span class="o">==</span> $right.File_SHA256
<span class="o">|</span> <span class="k">project</span>
    TimeGenerated,
    TI_hashEntity,
    DeviceName,
    FileName,
    FolderPath,
    Confidence,
    Tags
<span class="o">|</span> <span class="k">order by</span> TimeGenerated <span class="k">desc</span></code></pre></div>
</div>

<h2 class="relative group">Closing thoughts
    <div id="closing-thoughts" class="anchor"></div>
    
</h2>
<p>Coming from MISP, OpenCTI took me a little while to get used to: the mental model is different. But once you start navigating the entity graph and seeing how everything connects, it clicks. A malware hash becomes more than a hash: it’s part of a campaign, tied to a threat actor, mapped to ATT&amp;CK techniques. That context is what makes the difference in an investigation.</p>
<p>The Sentinel integration is genuinely useful for an MDR operation. You maintain one source of truth for threat intelligence and it flows automatically into your SIEM without any manual steps. No CSV exports, no copy-pasting, no manual watchlist updates.</p>
<p>In a follow-up post I’ll look at using the imported indicators in Sentinel analytics rules and how to build workbooks around the threat intelligence data. For now. This stack is running, the indicators are flowing, and it’s already looking AND working good. Need to get more familiar with OpenCTI but honest: it’s promising.</p>
]]></content:encoded><media:content url="https://www.modernsecurity.nl/opencti-threat-intelligence-sentinel/featured_hu_e8b6cb43606b8a95.jpg" medium="image" type="image/jpeg" width="1200" height="675"/><enclosure url="https://www.modernsecurity.nl/opencti-threat-intelligence-sentinel/featured_hu_e8b6cb43606b8a95.jpg" type="image/jpeg" length="83979"/></item><item><title>Microsoft Defender for Identity sensor guide (v3.x)</title><link>https://www.modernsecurity.nl/microsoft-defender-for-identity-guide-v3-x/</link><guid isPermaLink="true">https://www.modernsecurity.nl/microsoft-defender-for-identity-guide-v3-x/</guid><pubDate>Thu, 02 Apr 2026 21:31:00 +0100</pubDate><dc:creator>Farid Kalaidji</dc:creator><category>Microsoft Defender for Identity</category><category>Microsoft Defender XDR</category><description>Complete step-by-step guide to deploying and migrating to the Microsoft Defender for Identity (MDI) sensor v3.x and auditing included.</description><content:encoded><![CDATA[
<h2 class="relative group">Introduction
    <div id="introduction" class="anchor"></div>
    
</h2>
<p>In a <a href="https://www.modernsecurity.nl/install-microsoft-defender-for-identity/" >previous post on modernsecurity.nl</a>, I walked through the classic installation of Microsoft Defender for Identity (MDI) using the v2.x sensor: prerequisites, gMSA configuration, Windows event auditing, NTLM auditing, and the manual download-and-install process. If you’ve deployed MDI before, you’ll remember the overhead: downloading an installer package, running it on each domain controller, creating and maintaining a gMSA account, configuring audit GPOs, and dealing with Npcap.</p>
<p>That process is now behind us.</p>
<p>With the <strong>general availability of the Microsoft Defender for Identity sensor v3.x</strong> in early 2026, and the release of the portal-based migration wizard in March 2026, Microsoft has completely changed how MDI sensors are deployed and managed. The new sensor runs as an extension of <strong>Microsoft Defender for Endpoint (MDE)</strong>: if MDE is already on your domain controllers (as it should be), MDI protection is now a matter of a few clicks from the portal.</p>
<p>This guide covers everything you need:</p>
<ul>
<li>What changed and why it matters</li>
<li>Prerequisites for both fresh deployments and migrations</li>
<li>Deploying the sensor from the Defender portal</li>
<li>Migrating existing v2.x sensors to v3.x with zero downtime</li>
<li>Post-deployment and post-migration configuration: RPC auditing, automatic Windows auditing, and gMSA removal</li>
</ul>
<p>All steps are verified against Microsoft Learn documentation and tested in live environments.</p>

<h2 class="relative group">What changed with the MDI sensor v3.x
    <div id="what-changed-with-the-mdi-sensor-v3-x" class="anchor"></div>
    
</h2>
<p>The biggest change is architectural. The v3.x sensor is <strong>not a standalone agent</strong>. It runs as a component within the MDE/SENSE service already present on your domain controllers. This is the long-awaited unification of endpoint and identity telemetry into a single agent.</p>

<div class="ms-table" role="region" aria-label="Table" tabindex="0">
  <table>
      <thead>
          <tr>
              <th>Area</th>
              <th>v2.x (classic)</th>
              <th>v3.x (new)</th>
          </tr>
      </thead>
    <tbody>
        <tr>
            <td>Deployment</td>
            <td>Manual installer on each DC</td>
            <td>Portal-based activation, no installer</td>
        </tr>
        <tr>
            <td>Dependency</td>
            <td>Standalone agent</td>
            <td>Built on top of MDE (SENSE service)</td>
        </tr>
        <tr>
            <td>Authentication account</td>
            <td>gMSA required</td>
            <td>Local SYSTEM, no gMSA needed</td>
        </tr>
        <tr>
            <td>Windows auditing</td>
            <td>Manual GPO configuration</td>
            <td>Automatic configuration (preview) available</td>
        </tr>
        <tr>
            <td>RPC auditing</td>
            <td>Not available</td>
            <td>Available via asset rule tag</td>
        </tr>
        <tr>
            <td>Sensor updates</td>
            <td>Manual or delayed update ring</td>
            <td>Automatically via Windows Updates, no manual packages</td>
        </tr>
        <tr>
            <td>Delayed update ring</td>
            <td>Supported</td>
            <td>Not available (v2.x only)</td>
        </tr>
        <tr>
            <td>OS requirement</td>
            <td>Windows Server 2008 R2 and later</td>
            <td>Windows Server 2019 and later</td>
        </tr>
        <tr>
            <td>Npcap / WinPcap</td>
            <td>Required</td>
            <td>Not required</td>
        </tr>
    </tbody>
  </table>
</div>
<p>Beyond deployment simplicity, v3.x also brings detection improvements: it uses the <strong>Windows Filtering Platform (WFP)</strong> for deeper network inspection, adds <strong>enhanced RPC auditing</strong> for advanced identity attack detections, and caps resource usage at 30% CPU and 1.5 GB memory.</p>

<h2 class="relative group">Prerequisites
    <div id="prerequisites" class="anchor"></div>
    
</h2>
<p>Before diving into the requirements, a quick note on scope. The v3.x sensor applies to <strong>domain controllers running Windows Server 2019 or later</strong>. Two scenarios still require the v2.x classic sensor:</p>
<ul>
<li>Domain controllers running <strong>Windows Server 2016 or earlier</strong></li>
<li>Standalone servers running AD FS, AD CS, or Microsoft Entra Connect <strong>without a DC role</strong>: v3.x will never apply here since the sensor only runs on domain controllers</li>
</ul>
<p>DCs that <strong>also</strong> run AD FS, AD CS, or Entra Connect alongside the DC role are supported by v3.x as of March 2026, but the migration wizard does not support them yet. Those require a fresh deployment. See <a href="https://www.modernsecurity.nl/microsoft-defender-for-identity-guide-v3-x/#supported-server-roles" >Supported server roles</a> and the following decision tree:</p>
<figure><img
    class="my-0 rounded-md"
    loading="lazy"
    decoding="async"
    fetchpriority="auto"
    alt=""
    width="960"
    height="720"
    src="https://www.modernsecurity.nl/microsoft-defender-for-identity-guide-v3-x/image-36_hu_8cbc5dea166491c1.webp"
   
   
    data-zoom-src="https://www.modernsecurity.nl/microsoft-defender-for-identity-guide-v3-x/image-36.webp"><figcaption>Source: Microsoft</figcaption></figure>
<h3 class="relative group">Licensing and permissions
    <div id="licensing-and-permissions" class="anchor"></div>
    
</h3>
<p>One of the following licenses is required:</p>

<div class="ms-table" role="region" aria-label="Table" tabindex="0">
  <table>
      <thead>
          <tr>
              <th>License</th>
          </tr>
      </thead>
    <tbody>
        <tr>
            <td>Enterprise Mobility + Security E5 (EMS E5/A5)</td>
        </tr>
        <tr>
            <td>Microsoft 365 E5 (E5/A5/G5)</td>
        </tr>
        <tr>
            <td>Microsoft 365 E5/A5/G5/F5 Security</td>
        </tr>
        <tr>
            <td>Microsoft 365 F5 Security + Compliance</td>
        </tr>
    </tbody>
  </table>
</div>
<p>To deploy, you need one of the following:</p>

<div class="ms-table" role="region" aria-label="Table" tabindex="0">
  <table>
      <thead>
          <tr>
              <th>Role</th>
              <th>Detail</th>
          </tr>
      </thead>
    <tbody>
        <tr>
            <td>Security Administrator</td>
            <td>Microsoft Entra ID built-in role</td>
        </tr>
        <tr>
            <td>Unified RBAC (alternative)</td>
            <td><code>System settings (Read and manage)</code> + <code>Security settings (All permissions)</code></td>
        </tr>
    </tbody>
  </table>
</div>

<h3 class="relative group">Server requirements
    <div id="server-requirements" class="anchor"></div>
    
</h3>

<div class="ms-table" role="region" aria-label="Table" tabindex="0">
  <table>
      <thead>
          <tr>
              <th>Requirement</th>
              <th>Detail</th>
          </tr>
      </thead>
    <tbody>
        <tr>
            <td>Operating system</td>
            <td>Windows Server 2019 or later</td>
        </tr>
        <tr>
            <td>Cumulative update</td>
            <td><strong>March 2026</strong> or later (KB5078766 for Windows Server 2022; KB varies by OS version)</td>
        </tr>
        <tr>
            <td>MDE deployment</td>
            <td>Microsoft Defender for Endpoint deployed and running (SENSE service active)</td>
        </tr>
        <tr>
            <td>Microsoft Defender Antivirus</td>
            <td>Active or passive mode both supported</td>
        </tr>
        <tr>
            <td>Power plan</td>
            <td>Set to <strong>High Performance</strong> on each DC</td>
        </tr>
        <tr>
            <td>Time sync</td>
            <td>Within 5 minutes across all DCs</td>
        </tr>
        <tr>
            <td>Memory (Hyper-V)</td>
            <td>Disable “Enable Dynamic Memory” on the VM</td>
        </tr>
        <tr>
            <td>Memory (VMware)</td>
            <td>Set reserved memory equal to configured memory, or enable “Reserve all guest memory (All locked)”</td>
        </tr>
    </tbody>
  </table>
</div>
<blockquote><p>The March 2026 cumulative update is a hard dependency. Without it, activation or migration will fail. Apply it to all domain controllers before proceeding. The KB number varies by OS version: KB5078766 is for Windows Server 2022.</p>
</blockquote><p>If you are doing a <strong>fresh deployment</strong>, the target DC must not already have a v2.x sensor installed. If you are <strong>migrating</strong>, the v2.x sensor must be installed and running. Those prerequisites are listed separately in the <a href="https://www.modernsecurity.nl/microsoft-defender-for-identity-guide-v3-x/#migration-from-v2-x-to-v3-x" >Migration from v2.x to v3.x</a> section.</p>

<h3 class="relative group">Supported server roles
    <div id="supported-server-roles" class="anchor"></div>
    
</h3>
<p>As of April 2026:</p>

<div class="ms-table" role="region" aria-label="Table" tabindex="0">
  <table>
      <thead>
          <tr>
              <th>Role</th>
              <th>Support status</th>
          </tr>
      </thead>
    <tbody>
        <tr>
            <td>Domain controller only</td>
            <td>Fully supported, activation and migration wizard</td>
        </tr>
        <tr>
            <td>Domain controller + Entra Connect</td>
            <td>Rolling out: fresh deployment only, requires Windows Server 2019+, March 2026 CU</td>
        </tr>
        <tr>
            <td>Domain controller + AD FS</td>
            <td>Rolling out: fresh deployment only, requires Windows Server 2019+, March 2026 CU</td>
        </tr>
        <tr>
            <td>Domain controller + AD CS</td>
            <td>Rolling out: fresh deployment only, requires Windows Server 2019+, March 2026 CU</td>
        </tr>
        <tr>
            <td>Standalone AD FS / AD CS / Entra Connect (no DC role)</td>
            <td>Use v2.x sensor: v3.x does not apply</td>
        </tr>
    </tbody>
  </table>
</div>

<h3 class="relative group">Validating prerequisites
    <div id="validating-prerequisites" class="anchor"></div>
    
</h3>
<p>Microsoft provides two useful PowerShell scripts from the <code>DefenderForIdentity</code> module. Both are optional but recommended before a large rollout. Both can be found in the portal from: <strong>Identities &gt; Tools</strong>:</p>
<figure><img
    class="my-0 rounded-md"
    loading="lazy"
    decoding="async"
    fetchpriority="auto"
    alt=""
    width="1918"
    height="999"
    src="https://www.modernsecurity.nl/microsoft-defender-for-identity-guide-v3-x/image-42_hu_464232a566e290cf.webp"
   
   
    data-zoom-src="https://www.modernsecurity.nl/microsoft-defender-for-identity-guide-v3-x/image-42.webp"></figure><p><strong>Test-MDIReadiness</strong> checks sensor prerequisites: connectivity, permissions, MDE deployment, and overall sensor readiness:</p>
<div class="highlight-wrapper"><div class="highlight"><div class="ms-code-label">PowerShell</div><pre tabindex="0" class="chroma"><code class="language-powershell" data-lang="powershell"><span class="line"><span class="cl"><span class="nb">Install-Module</span> <span class="n">-Name</span> <span class="n">DefenderForIdentity</span>
</span></span><span class="line"><span class="cl"><span class="nb">Test-MDIReadiness</span></span></span></code></pre></div></div>
<p><strong>New-MDIConfigurationReport</strong> generates an HTML report of your current Windows event auditing configuration, showing exactly which audit policies and SACL settings are missing or misconfigured:</p>
<div class="highlight-wrapper"><div class="highlight"><div class="ms-code-label">PowerShell</div><pre tabindex="0" class="chroma"><code class="language-powershell" data-lang="powershell"><span class="line"><span class="cl"><span class="nb">New-MDIConfigurationReport</span> <span class="n">-Path</span> <span class="s2">&#34;C:\Reports&#34;</span> <span class="n">-Mode</span> <span class="n">Domain</span> <span class="n">-OpenHtmlReport</span></span></span></code></pre></div></div>
<p><strong>Test-MDIReadiness</strong> is also available directly in the Defender portal at <strong>Identities &gt; Tools (Preview)</strong>, no download required. <strong>New-MDIConfigurationReport</strong> requires the PowerShell module installed locally.</p>

<h2 class="relative group">Deploying the sensor
    <div id="deploying-the-sensor" class="anchor"></div>
    
</h2>

<h3 class="relative group">Activating the sensor
    <div id="activating-the-sensor" class="anchor"></div>
    
</h3>
<p>Microsoft recommends activating the sensor on <strong>all domain controllers, including read-only domain controllers (RODCs)</strong>. For complete coverage, make sure every DC, including RODCs, has MDE deployed and the March 2026 cumulative update installed before proceeding.</p>
<p>Navigate to the <a href="https://security.microsoft.com/"  target="_blank" rel="noreferrer">Microsoft Defender portal</a> and go to <strong>System &gt; Settings &gt; Identities &gt; Activation</strong>.</p>
<p>The portal auto-discovers your domain controllers from the <strong>Device Inventory</strong> (populated by MDE onboarding). Each server is listed with its current activation state:</p>

<div class="ms-table" role="region" aria-label="Table" tabindex="0">
  <table>
      <thead>
          <tr>
              <th>Activation state</th>
              <th>What it means</th>
          </tr>
      </thead>
    <tbody>
        <tr>
            <td>Activate new sensor</td>
            <td>DC is MDE-onboarded and eligible for v3.x activation</td>
        </tr>
        <tr>
            <td>Install classic sensor</td>
            <td>DC doesn’t meet v3.x requirements. Use the classic installer from the Sensors page</td>
        </tr>
        <tr>
            <td>OS upgrade is required</td>
            <td>DC runs an unsupported OS version</td>
        </tr>
    </tbody>
  </table>
</div>
<blockquote><p>In some portal versions the label may show as “Activate sensor v3.x” instead of “Activate new sensor”: both mean the same thing.</p>
</blockquote><p>When you first land on this page with no sensors deployed, you may see a <strong>“Simplify Your Installation Process”</strong> dialog. Click <strong>Activate servers</strong> to proceed with the new activation-based flow, no installer download needed.</p>
<figure><img
    class="my-0 rounded-md"
    loading="lazy"
    decoding="async"
    fetchpriority="auto"
    alt=""
    width="1919"
    height="1000"
    src="https://www.modernsecurity.nl/microsoft-defender-for-identity-guide-v3-x/image-17_hu_18bbd5da94a7aa8a.webp"
   
   
    data-zoom-src="https://www.modernsecurity.nl/microsoft-defender-for-identity-guide-v3-x/image-17.webp"></figure><p>You’ll also see two activation modes:</p>
<ul>
<li><strong>Automatically activate eligible servers</strong>: MDI activates sensors as soon as eligible DCs are discovered. Good for consistent environments.</li>
<li><strong>Manually select servers to activate</strong>: You control which DCs get activated. Recommended for phased rollouts and MSSP/MSP multi-tenant management.</li>
</ul>
<p>To activate:</p>
<ol>
<li>Select one or more domain controllers from the list.</li>
<li>Click <strong>Activate</strong> in the toolbar.</li>
<li>In the <strong>“Activate New Sensor”</strong> confirmation dialog, verify the selected servers and click <strong>Activate</strong>.</li>
</ol>
<figure><img
    class="my-0 rounded-md"
    loading="lazy"
    decoding="async"
    fetchpriority="auto"
    alt=""
    width="1919"
    height="999"
    src="https://www.modernsecurity.nl/microsoft-defender-for-identity-guide-v3-x/image-19_hu_174040612debfc0f.webp"
   
   
    data-zoom-src="https://www.modernsecurity.nl/microsoft-defender-for-identity-guide-v3-x/image-19.webp"></figure><figure><img
    class="my-0 rounded-md"
    loading="lazy"
    decoding="async"
    fetchpriority="auto"
    alt=""
    width="1919"
    height="999"
    src="https://www.modernsecurity.nl/microsoft-defender-for-identity-guide-v3-x/image-20_hu_8841a164374314d7.webp"
   
   
    data-zoom-src="https://www.modernsecurity.nl/microsoft-defender-for-identity-guide-v3-x/image-20.webp"></figure><p>No installer download, no remote execution, no reboot required. When activation completes, a green success banner appears, click <strong>Click here to see the onboarded servers</strong> to go directly to the Sensors page.</p>

<h3 class="relative group">Verifying sensor status
    <div id="verifying-sensor-status" class="anchor"></div>
    
</h3>
<p>Navigate to <strong>Settings &gt; Identities &gt; On-premises &gt; Sensors</strong></p>
<p>After activation, sensors will initially appear with the following status. This is expected:</p>

<div class="ms-table" role="region" aria-label="Table" tabindex="0">
  <table>
      <thead>
          <tr>
              <th>Column</th>
              <th>Initial value</th>
          </tr>
      </thead>
    <tbody>
        <tr>
            <td>Service status</td>
            <td>Onboarding</td>
        </tr>
        <tr>
            <td>Sensor status</td>
            <td>Outdated</td>
        </tr>
        <tr>
            <td>Version</td>
            <td>3.0.0</td>
        </tr>
    </tbody>
  </table>
</div>
<figure><img
    class="my-0 rounded-md"
    loading="lazy"
    decoding="async"
    fetchpriority="auto"
    alt=""
    width="1919"
    height="985"
    src="https://www.modernsecurity.nl/microsoft-defender-for-identity-guide-v3-x/image-21_hu_429307434e7b6cd4.webp"
   
   
    data-zoom-src="https://www.modernsecurity.nl/microsoft-defender-for-identity-guide-v3-x/image-21.webp"></figure><p>Wait 15–30 minutes and refresh. A healthy sensor will show:</p>

<div class="ms-table" role="region" aria-label="Table" tabindex="0">
  <table>
      <thead>
          <tr>
              <th>Column</th>
              <th>Expected value</th>
          </tr>
      </thead>
    <tbody>
        <tr>
            <td>Service status</td>
            <td>Running</td>
        </tr>
        <tr>
            <td>Sensor status</td>
            <td>Up to date</td>
        </tr>
        <tr>
            <td>Version</td>
            <td>3.0.7.419 or later</td>
        </tr>
    </tbody>
  </table>
</div>
<figure><img
    class="my-0 rounded-md"
    loading="lazy"
    decoding="async"
    fetchpriority="auto"
    alt=""
    width="1918"
    height="987"
    src="https://www.modernsecurity.nl/microsoft-defender-for-identity-guide-v3-x/image-22_hu_926dce4c05376d64.webp"
   
   
    data-zoom-src="https://www.modernsecurity.nl/microsoft-defender-for-identity-guide-v3-x/image-22.webp"></figure><blockquote><p>The first activation on a tenant can take up to 1 hour to show as Running. Subsequent activations typically reflect within 5 minutes. No restart is required.</p>
</blockquote>
<h3 class="relative group">Configuring RPC auditing
    <div id="configuring-rpc-auditing" class="anchor"></div>
    
</h3>
<p>RPC (Remote Procedure Call) is a core Windows protocol heavily used in Active Directory for authentication, replication, and directory access. Attackers abuse it for lateral movement and privilege escalation. The v3.x sensor supports <strong>enhanced RPC auditing</strong> for advanced identity attack detections, but this must be explicitly enabled by applying the <strong>Unified Sensor RPC Audit</strong> tag via an asset rule.</p>
<p>Navigate to <strong>Settings &gt; Microsoft Defender XDR &gt; Asset rule management</strong> and click <strong>Create a new rule</strong></p>
<figure><img
    class="my-0 rounded-md"
    loading="lazy"
    decoding="async"
    fetchpriority="auto"
    alt=""
    width="1917"
    height="999"
    src="https://www.modernsecurity.nl/microsoft-defender-for-identity-guide-v3-x/image-24_hu_269aded5d5d60841.webp"
   
   
    data-zoom-src="https://www.modernsecurity.nl/microsoft-defender-for-identity-guide-v3-x/image-24.webp"></figure><p>In the wizard:</p>
<ol>
<li>On <strong>Name and description</strong>, enter <code>Unified Sensor RPC Audit</code> as the rule name, add a description, and click <strong>Next</strong>.</li>
</ol>
<figure><img
    class="my-0 rounded-md"
    loading="lazy"
    decoding="async"
    fetchpriority="auto"
    alt="Name and description step"
    width="1919"
    height="997"
    src="https://www.modernsecurity.nl/microsoft-defender-for-identity-guide-v3-x/image-33_hu_49e38fe767c6b743.webp"
   
   
    data-zoom-src="https://www.modernsecurity.nl/microsoft-defender-for-identity-guide-v3-x/image-33.webp"></figure><ol start="2">
<li>
<p>On <strong>Rule conditions</strong>, define which devices the rule targets. Use <strong>Device name</strong> with <strong>Starts with</strong> conditions to match your DC naming convention. Use <strong>OR</strong> logic to cover multiple DCs. You can also filter by <strong>Domain</strong> or <strong>Device tag</strong>. Click <strong>Next</strong>.</p>
<p>Only target devices that already have the MDI v3.x sensor installed and running. The tag has no effect on devices without the v3.x sensor.</p>
</li>
</ol>
<figure><img
    class="my-0 rounded-md"
    loading="lazy"
    decoding="async"
    fetchpriority="auto"
    alt="Rule conditions step"
    width="1919"
    height="997"
    src="https://www.modernsecurity.nl/microsoft-defender-for-identity-guide-v3-x/image-29_hu_745f99b471044fac.webp"
   
   
    data-zoom-src="https://www.modernsecurity.nl/microsoft-defender-for-identity-guide-v3-x/image-29.webp"></figure><ol start="3">
<li>On <strong>Select actions</strong>, expand <strong>Apply a tag</strong> and select or type <code>Unified Sensor RPC Audit</code>. Click <strong>Next</strong>.</li>
</ol>
<figure><img
    class="my-0 rounded-md"
    loading="lazy"
    decoding="async"
    fetchpriority="auto"
    alt="Select actions step"
    width="1919"
    height="995"
    src="https://www.modernsecurity.nl/microsoft-defender-for-identity-guide-v3-x/image-30_hu_27ff160ee5ce46d2.webp"
   
   
    data-zoom-src="https://www.modernsecurity.nl/microsoft-defender-for-identity-guide-v3-x/image-30.webp"></figure><ol start="4">
<li>On <strong>Review and finish</strong>, verify the rule name, tag, and number of affected devices. Click <strong>Submit</strong>.</li>
</ol>
<figure><img
    class="my-0 rounded-md"
    loading="lazy"
    decoding="async"
    fetchpriority="auto"
    alt="Review and finish step"
    width="1919"
    height="998"
    src="https://www.modernsecurity.nl/microsoft-defender-for-identity-guide-v3-x/image-31_hu_5ae5210d5d7fb439.webp"
   
   
    data-zoom-src="https://www.modernsecurity.nl/microsoft-defender-for-identity-guide-v3-x/image-31.webp"></figure><figure><img
    class="my-0 rounded-md"
    loading="lazy"
    decoding="async"
    fetchpriority="auto"
    alt=""
    width="1919"
    height="998"
    src="https://www.modernsecurity.nl/microsoft-defender-for-identity-guide-v3-x/image-32_hu_32f5f68b2a1ad7ac.webp"
   
   
    data-zoom-src="https://www.modernsecurity.nl/microsoft-defender-for-identity-guide-v3-x/image-32.webp"></figure><blockquote><p>The rule can take <strong>up to 1 hour</strong> to take effect. To remove RPC auditing from a device later, delete the rule or update the conditions to exclude it.</p>
</blockquote>
<h3 class="relative group">Enabling automatic Windows auditing
    <div id="enabling-automatic-windows-auditing" class="anchor"></div>
    
</h3>
<p>Windows event log collection is the foundation of MDI’s detection engine. The sensor relies on events such as 4662 (object access), 4776 (NTLM authentication), and 4688 (process creation) to detect suspicious activity.</p>
<p>In the v2.x era, this required manually configuring Group Policy Objects, SACL entries on the domain root, and NTLM auditing registry values. With v3.x there’s a preview feature that handles all of this automatically.</p>
<p>Navigate to <strong>Settings &gt; Identities &gt; General &gt; Advanced features</strong></p>
<p>The <strong>Automatic Windows auditing configuration (preview)</strong> toggle is set to <strong>Off</strong> by default. Toggle it to <strong>On</strong> and click <strong>Save preferences</strong>.</p>
<figure><img
    class="my-0 rounded-md"
    loading="lazy"
    decoding="async"
    fetchpriority="auto"
    alt=""
    width="1919"
    height="999"
    src="https://www.modernsecurity.nl/microsoft-defender-for-identity-guide-v3-x/image-34_hu_d08989f3065ddb3b.webp"
   
   
    data-zoom-src="https://www.modernsecurity.nl/microsoft-defender-for-identity-guide-v3-x/image-34.webp"></figure><figure><img
    class="my-0 rounded-md"
    loading="lazy"
    decoding="async"
    fetchpriority="auto"
    alt=""
    width="1919"
    height="998"
    src="https://www.modernsecurity.nl/microsoft-defender-for-identity-guide-v3-x/image-35_hu_95554b4229f167f1.webp"
   
   
    data-zoom-src="https://www.modernsecurity.nl/microsoft-defender-for-identity-guide-v3-x/image-35.webp"></figure><p>What this configures automatically on each eligible DC:</p>
<ul>
<li>Directory Services advanced auditing (SACL on the domain root object)</li>
<li>NTLM auditing via Windows Registry</li>
<li>Domain object auditing (SACL on the Configuration partition)</li>
<li>AD FS auditing (SACL on the AD FS configuration container)</li>
<li>Windows audit policy subcategories via Local Security Authority (LSA) APIs</li>
</ul>
<p>The check runs <strong>once every 24 hours</strong>, so it will self-correct any auditing drift over time, not just at initial deployment.</p>
<blockquote><p><strong>GPO conflict warning:</strong> GPO settings applied to domain controllers can conflict with local settings applied by the sensor. If you have existing GPOs enforcing audit policies, check for conflicts after enabling this feature. The health alerts in <strong>Settings &gt; Identities &gt; Health issues</strong> will surface any configuration gaps that couldn’t be auto-corrected.</p>
</blockquote><blockquote><p>This feature only applies to domain controllers with the v3.x sensor installed and updated to the latest cumulative update. Manual GPO-based configuration still works if you prefer. See the <a href="https://learn.microsoft.com/en-us/defender-for-identity/deploy/configure-windows-event-collection"  target="_blank" rel="noreferrer">Microsoft Learn documentation</a>.</p>
</blockquote>
<h2 class="relative group">Migration from v2.x to v3.x
    <div id="migration-from-v2-x-to-v3-x" class="anchor"></div>
    
</h2>
<p>If you have existing MDI v2.x sensors, this section walks through the migration. The migration itself is portal-driven and non-disruptive: the v2.x sensor keeps running until the v3.x sensor is fully ready. After migration completes, there are a few configuration steps to apply, including switching away from gMSA.</p>

<h3 class="relative group">Migration prerequisites
    <div id="migration-prerequisites" class="anchor"></div>
    
</h3>

<div class="ms-table" role="region" aria-label="Table" tabindex="0">
  <table>
      <thead>
          <tr>
              <th>Requirement</th>
              <th>Detail</th>
          </tr>
      </thead>
    <tbody>
        <tr>
            <td>Current sensor</td>
            <td>MDI v2.x installed and running</td>
        </tr>
        <tr>
            <td>Operating system</td>
            <td>Windows Server 2019 or later</td>
        </tr>
        <tr>
            <td>Cumulative update</td>
            <td>March 2026 or later (KB5078766 for Windows Server 2022; KB varies by OS version)</td>
        </tr>
        <tr>
            <td>MDE</td>
            <td>Microsoft Defender for Endpoint deployed and active</td>
        </tr>
        <tr>
            <td>DC role</td>
            <td>Domain controller only: no additional identity roles (AD FS, AD CS, Entra Connect)</td>
        </tr>
    </tbody>
  </table>
</div>
<blockquote><p><strong>Important:</strong> The migration wizard does not support domain controllers that also run AD FS, AD CS, or Entra Connect roles, even though v3.x itself now supports these DCs via fresh deployment. If your DC carries one of these additional roles, uninstall the v2.x sensor manually and then activate v3.x from the Activation page instead of using the Migrate button.</p>
</blockquote><blockquote><p><strong>Common issue:</strong> If a DC doesn’t appear as “Ready for migration”, check the MDE/SENSE service version first. An outdated MDE sensor can block the migration. Update MDE to the latest version and try again.</p>
</blockquote>
<h3 class="relative group">Running the migration
    <div id="running-the-migration" class="anchor"></div>
    
</h3>
<p>Navigate to <strong>Settings &gt; Identities &gt; On-premises &gt; Sensors</strong>. Eligible servers show <strong>Ready for migration</strong> in the Migration state column.</p>
<figure><img
    class="my-0 rounded-md"
    loading="lazy"
    decoding="async"
    fetchpriority="auto"
    alt=""
    width="1919"
    height="987"
    src="https://www.modernsecurity.nl/microsoft-defender-for-identity-guide-v3-x/image-37_hu_f55a354c6657a090.webp"
   
   
    data-zoom-src="https://www.modernsecurity.nl/microsoft-defender-for-identity-guide-v3-x/image-37.webp"></figure><ol>
<li>Select the DCs you want to migrate. You can select all at once or work in batches.</li>
<li>Click <strong>Migrate</strong> in the toolbar.</li>
<li>In the confirmation dialog, verify the server names and click <strong>Migrate</strong>.</li>
</ol>
<figure><img
    class="my-0 rounded-md"
    loading="lazy"
    decoding="async"
    fetchpriority="auto"
    alt=""
    width="1919"
    height="987"
    src="https://www.modernsecurity.nl/microsoft-defender-for-identity-guide-v3-x/image-38_hu_61bcdb11af46c310.webp"
   
   
    data-zoom-src="https://www.modernsecurity.nl/microsoft-defender-for-identity-guide-v3-x/image-38.webp"></figure><figure><img
    class="my-0 rounded-md"
    loading="lazy"
    decoding="async"
    fetchpriority="auto"
    alt="MDI Defender for Identity"
    width="1919"
    height="999"
    src="https://www.modernsecurity.nl/microsoft-defender-for-identity-guide-v3-x/image-39_hu_6e7d9c0eb126ce7e.webp"
   
   
    data-zoom-src="https://www.modernsecurity.nl/microsoft-defender-for-identity-guide-v3-x/image-39.webp"></figure><p>Migration takes up to 20 minutes per batch. During this time:</p>
<ul>
<li>The v2.x sensor continues running and sending telemetry, no detection gap</li>
<li>The v3.x sensor is installed and initialized in the background</li>
<li>Switchover happens automatically once v3.x is ready</li>
<li>No reboot is required</li>
</ul>
<figure><img
    class="my-0 rounded-md"
    loading="lazy"
    decoding="async"
    fetchpriority="auto"
    alt=""
    width="1919"
    height="987"
    src="https://www.modernsecurity.nl/microsoft-defender-for-identity-guide-v3-x/image-40_hu_7fa13b58d670f283.webp"
   
   
    data-zoom-src="https://www.modernsecurity.nl/microsoft-defender-for-identity-guide-v3-x/image-40.webp"></figure><p>The Migration state column will progress: <strong>Ready for migration</strong> → <strong>Migrating</strong> → <strong>Already V3 sensor</strong>.</p>
<p>Once complete, confirm the sensors show Service status <strong>Running</strong>, Sensor status <strong>Up to date</strong>, and version <strong>3.0.7.419</strong> or later.</p>

<h3 class="relative group">Post-migration configuration
    <div id="post-migration-configuration" class="anchor"></div>
    
</h3>
<p>After migration completes, apply the following configuration steps:</p>
<p><strong>Remove gMSA</strong></p>
<p>The v3.x sensor uses the <strong>Local SYSTEM</strong> account for all Active Directory queries and response actions. There is no longer a need for a Group Managed Service Account.</p>
<blockquote><p><strong>Critical:</strong> If gMSA remains enabled after migration, response actions will stop working. This includes disabling compromised accounts, resetting passwords, and forcing password expiration, both automated and manual.</p>
</blockquote><p>Navigate to <strong>Settings &gt; Identities &gt; General &gt; Manage action accounts</strong>, select <strong>Automatically use the sensor’s local system account</strong>, and click <strong>Save</strong>.</p>
<figure><img
    class="my-0 rounded-md"
    loading="lazy"
    decoding="async"
    fetchpriority="auto"
    alt=""
    width="1919"
    height="999"
    src="https://www.modernsecurity.nl/microsoft-defender-for-identity-guide-v3-x/image-41_hu_a0bbb8d98c06f39a.webp"
   
   
    data-zoom-src="https://www.modernsecurity.nl/microsoft-defender-for-identity-guide-v3-x/image-41.webp"></figure><p>If you’re running a phased migration with some DCs still on v2.x, switch all sensors to local system accounts now. Mixing gMSA and local system in the same environment causes inconsistencies in response actions.</p>
<p><strong>Configure RPC auditing</strong></p>
<p>If the Unified Sensor RPC Audit asset rule doesn’t exist yet, create it following the steps in the <a href="https://www.modernsecurity.nl/microsoft-defender-for-identity-guide-v3-x/#configuring-rpc-auditing" >Configuring RPC auditing</a> section above. If the rule already exists, update the conditions to include the newly migrated DCs.</p>
<p><strong>Enable automatic Windows auditing</strong></p>
<p>Navigate to <strong>Settings &gt; Identities &gt; General &gt; Advanced features</strong> and enable the <strong>Automatic Windows auditing configuration (preview)</strong> toggle if <a href="https://www.modernsecurity.nl/microsoft-defender-for-identity-guide-v3-x/#enabling-automatic-windows-auditing" >not already active</a>. Existing auditing settings from the v2.x sensor are preserved during migration, but enabling automatic auditing will validate and correct any gaps.</p>

<h3 class="relative group">Cleaning up the v2.x sensor
    <div id="cleaning-up-the-v2-x-sensor" class="anchor"></div>
    
</h3>
<p>After confirming the v3.x sensor is healthy, remove the legacy components from each DC.</p>
<p><strong>Uninstall the v2.x sensor:</strong> Go to <strong>Settings &gt; Apps</strong> (or <strong>Add/Remove Programs</strong>) and uninstall <strong>“Azure Advanced Threat Protection Sensor”</strong>.</p>
<blockquote><p>This may require a <strong>server reboot</strong>. Plan it during a maintenance window. After uninstalling, the sensor entry is automatically removed from the portal. If it persists, delete it manually from <strong>Settings &gt; Identities &gt; Sensors</strong>.</p>
</blockquote><p><strong>Remove Npcap:</strong> The v2.x sensor installed Npcap for network packet capture. The v3.x sensor does not use it. Unless another application on the DC requires Npcap, uninstall it via <strong>Add/Remove Programs</strong>.</p>

<h2 class="relative group">Health alerts
    <div id="health-alerts" class="anchor"></div>
    
</h2>
<p>After deployment, keep an eye on <strong>Settings &gt; Identities &gt; Health issues</strong> for these two alerts:</p>

<div class="ms-table" role="region" aria-label="Table" tabindex="0">
  <table>
      <thead>
          <tr>
              <th>Alert</th>
              <th>Cause</th>
          </tr>
      </thead>
    <tbody>
        <tr>
            <td>Sensor v3.x RPC audit misconfigured</td>
            <td>The Unified Sensor RPC Audit asset rule is missing or not matching the DC</td>
        </tr>
        <tr>
            <td>Windows event auditing gaps</td>
            <td>Automatic auditing found issues it could not auto-correct, typically a conflicting GPO</td>
        </tr>
    </tbody>
  </table>
</div>

<h2 class="relative group">Frequently asked questions
    <div id="frequently-asked-questions" class="anchor"></div>
    
</h2>
<p><strong>Do I need to uninstall v2.x before activating v3.x?</strong><br>
For fresh deployments on a clean DC, yes: a DC cannot have both sensors simultaneously. For migrations, the portal wizard manages the transition automatically without a manual uninstall first.</p>
<p><strong>What are the known limitations in v3.x?</strong><br>
Known limitations of v3.x are: no VPN integration, no syslog notifications, and limited Azure ExpressRoute compatibility.</p>
<p><strong>Will I lose detection coverage during migration?</strong><br>
No. The v2.x sensor continues running and reporting until the v3.x sensor is fully initialized. There is no detection gap.</p>
<p><strong>My DC runs Windows Server 2016: can I use v3.x?</strong>
No. v3.x requires Windows Server 2019 or later with the March 2026 cumulative update. Either upgrade the OS or continue with the v2.x sensor.</p>
<p><strong>Is the March 2026 cumulative update a hard requirement?</strong><br>
Yes. Without it, activation or migration will fail. Apply it before starting.</p>
<p><strong>Can I still configure Windows auditing manually?</strong><br>
Yes. Automatic auditing is a preview feature and optional. Manual GPO-based configuration continues to work with v3.x.</p>
<p><strong>What about AD FS or AD CS servers?</strong><br>
For standalone servers not running a DC role, continue with v2.x: v3.x does not apply there. For DCs that also run AD FS, AD CS, or Entra Connect roles, v3.x support is rolling out as of March 2026. Note that the migration wizard does not support these DCs. They require a fresh v3.x deployment: uninstall v2.x manually, then activate v3.x from the Activation page.</p>
<p><strong>The RPC audit rule is applied, how do I verify it’s working?</strong>
Check <strong>Settings &gt; Identities &gt; Health issues</strong>. If the tag is correctly applied and the sensor is running, the “Sensor v3.x RPC audit misconfigured” alert will not appear. Allow up to 1 hour after rule creation.</p>

<h2 class="relative group">References
    <div id="references" class="anchor"></div>
    
</h2>
<p><a href="https://www.modernsecurity.nl/install-microsoft-defender-for-identity/" >Install Microsoft Defender for Identity (classic v2.x guide), modernsecurity.nl</a></p>
<p><a href="https://learn.microsoft.com/en-us/defender-for-identity/deploy/prerequisites-sensor-version-3"  target="_blank" rel="noreferrer">Defender for Identity sensor v3.x prerequisites: Microsoft Learn</a></p>
<p><a href="https://learn.microsoft.com/en-us/defender-for-identity/deploy/activate-sensor"  target="_blank" rel="noreferrer">Activate the Defender for Identity sensor v3.x: Microsoft Learn</a></p>
<p><a href="https://learn.microsoft.com/en-us/defender-for-identity/deploy/migrate-to-sensor-v3"  target="_blank" rel="noreferrer">Migrate from sensor v2.x to sensor v3.x: Microsoft Learn</a></p>
<p><a href="https://learn.microsoft.com/en-us/defender-for-identity/deploy/configure-windows-event-collection"  target="_blank" rel="noreferrer">Configure Windows event collection: Microsoft Learn</a></p>
<p><a href="https://learn.microsoft.com/en-us/defender-for-identity/whats-new"  target="_blank" rel="noreferrer">What’s new in Microsoft Defender for Identity: Microsoft Learn</a></p>

<h2 class="relative group">Conclusion
    <div id="conclusion" class="anchor"></div>
    
</h2>
<p>The Microsoft Defender for Identity sensor v3.x is a major improvement in how identity security is deployed and operated. By building on MDE infrastructure already present on your domain controllers, Microsoft has removed most of the friction that made MDI deployments time-consuming. No more installer packages, no gMSA accounts to manage, no manual audit GPOs, no Npcap to maintain.</p>
<p>For MSSP and enterprise teams managing MDI across multiple tenants, this simplification is significant. Activation is portal-based and takes minutes. Post-deployment configuration, RPC audit tagging and automatic Windows auditing, runs without touching Group Policy.</p>
<p>If you’re still running v2.x, the migration path is now stable and production-ready. Check the March 2026 cumulative update, confirm MDE is deployed and healthy on your DCs, and use the built-in migration wizard. Once migration completes, switch from gMSA to local system and apply the RPC audit tag. The v2.x sensor stays running until v3.x is ready, no maintenance window needed.</p>
]]></content:encoded><media:content url="https://www.modernsecurity.nl/microsoft-defender-for-identity-guide-v3-x/featured_hu_9cb310abc6e98c19.jpg" medium="image" type="image/jpeg" width="1200" height="884"/><enclosure url="https://www.modernsecurity.nl/microsoft-defender-for-identity-guide-v3-x/featured_hu_9cb310abc6e98c19.jpg" type="image/jpeg" length="64146"/></item><item><title>Defender XDR advanced hunting tables: ingest directly into Sentinel data lake</title><link>https://www.modernsecurity.nl/defender-xdr-advanced-hunting-data-lake/</link><guid isPermaLink="true">https://www.modernsecurity.nl/defender-xdr-advanced-hunting-data-lake/</guid><pubDate>Fri, 13 Mar 2026 21:43:35 +0100</pubDate><dc:creator>Farid Kalaidji</dc:creator><category>Microsoft Sentinel</category><description>Defender XDR advanced hunting tables now ingest directly into Sentinel data lake. No DCR, no analytics tier costs. Read how in my blogpost.</description><content:encoded><![CDATA[<p>If you’ve read my <a href="https://www.modernsecurity.nl/microsoft-sentinel-xdr-data-lake-guide/" >Microsoft Sentinel data lake implementation guide</a>, you know I covered a DCR-based workaround for storing Defender XDR Advanced Hunting data long-term without paying full analytics tier ingestion costs.</p>
<p>The approach: enable the XDR connector and use a Workspace Transformation DCR to redirect data from the original XDR table into that custom table. It worked: the analytics tier was skipped and data landed in the lake at a much lower cost.</p>
<p>But it was a workaround. You had to create and maintain custom tables, manually map schemas, and keep the transformation DCR in sync with any table changes. The XDR connector still needed to be active, and the whole setup was kind of fragile compared to a native solution.</p>
<p>This month Microsoft made that workaround obsolete 🙂</p>
<p>Lake-only ingestion for Defender XDR Advanced Hunting tables is now <strong>generally available</strong>. You can configure supported tables to stream directly into the Sentinel data lake from the Defender portal: no custom tables, no DCR, no schema mapping to maintain. The same outcome, natively supported.</p>
<p>This post covers what changed, which tables are supported, the key limitations to understand before switching, and a step-by-step configuration walkthrough the portal.</p>

<h2 class="relative group">The problem with the old approaches
    <div id="the-problem-with-the-old-approaches" class="anchor"></div>
    
</h2>
<p>Before this release, there were four ways to handle Defender XDR Advanced Hunting data in Sentinel:</p>

<div class="ms-table" role="region" aria-label="Table" tabindex="0">
  <table>
      <thead>
          <tr>
              <th>Approach</th>
              <th>How it worked</th>
              <th>Downside</th>
          </tr>
      </thead>
    <tbody>
        <tr>
            <td>XDR default (30 days)</td>
            <td>Data stays native in Defender XDR</td>
            <td>No long-term retention</td>
        </tr>
        <tr>
            <td>Extend to 90 days in analytics tier</td>
            <td>Included free in XDR license, data ingested into Log Analytics</td>
            <td>Still limited to 90 days, goes through analytics tier</td>
        </tr>
        <tr>
            <td>Analytics tier via XDR connector</td>
            <td>Set retention &gt; 30 days, data ingested into Log Analytics + mirrored to lake</td>
            <td>Full analytics ingestion cost</td>
        </tr>
        <tr>
            <td>DCR workaround (custom <code>_CL</code> table)</td>
            <td>Workspace Transformation DCR redirects XDR data to a custom lake-only table</td>
            <td>Analytics cost avoided, but complex: custom tables, schema mapping, DCR maintenance</td>
        </tr>
        <tr>
            <td><strong>Lake-only ingestion (GA Feb 2026)</strong></td>
            <td><strong>Data streams directly from XDR to Sentinel data lake</strong></td>
            <td><strong>No analytics ingestion cost, no DCR, no custom tables</strong></td>
        </tr>
    </tbody>
  </table>
</div>

<h2 class="relative group">What lake-only ingestion actually means
    <div id="what-lake-only-ingestion-actually-means" class="anchor"></div>
    
</h2>
<p>When you configure a table for lake-only ingestion, a copy of the data is streamed directly from Defender XDR into the Sentinel data lake tier. The data never touches the analytics tier in your Log Analytics workspace.</p>
<p>Defender XDR still retains the data in its own native tier for 30 days. Advanced Hunting in the Defender portal continues to work normally for that window. Custom detection rules and automated response rules are unaffected.</p>
<p>What changes is what happens beyond 30 days: instead of the data disappearing or requiring an expensive analytics pipeline, a copy flows continuously into the data lake for up to 12 years. There are important limitations to understand before switching. See the limitations section below.</p>

<h2 class="relative group">Supported tables at GA
    <div id="supported-tables-at-ga" class="anchor"></div>
    
</h2>
<p>Lake-only ingestion is supported for the following Defender XDR Advanced Hunting tables across three Defender workloads. Microsoft Defender for Identity (MDI) and (UEBA) behaviors support is not yet available but is on the roadmap.</p>
<p><strong>Defender for Endpoint (MDE)</strong></p>

<div class="ms-table" role="region" aria-label="Table" tabindex="0">
  <table>
      <thead>
          <tr>
              <th>Table</th>
              <th>What it contains</th>
          </tr>
      </thead>
    <tbody>
        <tr>
            <td>DeviceInfo</td>
            <td>Device inventory, OS details, domain membership, and sensor health per device</td>
        </tr>
        <tr>
            <td>DeviceNetworkInfo</td>
            <td>Network adapters, IP addresses, MAC addresses, and DNS configuration per device</td>
        </tr>
        <tr>
            <td>DeviceProcessEvents</td>
            <td>Process creation events including parent/child process relationships and command lines</td>
        </tr>
        <tr>
            <td>DeviceNetworkEvents</td>
            <td>Outbound and inbound network connections including remote IPs, ports, and protocols</td>
        </tr>
        <tr>
            <td>DeviceFileEvents</td>
            <td>File creation, modification, and deletion events across monitored endpoints</td>
        </tr>
        <tr>
            <td>DeviceRegistryEvents</td>
            <td>Registry key and value creation, modification, and deletion events</td>
        </tr>
        <tr>
            <td>DeviceLogonEvents</td>
            <td>Interactive and remote logon events including logon type and account details</td>
        </tr>
        <tr>
            <td>DeviceImageLoadEvents</td>
            <td>DLL and driver load events per process: high volume, rarely used for real-time detection</td>
        </tr>
        <tr>
            <td>DeviceEvents</td>
            <td>Broad category of additional endpoint events not covered by dedicated tables</td>
        </tr>
        <tr>
            <td>DeviceFileCertificateInfo</td>
            <td>Certificate information for signed files observed on endpoints</td>
        </tr>
    </tbody>
  </table>
</div>
<p><strong>Defender for Office 365 (MDO)</strong></p>

<div class="ms-table" role="region" aria-label="Table" tabindex="0">
  <table>
      <thead>
          <tr>
              <th>Table</th>
              <th>What it contains</th>
          </tr>
      </thead>
    <tbody>
        <tr>
            <td>EmailAttachmentInfo</td>
            <td>File attachments in emails including name, size, SHA256, and malware verdict</td>
        </tr>
        <tr>
            <td>EmailEvents</td>
            <td>Email delivery events including sender, recipient, subject, and delivery action</td>
        </tr>
        <tr>
            <td>EmailPostDeliveryEvents</td>
            <td>Actions taken on emails after delivery, such as manual remediation or ZAP</td>
        </tr>
        <tr>
            <td>EmailUrlInfo</td>
            <td>URLs found in emails and their associated threat verdicts</td>
        </tr>
        <tr>
            <td>UrlClickEvents</td>
            <td>User clicks on URLs in emails, Teams messages, and Office documents</td>
        </tr>
    </tbody>
  </table>
</div>
<p><strong>Defender for Cloud Apps (MDA)</strong></p>

<div class="ms-table" role="region" aria-label="Table" tabindex="0">
  <table>
      <thead>
          <tr>
              <th>Table</th>
              <th>What it contains</th>
          </tr>
      </thead>
    <tbody>
        <tr>
            <td>CloudAppEvents</td>
            <td>Activity events across connected SaaS applications including OAuth, file access, and admin actions</td>
        </tr>
    </tbody>
  </table>
</div>

<h2 class="relative group">Prerequisites
    <div id="prerequisites" class="anchor"></div>
    
</h2>
<p>Before configuring lake-only ingestion, the following must be in place:</p>

<div class="ms-table" role="region" aria-label="Table" tabindex="0">
  <table>
      <thead>
          <tr>
              <th>Requirement</th>
              <th>Details</th>
          </tr>
      </thead>
    <tbody>
        <tr>
            <td>Sentinel data lake enabled</td>
            <td>Must be provisioned in your tenant. See my <a href="https://www.modernsecurity.nl/microsoft-sentinel-xdr-data-lake-guide/" >implementation guide</a> if you haven’t set this up yet.</td>
        </tr>
        <tr>
            <td>Sentinel workspace connected to Defender portal</td>
            <td>The table management experience is only available in the unified Defender portal.</td>
        </tr>
        <tr>
            <td>Microsoft Sentinel contributor role or higher</td>
            <td>Required to modify table retention and tier settings.</td>
        </tr>
        <tr>
            <td>Defender portal only</td>
            <td>This configuration is not available in the Azure portal.</td>
        </tr>
    </tbody>
  </table>
</div>

<h2 class="relative group">How to configure lake-only ingestion (step by step)
    <div id="how-to-configure-lake-only-ingestion-step-by-step" class="anchor"></div>
    
</h2>
<p>The entire configuration lives in the Defender portal under table management. No DCR creation, no Azure Monitor Agent, no connector deployment in the Azure portal.</p>
<p><strong>Step 1: Open table management</strong></p>
<p>In the Defender portal, expand <strong>Microsoft Sentinel</strong> in the left navigation bar. Go to <strong>Configuration &gt; Tables</strong>.</p>
<figure><img
    class="my-0 rounded-md"
    loading="lazy"
    decoding="async"
    fetchpriority="auto"
    alt=""
    width="1918"
    height="999"
    src="https://www.modernsecurity.nl/defender-xdr-advanced-hunting-data-lake/image-10_hu_f7983a46a02d397b.webp"
   
   
    data-zoom-src="https://www.modernsecurity.nl/defender-xdr-advanced-hunting-data-lake/image-10.webp"></figure><p><strong>Step 2: Find the table you want to configure</strong></p>
<p>Use the search bar to filter by table name, for example <code>DeviceNetworkEvents</code>. The overview shows the current tier, analytics retention, and total retention for all tables in your workspace.</p>
<figure><img
    class="my-0 rounded-md"
    loading="lazy"
    decoding="async"
    fetchpriority="auto"
    alt=""
    width="1917"
    height="998"
    src="https://www.modernsecurity.nl/defender-xdr-advanced-hunting-data-lake/image-11_hu_735a5267efd82011.webp"
   
   
    data-zoom-src="https://www.modernsecurity.nl/defender-xdr-advanced-hunting-data-lake/image-11.webp"></figure><p><strong>Step 3: Open data retention settings</strong></p>
<p>Select the table to open the side panel, then click <strong>Data retention settings</strong>.</p>
<figure><img
    class="my-0 rounded-md"
    loading="lazy"
    decoding="async"
    fetchpriority="auto"
    alt=""
    width="1916"
    height="998"
    src="https://www.modernsecurity.nl/defender-xdr-advanced-hunting-data-lake/image-12_hu_d4254b8d2dc05ef5.webp"
   
   
    data-zoom-src="https://www.modernsecurity.nl/defender-xdr-advanced-hunting-data-lake/image-12.webp"></figure><p><strong>Step 4: Select data lake tier</strong></p>
<p>In the retention settings panel, select the <strong>Data lake tier</strong> option. You will notice that the analytics retention control is locked at 30 days. This is the included XDR license retention. Set the total retention period you want in the data lake (up to 12 years).</p>
<figure><img
    class="my-0 rounded-md"
    loading="lazy"
    decoding="async"
    fetchpriority="auto"
    alt=""
    width="1917"
    height="999"
    src="https://www.modernsecurity.nl/defender-xdr-advanced-hunting-data-lake/image-13_hu_34d52e1f6abd8292.webp"
   
   
    data-zoom-src="https://www.modernsecurity.nl/defender-xdr-advanced-hunting-data-lake/image-13.webp"></figure><p><strong>Step 5: Save</strong></p>
<p>Click save. New data will start flowing directly into the data lake. Expect a delay of 90–120 minutes before data appears in the lake.</p>
<blockquote><p><strong>Note:</strong> switching to data lake tier only applies to new incoming data. Existing data already in the analytics tier is not moved or back filled. If you previously had a table ingesting into the analytics tier and want to migrate, plan the transition window accordingly.</p>
</blockquote>
<h2 class="relative group">How to query data in lake-only tables
    <div id="how-to-query-data-in-lake-only-tables" class="anchor"></div>
    
</h2>
<p>Data in the data lake tier is not available through the regular Sentinel Logs blade or through Log Analytics workspace queries. You access it through the data lake exploration experience in the Defender portal.</p>
<p>Navigate to <strong>Microsoft Sentinel &gt; Data lake exploration &gt; KQL queries</strong> and run your KQL query against the table name as normal. Full KQL capabilities are supported including join and union operators.</p>
<figure><img
    class="my-0 rounded-md"
    loading="lazy"
    decoding="async"
    fetchpriority="auto"
    alt="Defender XDR Sentinel Data Lake Advanced Hunting"
    width="1918"
    height="998"
    src="https://www.modernsecurity.nl/defender-xdr-advanced-hunting-data-lake/image-14_hu_30b17ecb92500ccd.webp"
   
   
    data-zoom-src="https://www.modernsecurity.nl/defender-xdr-advanced-hunting-data-lake/image-14.webp"></figure><p>For scheduled or large-scale retrospective queries, use <strong>KQL jobs</strong>. These run against the full retention window in the lake and can promote results back into the analytics tier if needed for further investigation.</p>
<figure><img
    class="my-0 rounded-md"
    loading="lazy"
    decoding="async"
    fetchpriority="auto"
    alt=""
    width="1917"
    height="998"
    src="https://www.modernsecurity.nl/defender-xdr-advanced-hunting-data-lake/image-15_hu_3fcda90c9367e6f6.webp"
   
   
    data-zoom-src="https://www.modernsecurity.nl/defender-xdr-advanced-hunting-data-lake/image-15.webp"></figure>
<h2 class="relative group">Limitations to know before you switch
    <div id="limitations-to-know-before-you-switch" class="anchor"></div>
    
</h2>
<p>This is the part that matters operationally. The lake-only tier is not a full replacement for the analytics tier.</p>

<div class="ms-table" role="region" aria-label="Table" tabindex="0">
  <table>
      <thead>
          <tr>
              <th>Capability</th>
              <th>Analytics tier</th>
              <th>Data lake tier</th>
          </tr>
      </thead>
    <tbody>
        <tr>
            <td>Analytics rules</td>
            <td>✅</td>
            <td>❌</td>
        </tr>
        <tr>
            <td>Hunting queries (Sentinel)</td>
            <td>✅</td>
            <td>❌</td>
        </tr>
        <tr>
            <td>Workbooks</td>
            <td>✅</td>
            <td>❌</td>
        </tr>
        <tr>
            <td>Playbooks / automation</td>
            <td>✅</td>
            <td>❌</td>
        </tr>
        <tr>
            <td>Data export</td>
            <td>✅</td>
            <td>❌</td>
        </tr>
        <tr>
            <td>Real-time alerting</td>
            <td>✅</td>
            <td>❌</td>
        </tr>
        <tr>
            <td>KQL queries (data lake explorer)</td>
            <td>✅</td>
            <td>✅</td>
        </tr>
        <tr>
            <td>KQL jobs (scheduled)</td>
            <td>✅</td>
            <td>✅</td>
        </tr>
        <tr>
            <td>Jupyter notebooks</td>
            <td>✅</td>
            <td>✅</td>
        </tr>
        <tr>
            <td>Summary rules</td>
            <td>✅</td>
            <td>✅</td>
        </tr>
        <tr>
            <td>Search jobs</td>
            <td>✅</td>
            <td>✅</td>
        </tr>
        <tr>
            <td>Retention up to 12 years</td>
            <td>✅ (with data lake mirroring)</td>
            <td>✅</td>
        </tr>
    </tbody>
  </table>
</div>
<p>One important distinction: <strong>Defender XDR custom detection rules continue to work</strong> when you switch to lake-only, as they run against the native XDR tier in the Defender portal, not against Sentinel’s analytics tier.</p>
<p>What stops working is the <strong>Sentinel side</strong>: analytics rules, hunting queries, workbooks, and playbooks that reference that table. If any of those are in use, switching to lake-only will break them silently: the table simply won’t have data in the analytics tier anymore.</p>
<p>The practical guidance: if you run active <strong>Sentinel</strong> analytics rules or Sentinel hunting queries referencing a specific XDR table, keep that table in the analytics tier. If a table is primarily used for investigation, forensics, or retrospective hunting, and detections only live on the Defender XDR side, lake-only is the right choice.</p>
<p>Good candidates for lake-only: <code>DeviceFileCertificateInfo</code>, <code>DeviceImageLoadEvents</code>, <code>DeviceNetworkInfo</code>, <code>EmailUrlInfo</code>, <code>UrlClickEvents</code>.</p>
<p>Tables to evaluate carefully before switching: <code>DeviceProcessEvents</code>, <code>DeviceNetworkEvents</code>, <code>DeviceLogonEvents</code>. These are commonly used in custom Sentinel analytics rules.</p>

<h2 class="relative group">Cost considerations
    <div id="cost-considerations" class="anchor"></div>
    
</h2>
<p>The cost difference is significant for high-volume tables.</p>
<p>When data goes through the analytics tier first, you pay the analytics ingestion rate for every GB. When data goes directly to the data lake tier, you pay the data lake ingestion rate ($0.05/GB in East US) plus storage, but avoid analytics tier ingestion costs entirely. There is also a data processing charge ($0.10/GB) for data ingested directly to lake tier. This does not apply to data mirrored from the analytics tier.</p>
<p>For tables like <code>DeviceNetworkEvents</code> or <code>CloudAppEvents</code> that generate significant daily volume, this difference is substantial. If you were previously not ingesting these tables at all due to cost, lake-only ingestion makes long-term retention financially realistic.</p>
<blockquote><p><strong>Note:</strong> always verify current pricing in the <a href="https://azure.microsoft.com/pricing/details/microsoft-sentinel/"  target="_blank" rel="noreferrer">Microsoft Sentinel pricing page</a> as rates vary by region and are subject to change.</p>
</blockquote>
<h2 class="relative group">Migrating from the DCR workaround
    <div id="migrating-from-the-dcr-workaround" class="anchor"></div>
    
</h2>
<p>If you followed the approach in my <a href="https://www.modernsecurity.nl/microsoft-sentinel-xdr-data-lake-guide/" >older post</a> and are currently running the Workspace Transformation DCR workaround with custom <code>_CL</code> tables, here is how to migrate cleanly to the native solution.</p>
<p><strong>Before you switch:</strong></p>
<ul>
<li>Verify that no active Sentinel analytics rules or Sentinel hunting queries reference the custom <code>_CL</code> table you created. If they do, update them first to reference the new native table.</li>
<li>Note your current retention setting on the custom table. You will want to match this when configuring the native lake-only retention.</li>
<li>Accept that historical data in the custom <code>_CL</code> table stays there. Switching to native lake-only ingestion does not migrate or merge existing data. The two datasets will exist in parallel until the custom table’s retention expires.</li>
</ul>
<p><strong>Steps to migrate:</strong></p>
<ol>
<li>Configure the original XDR table (e.g. <code>DeviceProcessEvents</code>) for lake-only ingestion using the steps in this post.</li>
<li>Wait 90–120 minutes for data to start flowing into the native table in the data lake.</li>
<li>Verify data is arriving in the data lake by running a KQL query in <strong>Microsoft Sentinel &gt; Data lake exploration &gt; KQL queries</strong>.</li>
<li>Once confirmed, remove the Workspace Transformation DCR rule for that table, or update it to drop all rows to <code>source | take 0</code> if other tables share the same DCR and you are not ready to remove it entirely.</li>
<li>Optionally reduce the retention on the custom <code>_CL</code> table once the historical data is no longer needed.</li>
</ol>
<p>The main benefit beyond simplicity: the native table preserves the original schema exactly, including all columns. The DCR workaround required manual schema mapping and often dropped columns or required ongoing maintenance when Microsoft updated the source table structure.</p>

<h2 class="relative group">Sources
    <div id="sources" class="anchor"></div>
    
</h2>
<p><a href="https://learn.microsoft.com/en-us/azure/sentinel/datalake/sentinel-lake-overview"  target="_blank" rel="noreferrer">Microsoft Sentinel data lake overview: Microsoft Learn</a></p>
<p><a href="https://techcommunity.microsoft.com/blog/microsoftsentinelblog/data-lake-tier-ingestion-for-microsoft-defender-advanced-hunting-tables-is-now-g/4494206"  target="_blank" rel="noreferrer">Microsoft GA announcement: Tech Community, February 11, 2026</a></p>
<p><a href="https://learn.microsoft.com/en-us/azure/sentinel/manage-data-overview"  target="_blank" rel="noreferrer">Manage data tiers and retention in Microsoft Sentinel: Microsoft Learn</a></p>

<h2 class="relative group">Summary
    <div id="summary" class="anchor"></div>
    
</h2>
<p>Lake-only ingestion for Defender XDR Advanced Hunting tables removes the biggest practical barrier to long-term XDR data retention. You no longer need a DCR pipeline, you no longer pay analytics ingestion rates for data that’s primarily used for historical hunting, and you configure everything natively in the Defender portal in a few clicks.</p>
<p>If you have Sentinel data lake enabled, this is one of the first things worth reviewing. Go through the supported table list, identify which tables you don’t have active Sentinel analytics rules on, and switch those to lake-only. Start with the high-volume candidates and work from there.</p>
<p>For the full Sentinel data lake setup and background, check out my <a href="https://www.modernsecurity.nl/microsoft-sentinel-xdr-data-lake-guide/" >implementation guide</a>.</p>
]]></content:encoded><media:content url="https://www.modernsecurity.nl/defender-xdr-advanced-hunting-data-lake/featured_hu_7f18905a4823e625.jpg" medium="image" type="image/jpeg" width="1200" height="800"/><enclosure url="https://www.modernsecurity.nl/defender-xdr-advanced-hunting-data-lake/featured_hu_7f18905a4823e625.jpg" type="image/jpeg" length="168209"/></item><item><title>Manage your live response library directly in Microsoft Defender</title><link>https://www.modernsecurity.nl/live-response-library-in-microsoft-defender/</link><guid isPermaLink="true">https://www.modernsecurity.nl/live-response-library-in-microsoft-defender/</guid><pubDate>Fri, 20 Feb 2026 21:20:15 +0100</pubDate><dc:creator>Farid Kalaidji</dc:creator><category>Microsoft Defender XDR</category><category>Microsoft Defender for Endpoint</category><description>Microsoft Defender for Endpoint now includes centralized library management for live response. Learn what it does, how to set it up.</description><content:encoded><![CDATA[<p>If you’ve been using live response in Microsoft Defender for Endpoint for a while, you’ve probably felt the friction. A critical incident comes in, you initiate a session, and then the race begins: digging through folders, shared drives, and old Teams chats trying to locate the right PowerShell script before the attacker moves laterally to the next system.</p>
<p>In DFIR scenarios where every minute counts, that lack of a centralized, ready-to-go script library is a real operational problem. You’re context-switching between the investigation and hunting for tools that should already be at your fingertips. That pain point is now addressed. Microsoft introduced <strong>library management for live response</strong>, which entered public preview in February 2026 and reached general availability in March 2026.</p>
<p>If you’re new to live response itself, I covered the foundations, including selective isolation and how it enables safe forensics during containment, in my earlier post: <a href="https://www.modernsecurity.nl/mde-selective-isolation-velociraptor/" >Selective Isolation in Defender for Endpoint – Combining tools like Velociraptor for DFIR</a>. This post builds on that and focuses specifically on the new library management experience.</p>

<h2 class="relative group">What is live response library management?
    <div id="what-is-live-response-library-management" class="anchor"></div>
    
</h2>
<p>Library management is a dedicated section in the Microsoft Defender portal that provides a <strong>centralized, tenant-level repository</strong> for all scripts and files used during live response sessions. Before this feature existed, the only way to add a script to the library was from within an active session, not ideal during an escalating incident.</p>
<p>The problem it solves is a familiar one: scripts scattered across personal laptops, shared drives, and GitHub repos with no consistent versioning, no team-wide visibility, and no audit trail. Library management consolidates all of that into a single managed location inside Defender itself.</p>

<h2 class="relative group">Prerequisites and licensing
    <div id="prerequisites-and-licensing" class="anchor"></div>
    
</h2>

<div class="ms-table" role="region" aria-label="Table" tabindex="0">
  <table>
      <thead>
          <tr>
              <th>Requirement</th>
              <th>Details</th>
          </tr>
      </thead>
    <tbody>
        <tr>
            <td><strong>MDE license</strong></td>
            <td>Microsoft Defender for Endpoint Plan 1, Plan 2, or Microsoft Defender for Business</td>
        </tr>
        <tr>
            <td><strong>Copilot analysis</strong></td>
            <td>Requires a separate Microsoft Security Copilot license</td>
        </tr>
        <tr>
            <td><strong>RBAC – basic live response</strong></td>
            <td>Initiate sessions, download files, and perform read-only actions</td>
        </tr>
        <tr>
            <td><strong>RBAC – advanced live response</strong></td>
            <td>Upload files, run scripts, and perform advanced actions, required for modifying the library</td>
        </tr>
    </tbody>
  </table>
</div>

<h2 class="relative group">What you can do with it
    <div id="what-you-can-do-with-it" class="anchor"></div>
    
</h2>
<p>All operations are available <strong>outside of an active live response session</strong>, which is the key improvement over the previous experience:</p>
<ul>
<li><strong>Upload</strong> PowerShell scripts, batch files, and other response utilities in advance</li>
<li><strong>View</strong> script contents directly in the Defender portal without switching to an external editor</li>
<li><strong>Download</strong> files back to your workstation when needed</li>
<li><strong>Delete</strong> outdated or redundant scripts in a single click</li>
<li><strong>Analyze</strong> scripts using Microsoft Security Copilot (license required)</li>
</ul>
<p>The Copilot analysis is worth highlighting. Select a script and choose <strong>Analyze</strong>, and Security Copilot generates a natural-language summary covering what the script does, the methods it uses, any network calls or privilege operations, and potential execution risks. This is especially useful when analysts are working with inherited toolsets. Without a Copilot license, you can still view script contents. You just won’t get the automated analysis.</p>

<h2 class="relative group">How to set it up
    <div id="how-to-set-it-up" class="anchor"></div>
    
</h2>
<p>Navigate to the library management page via <strong>Settings → Endpoints → Library management</strong> in the <a href="https://security.microsoft.com"  target="_blank" rel="noreferrer">Microsoft Defender portal</a>. You can also reach it directly from within an active live response session.</p>
<figure><img
    class="my-0 rounded-md"
    loading="lazy"
    decoding="async"
    fetchpriority="auto"
    alt=""
    width="1897"
    height="988"
    src="https://www.modernsecurity.nl/live-response-library-in-microsoft-defender/image-6_hu_b3d207442ada19c0.webp"
   
   
    data-zoom-src="https://www.modernsecurity.nl/live-response-library-in-microsoft-defender/image-6.webp"></figure><p>To upload a script:</p>
<ol>
<li>Select <strong>Upload</strong> from the top menu</li>
<li>In the upload panel, select <strong>Upload file to library</strong> and choose your file</li>
<li>Add a <strong>file description</strong>. This is the only documentation other analysts will see, so make it count</li>
<li>If you’re replacing an existing script, check <strong>Overwrite file</strong></li>
<li>Optionally add a <strong>parameters description</strong> if the script accepts arguments</li>
<li>Select <strong>Submit</strong> to complete the upload</li>
</ol>
<figure><img
    class="my-0 rounded-md"
    loading="lazy"
    decoding="async"
    fetchpriority="auto"
    alt="live response library directly in Microsoft Defender"
    width="1895"
    height="988"
    src="https://www.modernsecurity.nl/live-response-library-in-microsoft-defender/image-7_hu_f037255eecdfcc59.webp"
   
   
    data-zoom-src="https://www.modernsecurity.nl/live-response-library-in-microsoft-defender/image-7.webp"></figure><figure><img
    class="my-0 rounded-md"
    loading="lazy"
    decoding="async"
    fetchpriority="auto"
    alt=""
    width="1895"
    height="987"
    src="https://www.modernsecurity.nl/live-response-library-in-microsoft-defender/image-8_hu_202fbb4ea2c6a346.webp"
   
   
    data-zoom-src="https://www.modernsecurity.nl/live-response-library-in-microsoft-defender/image-8.webp"></figure><p>The file is immediately available to all authorized analysts across the tenant. There are no per-device or per-device-group restrictions at the library level.</p>

<h2 class="relative group">Audit logging
    <div id="audit-logging" class="anchor"></div>
    
</h2>
<p>All library management actions are tracked in the Microsoft Defender audit log: uploads, downloads, deletions, and file listings, each recorded with user context and a timestamp. To view these logs, go to <strong>Settings → Audit</strong> and filter using the following criteria:</p>
<ul>
<li><strong>Activities – friendly names</strong>: Ran live response session</li>
<li><strong>Record types</strong>: MSDEResponseActions For managed service environments where multiple analysts share access to the same tenant library, this gives you full visibility into who changed what and when.</li>
</ul>
<figure><img
    class="my-0 rounded-md"
    loading="lazy"
    decoding="async"
    fetchpriority="auto"
    alt=""
    width="1895"
    height="987"
    src="https://www.modernsecurity.nl/live-response-library-in-microsoft-defender/image-9_hu_8500f473db31176.webp"
   
   
    data-zoom-src="https://www.modernsecurity.nl/live-response-library-in-microsoft-defender/image-9.webp"></figure>
<h2 class="relative group">What this means for SOC teams
    <div id="what-this-means-for-soc-teams" class="anchor"></div>
    
</h2>
<p>Library management shifts the mindset from reactive to prepared. Instead of scrambling mid-incident, teams can now pre-stage a standard toolkit before any alert fires, triage scripts, forensic collectors, persistence checkers, and keep it versioned through the description field. New analysts can explore the team’s standard toolset through the portal, with Copilot to explain anything unfamiliar.</p>
<p>In an MSP or MSSP context, this has immediate operational value. Inconsistent script collections across customer tenants are the norm when you’re managing 50+ environments. A centralized, auditable library per tenant brings consistency that previously required custom automation around the Live Response API.</p>

<h2 class="relative group">A word on security
    <div id="a-word-on-security" class="anchor"></div>
    
</h2>
<p>Live response runs in a privileged context on endpoints. A centralized script library increases the blast radius if an account is compromised or if scripts aren’t reviewed before upload. A few things worth enforcing: separate upload and execute permissions in RBAC so not every analyst who can run scripts can also add new ones, restrict live response on tier-0 assets unless a formal escalation process is in place, and don’t treat Copilot analysis as a security gate. It provides context, not sandboxing. Test scripts in a controlled environment before they land in a shared tenant library.</p>

<h2 class="relative group">Resources
    <div id="resources" class="anchor"></div>
    
</h2>
<p><a href="https://www.modernsecurity.nl/mde-selective-isolation-velociraptor/" >Selective Isolation in Defender for Endpoint – modernsecurity.nl</a></p>
<p><a href="https://learn.microsoft.com/en-us/defender-endpoint/configure-libraries-live-response"  target="_blank" rel="noreferrer">Manage the live response file library in Microsoft Defender for Endpoint – Microsoft Learn</a></p>
<p><a href="https://learn.microsoft.com/en-us/defender-endpoint/live-response-command-examples"  target="_blank" rel="noreferrer">Live response command examples – Microsoft Learn</a></p>
<p><a href="https://learn.microsoft.com/en-us/defender-endpoint/whats-new-in-microsoft-defender-endpoint"  target="_blank" rel="noreferrer">What’s new in Microsoft Defender for Endpoint – Microsoft Learn</a></p>
<p><a href="https://techcommunity.microsoft.com/blog/microsoftthreatprotectionblog/monthly-news---march-2026/4498458"  target="_blank" rel="noreferrer">Monthly news – March 2026 (February updates) – Microsoft Tech Community</a></p>

<h2 class="relative group">Summary
    <div id="summary" class="anchor"></div>
    
</h2>
<p>Library management for live response is one of those features that quietly makes a significant operational difference. It removes friction from incident response preparation, brings consistency across analyst teams, and adds an audit trail that managed service providers have needed for a while. The feature entered public preview in February 2026 and reached general availability in March 2026.</p>
]]></content:encoded><media:content url="https://www.modernsecurity.nl/live-response-library-in-microsoft-defender/featured_hu_920ac5766cc7bbfc.jpg" medium="image" type="image/jpeg" width="1200" height="625"/><enclosure url="https://www.modernsecurity.nl/live-response-library-in-microsoft-defender/featured_hu_920ac5766cc7bbfc.jpg" type="image/jpeg" length="69292"/></item><item><title>UEBA behaviors layer in Microsoft Sentinel: from raw logs to behavioral intelligence</title><link>https://www.modernsecurity.nl/ueba-behaviors-layer-in-microsoft-sentinel/</link><guid isPermaLink="true">https://www.modernsecurity.nl/ueba-behaviors-layer-in-microsoft-sentinel/</guid><pubDate>Sun, 11 Jan 2026 20:41:02 +0100</pubDate><dc:creator>Farid Kalaidji</dc:creator><category>Microsoft Sentinel</category><category>Microsoft Defender XDR</category><description>Learn about the UEBA behaviors layer in Microsoft Sentinel. What it does, how to enable it, and use it for investigation and threat hunting.</description><content:encoded><![CDATA[<p>Every SOC analyst knows the feeling. An alert fires. You open the incident. And then the real work begins: correlating AWS CloudTrail API calls, translating firewall log schemas, joining tables across data sources you barely recognize, all to answer one question: <em>what actually happened?</em></p>
<p>Microsoft’s new <strong>UEBA behaviors layer</strong> in <a href="https://www.modernsecurity.nl/microsoft-sentinel/" >Microsoft Sentinel</a> changes that. Instead of forcing analysts to reconstruct the story from raw telemetry, it produces it for them: normalized, enriched, MITRE-mapped behavioral summaries that explain “who did what to whom” in plain language. It went <strong>generally available</strong> in early 2026, and if you’re running Sentinel with non-Microsoft data sources like AWS CloudTrail, Palo Alto, or GCP, this is something you should enable today.</p>
<p>In this post I’ll walk you through what the behaviors layer is, how it works under the hood, how to enable it, and what you can do with it: including practical KQL queries for investigation, threat hunting, and detection.</p>

<h2 class="relative group">What is the UEBA behaviors layer?
    <div id="what-is-the-ueba-behaviors-layer" class="anchor"></div>
    
</h2>
<p>Before this feature existed, Microsoft Sentinel’s UEBA already provided <strong>anomaly detection</strong>, flagging when a user deviated from their behavioral baseline. That’s valuable, but anomalies are event-level: a single unusual API call, a first-time login from a new location.</p>
<p>The behaviors layer sits in a different spot in the stack. Rather than flagging individual events, it <strong>aggregates and sequences related events across a time window</strong> into a single, structured behavior record. Think of it as the difference between:</p>
<blockquote><p>“User performed <code>s3:GetObject</code> 847 times between 14:00–15:00″</p>
</blockquote><p>versus raw CloudTrail telling you nothing without a KQL query to make sense of it.</p>
<p>There are two types of behaviors:</p>
<ul>
<li><strong>Aggregation behaviors</strong>: volume-based patterns. Example: “User accessed 50+ AWS resources in 1 hour.” Useful for spotting data exfiltration attempts or compromised accounts doing bulk operations.</li>
<li><strong>Sequencing behaviors</strong>: multi-step chains. Example: “Access key created → used from new IP → privileged API calls made.” These surface the kind of attack progressions that are invisible when you look at individual events.</li>
</ul>
<p>Every behavior record includes:</p>
<ul>
<li>A plain-language title and description</li>
<li>MITRE ATT&amp;CK tactic and technique mapping</li>
<li>Entity roles (who was the actor, what was the target)</li>
<li>References back to the raw log events that contributed to it</li>
</ul>
<figure><img
    class="my-0 rounded-md"
    loading="lazy"
    decoding="async"
    fetchpriority="auto"
    alt=""
    width="1243"
    height="726"
    src="https://www.modernsecurity.nl/ueba-behaviors-layer-in-microsoft-sentinel/behavior-analytics-top-down_hu_fbcfda88ea71f4b9.webp"
   
   
    data-zoom-src="https://www.modernsecurity.nl/ueba-behaviors-layer-in-microsoft-sentinel/behavior-analytics-top-down.webp"></figure><p>Crucially, <strong>behaviors are not alerts</strong>. They don’t fire because something is malicious. They fire because a pattern was detected. That distinction matters: behaviors give you neutral, factual context that you then interpret in light of other signals.</p>

<h2 class="relative group">How it’s built: generative AI under the hood
    <div id="how-its-built-generative-ai-under-the-hood" class="anchor"></div>
    
</h2>
<p>The behaviors layer uses <strong>generative AI</strong> to create and scale the behavior logic. Microsoft uses AI to develop the detection patterns, map entities, perform MITRE mapping, and generate the natural-language explanations: all with quality guardrails to keep outputs consistent and auditable.</p>
<p>This is worth understanding because it explains the current scope: the initial release focuses on <strong>non-Microsoft data sources</strong> that traditionally lack easy behavioral context in Sentinel. Microsoft’s own data sources (Entra ID, Defender for Endpoint, etc.) already have rich signal: the gap has always been the third-party telemetry.</p>

<h2 class="relative group">Supported data sources
    <div id="supported-data-sources" class="anchor"></div>
    
</h2>
<p>At GA, the behaviors layer covers:</p>

<div class="ms-table" role="region" aria-label="Table" tabindex="0">
  <table>
      <thead>
          <tr>
              <th>Data source</th>
              <th>Details</th>
          </tr>
      </thead>
    <tbody>
        <tr>
            <td><strong>CommonSecurityLog</strong></td>
            <td>CyberArk Vault, Palo Alto Threats (vendor-specific: other vendors in CommonSecurityLog won’t generate behaviors)</td>
        </tr>
        <tr>
            <td><strong>AWSCloudTrail</strong></td>
            <td>EC2, IAM, S3, EKS, Secrets Manager and more</td>
        </tr>
        <tr>
            <td><strong>GCPAuditLogs</strong></td>
            <td>General GCP management activity</td>
        </tr>
    </tbody>
  </table>
</div>
<p>Important: coverage is expanding over time, but you need to verify your specific vendor logs are supported before expecting results. If your CommonSecurityLog connector ingests data from unsupported vendors, the behaviors layer will simply not generate records for that data. It won’t error, it’ll just be silent.</p>

<h2 class="relative group">How to enable the UEBA behaviors layer
    <div id="how-to-enable-the-ueba-behaviors-layer" class="anchor"></div>
    
</h2>

<h3 class="relative group">Prerequisites
    <div id="prerequisites" class="anchor"></div>
    
</h3>
<ul>
<li>Microsoft Sentinel workspace <strong>onboarded to the Defender portal</strong>: the Azure portal path does not support the behaviors layer</li>
<li>One or more supported data sources ingested into the <strong>Analytics tier</strong> (not Auxiliary or Summary Rules tier, behaviors only process Analytics-tier data)</li>
<li>Currently supported for <strong>a single workspace per tenant</strong>, so choose the one with the most relevant ingestion</li>
</ul>

<h3 class="relative group">Enabling the behaviors layer
    <div id="enabling-the-behaviors-layer" class="anchor"></div>
    
</h3>
<ol>
<li>In the <strong>Defender portal</strong>, go to <strong>Settings → Microsoft Sentinel → SIEM workspaces</strong></li>
<li>Select your workspace</li>
<li>Go to <strong>Entity behavior analytics → Configure UEBA</strong></li>
<li>Navigate to the <strong>Behaviors layer</strong> tab. This is separate from the main UEBA toggle</li>
<li>Enable the feature and connect your supported data sources</li>
</ol>
<figure><img
    class="my-0 rounded-md"
    loading="lazy"
    decoding="async"
    fetchpriority="auto"
    alt=""
    width="1897"
    height="988"
    src="https://www.modernsecurity.nl/ueba-behaviors-layer-in-microsoft-sentinel/image-5_hu_e319266f472689b9.webp"
   
   
    data-zoom-src="https://www.modernsecurity.nl/ueba-behaviors-layer-in-microsoft-sentinel/image-5.webp"></figure><p>Note that data sources here are <strong>configured independently</strong> from regular UEBA. Even if you already have AWSCloudTrail enabled for UEBA anomalies, you need to explicitly enable it for the behaviors layer too.</p>
<p>Once enabled, two new tables appear in your Log Analytics workspace:</p>
<ul>
<li><code>SentinelBehaviorInfo</code>: the behavior records (title, description, MITRE mapping, time window)</li>
<li><code>SentinelBehaviorEntities</code>: the entities involved in each behavior (account, device, IP, etc.)</li>
</ul>
<p>In <strong>Advanced Hunting</strong>, these tables appear without the “Sentinel” prefix, so <code>BehaviorInfo</code> and <code>BehaviorEntities</code>. If you already have Defender XDR behaviors enabled (e.g. from Defender for Cloud Apps), these queries will return results from both XDR and UEBA behaviors combined.</p>

<h2 class="relative group">Querying behaviors: practical KQL
    <div id="querying-behaviors-practical-kql" class="anchor"></div>
    
</h2>

<h3 class="relative group">Investigating an entity during an incident
    <div id="investigating-an-entity-during-an-incident" class="anchor"></div>
    
</h3>
<p>When you’re triaging an incident and want to understand what a specific account was doing:</p>
<div class="highlight-wrapper"><div class="highlight"><div class="ms-code-label">KQL</div><pre tabindex="0" class="chroma"><code class="language-kql" data-lang="kql"><span class="k">let</span> targetAccount = <span class="s">&#34;user@yourdomain.com&#34;</span>;
<span class="k">let</span> lookback = 24h;
<span class="k">let</span> behaviorIds =
    BehaviorEntities
    <span class="o">|</span> <span class="k">where</span> TimeGenerated <span class="o">&gt;</span> <span class="nf">ago</span>(lookback)
    <span class="o">|</span> <span class="k">where</span> AccountUpn <span class="o">==</span> targetAccount
    <span class="o">|</span> <span class="k">project</span> BehaviorId;
BehaviorInfo
<span class="o">|</span> <span class="k">where</span> TimeGenerated <span class="o">&gt;</span> <span class="nf">ago</span>(lookback)
<span class="o">|</span> <span class="k">join</span> <span class="k">kind</span>=<span class="k">inner</span> (behaviorIds) <span class="k">on</span> BehaviorId
<span class="o">|</span> <span class="k">project</span> TimeGenerated, Title, Description, AttackTechniques, Categories, BehaviorId
<span class="o">|</span> <span class="k">order by</span> TimeGenerated <span class="k">desc</span></code></pre></div>
</div>
<p>This gives you a timeline of what that account did: at the behavior level, not the raw event level. Instead of reviewing hundreds of API calls, you see 3–5 meaningful summaries.</p>

<h3 class="relative group">Threat hunting across the MITRE ATT&amp;CK chain
    <div id="threat-hunting-across-the-mitre-attck-chain" class="anchor"></div>
    
</h3>
<p>Looking for entities that hit multiple tactics within a short window, a classic indicator of an active attack in progress:</p>
<div class="highlight-wrapper"><div class="highlight"><div class="ms-code-label">KQL</div><pre tabindex="0" class="chroma"><code class="language-kql" data-lang="kql"><span class="k">let</span> lookback = 12h;
<span class="k">let</span> tacticFilter = <span class="nf">dynamic</span>([<span class="s">&#34;Persistence&#34;</span>, <span class="s">&#34;Discovery&#34;</span>, <span class="s">&#34;PrivilegeEscalation&#34;</span>]);
<span class="k">let</span> behaviorInfo =
    BehaviorInfo
    <span class="o">|</span> <span class="k">where</span> TimeGenerated <span class="o">&gt;</span> <span class="nf">ago</span>(lookback)
    <span class="o">|</span> <span class="k">where</span> Categories <span class="k">has_any</span> (tacticFilter)
    <span class="o">|</span> <span class="k">project</span> BehaviorId, Categories, Title, TimeGenerated;
BehaviorEntities
<span class="o">|</span> <span class="k">where</span> TimeGenerated <span class="o">&gt;</span> <span class="nf">ago</span>(lookback)
<span class="o">|</span> <span class="k">extend</span> EntityName = <span class="nf">coalesce</span>(AccountUpn, DeviceName, CloudResourceId)
<span class="o">|</span> <span class="k">join</span> <span class="k">kind</span>=<span class="k">inner</span> (behaviorInfo) <span class="k">on</span> BehaviorId
<span class="o">|</span> <span class="k">summarize</span>
    TacticsCovered = <span class="nf">make_set</span>(Categories),
    BehaviorTitles = <span class="nf">make_set</span>(Title),
    TotalBehaviors = <span class="k">count</span>()
    <span class="k">by</span> EntityName
<span class="o">|</span> <span class="k">where</span> <span class="nf">array_length</span>(TacticsCovered) <span class="o">&gt;=</span> 2
<span class="o">|</span> <span class="k">order by</span> TotalBehaviors <span class="k">desc</span></code></pre></div>
</div>
<p>Entities showing up across multiple MITRE tactics in a 12-hour window are worth a closer look.</p>

<h3 class="relative group">Finding the rarest behaviors
    <div id="finding-the-rarest-behaviors" class="anchor"></div>
    
</h3>
<p>Rare behaviors are a natural hunting signal: if something only happened once or twice in your environment, it’s worth understanding why:</p>
<div class="highlight-wrapper"><div class="highlight"><div class="ms-code-label">KQL</div><pre tabindex="0" class="chroma"><code class="language-kql" data-lang="kql">BehaviorInfo
<span class="o">|</span> <span class="k">where</span> TimeGenerated <span class="o">&gt;</span> <span class="nf">ago</span>(7d)
<span class="o">|</span> <span class="k">summarize</span>
    Occurrences = <span class="nf">dcount</span>(BehaviorId),
    FirstSeen = <span class="nf">min</span>(TimeGenerated),
    LastSeen = <span class="nf">max</span>(TimeGenerated)
    <span class="k">by</span> Title, AttackTechniques
<span class="o">|</span> <span class="k">order by</span> Occurrences <span class="k">asc</span>
<span class="o">|</span> <span class="k">take</span> 20</code></pre></div>
</div>
<p>This gives you a ranked list of the rarest behavior types seen in the last 7 days, a good starting point for building analytics rules on top of behaviors rather than raw logs.</p>

<h3 class="relative group">Filtering by MITRE technique
    <div id="filtering-by-mitre-technique" class="anchor"></div>
    
</h3>
<p>If you want to scope an investigation to a specific technique: say you’ve had a threat intel tip about T1552 (Unsecured Credentials):</p>
<div class="highlight-wrapper"><div class="highlight"><div class="ms-code-label">KQL</div><pre tabindex="0" class="chroma"><code class="language-kql" data-lang="kql"><span class="k">let</span> targetTechniques = <span class="nf">dynamic</span>([<span class="s">&#34;T1552&#34;</span>, <span class="s">&#34;T1078&#34;</span>]);
<span class="k">let</span> behaviorInfoFiltered =
    BehaviorInfo
    <span class="o">|</span> <span class="k">where</span> TimeGenerated <span class="o">&gt;</span> <span class="nf">ago</span>(48h)
    <span class="o">|</span> <span class="k">where</span> AttackTechniques <span class="k">has_any</span> (targetTechniques)
    <span class="o">|</span> <span class="k">project</span> BehaviorId, AttackTechniques, Title;
BehaviorEntities
<span class="o">|</span> <span class="k">where</span> TimeGenerated <span class="o">&gt;</span> <span class="nf">ago</span>(48h)
<span class="o">|</span> <span class="k">join</span> <span class="k">kind</span>=<span class="k">inner</span> (behaviorInfoFiltered) <span class="k">on</span> BehaviorId
<span class="o">|</span> <span class="k">project</span> TimeGenerated, AccountUpn, CloudResourceId, Title, AttackTechniques
<span class="o">|</span> <span class="k">order by</span> TimeGenerated <span class="k">desc</span></code></pre></div>
</div>

<h2 class="relative group">The UEBA behaviors workbook
    <div id="the-ueba-behaviors-workbook" class="anchor"></div>
    
</h2>
<p>Microsoft also released the <strong>UEBA behaviors workbook</strong> as part of the <strong>UEBA essentials solution</strong> in the Content Hub. It provides three pre-built tabs:</p>
<ul>
<li><strong>Overview</strong>: high-level metrics, MITRE coverage heatmaps, behavior type distribution trends. Good for SOC managers and daily pulse-checks.</li>
<li><strong>Investigation</strong>: entity-centric timeline view, built for incident responders who need to drill into a specific user or resource.</li>
<li><strong>Hunting</strong>: anomaly detection overlaid with behaviors, designed for threat hunters doing proactive discovery.</li>
</ul>
<p>To deploy it: <strong>Microsoft Sentinel → Content Hub → search “UEBA essentials” → Save</strong>. The workbook is one of the content items in that solution alongside prebuilt hunting queries.</p>
<figure><img
    class="my-0 rounded-md"
    loading="lazy"
    decoding="async"
    fetchpriority="auto"
    alt=""
    width="2000"
    height="1139"
    src="https://www.modernsecurity.nl/ueba-behaviors-layer-in-microsoft-sentinel/clipboard-image-1-1770318590525_hu_7eb6d9a52b15c84a.webp"
   
   
    data-zoom-src="https://www.modernsecurity.nl/ueba-behaviors-layer-in-microsoft-sentinel/clipboard-image-1-1770318590525.webp"></figure>
<h2 class="relative group">What to watch out for
    <div id="what-to-watch-out-for" class="anchor"></div>
    
</h2>
<p><strong>Cost</strong></p>
<p>Behaviors are stored as Log Analytics records and billed at standard Sentinel ingestion rates. The volume depends entirely on how much raw telemetry you’re ingesting from the supported sources. Before enabling in production, check your current CloudTrail or GCPAuditLogs ingestion volume and estimate how many behavior records that might generate. High-volume sources like active AWS environments can add up quickly.</p>
<p><strong>Single workspace limitation</strong></p>
<p>At GA, this only works on one workspace per tenant. If you have a multi-workspace architecture, choose the workspace that ingests the most relevant non-Microsoft data.</p>
<p><strong>Analytics tier requirement</strong></p>
<p>Behaviors only process data in the Analytics tier. If you’ve moved AWS or GCP logs to the Auxiliary tier for cost reasons, those logs won’t feed the behaviors layer.</p>
<p><strong>Supported vendors only</strong></p>
<p>CommonSecurityLog is a catch-all table. Just because you have a CEF connector sending data doesn’t mean behaviors will fire. Only CyberArk Vault and Palo Alto Threats are supported at this time for CommonSecurityLog.</p>

<h2 class="relative group">Why this matters for MSSPs and MDR providers
    <div id="why-this-matters-for-mssps-and-mdr-providers" class="anchor"></div>
    
</h2>
<p>Running an MSSP or MDR service across a multi-tenant environment, the behaviors layer is particularly interesting because it abstracts away log schema complexity. Your analysts don’t need to memorize every AWS service API or Palo Alto log field: the behavior record gives them the story in plain language, with MITRE context already attached.</p>
<p>For detection engineering, it raises the abstraction level for rule authoring. Instead of writing analytics rules that join multiple raw tables and handle schema variations, you can build on top of <code>BehaviorInfo</code> as a normalized, enriched foundation. That means faster rule development and rules that are easier to explain to clients.</p>

<h2 class="relative group">Resources
    <div id="resources" class="anchor"></div>
    
</h2>
<p><strong>Microsoft documentation</strong></p>
<ul>
<li><a href="https://learn.microsoft.com/en-us/azure/sentinel/entity-behaviors-layer"  target="_blank" rel="noreferrer">Translate raw security logs to behavioral insights using UEBA behaviors in Microsoft Sentinel</a></li>
<li><a href="https://learn.microsoft.com/en-us/azure/sentinel/identify-threats-with-entity-behavior-analytics"  target="_blank" rel="noreferrer">Advanced threat detection with UEBA in Microsoft Sentinel</a></li>
<li><a href="https://learn.microsoft.com/en-us/azure/sentinel/enable-entity-behavior-analytics"  target="_blank" rel="noreferrer">Enable entity behavior analytics</a></li>
<li><a href="https://learn.microsoft.com/en-us/azure/sentinel/ueba-reference"  target="_blank" rel="noreferrer">UEBA reference, tables and fields</a></li>
</ul>
<p><strong>Tech Community blogs</strong></p>
<ul>
<li><a href="https://techcommunity.microsoft.com/blog/microsoftsentinelblog/turn-complexity-into-clarity-introducing-the-new-ueba-behaviors-layer-in-microso/4484493"  target="_blank" rel="noreferrer">Turn complexity into clarity: introducing the new UEBA behaviors layer</a>: GA announcement, January 2026</li>
<li><a href="https://techcommunity.microsoft.com/blog/microsoftsentinelblog/accelerate-your-ueba-journey-introducing-the-microsoft-sentinel-behaviors-workbo/4488278"  target="_blank" rel="noreferrer">Accelerate your UEBA journey: introducing the Microsoft Sentinel behaviors workbook</a>: February 2026</li>
</ul>
<p><strong>Video</strong></p>
<lite-youtube videoid="LaoqNSB2BAY" playlabel="LaoqNSB2BAY" params=""></lite-youtube>


<h2 class="relative group">Final thoughts
    <div id="final-thoughts" class="anchor"></div>
    
</h2>
<p>The UEBA behaviors layer is one of those features that’s easy to overlook because it doesn’t announce itself with a dramatic alert. But it’s doing something genuinely useful: turning high-volume, low-context telemetry from non-Microsoft sources into security-grade intelligence that analysts can actually act on.</p>
<p>If you’re running Sentinel with AWS, GCP, or Palo Alto data, enable it, deploy the workbook, and start building hunting queries on top of it. The normalized behavioral layer is a better foundation for detection than raw logs, and the KQL you write against <code>BehaviorInfo</code> will be cleaner and more maintainable than anything you’d write directly against <code>AWSCloudTrail</code>.</p>
<p><em>Got feedback or questions about how you’re using the UEBA behaviors layer in your environment? Leave a comment or reach out via the contact page.</em></p>
]]></content:encoded><media:content url="https://www.modernsecurity.nl/ueba-behaviors-layer-in-microsoft-sentinel/featured_hu_6f0dba2d3b546ab2.jpg" medium="image" type="image/jpeg" width="1200" height="638"/><enclosure url="https://www.modernsecurity.nl/ueba-behaviors-layer-in-microsoft-sentinel/featured_hu_6f0dba2d3b546ab2.jpg" type="image/jpeg" length="68787"/></item><item><title>Microsoft Defender for Cloud Apps: AI agent monitoring and real-time protection</title><link>https://www.modernsecurity.nl/defender-for-cloud-apps-ai-agent-monitoring/</link><guid isPermaLink="true">https://www.modernsecurity.nl/defender-for-cloud-apps-ai-agent-monitoring/</guid><pubDate>Sat, 20 Dec 2025 19:19:00 +0100</pubDate><dc:creator>Farid Kalaidji</dc:creator><category>Microsoft Defender for Cloud Apps</category><category>Microsoft Defender XDR</category><description>Learn how to set up Microsoft Defender for Cloud Apps AI agent monitoring. Covers inventory, advanced hunting, and real-time protection.</description><content:encoded><![CDATA[<p>Low-code platforms like <strong>Microsoft Copilot Studio</strong> make it easy for business users to build and deploy AI agents without going through IT or security. That’s useful, but it also means agents are getting created outside of any centralized review: with access to data, external systems, and tool calls that security teams often know nothing about.</p>
<p><strong>Microsoft Defender for Cloud Apps AI agent monitoring</strong> was introduced as a preview feature to address exactly this. With real-time protection landing this month, the full stack is now available. This guide covers how it works and how to set it up.</p>

<h2 class="relative group">Why Copilot Studio AI agents are a security risk
    <div id="why-copilot-studio-ai-agents-are-a-security-risk" class="anchor"></div>
    
</h2>
<p>Copilot Studio agents can call external APIs, process user input, and take actions, often with permissions that were set up quickly and never reviewed. Attackers can abuse this in a few ways:</p>
<ul>
<li>Injecting malicious prompts to manipulate what the agent does</li>
<li>Triggering tool calls the agent wasn’t designed to make</li>
<li>Exploiting connected data sources to escalate privileges or exfiltrate data</li>
</ul>
<p>The people building these agents are usually not security-aware, and there’s no enforcement gate before an agent goes live. Microsoft Defender for Cloud Apps AI agent monitoring is designed to fill that gap.</p>

<h2 class="relative group">What Microsoft Defender for Cloud Apps AI agent monitoring does
    <div id="what-microsoft-defender-for-cloud-apps-ai-agent-monitoring-does" class="anchor"></div>
    
</h2>
<p><a href="https://www.modernsecurity.nl/microsoft-defender-for-cloud-apps/" >Defender for Cloud Apps</a> covers three things here:</p>
<p><strong>AI agent inventory</strong></p>
<p>Defender automatically discovers all Copilot Studio agents in your tenant and surfaces them in a central view. You can see what agents exist, who owns them, and what their security posture looks like, without requiring agent builders to do anything.</p>
<p><strong>Audit logging and threat detection</strong></p>
<p>Once the inventory is enabled and the Microsoft 365 connector is active, Defender collects audit logs for all Copilot Studio agents and monitors them for suspicious activity. Detections come through as alerts in the XDR incidents and alerts experience.</p>
<p><strong>Real-time protection during runtime</strong></p>
<p>This is what landed in December 2025. Defender inspects tool invocations <em>before</em> the agent executes them. If a prompt looks suspicious, the tool call is blocked, the user gets a notification, and an alert is created in the Defender portal. Active blocking, not detection after the fact.</p>
<p><em>One important caveat: if Defender doesn’t respond to a tool invocation check within <strong>one second</strong>, the agent proceeds and the tool call is allowed. This fail-open behavior is worth understanding if you’re relying on real-time protection as a hard control.</em></p>

<h2 class="relative group">Prerequisites
    <div id="prerequisites" class="anchor"></div>
    
</h2>
<p><strong>Before enabling Defender for Cloud Apps AI agent monitoring, make sure you have:</strong></p>
<ul>
<li><strong>Microsoft Defender for Cloud Apps</strong> license until the 1st of july 2026 (included in Microsoft 365 E5) &gt; <strong>Note this has been changed and you need the Agent 365 / E7 license to use this feature</strong></li>
<li><strong>Microsoft Defender preview features</strong> enabled for Defender for Cloud Apps, Defender for Cloud, and Microsoft Defender XDR</li>
<li><strong>Microsoft 365 app connector</strong> connected in Defender for Cloud Apps</li>
<li>Access to your <strong>Power Platform administrator</strong> onboarding spans both the Defender portal and the Power Platform admin center</li>
</ul>

<h2 class="relative group">Step 1: Enable the AI agent inventory
    <div id="step-1-enable-the-ai-agent-inventory" class="anchor"></div>
    
</h2>
<p>This is the foundation. Without it, monitoring and real-time protection won’t work.</p>
<ol>
<li>Sign in to the <strong>Microsoft Defender portal</strong> as a system administrator</li>
<li>Go to <strong>System &gt; Settings &gt; Cloud Apps &gt; Copilot Studio AI agents</strong></li>
<li>Toggle <strong>Copilot Studio AI agents</strong> on. This confirms you’ve accepted the terms</li>
</ol>
<figure><img
    class="my-0 rounded-md"
    loading="lazy"
    decoding="async"
    fetchpriority="auto"
    alt="AI agent monitoring"
    width="1896"
    height="990"
    src="https://www.modernsecurity.nl/defender-for-cloud-apps-ai-agent-monitoring/image-4_hu_513109bd2acc39b8.webp"
   
   
    data-zoom-src="https://www.modernsecurity.nl/defender-for-cloud-apps-ai-agent-monitoring/image-4.webp"></figure><figure><img
    class="my-0 rounded-md"
    loading="lazy"
    decoding="async"
    fetchpriority="auto"
    alt=""
    width="1895"
    height="989"
    src="https://www.modernsecurity.nl/defender-for-cloud-apps-ai-agent-monitoring/image-1_hu_aa7554e2464cd959.webp"
   
   
    data-zoom-src="https://www.modernsecurity.nl/defender-for-cloud-apps-ai-agent-monitoring/image-1.webp"></figure><figure><img
    class="my-0 rounded-md"
    loading="lazy"
    decoding="async"
    fetchpriority="auto"
    alt=""
    width="1897"
    height="985"
    src="https://www.modernsecurity.nl/defender-for-cloud-apps-ai-agent-monitoring/image-2_hu_f0a28d9375415a75.webp"
   
   
    data-zoom-src="https://www.modernsecurity.nl/defender-for-cloud-apps-ai-agent-monitoring/image-2.webp"></figure><p>Your <strong>Power Platform administrator</strong> then needs to complete the other side:</p>
<ol>
<li>Go to the <a href="https://admin.preview.powerplatform.microsoft.com/security/threatdetection"  target="_blank" rel="noreferrer">Power Platform admin center</a></li>
<li>Navigate to <strong>Security &gt; Threat Protection</strong></li>
<li>Select <strong>Microsoft Defender – Copilot Studio AI agents</strong></li>
<li>Enable it</li>
</ol>
<figure><img
    class="my-0 rounded-md"
    loading="lazy"
    decoding="async"
    fetchpriority="auto"
    alt=""
    width="1895"
    height="987"
    src="https://www.modernsecurity.nl/defender-for-cloud-apps-ai-agent-monitoring/image-3_hu_7ecf5b9173a75a13.webp"
   
   
    data-zoom-src="https://www.modernsecurity.nl/defender-for-cloud-apps-ai-agent-monitoring/image-3.webp"></figure><p>When connected, a green status indicator appears in the AI agents inventory section in the Defender portal. Allow up to <strong>30 minutes</strong> for the initial connection, and potentially longer for the full inventory to populate in larger environments.</p>
<figure><img
    class="my-0 rounded-md"
    loading="lazy"
    decoding="async"
    fetchpriority="auto"
    alt=""
    width="1897"
    height="987"
    src="https://www.modernsecurity.nl/defender-for-cloud-apps-ai-agent-monitoring/image_hu_cb138ad18e2e0042.webp"
   
   
    data-zoom-src="https://www.modernsecurity.nl/defender-for-cloud-apps-ai-agent-monitoring/image.webp"></figure>
<h2 class="relative group">Step 2: Enable real-time protection during runtime
    <div id="step-2-enable-real-time-protection-during-runtime" class="anchor"></div>
    
</h2>
<p>This step involves three parties: you as the security admin, a Power Platform administrator, and an Entra admin (or someone with app registration permissions). The order matters.</p>

<h3 class="relative group">Get the webhook URL from the Defender portal
    <div id="get-the-webhook-url-from-the-defender-portal" class="anchor"></div>
    
</h3>
<ol>
<li>In the Defender portal, go to <strong>System &gt; Settings &gt; Cloud Apps &gt; Copilot Studio AI agents</strong></li>
<li>Check the <strong>Microsoft 365 app connector</strong> status: if it’s not connected, enable it first. Without it, real-time blocking still works, but alerts won’t appear in the Defender portal</li>
<li>Copy the <strong>webhook URL</strong> (endpoint) shown in the real-time protection section. You’ll need this for the Entra app registration</li>
</ol>
<figure><img
    class="my-0 rounded-md"
    loading="lazy"
    decoding="async"
    fetchpriority="auto"
    alt=""
    width="1896"
    height="987"
    src="https://www.modernsecurity.nl/defender-for-cloud-apps-ai-agent-monitoring/image-1-2_hu_993419c359462a29.webp"
   
   
    data-zoom-src="https://www.modernsecurity.nl/defender-for-cloud-apps-ai-agent-monitoring/image-1-2.webp"></figure>
<h3 class="relative group">Register a Microsoft Entra application
    <div id="register-a-microsoft-entra-application" class="anchor"></div>
    
</h3>
<p>This step creates the secure, secretless authentication bridge between Copilot Studio and Defender. You need someone with app registration permissions in Entra.</p>
<p><strong>Option A: PowerShell (recommended):</strong></p>
<p>Download the <a href="https://www.powershellgallery.com/packages/Create-CopilotWebhookApp/1.0.1"  target="_blank" rel="noreferrer">Create-CopilotWebhookApp.ps1</a> script and run it with the following parameters:</p>
<div class="highlight-wrapper"><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="cl">.\Create-CopilotWebhookApp.ps1 `
</span></span><span class="line"><span class="cl">  -TenantId &#34;your-tenant-id&#34; `
</span></span><span class="line"><span class="cl">  -Endpoint &#34;https://endpoint-from-defender-portal&#34; `
</span></span><span class="line"><span class="cl">  -DisplayName &#34;Copilot Studio - Defender Real-time Protection&#34; `
</span></span><span class="line"><span class="cl">  -FICName &#34;DefenderFIC&#34;</span></span></code></pre></div></div>
<p>The script outputs an <strong>App ID</strong>: copy it, you’ll need it in the next steps.</p>
<p><strong>Option B: manually via Azure portal:</strong></p>
<ol>
<li>Go to <strong>Azure portal &gt; Microsoft Entra ID &gt; App registrations &gt; New registration</strong></li>
<li>Give it a name, select <strong>Accounts in this organizational directory only</strong>, and register</li>
<li>Copy the <strong>App ID</strong></li>
<li>Go to <strong>Certificates &amp; secrets &gt; Federated credentials &gt; Add credential</strong></li>
<li>Select <strong>Other issuer</strong> as the scenario</li>
<li>Set the <strong>issuer</strong> to: <code>https://login.microsoftonline.com/{your-tenant-id}/v2.0</code></li>
<li>Set the <strong>subject</strong> using the following PowerShell to generate the base64-encoded values:</li>
</ol>
<div class="highlight-wrapper"><div class="highlight"><div class="ms-code-label">PowerShell</div><pre tabindex="0" class="chroma"><code class="language-powershell" data-lang="powershell"><span class="line"><span class="cl"><span class="c"># Encode tenant ID</span>
</span></span><span class="line"><span class="cl"><span class="nv">$tenantId</span> <span class="p">=</span> <span class="p">[</span><span class="no">Guid</span><span class="p">]::</span><span class="n">Parse</span><span class="p">(</span><span class="s2">&#34;your-tenant-id&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="nv">$b64TenantId</span> <span class="p">=</span> <span class="p">[</span><span class="no">Convert</span><span class="p">]::</span><span class="n">ToBase64String</span><span class="p">(</span><span class="nv">$tenantId</span><span class="p">.</span><span class="py">ToByteArray</span><span class="p">()).</span><span class="py">Replace</span><span class="p">(</span><span class="s1">&#39;+&#39;</span><span class="p">,</span><span class="s1">&#39;-&#39;</span><span class="p">).</span><span class="py">Replace</span><span class="p">(</span><span class="s1">&#39;/&#39;</span><span class="p">,</span><span class="s1">&#39;_&#39;</span><span class="p">).</span><span class="py">TrimEnd</span><span class="p">(</span><span class="s1">&#39;=&#39;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c"># Encode endpoint URL</span>
</span></span><span class="line"><span class="cl"><span class="nv">$endpoint</span> <span class="p">=</span> <span class="s2">&#34;https://endpoint-from-defender-portal&#34;</span>
</span></span><span class="line"><span class="cl"><span class="nv">$b64Endpoint</span> <span class="p">=</span> <span class="p">[</span><span class="no">Convert</span><span class="p">]::</span><span class="n">ToBase64String</span><span class="p">([</span><span class="no">Text.Encoding</span><span class="p">]::</span><span class="n">UTF8</span><span class="p">.</span><span class="py">GetBytes</span><span class="p">(</span><span class="nv">$endpoint</span><span class="p">)).</span><span class="py">Replace</span><span class="p">(</span><span class="s1">&#39;+&#39;</span><span class="p">,</span><span class="s1">&#39;-&#39;</span><span class="p">).</span><span class="py">Replace</span><span class="p">(</span><span class="s1">&#39;/&#39;</span><span class="p">,</span><span class="s1">&#39;_&#39;</span><span class="p">).</span><span class="py">TrimEnd</span><span class="p">(</span><span class="s1">&#39;=&#39;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="nb">Write-Output</span> <span class="s2">&#34;/eid1/c/pub/t/</span><span class="nv">$b64TenantId</span><span class="s2">/a/m1WPnYRZpEaQKq1Cceg--g/</span><span class="nv">$b64Endpoint</span><span class="s2">&#34;</span></span></span></code></pre></div></div>
<p>Paste the output as the <strong>subject value</strong> and save the credential.</p>

<h3 class="relative group">Configure threat detection in the Power Platform admin center
    <div id="configure-threat-detection-in-the-power-platform-admin-center" class="anchor"></div>
    
</h3>
<p>Share the <strong>App ID</strong> and the <strong>webhook URL</strong> from the Defender portal with your Power Platform administrator. They need to complete the following:</p>
<ol>
<li>Sign in to the <a href="https://aka.ms/ppac"  target="_blank" rel="noreferrer">Power Platform admin center</a></li>
<li>Go to <strong>Security &gt; Threat detection &gt; Additional threat detection</strong></li>
<li>Select the environment and click <strong>Set up</strong></li>
<li>Enable <strong>Allow Copilot Studio to share data with a threat detection provider</strong></li>
<li>Enter the <strong>Azure Entra App ID</strong> and the <strong>endpoint link</strong> from the Defender portal</li>
<li>Under <strong>Set error behavior</strong>, choose what happens if the threat detection system doesn’t respond in time: the default is <strong>Allow the agent to respond</strong>, but you can set it to <strong>Block the query</strong> for a stricter posture</li>
<li>Click <strong>Save</strong></li>
</ol>
<figure><img
    class="my-0 rounded-md"
    loading="lazy"
    decoding="async"
    fetchpriority="auto"
    alt=""
    width="1896"
    height="986"
    src="https://www.modernsecurity.nl/defender-for-cloud-apps-ai-agent-monitoring/image-2-2_hu_4ea47ea409fca8d2.webp"
   
   
    data-zoom-src="https://www.modernsecurity.nl/defender-for-cloud-apps-ai-agent-monitoring/image-2-2.webp"></figure>
<h3 class="relative group">Register the App ID in the Defender portal
    <div id="register-the-app-id-in-the-defender-portal" class="anchor"></div>
    
</h3>
<ol>
<li>Back in the Defender portal, go to <strong>System &gt; Settings &gt; Cloud Apps &gt; Copilot Studio AI agents</strong></li>
<li>Enter the <strong>App ID</strong> in the designated field and click <strong>Save</strong></li>
</ol>
<figure><img
    class="my-0 rounded-md"
    loading="lazy"
    decoding="async"
    fetchpriority="auto"
    alt=""
    width="1895"
    height="988"
    src="https://www.modernsecurity.nl/defender-for-cloud-apps-ai-agent-monitoring/image-3-2_hu_a2789dcf39241790.webp"
   
   
    data-zoom-src="https://www.modernsecurity.nl/defender-for-cloud-apps-ai-agent-monitoring/image-3-2.webp"></figure><p>When everything is connected correctly, the real-time protection section shows a green connected status.</p>
<blockquote><p>If you update the App ID in Power Platform, wait about a minute before saving in the Defender portal: propagation takes a moment and you’ll get a validation error if you’re too fast.</p>
</blockquote><p><strong>Important:</strong> Real-time protection currently only applies to agents using <strong>generative orchestration</strong>. Classic agents that use fixed, deterministic flows are not covered.</p>

<h2 class="relative group">Hunt for risky agents with advanced hunting
    <div id="hunt-for-risky-agents-with-advanced-hunting" class="anchor"></div>
    
</h2>
<p>Once the AI agent inventory is live, you can use <strong>advanced hunting</strong> to look for misconfigurations and risky Copilot Studio agents.</p>
<p>The <strong><code>AIAgentsInfo</code></strong> table in the <strong>Apps &amp; identities</strong> section contains data for all discovered agents. You can write custom queries or use the pre-built community queries:</p>
<ol>
<li>Go to <strong>Investigation &amp; response &gt; Hunting &gt; Advanced hunting</strong></li>
<li>In the <strong>Queries</strong> tab, open <strong>Community queries</strong></li>
<li>The <strong>AI agents</strong> folder contains ready-made queries for common risk scenarios</li>
</ol>
<p>The misconfigurations below are all detectable via this table and are worth running as a first sweep after the inventory comes online.</p>

<h2 class="relative group">What happens when a threat is detected
    <div id="what-happens-when-a-threat-is-detected" class="anchor"></div>
    
</h2>
<p>When Defender for Cloud Apps flags a suspicious Copilot Studio agent prompt or tool invocation:</p>
<ul>
<li>The tool call is blocked before it runs</li>
<li>The end user gets a notification that their message was blocked</li>
<li>An alert is created in the Defender portal under XDR incidents and alerts</li>
<li>The alert is correlated with other XDR signals, so your SOC gets full incident context</li>
</ul>
<p>With the Microsoft 365 connector active, these alerts also land in the unified incident queue alongside endpoint, identity, and cloud alerts.</p>

<h2 class="relative group">Common Copilot Studio agent misconfigurations
    <div id="common-copilot-studio-agent-misconfigurations" class="anchor"></div>
    
</h2>
<p>Getting the monitoring in place is step one. What you’ll actually find in the inventory is often more concerning than expected. These are the most common misconfigurations to look for once you have the <code>AIAgentsInfo</code> table available.</p>
<p><strong>Agents without authentication</strong></p>
<p>When no authentication is configured on a Copilot Studio agent, it doesn’t authenticate as the user interacting with it. It authenticates as the creator. That means any user of that agent can effectively access resources and data as the maker, including things they wouldn’t normally have access to. Agents intended for internal use should always require authentication. Use this query to find them:</p>
<div class="highlight-wrapper"><div class="highlight"><div class="ms-code-label">KQL</div><pre tabindex="0" class="chroma"><code class="language-kql" data-lang="kql">AIAgentsInfo
<span class="o">|</span> <span class="k">summarize</span> <span class="nf">arg_max</span>(Timestamp, *) <span class="k">by</span> AIAgentId
<span class="o">|</span> <span class="k">where</span> AgentStatus <span class="o">!=</span> <span class="s">&#34;Deleted&#34;</span>
<span class="o">|</span> <span class="k">where</span> UserAuthenticationType <span class="o">==</span> <span class="s">&#34;None&#34;</span>
<span class="o">|</span> <span class="k">project-reorder</span> AgentCreationTime, AIAgentId, AIAgentName, AgentStatus, CreatorAccountUpn, OwnerAccountUpns</code></pre></div>
</div>
<p>Microsoft’s recommendation: confirm with the owner whether public access is intentional, and review all topics, actions, and knowledge sources to ensure no sensitive data is exposed.</p>
<p><strong>Agents without an owner</strong></p>
<p>Every published agent should have a designated owner: someone accountable for what it does and what it has access to. Agents without an owner are a governance gap: if something goes wrong, there’s no one to contact and no one managing its lifecycle. Find them with:</p>
<div class="highlight-wrapper"><div class="highlight"><div class="ms-code-label">KQL</div><pre tabindex="0" class="chroma"><code class="language-kql" data-lang="kql">AIAgentsInfo
<span class="o">|</span> <span class="k">where</span> AgentStatus <span class="o">==</span> <span class="s">&#34;Published&#34;</span>
<span class="o">|</span> <span class="k">where</span> <span class="k">isempty</span>(OwnerAccountUpns)
<span class="o">|</span> <span class="k">project</span> AgentCreationTime, AIAgentName, AIAgentId, CreatorAccountUpn, OwnerAccountUpns</code></pre></div>
</div>
<p><strong>Hard-coded credentials in topics or actions</strong></p>
<p>Agents with credentials hard-coded into their topics or actions can expose those credentials to unintended parties: anyone who can read the agent configuration or intercept its traffic. This is a pattern that’s easy to introduce quickly and hard to spot manually at scale. The query below scans for common credential patterns including API keys, tokens, and basic auth strings:</p>
<div class="highlight-wrapper"><div class="highlight"><div class="ms-code-label">KQL</div><pre tabindex="0" class="chroma"><code class="language-kql" data-lang="kql"><span class="k">let</span> suspicious_patterns = <span class="s">@&#34;(AKIA[0-9A-Z]{16})|(AIza[0-9A-Za-z_\-]{35})|(xox[baprs]-[0-9a-zA-Z]{10,48})|(ghp_[A-Za-z0-9]{36,59})|(sk_(live|test)_[A-Za-z0-9]{24})|(SG\.[A-Za-z0-9]{22}\.[A-Za-z0-9]{43})|(\d{8}:[\w\-]{35})|(eyJ[A-Za-z0-9_\-]+\.[A-Za-z0-9_\-]+\.[A-Za-z0-9_\-]+)|(Authorization\s*:\s*Basic\s+[A-Za-z0-9=:+]+)|([A-Za-z]+:\/\/[^\/\s]+:[^\/\s]+@[^\/\s]+)&#34;</span>;
AIAgentsInfo
<span class="o">|</span> <span class="k">summarize</span> <span class="nf">arg_max</span>(Timestamp, *) <span class="k">by</span> AIAgentId
<span class="o">|</span> <span class="k">where</span> AgentStatus <span class="o">!=</span> <span class="s">&#34;Deleted&#34;</span>
<span class="o">|</span> <span class="k">mv-expand</span> tool = AgentToolsDetails
<span class="o">|</span> <span class="k">mv-expand</span> topic = AgentTopicsDetails
<span class="o">|</span> <span class="k">where</span> <span class="k">isnotempty</span>(tool) <span class="k">and</span> <span class="k">isnotempty</span>(topic)
<span class="o">|</span> <span class="k">where</span> tool <span class="k">matches regex</span> suspicious_patterns <span class="k">or</span> topic <span class="k">matches regex</span> suspicious_patterns
<span class="o">|</span> <span class="k">extend</span> SuspiciousMatchTool = tool, SuspiciousMatchTopic = topic
<span class="o">|</span> <span class="k">project-reorder</span> AgentCreationTime, AIAgentId, AIAgentName, AgentStatus, CreatorAccountUpn, OwnerAccountUpns, SuspiciousMatchTool, SuspiciousMatchTopic</code></pre></div>
</div>
<p>If credentials are needed, the right approach is to store them in <strong>Azure Key Vault</strong> and retrieve them at runtime via environment variables, not embed them in the agent configuration.</p>
<p><strong>Email actions with AI-controlled recipients</strong></p>
<p>This one is particularly relevant for agents using generative orchestration. If an agent can send email and the recipient address is determined dynamically by the LLM rather than hard-coded, a successful prompt injection attack (XPIA) can instruct the agent to forward data to an attacker-controlled address. This query finds agents in that configuration:</p>
<div class="highlight-wrapper"><div class="highlight"><div class="ms-code-label">KQL</div><pre tabindex="0" class="chroma"><code class="language-kql" data-lang="kql">AIAgentsInfo
<span class="o">|</span> <span class="k">summarize</span> <span class="nf">arg_max</span>(Timestamp, *) <span class="k">by</span> AIAgentId
<span class="o">|</span> <span class="k">where</span> AgentStatus <span class="o">!=</span> <span class="s">&#34;Deleted&#34;</span>
<span class="o">|</span> <span class="k">extend</span> IsGenAIOrchestrator = <span class="nf">tostring</span>(<span class="nf">todynamic</span>(RawAgentInfo).Bot.Attributes.configuration) <span class="k">has</span> <span class="s">&#39;&#34;GenerativeActionsEnabled&#34;: true&#39;</span>
<span class="o">|</span> <span class="k">where</span> IsGenAIOrchestrator
<span class="o">|</span> mvexpand Action = AgentToolsDetails
<span class="o">|</span> <span class="k">extend</span> OperationId = <span class="nf">tostring</span>(Action.action.operationId), ActionName = <span class="nf">tostring</span>(Action.modelDisplayName)
<span class="o">|</span> <span class="k">where</span> OperationId <span class="o">==</span> <span class="s">&#34;SendEmailV2&#34;</span>
<span class="o">|</span> <span class="k">where</span> <span class="k">isempty</span>(Action.inputs)
<span class="o">|</span> <span class="k">project-reorder</span> AgentCreationTime, AIAgentId, AIAgentName, AgentStatus, CreatorAccountUpn, OwnerAccountUpns, ActionName</code></pre></div>
</div>
<p>If a hard-coded recipient isn’t feasible, at minimum confirm with the owner that the use case warrants AI-controlled addressing and document it.</p>
<p><strong>Agents using MCP tools</strong></p>
<p>Model Context Protocol (MCP) tools give agents access to external resources and APIs. That’s powerful, but each MCP server is an additional attack surface, and agents connecting to MCP servers that are no longer needed, or that were added without security review, represent unnecessary exposure. Use this to get an overview:</p>
<div class="highlight-wrapper"><div class="highlight"><div class="ms-code-label">KQL</div><pre tabindex="0" class="chroma"><code class="language-kql" data-lang="kql">AIAgentsInfo
<span class="o">|</span> <span class="k">summarize</span> <span class="nf">arg_max</span>(Timestamp, *) <span class="k">by</span> AIAgentId
<span class="o">|</span> <span class="k">where</span> AgentStatus <span class="o">!=</span> <span class="s">&#34;Deleted&#34;</span>
<span class="o">|</span> mvexpand Action = AgentToolsDetails
<span class="o">|</span> <span class="k">where</span> Action.action.operationDetails[<span class="s">&#34;$kind&#34;</span>] <span class="o">==</span> <span class="s">&#34;ModelContextProtocolMetadata&#34;</span>
<span class="o">|</span> <span class="k">extend</span> MCPName = Action.action.operationDetails[<span class="s">&#34;operationId&#34;</span>]
<span class="o">|</span> <span class="k">summarize</span> MCPTools = <span class="nf">make_set</span>(MCPName) <span class="k">by</span> AIAgentName, AIAgentId, EnvironmentId, CreatorAccountUpn</code></pre></div>
</div>
<p>Follow up with the agent owner on each MCP tool and remove any that are no longer required.</p>
<p><strong>HTTP actions on nonstandard ports</strong></p>
<p>Agents making HTTP requests to ports other than 80 or 443 are worth investigating. It could indicate the agent is calling internal services, non-standard APIs, or infrastructure that shouldn’t be accessible via an agent. Find them with:</p>
<div class="highlight-wrapper"><div class="highlight"><div class="ms-code-label">KQL</div><pre tabindex="0" class="chroma"><code class="language-kql" data-lang="kql">AIAgentsInfo
<span class="o">|</span> <span class="k">summarize</span> <span class="nf">arg_max</span>(Timestamp, *) <span class="k">by</span> AIAgentId
<span class="o">|</span> <span class="k">where</span> AgentStatus <span class="o">!=</span> <span class="s">&#34;Deleted&#34;</span>
<span class="o">|</span> mvexpand Topic = AgentTopicsDetails
<span class="o">|</span> <span class="k">where</span> Topic <span class="k">has</span> <span class="s">&#34;HttpRequestAction&#34;</span>
<span class="o">|</span> <span class="k">extend</span> TopicActions = Topic.beginDialog.actions
<span class="o">|</span> mvexpand action = TopicActions
<span class="o">|</span> <span class="k">where</span> action[<span class="s">&#39;$kind&#39;</span>] <span class="o">==</span> <span class="s">&#34;HttpRequestAction&#34;</span>
<span class="o">|</span> <span class="k">extend</span> Url = <span class="nf">tostring</span>(action.url.literalValue)
<span class="o">|</span> <span class="k">extend</span> ParsedUrl = <span class="nf">parse_url</span>(Url)
<span class="o">|</span> <span class="k">extend</span> Port = <span class="nf">tostring</span>(ParsedUrl[<span class="s">&#34;Port&#34;</span>])
<span class="o">|</span> <span class="k">where</span> <span class="k">isnotempty</span>(Port) <span class="k">and</span> Port <span class="o">!=</span> 443
<span class="o">|</span> <span class="k">project-reorder</span> AgentCreationTime, AIAgentId, AIAgentName, ParsedUrl, Url, Port, AgentStatus, CreatorAccountUpn, OwnerAccountUpns</code></pre></div>
</div>

<h2 class="relative group">Resources:
    <div id="resources" class="anchor"></div>
    
</h2>
<p><a href="https://learn.microsoft.com/en-us/defender-xdr/ai-agent-inventory"  target="_blank" rel="noreferrer">Protect AI agents in Microsoft Defender XDR – Microsoft Learn</a></p>
<p><a href="https://learn.microsoft.com/en-us/defender-cloud-apps/ai-agent-protection"  target="_blank" rel="noreferrer">Protect your Copilot Studio AI agents (Preview) – Microsoft Learn</a></p>
<p><a href="https://learn.microsoft.com/en-us/defender-cloud-apps/ai-agent-inventory"  target="_blank" rel="noreferrer">Discover and protect your AI agents (Preview) – Microsoft Learn</a></p>
<p><a href="https://learn.microsoft.com/en-us/defender-cloud-apps/real-time-agent-protection-during-runtime"  target="_blank" rel="noreferrer">Real-time protection during agent runtime (Preview) – Microsoft Learn</a></p>

<h2 class="relative group">Wrapping up
    <div id="wrapping-up" class="anchor"></div>
    
</h2>
<p>If your organization is building agents in Copilot Studio, or you expect business users to start, Microsoft Defender for Cloud Apps AI agent monitoring is worth setting up before you’re flying blind. The inventory alone gives you visibility into what’s running. Real-time protection goes further by actively blocking suspicious activity at the moment it happens.</p>
<p>Loop in your Power Platform admin, enable the preview features, and get the inventory running. It’s a quick setup for a threat surface that most security teams aren’t watching yet.</p>
]]></content:encoded><media:content url="https://www.modernsecurity.nl/defender-for-cloud-apps-ai-agent-monitoring/featured_hu_5c9c5c12fa2213cf.jpg" medium="image" type="image/jpeg" width="1200" height="677"/><enclosure url="https://www.modernsecurity.nl/defender-for-cloud-apps-ai-agent-monitoring/featured_hu_5c9c5c12fa2213cf.jpg" type="image/jpeg" length="63307"/></item><item><title>Proactively Block Cloud Apps (like AI) with Microsoft Defender for Cloud Apps and Defender for Endpoint</title><link>https://www.modernsecurity.nl/block-apps-microsoft-defender-for-cloud-apps/</link><guid isPermaLink="true">https://www.modernsecurity.nl/block-apps-microsoft-defender-for-cloud-apps/</guid><pubDate>Fri, 24 Oct 2025 21:30:20 +0100</pubDate><dc:creator>Farid Kalaidji</dc:creator><category>Microsoft Defender for Cloud Apps</category><category>Microsoft Defender XDR</category><description>Learn how to block shadow IT and risky cloud applications (like AI apps) using Microsoft Defender for Cloud Apps with Defender for Endpoint.</description><content:encoded><![CDATA[<p>Shadow IT remains one of the biggest challenges for security teams. Users access cloud applications daily without IT awarenes, shady AI tooling, file sharing services, or apps that don’t meet compliance requirements like SOC 2 or ISO 27001.</p>
<p>With the integration between <a href="https://www.modernsecurity.nl/microsoft-defender-for-cloud-apps/" >Microsoft Defender for Cloud Apps</a> and <a href="https://www.modernsecurity.nl/microsoft-defender-for-endpoint/" >Microsoft Defender for Endpoint</a>, you can proactively block apps on your endpoints before users even access them. This goes beyond monitoring: you can automatically block apps based on their risk score, category (like Generative AI), or specific compliance and security attributes.</p>
<p>In this guide, I’ll walk you through the complete setup, prerequisites, and how to create policies that automatically block risky or unwanted apps.</p>

<h2 class="relative group">How it works
    <div id="how-it-works" class="anchor"></div>
    
</h2>
<p>When you mark an app as <strong>Unsanctioned</strong> in Defender for Cloud Apps, the domains associated with that app are automatically synced to Defender for Endpoint as custom URL indicators. From there, Network Protection blocks access at the endpoint level, this happens on all onboarded devices running Microsoft Defender Antivirus with Network Protection enabled.</p>
<p>The integration works like this:</p>
<ol>
<li>You mark an app as Unsanctioned in Defender for Cloud Apps (manually or via policy)</li>
<li>The domains used by that app sync to Defender for Endpoint (up to 1 hour)</li>
<li>Defender for Endpoint creates custom URL indicators for those domains</li>
<li>The indicators propagate to your endpoint devices (up to 2 hours)</li>
<li>Network Protection blocks access when users try to reach those domains</li>
</ol>
<figure><img
    class="my-0 rounded-md"
    loading="lazy"
    decoding="async"
    fetchpriority="auto"
    alt="Blocking AI apps with Microsoft Defender for Cloud Apps"
    width="998"
    height="562"
    src="https://www.modernsecurity.nl/block-apps-microsoft-defender-for-cloud-apps/image_hu_6ce1ccf659840a1b.webp"
   
   
    data-zoom-src="https://www.modernsecurity.nl/block-apps-microsoft-defender-for-cloud-apps/image.webp"></figure><p><strong>Total maximum latency: up to 3 hours</strong> from marking an app as unsanctioned to actual blocking on devices. In practice it’s often faster, but plan for the full window if you’re doing time-sensitive blocking.</p>
<p>One important limitation: blocking works at the <strong>domain level</strong>, not full URL paths. So <code>drive.google.com</code> can be blocked, but <code>google.com/drive</code> will not work. Keep this in mind when planning your blocking strategy.</p>

<h2 class="relative group">How is this different from Web Content Filtering?
    <div id="how-is-this-different-from-web-content-filtering" class="anchor"></div>
    
</h2>
<p>Both use Network Protection for enforcement, but they serve different purposes:</p>
<p><strong>Web Content Filtering (WCF)</strong> blocks based on URL categorie, broad classifications like “Adult Content,” “Gambling,” “Social Networking,” or “High Bandwidth.” It’s category-based filtering where you block entire types of websites.</p>
<p><strong>Defender for Cloud Apps blocking</strong> is app-specific. The Cloud App Catalog contains over 31,000 apps, each scored on more than 90 risk factors across security, compliance, legal, and general categories. You’re not blocking “all cloud storage”, you’re blocking specific apps that don’t meet your security requirements while allowing others.</p>

<h3 class="relative group">Order of Precedence
    <div id="order-of-precedence" class="anchor"></div>
    
</h3>
<p>When multiple web protection features are configured, they’re evaluated in this order:</p>

<div class="ms-table" role="region" aria-label="Table" tabindex="0">
  <table>
      <thead>
          <tr>
              <th>Priority</th>
              <th>Feature</th>
              <th>Action</th>
          </tr>
      </thead>
    <tbody>
        <tr>
            <td>1 (Highest)</td>
            <td>Custom Indicators (includes Defender for Cloud Apps policies)</td>
            <td>Allow</td>
        </tr>
        <tr>
            <td>2</td>
            <td>Custom Indicators</td>
            <td>Warn</td>
        </tr>
        <tr>
            <td>3</td>
            <td>Custom Indicators</td>
            <td>Block</td>
        </tr>
        <tr>
            <td>4</td>
            <td>Web Threats (malware, phishing)</td>
            <td>Block</td>
        </tr>
        <tr>
            <td>5 (Lowest)</td>
            <td>Web Content Filtering</td>
            <td>Block</td>
        </tr>
    </tbody>
  </table>
</div>
<p>This means if you have a Web Content Filtering policy blocking “Cloud Storage” but you’ve sanctioned a specific app like OneDrive in Defender for Cloud Apps, OneDrive will still be accessible because custom indicators (Allow) take precedence over WCF.</p>

<h2 class="relative group">Prerequisites
    <div id="prerequisites" class="anchor"></div>
    
</h2>

<h3 class="relative group">Licensing
    <div id="licensing" class="anchor"></div>
    
</h3>
<p>You need one of the following combinations:</p>
<ul>
<li>Microsoft Defender for Cloud Apps + Microsoft Defender for Endpoint Plan 2</li>
<li>Microsoft 365 E5</li>
<li>Microsoft Defender for Endpoint with Microsoft Defender for Business</li>
</ul>

<h3 class="relative group">Microsoft Defender for Endpoint Configuration
    <div id="microsoft-defender-for-endpoint-configuration" class="anchor"></div>
    
</h3>
<p>The following must be enabled on your devices:</p>

<div class="ms-table" role="region" aria-label="Table" tabindex="0">
  <table>
      <thead>
          <tr>
              <th>Setting</th>
              <th>Location</th>
              <th>Required State</th>
          </tr>
      </thead>
    <tbody>
        <tr>
            <td>Real-time protection</td>
            <td>Microsoft Defender Antivirus</td>
            <td>Enabled</td>
        </tr>
        <tr>
            <td>Cloud-delivered protection</td>
            <td>Microsoft Defender Antivirus</td>
            <td>Enabled</td>
        </tr>
        <tr>
            <td>Network Protection</td>
            <td>Microsoft Defender for Endpoint</td>
            <td><strong>Block mode</strong> (not Audit)</td>
        </tr>
        <tr>
            <td>Custom network indicators</td>
            <td>Settings → Endpoints → Advanced features</td>
            <td>Enabled</td>
        </tr>
    </tbody>
  </table>
</div>
<p><strong>Important:</strong> Network Protection in Audit mode will log events but won’t actually block anything. Custom network indicators must be enabled or Defender for Cloud Apps won’t be able to create the URL indicators.</p>

<h3 class="relative group">Supported Operating Systems
    <div id="supported-operating-systems" class="anchor"></div>
    
</h3>

<div class="ms-table" role="region" aria-label="Table" tabindex="0">
  <table>
      <thead>
          <tr>
              <th>OS</th>
              <th>Minimum Version</th>
          </tr>
      </thead>
    <tbody>
        <tr>
            <td>Windows</td>
            <td>Windows 10 version 1809 (RS5) OS Build 17763.379 or higher, Windows 11</td>
        </tr>
        <tr>
            <td>macOS</td>
            <td>Big Sur (11) or higher, with MDE version 20.123072.25.0+</td>
        </tr>
        <tr>
            <td>iOS</td>
            <td>14.0 or higher</td>
        </tr>
        <tr>
            <td>Android</td>
            <td>8.0 or higher</td>
        </tr>
        <tr>
            <td>Linux</td>
            <td>See Microsoft’s specific distro requirements</td>
        </tr>
    </tbody>
  </table>
</div>

<h2 class="relative group">Browser behavior
    <div id="browser-behavior" class="anchor"></div>
    
</h2>
<p>This is where it gets nuanced:</p>
<p><strong>Microsoft Edge</strong>: Uses SmartScreen directly. Users see a proper block page with your custom message when they hit a blocked app. Network Protection is not required for Edge on Windows, SmartScreen handles it natively.</p>
<figure><img
    class="my-0 rounded-md"
    loading="lazy"
    decoding="async"
    fetchpriority="auto"
    alt=""
    width="1920"
    height="1140"
    src="https://www.modernsecurity.nl/block-apps-microsoft-defender-for-cloud-apps/image-1_hu_6f814638654709dd.webp"
   
   
    data-zoom-src="https://www.modernsecurity.nl/block-apps-microsoft-defender-for-cloud-apps/image-1.webp"></figure><p><strong>Chrome, Firefox, Brave, Opera, Safari</strong>: Network Protection handles blocking at the network level. Users see a “Secure Connection Failed” error in the browser, plus a Windows/macOS toast notification explaining the block.</p>
<figure><img
    class="my-0 rounded-md"
    loading="lazy"
    decoding="async"
    fetchpriority="auto"
    alt=""
    width="1919"
    height="1137"
    src="https://www.modernsecurity.nl/block-apps-microsoft-defender-for-cloud-apps/image-2_hu_20f8b7a7d2090f55.webp"
   
   
    data-zoom-src="https://www.modernsecurity.nl/block-apps-microsoft-defender-for-cloud-apps/image-2.webp"></figure><p>For Network Protection to properly inspect HTTPS traffic in non-Edge browsers, connections must use TCP/IP (not UDP/QUIC) and the TLS ClientHello must not be encrypted. If you want full coverage, consider deploying browser policies:</p>
<p><strong>Chrome enterprise policies:</strong></p>
<ul>
<li><code>QuicAllowed</code> = false</li>
<li><code>EncryptedClientHelloEnabled</code> = false</li>
</ul>
<p><strong>Firefox policies:</strong></p>
<ul>
<li><code>network.http.http3.enable</code> = false</li>
<li><code>DisableEncryptedClientHello</code> = true</li>
</ul>

<h3 class="relative group">About the Microsoft Defender Browser Protection Extension
    <div id="about-the-microsoft-defender-browser-protection-extension" class="anchor"></div>
    
</h3>
<p>You may see references to the “Microsoft Defender Browser Protection” extension in some Microsoft documentation. This is a <strong>consumer-focused browser add-on</strong> that provides SmartScreen-like phishing/malware protection to Chrome users.</p>
<p>For enterprise customers with Microsoft Defender for Endpoint deployed, this extension is <strong>not required</strong> for Defender for Cloud Apps blocking to work. Network Protection handles blocking in third-party browsers at the OS level.</p>
<p>Microsoft’s guidance for enterprise customers is to use Network Protection rather than the browser extension. The extension is being deprecated for Manifest V3 and provides redundant functionality for MDE-protected devices.</p>

<h2 class="relative group">Step 1: Enable the integration
    <div id="step-1-enable-the-integration" class="anchor"></div>
    
</h2>
<p>You need to configure settings in two places.</p>

<h3 class="relative group">In the Defender Portal (Microsoft Defender for Cloud Apps settings)
    <div id="in-the-defender-portal-microsoft-defender-for-cloud-apps-settings" class="anchor"></div>
    
</h3>
<ol>
<li>Go to <strong>Settings</strong> → <strong>Cloud Apps</strong> → <strong>Cloud Discovery</strong> → <strong>Microsoft Defender for Endpoint</strong></li>
<li>Enable <strong>Enforce app access</strong></li>
<li>Click <strong>Save</strong></li>
</ol>
<figure><img
    class="my-0 rounded-md"
    loading="lazy"
    decoding="async"
    fetchpriority="auto"
    alt=""
    width="2000"
    height="1095"
    src="https://www.modernsecurity.nl/block-apps-microsoft-defender-for-cloud-apps/image-3_hu_9ab52782c33cc070.webp"
   
   
    data-zoom-src="https://www.modernsecurity.nl/block-apps-microsoft-defender-for-cloud-apps/image-3.webp"></figure><p>It can take up to 30 minutes for this setting to take effect</p>

<h3 class="relative group">In the Defender Portal (Endpoint settings)
    <div id="in-the-defender-portal-endpoint-settings" class="anchor"></div>
    
</h3>
<ol>
<li>Go to <strong>Settings</strong> → <strong>Endpoints</strong> → <strong>Advanced features</strong></li>
<li>Enable <strong>Microsoft Defender for Cloud Apps</strong> (for discovery)</li>
<li>Enable <strong>Custom network indicators</strong> (required for blocking)</li>
<li>Click <strong>Save preferences</strong></li>
</ol>
<figure><img
    class="my-0 rounded-md"
    loading="lazy"
    decoding="async"
    fetchpriority="auto"
    alt=""
    width="2000"
    height="1097"
    src="https://www.modernsecurity.nl/block-apps-microsoft-defender-for-cloud-apps/image-4_hu_cc7e29a483e33f3c.webp"
   
   
    data-zoom-src="https://www.modernsecurity.nl/block-apps-microsoft-defender-for-cloud-apps/image-4.webp"></figure><p>Without Custom network indicators enabled, the blocking won’t work: Defender for Cloud Apps won’t be able to create the URL indicators that Network Protection uses.</p>

<h2 class="relative group">Step 2: Understanding the Microsoft Defender for Cloud Apps catalog
    <div id="step-2-understanding-the-microsoft-defender-for-cloud-apps-catalog" class="anchor"></div>
    
</h2>
<p>Before you start blocking apps, you need to understand how apps are scored. The Cloud App Catalog contains over 31,000 discoverable cloud apps, each scored from 1-10 based on more than 90 risk factors.</p>
<p><strong>The scale</strong>: 1 = highest risk, 10 = lowest risk.</p>
<figure><img
    class="my-0 rounded-md"
    loading="lazy"
    decoding="async"
    fetchpriority="auto"
    alt=""
    width="360"
    height="331"
    src="https://www.modernsecurity.nl/block-apps-microsoft-defender-for-cloud-apps/image-9.webp"
   
   
    data-zoom-src="https://www.modernsecurity.nl/block-apps-microsoft-defender-for-cloud-apps/image-9.webp"></figure><p>This trips people up: lower numbers are worse.</p>

<h3 class="relative group">Risk categories
    <div id="risk-categories" class="anchor"></div>
    
</h3>

<div class="ms-table" role="region" aria-label="Table" tabindex="0">
  <table>
      <thead>
          <tr>
              <th>Category</th>
              <th>What It Evaluates</th>
          </tr>
      </thead>
    <tbody>
        <tr>
            <td><strong>General</strong></td>
            <td>Company stability, domain age, founding year, popularity</td>
        </tr>
        <tr>
            <td><strong>Security</strong></td>
            <td>MFA support, encryption at rest, data classification, admin/user audit trails, data ownership</td>
        </tr>
        <tr>
            <td><strong>Compliance</strong></td>
            <td>SOC 2, ISO 27001, HIPAA, PCI-DSS, CSA, and other certifications</td>
        </tr>
        <tr>
            <td><strong>Legal</strong></td>
            <td>DMCA compliance, data retention policy, GDPR readiness, data ownership terms</td>
        </tr>
    </tbody>
  </table>
</div>

<h3 class="relative group">Viewing the catalog
    <div id="viewing-the-catalog" class="anchor"></div>
    
</h3>
<ol>
<li>Go to <strong>Cloud Apps</strong> → <strong>Cloud app catalog</strong></li>
<li>Use the <strong>Category</strong> filter on the left to browse by app type (Generative AI, Cloud Storage, etc.)</li>
<li>Toggle <strong>Advanced filters</strong> to filter by specific risk factors</li>
</ol>
<figure><img
    class="my-0 rounded-md"
    loading="lazy"
    decoding="async"
    fetchpriority="auto"
    alt=""
    width="2000"
    height="1095"
    src="https://www.modernsecurity.nl/block-apps-microsoft-defender-for-cloud-apps/image-5_hu_d072a4f10bca39a1.webp"
   
   
    data-zoom-src="https://www.modernsecurity.nl/block-apps-microsoft-defender-for-cloud-apps/image-5.webp"></figure><p>For example, to find risky cloud storage apps:</p>
<ul>
<li>Category: Cloud storage</li>
<li>Risk score: 5 or lower</li>
<li>Compliance risk factor → SOC 2: No</li>
<li>Security risk factor → Data-at-rest encryption: Not supported</li>
</ul>
<figure><img
    class="my-0 rounded-md"
    loading="lazy"
    decoding="async"
    fetchpriority="auto"
    alt=""
    width="2000"
    height="1099"
    src="https://www.modernsecurity.nl/block-apps-microsoft-defender-for-cloud-apps/image-6_hu_50f5889bdd18413f.webp"
   
   
    data-zoom-src="https://www.modernsecurity.nl/block-apps-microsoft-defender-for-cloud-apps/image-6.webp"></figure>
<h3 class="relative group">Customizing Risk Score weights
    <div id="customizing-risk-score-weights" class="anchor"></div>
    
</h3>
<p>If certain factors matter more to your organization, you can adjust the weighting:</p>
<ol>
<li>Go to <strong>Settings</strong> → <strong>Cloud Apps</strong> → <strong>Cloud Discovery</strong> → <strong>Score metrics</strong></li>
<li>Adjust the <strong>Importance</strong> slider for each category: Ignored, Low, Medium, High, or Very High</li>
<li>Enable <strong>N/A values</strong> checkbox if you want missing information to negatively impact scores</li>
</ol>
<figure><img
    class="my-0 rounded-md"
    loading="lazy"
    decoding="async"
    fetchpriority="auto"
    alt=""
    width="2000"
    height="1096"
    src="https://www.modernsecurity.nl/block-apps-microsoft-defender-for-cloud-apps/image-7_hu_6c1e592ef23a07bf.webp"
   
   
    data-zoom-src="https://www.modernsecurity.nl/block-apps-microsoft-defender-for-cloud-apps/image-7.webp"></figure>
<h3 class="relative group">Overriding Risk Scores
    <div id="overriding-risk-scores" class="anchor"></div>
    
</h3>
<p>Sometimes you’ve vetted an app internally even though its catalog score is low. You can override scores for specific apps:</p>
<ol>
<li>In the Cloud app catalog, find the app</li>
<li>Click the three dots → <strong>Override app score</strong></li>
<li>Select your custom score</li>
<li>Add an App note explaining your justification</li>
</ol>
<figure><img
    class="my-0 rounded-md"
    loading="lazy"
    decoding="async"
    fetchpriority="auto"
    alt=""
    width="2000"
    height="1097"
    src="https://www.modernsecurity.nl/block-apps-microsoft-defender-for-cloud-apps/image-8_hu_9350743822f16a82.webp"
   
   
    data-zoom-src="https://www.modernsecurity.nl/block-apps-microsoft-defender-for-cloud-apps/image-8.webp"></figure>
<h2 class="relative group">Step 3: Manually block apps (Unsanction)
    <div id="step-3-manually-block-apps-unsanction" class="anchor"></div>
    
</h2>

<h3 class="relative group">Block from discovered apps
    <div id="block-from-discovered-apps" class="anchor"></div>
    
</h3>
<ol>
<li>Go to <strong>Cloud Apps</strong> → <strong>Cloud Discovery</strong> → <strong>Discovered apps</strong> tab</li>
<li>Find the app you want to block</li>
<li>Click the three dots at the end of the row → <strong>Unsanctioned</strong></li>
<li>Click <strong>Save</strong></li>
</ol>
<figure><img
    class="my-0 rounded-md"
    loading="lazy"
    decoding="async"
    fetchpriority="auto"
    alt=""
    width="2000"
    height="1097"
    src="https://www.modernsecurity.nl/block-apps-microsoft-defender-for-cloud-apps/image-11_hu_1313c7efbd9701b8.webp"
   
   
    data-zoom-src="https://www.modernsecurity.nl/block-apps-microsoft-defender-for-cloud-apps/image-11.webp"></figure>
<h3 class="relative group">Block from the Cloud App catalog
    <div id="block-from-the-cloud-app-catalog" class="anchor"></div>
    
</h3>
<p>You can also proactively block apps that haven’t been discovered in your environment yet:</p>
<ol>
<li>Go to <strong>Cloud Apps</strong> → <strong>Cloud app catalog</strong></li>
<li>Find an app (e.g., search for a specific AI tool)</li>
<li>Click the three dots → <strong>Unsanctioned</strong></li>
</ol>
<figure><img
    class="my-0 rounded-md"
    loading="lazy"
    decoding="async"
    fetchpriority="auto"
    alt=""
    width="2000"
    height="1097"
    src="https://www.modernsecurity.nl/block-apps-microsoft-defender-for-cloud-apps/image-12_hu_72582c67e1ad7779.webp"
   
   
    data-zoom-src="https://www.modernsecurity.nl/block-apps-microsoft-defender-for-cloud-apps/image-12.webp"></figure><p>This is useful for preemptively blocking apps before anyone even tries to use them.</p>

<h3 class="relative group">What happens after unsanctioning
    <div id="what-happens-after-unsanctioning" class="anchor"></div>
    
</h3>
<p>Once marked as unsanctioned:</p>
<ol>
<li>Domains sync to Defender for Endpoint within approximately 1 hour</li>
<li>URL indicators are created automatically</li>
<li>Indicators propagate to devices within approximately 2 hours</li>
<li>Users attempting to access the app get blocked</li>
</ol>
<figure><img
    class="my-0 rounded-md"
    loading="lazy"
    decoding="async"
    fetchpriority="auto"
    alt=""
    width="2000"
    height="1096"
    src="https://www.modernsecurity.nl/block-apps-microsoft-defender-for-cloud-apps/image-13_hu_7455eda35f2207b2.webp"
   
   
    data-zoom-src="https://www.modernsecurity.nl/block-apps-microsoft-defender-for-cloud-apps/image-13.webp"></figure>
<h2 class="relative group">Step 4: Automate Blocking with App Discovery policies
    <div id="step-4-automate-blocking-with-app-discovery-policies" class="anchor"></div>
    
</h2>
<p>Manual blocking doesn’t scale. For proactive protection, create policies that automatically unsanction apps based on your criteria.</p>

<h3 class="relative group">Create an App Discovery policy
    <div id="create-an-app-discovery-policy" class="anchor"></div>
    
</h3>
<ol>
<li>Go to <strong>Cloud Apps</strong> → <strong>Policies</strong> → <strong>Policy management</strong></li>
<li>Select the <strong>Shadow IT</strong> tab</li>
<li>Click <strong>Create policy</strong> → <strong>App discovery policy</strong></li>
</ol>

<h3 class="relative group">Example policy 1: Block high-risk apps
    <div id="example-policy-1-block-high-risk-apps" class="anchor"></div>
    
</h3>
<p>This policy automatically blocks apps with poor risk scores that are actually being used.</p>
<p><strong>Configuration:</strong></p>
<ul>
<li><strong>Name</strong>: Block High-Risk Apps</li>
<li><strong>Severity</strong>: High</li>
<li>Under <strong>Apps matching all of the following</strong>:
<ul>
<li>Risk score: equals 5 or lower</li>
</ul>
</li>
<li>Under <strong>Trigger a policy match if all the following occur on the same day</strong>:
<ul>
<li>Daily traffic: greater than 50 MB</li>
<li>Users: greater than 5</li>
</ul>
</li>
<li><strong>Governance actions</strong>: Tag app as <strong>Unsanctioned</strong></li>
</ul>
<figure><img
    class="my-0 rounded-md"
    loading="lazy"
    decoding="async"
    fetchpriority="auto"
    alt=""
    width="2000"
    height="1763"
    src="https://www.modernsecurity.nl/block-apps-microsoft-defender-for-cloud-apps/image-15_hu_56b067491a5e15e5.webp"
   
   
    data-zoom-src="https://www.modernsecurity.nl/block-apps-microsoft-defender-for-cloud-apps/image-15.webp"></figure><p>The traffic and user thresholds prevent blocking apps that nobody’s actually using.</p>

<h3 class="relative group">Example policy 2: Block all generative AI apps
    <div id="example-policy-2-block-all-generative-ai-apps" class="anchor"></div>
    
</h3>
<p>With AI tools proliferating, many organizations want to block unapproved AI apps by default.</p>
<p><strong>Configuration:</strong></p>
<ul>
<li><strong>Name</strong>: Block Unapproved AI Apps</li>
<li><strong>Severity</strong>: Medium</li>
<li>Under <strong>Apps matching all of the following</strong>:
<ul>
<li>Category: equals <strong>Generative AI</strong></li>
</ul>
</li>
<li><strong>Governance actions</strong>: Tag app as <strong>Unsanctioned</strong></li>
</ul>
<figure><img
    class="my-0 rounded-md"
    loading="lazy"
    decoding="async"
    fetchpriority="auto"
    alt=""
    width="2000"
    height="1688"
    src="https://www.modernsecurity.nl/block-apps-microsoft-defender-for-cloud-apps/image-16_hu_224831e090ca9059.webp"
   
   
    data-zoom-src="https://www.modernsecurity.nl/block-apps-microsoft-defender-for-cloud-apps/image-16.webp"></figure><p>After enabling this policy, manually sanction the AI tools your organization has approved (Microsoft Copilot, ChatGPT Enterprise with your corporate contract, etc.).</p>

<h3 class="relative group">Example policy 3: Compliance-driven blocking
    <div id="example-policy-3-compliance-driven-blocking" class="anchor"></div>
    
</h3>
<p>Block apps that don’t meet your compliance requirements.</p>
<p><strong>Configuration:</strong></p>
<ul>
<li><strong>Name</strong>: Block Non-Compliant Apps</li>
<li><strong>Severity</strong>: High</li>
<li>Under <strong>Apps matching all of the following</strong>:
<ul>
<li>Compliance risk factor → SOC 2: equals <strong>No</strong></li>
<li>Users: greater than 10</li>
</ul>
</li>
<li><strong>Governance actions</strong>: Tag app as <strong>Unsanctioned</strong></li>
</ul>
<figure><img
    class="my-0 rounded-md"
    loading="lazy"
    decoding="async"
    fetchpriority="auto"
    alt=""
    width="2000"
    height="1691"
    src="https://www.modernsecurity.nl/block-apps-microsoft-defender-for-cloud-apps/image-17_hu_1dc7366d30a85d02.webp"
   
   
    data-zoom-src="https://www.modernsecurity.nl/block-apps-microsoft-defender-for-cloud-apps/image-17.webp"></figure>
<h3 class="relative group">Example policy 4: Block apps without encryption
    <div id="example-policy-4-block-apps-without-encryption" class="anchor"></div>
    
</h3>
<p><strong>Configuration:</strong></p>
<ul>
<li><strong>Name</strong>: Block Unencrypted Storage Apps</li>
<li><strong>Severity</strong>: High</li>
<li>Under <strong>Apps matching all of the following</strong>:
<ul>
<li>Category: equals <strong>Cloud storage</strong></li>
<li>Security risk factor → Data-at-rest encryption: equals <strong>Not supported</strong></li>
</ul>
</li>
<li><strong>Governance actions</strong>: Tag app as <strong>Unsanctioned</strong></li>
</ul>
<figure><img
    class="my-0 rounded-md"
    loading="lazy"
    decoding="async"
    fetchpriority="auto"
    alt=""
    width="2000"
    height="1764"
    src="https://www.modernsecurity.nl/block-apps-microsoft-defender-for-cloud-apps/image-18_hu_2571585a4d3f481c.webp"
   
   
    data-zoom-src="https://www.modernsecurity.nl/block-apps-microsoft-defender-for-cloud-apps/image-18.webp"></figure>
<h3 class="relative group">Policy behavior notes
    <div id="policy-behavior-notes" class="anchor"></div>
    
</h3>
<ul>
<li>Newly created policies can trigger alerts for apps that already exist in your environment. Microsoft limits this to once per 90 days per app per continuous report.</li>
<li>If there’s a conflict between manual governance actions and policy governance, the <strong>last operation applied takes precedence</strong>.</li>
<li>Data from snapshot reports don’t trigger alerts in app discovery policies.</li>
</ul>

<h2 class="relative group">Step 5: Block apps for specific Device Groups (Scoped Profiles)
    <div id="step-5-block-apps-for-specific-device-groups-scoped-profiles" class="anchor"></div>
    
</h2>
<p>Not every block should apply organization-wide. Marketing might need access to design tools that should be blocked for Finance. Scoped profiles let you target blocking to specific Defender for Endpoint device groups.</p>
<p><strong>Important</strong>: Scoped profiles work with <strong>Device Groups only</strong>, not User Groups. This is because Microsoft Defender for Endpoint executes the blocking, and MDE works at the device level.</p>

<h3 class="relative group">Create a Scoped Profile
    <div id="create-a-scoped-profile" class="anchor"></div>
    
</h3>
<ol>
<li>Go to <strong>Settings</strong> → <strong>Cloud Apps</strong> → <strong>Cloud Discovery</strong> → <strong>App tags</strong> → <strong>Scoped profiles</strong> tab</li>
<li>Click <strong>Add profile</strong></li>
<li>Configure:
<ul>
<li><strong>Name</strong>: Give it a descriptive name (e.g., “Marketing Exception” or “Finance Restrictions”)</li>
<li><strong>Description</strong>: Document the purpose</li>
<li><strong>Type</strong>: Choose <strong>Include</strong> or <strong>Exclude</strong>
<ul>
<li><strong>Include</strong>: Only devices in the selected groups are affected by blocks using this profile</li>
<li><strong>Exclude</strong>: All devices EXCEPT those in the selected groups are affected</li>
</ul>
</li>
<li><strong>Device groups</strong>: Select from your Defender for Endpoint device groups</li>
</ul>
</li>
<li>Click <strong>Save</strong></li>
</ol>
<figure><img
    class="my-0 rounded-md"
    loading="lazy"
    decoding="async"
    fetchpriority="auto"
    alt=""
    width="2000"
    height="1123"
    src="https://www.modernsecurity.nl/block-apps-microsoft-defender-for-cloud-apps/image-19_hu_e468c07397616dcf.webp"
   
   
    data-zoom-src="https://www.modernsecurity.nl/block-apps-microsoft-defender-for-cloud-apps/image-19.webp"></figure>
<h3 class="relative group">Apply a Scoped Profile when blocking
    <div id="apply-a-scoped-profile-when-blocking" class="anchor"></div>
    
</h3>
<p>When you unsanction an app:</p>
<ol>
<li>In the <strong>Tag as unsanctioned?</strong> dialog, you’ll see an option to <strong>Select a profile to include or exclude groups from being blocked</strong></li>
<li>Choose your scoped profile</li>
<li>Click <strong>Save</strong></li>
</ol>
<p>The app will only be blocked for devices matching that profile.</p>

<h3 class="relative group">Important notes on Scoped Profiles
    <div id="important-notes-on-scoped-profiles" class="anchor"></div>
    
</h3>
<ul>
<li>Device groups are pulled from Microsoft Defender for Endpoint. Create device groups there first if needed.</li>
<li>The scoped profile option only appears if the <strong>Win10 Endpoint Users</strong> data source has consistently received data during the past 30 days.</li>
<li>If you’re using <strong>Microsoft Defender for Business</strong> instead of full Defender for Endpoint, device groups are managed differently and won’t appear in Defender for Cloud Apps.</li>
<li>To change the scoped profile for an already-unsanctioned app, you must first remove the unsanctioned tag, then re-unsanction with the new profile.</li>
<li>It can take up to 2 hours for domain changes to propagate to devices after modifying scoping.</li>
</ul>

<h2 class="relative group">Step 6: Warn Users instead of blocking (Monitored)
    <div id="step-6-warn-users-instead-of-blocking-monitored" class="anchor"></div>
    
</h2>
<p>Sometimes a hard block is too aggressive. You might want to discourage use without completely preventing access. The <strong>Monitored</strong> tag provides a warning experience instead of blocking.</p>

<h3 class="relative group">The three app states
    <div id="the-three-app-states" class="anchor"></div>
    
</h3>

<div class="ms-table" role="region" aria-label="Table" tabindex="0">
  <table>
      <thead>
          <tr>
              <th>Tag</th>
              <th>Behavior</th>
              <th>Sync to MDE</th>
          </tr>
      </thead>
    <tbody>
        <tr>
            <td><strong>Sanctioned</strong></td>
            <td>Allowed</td>
            <td>Creates Allow indicator</td>
        </tr>
        <tr>
            <td><strong>Monitored</strong></td>
            <td>Warn</td>
            <td>Creates Warn indicator</td>
        </tr>
        <tr>
            <td><strong>Unsanctioned</strong></td>
            <td>Blocked</td>
            <td>Creates Block indicator</td>
        </tr>
    </tbody>
  </table>
</div>

<h3 class="relative group">How warnings work
    <div id="how-warnings-work" class="anchor"></div>
    
</h3>
<p>When you tag an app as <strong>Monitored</strong>:</p>
<ul>
<li>The domains sync to Defender for Endpoint with Action=Warn (usually within a few minutes)</li>
<li>Users see a warning page when they try to access the app</li>
<li>Users can choose to proceed (bypass the warning)</li>
<li>You can track bypass behavior in the Defender portal</li>
</ul>

<h3 class="relative group">Configure warning settings
    <div id="configure-warning-settings" class="anchor"></div>
    
</h3>
<ol>
<li>Go to <strong>Settings</strong> → <strong>Cloud Apps</strong> → <strong>Cloud Discovery</strong> → <strong>Microsoft Defender for Endpoint</strong></li>
<li>Configure the following:</li>
</ol>
<p><strong>Notification URL</strong>: Enter a URL pointing to a page explaining:</p>
<ul>
<li>Why the app is flagged as risky</li>
<li>What approved alternatives exist</li>
<li>How to request an exception</li>
</ul>
<figure><img
    class="my-0 rounded-md"
    loading="lazy"
    decoding="async"
    fetchpriority="auto"
    alt=""
    width="2000"
    height="1122"
    src="https://www.modernsecurity.nl/block-apps-microsoft-defender-for-cloud-apps/image-22_hu_826f0d0a98215c61.webp"
   
   
    data-zoom-src="https://www.modernsecurity.nl/block-apps-microsoft-defender-for-cloud-apps/image-22.webp"></figure><p><strong>Bypass duration</strong>: Configure how long (in hours) a user can access the app after bypassing the warning before seeing it again. Default is 24 hours.</p>

<h3 class="relative group">Tag an app as monitored
    <div id="tag-an-app-as-monitored" class="anchor"></div>
    
</h3>
<ol>
<li>Go to <strong>Cloud Apps</strong> → <strong>Cloud Discovery</strong> → <strong>Discovered apps</strong></li>
<li>Find the app</li>
<li>Click the three dots → <strong>Monitored</strong></li>
</ol>

<h3 class="relative group">Monitor user behavior
    <div id="monitor-user-behavior" class="anchor"></div>
    
</h3>
<p>Track how many users are bypassing warnings:</p>
<ol>
<li>Go to <strong>Cloud Apps</strong> → <strong>Cloud Discovery</strong> → <strong>Discovered apps</strong></li>
<li>Select the monitored app</li>
<li>View applied controls and bypass statistics on the app’s overview page</li>
</ol>
<p>High bypass rates indicate either a training opportunity or that you should formally sanction (or fully block) the app.</p>

<h2 class="relative group">Step 7: Customize the block page
    <div id="step-7-customize-the-block-page" class="anchor"></div>
    
</h2>
<p>When users hit a blocked app in Microsoft Edge, they see a block notification. You can customize this experience by providing a link to internal resources.</p>

<h3 class="relative group">Configure the block page URL
    <div id="configure-the-block-page-url" class="anchor"></div>
    
</h3>
<ol>
<li>Go to <strong>Settings</strong> → <strong>Cloud Apps</strong> → <strong>Cloud Discovery</strong> → <strong>Microsoft Defender for Endpoint</strong></li>
<li>In the <strong>Alerts</strong> dropdown, select <strong>Informational</strong></li>
<li>Under <strong>User warnings</strong> → <strong>Notification URL for blocked apps</strong>, enter your URL</li>
</ol>
<figure><img
    class="my-0 rounded-md"
    loading="lazy"
    decoding="async"
    fetchpriority="auto"
    alt=""
    width="2000"
    height="1122"
    src="https://www.modernsecurity.nl/block-apps-microsoft-defender-for-cloud-apps/image-23_hu_8a6dac28a416c1c6.webp"
   
   
    data-zoom-src="https://www.modernsecurity.nl/block-apps-microsoft-defender-for-cloud-apps/image-23.webp"></figure><p>Point this to a SharePoint page or internal wiki explaining:</p>
<ul>
<li>Why apps get blocked</li>
<li>Your organization’s acceptable use policy</li>
<li>How to request an exception</li>
<li>What approved alternatives exist</li>
</ul>
<p>When users click “Visit the Support page” on the block page, they’ll be redirected to this URL.</p>

<h2 class="relative group">Step 8: Anomaly Detection for Unusual Behavior
    <div id="step-8-anomaly-detection-for-unusual-behavior" class="anchor"></div>
    
</h2>
<p>Beyond policy-based blocking, Defender for Cloud Apps can detect anomalous behavior, like a user who suddenly uploads 600 GB to an app they’ve never used.</p>

<h3 class="relative group">Cloud Discovery Anomaly Detection
    <div id="cloud-discovery-anomaly-detection" class="anchor"></div>
    
</h3>
<p>This is enabled by default, but you can fine-tune it:</p>
<ol>
<li>Go to <strong>Cloud Apps</strong> → <strong>Policies</strong> → <strong>Policy management</strong> → <strong>Shadow IT</strong> tab</li>
<li>Click <strong>Create policy</strong> → <strong>Cloud Discovery anomaly detection policy</strong></li>
<li>Configure:
<ul>
<li><strong>Name</strong>: e.g., “Unusual Upload Activity”</li>
<li><strong>Filters</strong>: Target specific apps, categories, or risk scores</li>
<li><strong>Apply to</strong>: All continuous reports or specific reports</li>
<li><strong>Raise alerts only for suspicious activities occurring after</strong>: Set a date</li>
<li><strong>Daily alert limit</strong>: Prevent alert fatigue</li>
</ul>
</li>
</ol>
<p>Anomaly detection policies alert on unusual behavior but don’t auto-block. They’re early warning signals for investigation.</p>

<h2 class="relative group">Apps you cannot block
    <div id="apps-you-cannot-block" class="anchor"></div>
    
</h2>
<p>Microsoft prevents blocking certain business-critical services to avoid accidental outages:</p>
<ul>
<li>Microsoft Defender for Cloud Apps</li>
<li>Microsoft Defender Security Center</li>
<li>Microsoft 365 Security Center</li>
<li>Microsoft Defender for Identity</li>
<li>Microsoft Purview</li>
<li>Microsoft Entra Permissions Management</li>
<li>Microsoft Conditional Access Application Control</li>
<li>Microsoft Secure Score</li>
<li>Microsoft Intune</li>
<li>Microsoft Support</li>
<li>Microsoft AD FS Help</li>
<li>Microsoft Online Services</li>
</ul>
<p>Additionally, apps that are <strong>onboarded to inline proxy</strong> (Conditional Access App Control) or <strong>connected via app connector</strong> are automatically set to Sanctioned and cannot be blocked through this mechanism.</p>

<h2 class="relative group">Alternative: Block Script generation for Firewalls
    <div id="alternative-block-script-generation-for-firewalls" class="anchor"></div>
    
</h2>
<p>If you don’t have Defender for Endpoint deployed everywhere, you can still use Defender for Cloud Apps intelligence with your existing security appliances.</p>

<h3 class="relative group">Generate a Block Script
    <div id="generate-a-block-script" class="anchor"></div>
    
</h3>
<ol>
<li>Tag your target apps as Unsanctioned in Cloud Discovery</li>
<li>Go to the Cloud Discovery dashboard</li>
<li>Click <strong>Actions</strong> → <strong>Generate block script</strong></li>
<li>Select your appliance type (Fortigate, Palo Alto, Cisco, Blue Coat, etc.)</li>
<li>Click <strong>Generate script</strong></li>
<li>Import the generated file into your appliance</li>
</ol>
<figure><img
    class="my-0 rounded-md"
    loading="lazy"
    decoding="async"
    fetchpriority="auto"
    alt=""
    width="2000"
    height="1123"
    src="https://www.modernsecurity.nl/block-apps-microsoft-defender-for-cloud-apps/image-24_hu_67cb480d3b5a7eaf.webp"
   
   
    data-zoom-src="https://www.modernsecurity.nl/block-apps-microsoft-defender-for-cloud-apps/image-24.webp"></figure><div class="highlight-wrapper"><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="cl">config webfilter urlfilter
</span></span><span class="line"><span class="cl">	edit &lt;ID&gt;
</span></span><span class="line"><span class="cl">		config entries
</span></span><span class="line"><span class="cl">			edit 1
</span></span><span class="line"><span class="cl">				set url seocontentmachine.com
</span></span><span class="line"><span class="cl">				set type simple
</span></span><span class="line"><span class="cl">				set action block
</span></span><span class="line"><span class="cl">				set status enable
</span></span><span class="line"><span class="cl">			end
</span></span><span class="line"><span class="cl">		end
</span></span><span class="line"><span class="cl">	end</span></span></code></pre></div></div>

<h3 class="relative group">Export Domain List
    <div id="export-domain-list" class="anchor"></div>
    
</h3>
<p>For unsupported appliances:</p>
<ol>
<li>Go to <strong>Cloud Apps</strong> → <strong>Cloud Discovery</strong> → <strong>Discovered apps</strong></li>
<li>Filter for <strong>Unsanctioned</strong> apps</li>
<li>Use the export capability to export all domains</li>
<li>Configure your third-party appliance to block those domains</li>
</ol>

<h3 class="relative group">Third-Party Integrations
    <div id="third-party-integrations" class="anchor"></div>
    
</h3>
<p>If you use Zscaler NSS, iboss, Corrata, Menlo, or Open Systems, these have native integrations with Defender for Cloud Apps. Apps marked as unsanctioned are automatically blocked. However, these integrations don’t support scoped device group blocking or the warn-and-educate features.</p>

<h2 class="relative group">Monitoring and Hunting
    <div id="monitoring-and-hunting" class="anchor"></div>
    
</h2>
<p>Once blocking is in place, monitor what’s happening with Advanced Hunting queries.</p>

<h3 class="relative group">Find blocks from Defender for Cloud Apps in Microsoft Edge
    <div id="find-blocks-from-defender-for-cloud-apps-in-microsoft-edge" class="anchor"></div>
    
</h3>
<div class="highlight-wrapper"><div class="highlight"><div class="ms-code-label">KQL</div><pre tabindex="0" class="chroma"><code class="language-kql" data-lang="kql">DeviceEvents
<span class="o">|</span> <span class="k">where</span> ActionType <span class="o">==</span> <span class="s">&#34;SmartScreenUrlWarning&#34;</span>
<span class="o">|</span> <span class="k">extend</span> ParsedFields = <span class="nf">parse_json</span>(AdditionalFields)
<span class="o">|</span> <span class="k">project</span> Timestamp, DeviceName, RemoteUrl, InitiatingProcessFileName, 
          Experience = <span class="nf">tostring</span>(ParsedFields.Experience)
<span class="o">|</span> <span class="k">where</span> Experience <span class="o">==</span> <span class="s">&#34;CasbPolicy&#34;</span>
<span class="o">|</span> <span class="k">summarize</span> BlockCount = <span class="k">count</span>() <span class="k">by</span> RemoteUrl, DeviceName
<span class="o">|</span> <span class="k">order by</span> BlockCount <span class="k">desc</span></code></pre></div>
</div>

<h3 class="relative group">Find blocks in Non-Edge Browsers (Network Protection)
    <div id="find-blocks-in-non-edge-browsers-network-protection" class="anchor"></div>
    
</h3>
<div class="highlight-wrapper"><div class="highlight"><div class="ms-code-label">KQL</div><pre tabindex="0" class="chroma"><code class="language-kql" data-lang="kql">DeviceEvents
<span class="o">|</span> <span class="k">where</span> ActionType <span class="o">==</span> <span class="s">&#34;ExploitGuardNetworkProtectionBlocked&#34;</span>
<span class="o">|</span> <span class="k">extend</span> ParsedFields = <span class="nf">parse_json</span>(AdditionalFields)
<span class="o">|</span> <span class="k">project</span> Timestamp, DeviceName, RemoteUrl, InitiatingProcessFileName,
          ResponseCategory = <span class="nf">tostring</span>(ParsedFields.ResponseCategory)
<span class="o">|</span> <span class="k">where</span> ResponseCategory <span class="o">==</span> <span class="s">&#34;CasbPolicy&#34;</span>
<span class="o">|</span> <span class="k">summarize</span> BlockCount = <span class="k">count</span>() <span class="k">by</span> RemoteUrl, DeviceName
<span class="o">|</span> <span class="k">order by</span> BlockCount <span class="k">desc</span></code></pre></div>
</div>

<h3 class="relative group">ResponseCategory values
    <div id="responsecategory-values" class="anchor"></div>
    
</h3>

<div class="ms-table" role="region" aria-label="Table" tabindex="0">
  <table>
      <thead>
          <tr>
              <th>ResponseCategory</th>
              <th>Source</th>
          </tr>
      </thead>
    <tbody>
        <tr>
            <td>CasbPolicy</td>
            <td>Defender for Cloud Apps</td>
        </tr>
        <tr>
            <td>CustomPolicy</td>
            <td>Web Content Filtering</td>
        </tr>
        <tr>
            <td>CustomBlockList</td>
            <td>Custom Indicators</td>
        </tr>
        <tr>
            <td>Malicious</td>
            <td>Web Threats</td>
        </tr>
        <tr>
            <td>Phishing</td>
            <td>Web Threats</td>
        </tr>
    </tbody>
  </table>
</div>

<h3 class="relative group">Find users hitting blocked apps
    <div id="find-users-hitting-blocked-apps" class="anchor"></div>
    
</h3>
<div class="highlight-wrapper"><div class="highlight"><div class="ms-code-label">KQL</div><pre tabindex="0" class="chroma"><code class="language-kql" data-lang="kql">DeviceEvents
<span class="o">|</span> <span class="k">where</span> ActionType <span class="k">in</span> (<span class="s">&#34;SmartScreenUrlWarning&#34;</span>, <span class="s">&#34;ExploitGuardNetworkProtectionBlocked&#34;</span>)
<span class="o">|</span> <span class="k">extend</span> ParsedFields = <span class="nf">parse_json</span>(AdditionalFields)
<span class="o">|</span> <span class="k">where</span> <span class="nf">tostring</span>(ParsedFields.Experience) <span class="o">==</span> <span class="s">&#34;CasbPolicy&#34;</span> 
    <span class="k">or</span> <span class="nf">tostring</span>(ParsedFields.ResponseCategory) <span class="o">==</span> <span class="s">&#34;CasbPolicy&#34;</span>
<span class="o">|</span> <span class="k">summarize</span> 
    BlockCount = <span class="k">count</span>(),
    Apps = <span class="nf">make_set</span>(RemoteUrl)
    <span class="k">by</span> AccountName, DeviceName
<span class="o">|</span> <span class="k">order by</span> BlockCount <span class="k">desc</span></code></pre></div>
</div>

<h2 class="relative group">Troubleshooting
    <div id="troubleshooting" class="anchor"></div>
    
</h2>

<h3 class="relative group">Apps not being blocked
    <div id="apps-not-being-blocked" class="anchor"></div>
    
</h3>
<p>Check the following:</p>
<ol>
<li><strong>Network Protection enabled?</strong> Must be in Block mode, not Audit. Check with PowerShell: <code>Get-MpPreference | Select-Object EnableNetworkProtection</code> Value should be <code>1</code> (Block). If it’s <code>0</code> (Disabled) or <code>2</code> (Audit), blocking won’t work.</li>
<li><strong>Custom network indicators enabled?</strong> Required in Settings → Endpoints → Advanced features</li>
<li><strong>Time elapsed?</strong> Allow up to 3 hours after unsanctioning</li>
<li><strong>Domain vs URL?</strong> Full URL paths like <code>google.com/drive</code> won’t work, only domains</li>
<li><strong>QUIC enabled?</strong> Network Protection can’t inspect QUIC traffic in non-Edge browsers. Disable QUIC protocol via browser policies or Windows Firewall.</li>
</ol>

<h3 class="relative group">Verify Indicators were created
    <div id="verify-indicators-were-created" class="anchor"></div>
    
</h3>
<ol>
<li>Go to <strong>Settings</strong> → <strong>Endpoints</strong> → <strong>Indicators</strong> → <strong>URLs/Domains</strong></li>
<li>Look for the domains from your unsanctioned apps</li>
<li>Check the Action (Block/Warn) and scope</li>
</ol>

<h3 class="relative group">Check device configuration
    <div id="check-device-configuration" class="anchor"></div>
    
</h3>
<p>On an endpoint, verify Network Protection is active:</p>
<div class="highlight-wrapper"><div class="highlight"><div class="ms-code-label">PowerShell</div><pre tabindex="0" class="chroma"><code class="language-powershell" data-lang="powershell"><span class="line"><span class="cl"><span class="nb">Get-MpPreference</span> <span class="p">|</span> <span class="nb">Select-Object</span> <span class="n">EnableNetworkProtection</span></span></span></code></pre></div></div>

<div class="ms-table" role="region" aria-label="Table" tabindex="0">
  <table>
      <thead>
          <tr>
              <th>Value</th>
              <th>State</th>
          </tr>
      </thead>
    <tbody>
        <tr>
            <td>0</td>
            <td>Disabled</td>
        </tr>
        <tr>
            <td>1</td>
            <td>Enabled (Block mode)</td>
        </tr>
        <tr>
            <td>2</td>
            <td>Audit mode</td>
        </tr>
    </tbody>
  </table>
</div>

<h2 class="relative group">Best practices
    <div id="best-practices" class="anchor"></div>
    
</h2>
<p><strong>Start with monitoring</strong>: Deploy discovery first. Let it run for a few weeks. Understand what apps are actually in use before you start blocking. Nothing kills adoption faster than blocking something the CEO uses daily.</p>
<p><strong>Create an exception process</strong>: Document how users can request access to blocked apps. Put the link on your block page.</p>
<p><strong>Communicate before blocking</strong>: Send out communications before enabling blocking policies. Give users time to find alternatives.</p>
<p><strong>Use Monitored before Unsanctioned</strong>: For apps you’re unsure about, start with warnings. If users bypass constantly, you have data to justify either formally approving or fully blocking the app.</p>
<p><strong>Review policies quarterly</strong>: The app landscape changes. New apps appear, existing apps improve their security posture, and your organization’s needs evolve.</p>
<p><strong>Don’t rely solely on risk scores</strong>: A risk score of 6 doesn’t mean an app is safe. It means Microsoft hasn’t found evidence it’s particularly risky. Do your own due diligence for apps handling sensitive data.</p>
<p><strong>Consider browser configuration</strong>: For comprehensive coverage, deploy browser policies to disable QUIC and Encrypted Client Hello in non-Edge browsers.</p>
<p><strong>Test in scoped groups first</strong>: Use device groups to pilot blocking policies before rolling out organization-wide.</p>

<h2 class="relative group">References
    <div id="references" class="anchor"></div>
    
</h2>
<p><a href="https://learn.microsoft.com/en-us/defender-endpoint/network-protection"  target="_blank" rel="noreferrer">Network protection</a></p>
<p><a href="https://learn.microsoft.com/en-us/defender-cloud-apps/mde-govern"  target="_blank" rel="noreferrer">Govern discovered apps using Microsoft Defender for Endpoint</a></p>
<p><a href="https://learn.microsoft.com/en-us/defender-cloud-apps/governance-discovery"  target="_blank" rel="noreferrer">Govern discovered apps</a></p>
<p><a href="https://learn.microsoft.com/en-us/defender-cloud-apps/mde-integration"  target="_blank" rel="noreferrer">Integrate Microsoft Defender for Endpoint with Microsoft Defender for Cloud Apps</a></p>
<p><a href="https://learn.microsoft.com/en-us/defender-cloud-apps/cloud-discovery-policies"  target="_blank" rel="noreferrer">Cloud discovery policies</a></p>
<p><a href="https://learn.microsoft.com/en-us/defender-cloud-apps/risk-score"  target="_blank" rel="noreferrer">Cloud app catalog and risk scores</a></p>
<p><a href="https://learn.microsoft.com/en-us/defender-endpoint/web-protection-overview"  target="_blank" rel="noreferrer">Web protection overview</a></p>
<p><a href="https://www.modernsecurity.nl/block-apps-microsoft-defender-for-cloud-apps/microsoft-defender-for-cloud-apps-infographic-2024-07-11.pdf" >Download</a></p>

<h2 class="relative group">Summary
    <div id="summary" class="anchor"></div>
    
</h2>
<p>The Defender for Cloud Apps and Defender for Endpoint integration provides proactive, scalable control over Shadow IT:</p>
<ol>
<li><strong>Enable the integration</strong> in Cloud Apps settings and Endpoint advanced features</li>
<li><strong>Understand the catalog</strong> and how apps are scored (1-10, lower = riskier)</li>
<li><strong>Manually unsanction</strong> specific apps for immediate blocking</li>
<li><strong>Create App Discovery policies</strong> for automated blocking based on risk score, category, or compliance</li>
<li><strong>Use scoped profiles</strong> for device group-specific blocking</li>
<li><strong>Configure warnings</strong> (Monitored) for softer enforcement</li>
<li><strong>Customize block pages</strong> to educate users</li>
<li><strong>Monitor with Advanced Hunting</strong> to track effectiveness</li>
</ol>
<p>This shifts your security posture from reactive (discovering Shadow IT after the fact) to proactive (blocking risky apps before they become incidents).</p>
]]></content:encoded><media:content url="https://www.modernsecurity.nl/block-apps-microsoft-defender-for-cloud-apps/featured_hu_f9d7676ecfd025ba.jpg" medium="image" type="image/jpeg" width="1200" height="507"/><enclosure url="https://www.modernsecurity.nl/block-apps-microsoft-defender-for-cloud-apps/featured_hu_f9d7676ecfd025ba.jpg" type="image/jpeg" length="63388"/></item><item><title>Microsoft Sentinel data lake: implementation guide</title><link>https://www.modernsecurity.nl/microsoft-sentinel-xdr-data-lake-guide/</link><guid isPermaLink="true">https://www.modernsecurity.nl/microsoft-sentinel-xdr-data-lake-guide/</guid><pubDate>Sat, 20 Sep 2025 20:20:41 +0100</pubDate><dc:creator>Farid Kalaidji</dc:creator><category>Microsoft Sentinel</category><category>Microsoft Defender XDR</category><description>Guide to implement Microsoft Sentinel data lake step-by-step, cost optimization, DCR transformation, advanced analytics and management.</description><content:encoded><![CDATA[
<h2 class="relative group">Introduction
    <div id="introduction" class="anchor"></div>
    
</h2>

<h3 class="relative group">What is Microsoft Sentinel data lake
    <div id="what-is-microsoft-sentinel-data-lake" class="anchor"></div>
    
</h3>
<p>Microsoft Sentinel data lake is a purpose-built, cloud-native security data platform that addresses the fundamental challenge organizations face between comprehensive security coverage and cost sustainability. The platform transforms how organizations manage and analyze security data through:</p>
<ol>
<li><strong>Unifying security data</strong> across <a href="https://www.modernsecurity.nl/microsoft-defender-xdr/" >Microsoft Defender XDR</a>, third-party sources, assets, activity logs, and threat intelligence</li>
<li><strong>Optimizing costs</strong> with tiered storage, on-demand data promotion, and single copy architecture</li>
<li><strong>Enabling deep security insights</strong> with up to 12 years of queryable security data</li>
<li><strong>Powering AI and automation</strong> for faster detection and response</li>
</ol>
<figure><img
    class="my-0 rounded-md"
    loading="lazy"
    decoding="async"
    fetchpriority="auto"
    alt=""
    width="1921"
    height="1080"
    src="https://www.modernsecurity.nl/microsoft-sentinel-xdr-data-lake-guide/ms-security-sentinel-datalake-infographic-datalake-light-alt-png-4_hu_adabb74104ed4b77.webp"
   
   
    data-zoom-src="https://www.modernsecurity.nl/microsoft-sentinel-xdr-data-lake-guide/ms-security-sentinel-datalake-infographic-datalake-light-alt-png-4.webp"></figure>
<h3 class="relative group">The business challenge solved
    <div id="the-business-challenge-solved" class="anchor"></div>
    
</h3>
<p>Traditional SIEM solutions struggle with the cost and complexity of storing and querying long-term security data. Organizations often face impossible choices between comprehensive security coverage and budget constraints. Microsoft Sentinel data lake solves these challenges through centralized data management, cost-effective storage with significantly lower per-GB costs for historical data, maintained query capabilities ensuring no loss of analytical functionality, and automated data lifecycle management reducing operational overhead.</p>

<h3 class="relative group">Two-tier architecture benefits
    <div id="two-tier-architecture-benefits" class="anchor"></div>
    
</h3>
<figure><img
    class="my-0 rounded-md"
    loading="lazy"
    decoding="async"
    fetchpriority="low"
    alt="Data tiers architecture"
    src="https://learn.microsoft.com/en-us/azure/sentinel/datalake/media/setting-up-sentinel-data-lake/data-tiers.png"
    ></figure><p>Microsoft Sentinel data lake implements a sophisticated two-tier architecture optimized for both cost and performance:</p>

<div class="ms-table" role="region" aria-label="Table" tabindex="0">
  <table>
      <thead>
          <tr>
              <th><strong>Feature</strong></th>
              <th><strong>Analytics tier</strong></th>
              <th><strong>Data lake tier</strong></th>
          </tr>
      </thead>
    <tbody>
        <tr>
            <td><strong>Key characteristics</strong></td>
            <td>High-performance querying and indexing (hot/interactive retention)</td>
            <td>Cost-effective long-term retention (cold storage)</td>
        </tr>
        <tr>
            <td><strong>Best use cases</strong></td>
            <td>Real-time analytics rules, alerting, hunting, workbooks, all Sentinel SIEM features</td>
            <td>Compliance and regulatory logging, historical trend analysis and forensics, low-touch data not needed for real-time alerts</td>
        </tr>
        <tr>
            <td><strong>Query price included</strong></td>
            <td>Yes – queries included in ingestion cost</td>
            <td>No – queries charged separately at $0.005/GB scanned</td>
        </tr>
        <tr>
            <td><strong>Query performance</strong></td>
            <td>Optimized – sub-second response for recent data</td>
            <td>Slower – optimized for large-scale scans, good for auditing</td>
        </tr>
        <tr>
            <td><strong>Query capabilities</strong></td>
            <td>Full KQL in Defender and Azure portals via APIs</td>
            <td>Full KQL on single table with lookup enrichment, scheduled KQL/Spark jobs, Jupyter notebooks</td>
        </tr>
        <tr>
            <td><strong>Real-time analytics features</strong></td>
            <td>Yes – all detection rules, alerts, workbooks, hunting queries</td>
            <td>No – limitations on analytics rules, hunting queries, parsers, watchlists, workbooks, playbooks</td>
        </tr>
        <tr>
            <td><strong>Search jobs</strong></td>
            <td>Supported</td>
            <td>Supported</td>
        </tr>
        <tr>
            <td><strong>Summary rules</strong></td>
            <td>Supported</td>
            <td>Supported – Full KQL on single table, extendable with analytics table lookups</td>
        </tr>
        <tr>
            <td><strong>Restore capability</strong></td>
            <td>Supported</td>
            <td>Not supported</td>
        </tr>
        <tr>
            <td><strong>Data export</strong></td>
            <td>Supported</td>
            <td>Not supported</td>
        </tr>
        <tr>
            <td><strong>Retention period</strong></td>
            <td>90 days (Sentinel) / 30 days (Defender XDR), extendable to 2 years with prorated monthly charge</td>
            <td>Same as analytics by default, extendable to 12 years</td>
        </tr>
    </tbody>
  </table>
</div>
<p><strong>Critical Note:</strong> Data processing charge ($0.10/GB) applies ONLY to data ingested directly to data lake tier only. Data mirrored from analytics tier incurs NO processing charge.</p>

<h3 class="relative group">Key advantages over Azure Data Explorer (ADX)
    <div id="key-advantages-over-azure-data-explorer-adx" class="anchor"></div>
    
</h3>
<p>While Azure Data Explorer remains a powerful platform, it demands significant administrative investment. Organizations using ADX must manually create and maintain table structures, custom functions, monitoring systems, and data mappings. The Sentinel data lake eliminates this operational burden by having Microsoft handle the underlying infrastructure management.</p>

<h3 class="relative group">Impact on Auxiliary logging
    <div id="impact-on-auxiliary-logging" class="anchor"></div>
    
</h3>
<p>When organizations enable the Sentinel data lake, auxiliary log tables automatically disappear from both Defender Advanced Hunting and the Microsoft Sentinel portal interface. However, this data isn’t lost. It’s seamlessly migrated to the data lake environment where analysts can access it through KQL queries or Jupyter notebooks. This transition represents an automatic upgrade from auxiliary table storage to a more scalable data lake architecture.</p>

<h2 class="relative group">Prerequisites and requirements
    <div id="prerequisites-and-requirements" class="anchor"></div>
    
</h2>

<h3 class="relative group">Required permissions
    <div id="required-permissions" class="anchor"></div>
    
</h3>
<p>You need specific roles across different scopes:</p>

<div class="ms-table" role="region" aria-label="Table" tabindex="0">
  <table>
      <thead>
          <tr>
              <th>Permission Scope</th>
              <th>Required Role</th>
              <th>Purpose</th>
          </tr>
      </thead>
    <tbody>
        <tr>
            <td><strong>Azure Subscription</strong></td>
            <td>Subscription Owner</td>
            <td>Billing setup and resource creation</td>
        </tr>
        <tr>
            <td><strong>Microsoft Entra ID</strong></td>
            <td>Global Administrator OR Security Administrator</td>
            <td>Cross-tenant security platform configuration</td>
        </tr>
        <tr>
            <td><strong>Workspace Level</strong></td>
            <td>Microsoft Sentinel Reader</td>
            <td>Access to all participating workspaces</td>
        </tr>
    </tbody>
  </table>
</div>

<h3 class="relative group">Technical prerequisites
    <div id="technical-prerequisites" class="anchor"></div>
    
</h3>
<p><strong>Infrastructure requirements:</strong></p>
<ul>
<li>Existing Azure subscription with billing access</li>
<li>Resource group (existing or new) – <strong>cannot be changed after setup</strong></li>
<li>Microsoft Sentinel workspace(s) in correct region</li>
<li>Microsoft Sentinel primary workspace is connected to the Microsoft Defender XDR portal</li>
</ul>

<h2 class="relative group">Pricing model
    <div id="pricing-model" class="anchor"></div>
    
</h2>
<p>Understanding the cost structure of Microsoft Sentinel data lake is essential for planning your implementation and maximizing cost savings. The platform uses a consumption-based pricing model with distinct meters for ingestion, storage, processing, and compute.</p>
<p>The pricing model underwent changes as the platform transitioned from public preview to general availability. Most notably, data processing and asset data ingestion now incur charges, though these costs are offset by the substantial savings on storage and the elimination of analytics tier ingestion costs for appropriately routed data.</p>

<h3 class="relative group">Current pricing structure
    <div id="current-pricing-structure" class="anchor"></div>
    
</h3>

<div class="ms-table" role="region" aria-label="Table" tabindex="0">
  <table>
      <thead>
          <tr>
              <th><strong>Cost component</strong></th>
              <th><strong>Rate</strong></th>
              <th><strong>What it covers</strong></th>
          </tr>
      </thead>
    <tbody>
        <tr>
            <td><strong>Data lake ingestion</strong></td>
            <td>$0.05/GB</td>
            <td>Data entering data lake tier directly</td>
        </tr>
        <tr>
            <td><strong>Data processing</strong></td>
            <td>$0.10/GB</td>
            <td>All transformations (filtering, normalization, enrichment)</td>
        </tr>
        <tr>
            <td><strong>Data lake storage</strong></td>
            <td>$0.026/GB/month</td>
            <td>Storage beyond 30-day included period (6:1 compression applied)</td>
        </tr>
        <tr>
            <td><strong>Query execution</strong></td>
            <td>$0.005/GB</td>
            <td>Data scanned during KQL queries and jobs</td>
        </tr>
        <tr>
            <td><strong>Jupyter notebook compute</strong></td>
            <td>$0.15/compute hour</td>
            <td>Notebook sessions (cores × session time)</td>
        </tr>
        <tr>
            <td><strong>Asset data ingestion</strong></td>
            <td>$0.05/GB</td>
            <td>Entra ID, Microsoft 365, and Azure asset connector data</td>
        </tr>
    </tbody>
  </table>
</div>
<p><strong>For comparison – Analytics tier:</strong> $2.30-$4.60/GB ingestion (region and commitment dependent)</p>

<h3 class="relative group">Critical pricing notes
    <div id="critical-pricing-notes" class="anchor"></div>
    
</h3>
<p><strong>Included with ingestion:</strong></p>
<ul>
<li>30 days of storage included – No separate storage charges for first 30 days</li>
<li>No double billing – Data mirrored from analytics tier to data lake incurs no additional ingestion charges</li>
</ul>
<p><strong>Sentinel-specific advantage:</strong></p>
<ul>
<li>Filtering exemption – Sentinel workspaces have NO penalty charges for DCR filtering, regardless of volume reduction percentage (Standard Log Analytics charges penalties for filtering &gt;50%)</li>
</ul>
<p><strong>Uniform compression:</strong></p>
<ul>
<li>6:1 compression ratio – Applied consistently across all data sources for storage billing</li>
</ul>
<p><strong>October 2025 changes:</strong></p>
<ul>
<li>Data processing ($0.10/GB) – Now charged (was free during preview)</li>
<li>Asset data ingestion ($0.05/GB) – Now charged (was free during preview)</li>
</ul>

<h2 class="relative group">Data lake onboarding
    <div id="data-lake-onboarding" class="anchor"></div>
    
</h2>

<h3 class="relative group">Step 1: Initiate onboarding process
    <div id="step-1-initiate-onboarding-process" class="anchor"></div>
    
</h3>
<figure><img
    class="my-0 rounded-md"
    loading="lazy"
    decoding="async"
    fetchpriority="auto"
    alt=""
    width="1854"
    height="999"
    src="https://www.modernsecurity.nl/microsoft-sentinel-xdr-data-lake-guide/image_hu_7ca942deffe1e3c7.webp"
   
   
    data-zoom-src="https://www.modernsecurity.nl/microsoft-sentinel-xdr-data-lake-guide/image.webp"></figure><p><strong>Method 1: Via onboarding banner</strong></p>
<ol>
<li>Sign in to <a href="https://security.microsoft.com/"  target="_blank" rel="noreferrer">Microsoft Defender Portal</a></li>
<li>Look for data lake onboarding banner at top of page</li>
<li>Click <strong>Get started</strong></li>
</ol>
<p><strong>Method 2: Via settings navigation</strong></p>
<ol>
<li>Navigate to <strong>System</strong> → <strong>Settings</strong> → <strong>Microsoft Sentinel</strong> → <strong>Data lake</strong></li>
<li>Click <strong>Set up data lake</strong></li>
</ol>

<h3 class="relative group">Step 2: Permission validation screen
    <div id="step-2-permission-validation-screen" class="anchor"></div>
    
</h3>
<p>If you encounter the permissions screen, refer to the requirements above for required permissions.</p>

<h3 class="relative group">Step 3: Billing configuration
    <div id="step-3-billing-configuration" class="anchor"></div>
    
</h3>
<ul>
<li><strong>Subscription</strong>: Choose billing subscription carefully</li>
<li><strong>Resource group</strong>: Select or create resource group for data lake resources</li>
</ul>
<figure><img
    class="my-0 rounded-md"
    loading="lazy"
    decoding="async"
    fetchpriority="auto"
    alt=""
    width="589"
    height="1227"
    src="https://www.modernsecurity.nl/microsoft-sentinel-xdr-data-lake-guide/image-3.webp"
   
   
    data-zoom-src="https://www.modernsecurity.nl/microsoft-sentinel-xdr-data-lake-guide/image-3.webp"></figure><p>Click <strong>Set up data lake</strong> to begin provisioning process.</p>

<h3 class="relative group">Step 4: Monitor setup progress
    <div id="step-4-monitor-setup-progress" class="anchor"></div>
    
</h3>
<figure><img
    class="my-0 rounded-md"
    loading="lazy"
    decoding="async"
    fetchpriority="auto"
    alt=""
    width="1853"
    height="999"
    src="https://www.modernsecurity.nl/microsoft-sentinel-xdr-data-lake-guide/image-3-2_hu_f837fc3d152919a4.webp"
   
   
    data-zoom-src="https://www.modernsecurity.nl/microsoft-sentinel-xdr-data-lake-guide/image-3-2.webp"></figure><p><strong>Setup timeline:</strong> Refer to the Critical Requirements Reference box above for detailed timeline expectations.</p>

<h3 class="relative group">Step 5: Validate successful completion
    <div id="step-5-validate-successful-completion" class="anchor"></div>
    
</h3>
<figure><img
    class="my-0 rounded-md"
    loading="lazy"
    decoding="async"
    fetchpriority="auto"
    alt=""
    width="1851"
    height="998"
    src="https://www.modernsecurity.nl/microsoft-sentinel-xdr-data-lake-guide/image-4_hu_8fee1d8fe1c07c99.webp"
   
   
    data-zoom-src="https://www.modernsecurity.nl/microsoft-sentinel-xdr-data-lake-guide/image-4.webp"></figure><p><strong>Success indicators:</strong></p>
<ul>
<li>Completion banner <strong>Your data lake is ready</strong> with feature access cards</li>
<li>New navigation option: <strong>Data lake exploration</strong> under <strong>Sentinel</strong></li>
<li>Enhanced <strong>Tables</strong> management capabilities</li>
<li><strong>Jobs</strong> section becomes available</li>
</ul>
<figure><img
    class="my-0 rounded-md"
    loading="lazy"
    decoding="async"
    fetchpriority="auto"
    alt=""
    width="1854"
    height="997"
    src="https://www.modernsecurity.nl/microsoft-sentinel-xdr-data-lake-guide/image-4-2_hu_9bf76a670c4ef8b.webp"
   
   
    data-zoom-src="https://www.modernsecurity.nl/microsoft-sentinel-xdr-data-lake-guide/image-4-2.webp"></figure>
<h2 class="relative group">Data Connectors
    <div id="data-connectors" class="anchor"></div>
    
</h2>
<figure><img
    class="my-0 rounded-md"
    loading="lazy"
    decoding="async"
    fetchpriority="auto"
    alt=""
    width="1007"
    height="551"
    src="https://www.modernsecurity.nl/microsoft-sentinel-xdr-data-lake-guide/data-transformation-architecture_hu_71f350ca8e4ee827.webp"
   
   
    data-zoom-src="https://www.modernsecurity.nl/microsoft-sentinel-xdr-data-lake-guide/data-transformation-architecture.webp"></figure><p>Microsoft Sentinel data lake works with all existing Sentinel data connectors, including:</p>
<ul>
<li>DNS, proxy, and email telemetry</li>
<li>All Microsoft Defender XDR and Microsoft Sentinel data sources</li>
<li>Microsoft 365</li>
<li>Microsoft Entra ID</li>
<li>Microsoft Resource Graph</li>
<li>Endpoint Detection and Response (EDR) platforms</li>
<li>Firewall and network logs</li>
<li>Cloud infrastructure and workload telemetry</li>
<li>Identity and access logs (Microsoft Entra, Okta, etc.)</li>
</ul>
<p>Below the steps to activate for example the Defender XDR data connector (in case you haven’t got it enabled yet).</p>
<p><strong>Access XDR data connector</strong></p>
<ol>
<li>Navigate to <strong>Microsoft Defender Portal</strong> → <strong>Microsoft Sentinel</strong> → <strong>Configuration</strong> → <strong>Data connectors</strong></li>
<li>Search for “Microsoft Defender XDR” in the connector gallery</li>
<li>Click <strong>Open connector page</strong></li>
</ol>
<figure><img
    class="my-0 rounded-md"
    loading="lazy"
    decoding="async"
    fetchpriority="auto"
    alt=""
    width="1853"
    height="996"
    src="https://www.modernsecurity.nl/microsoft-sentinel-xdr-data-lake-guide/image-5_hu_fd2a354aebcf2ca5.webp"
   
   
    data-zoom-src="https://www.modernsecurity.nl/microsoft-sentinel-xdr-data-lake-guide/image-5.webp"></figure><p><strong>Configure integration components</strong> The XDR connector configuration includes three main sections:</p>
<ol>
<li><strong>Connect incidents and alerts</strong>: Enables basic integration for incident synchronization between platforms</li>
<li><strong>Connect entities</strong>: Integrates on-premises Active Directory user identities through Microsoft Defender for Identity</li>
<li><strong>Connect events</strong>: Enables collection of raw advanced hunting events from Defender components</li>
</ol>
<p><strong>Understanding XDR data streams</strong></p>
<p><strong>Free data streams (included with XDR integration):</strong></p>
<ul>
<li><strong>SecurityAlert</strong>: Alerts from all Defender products</li>
<li><strong>SecurityIncident</strong>: Unified incident management data</li>
<li><strong>Bi-directional synchronization</strong>: Incidents sync between Sentinel and Defender portals</li>
</ul>
<p><strong>Paid data streams (require analytics tier ingestion):</strong></p>
<ul>
<li><strong>DeviceProcessEvents</strong>: Process execution and command-line data</li>
<li><strong>DeviceNetworkEvents</strong>: Network connection and communication data</li>
<li><strong>DeviceFileEvents</strong>: File creation, modification, and access events</li>
<li><strong>DeviceLogonEvents</strong>: Authentication and session data</li>
<li><strong>EmailEvents</strong>: Email security and communication data</li>
<li><strong>CloudAppEvents</strong>: Cloud application activity and security events</li>
<li><strong>IdentityLogonEvents</strong>: Identity provider authentication events</li>
</ul>
<p><mark>If you’ve Sentinel setup before and transitioned to the Unified Experience (Defender portal), existing connectors continue working without interruption. However, Microsoft Defender connectors (XDR, Endpoint, Identity, Office 365, Cloud Apps, and Defender for Cloud) won’t appear in the Data connectors tab under Sentinel. They’re automatically managed as part of the unified experience. To view these connectors, access Microsoft Sentinel through the Azure portal or from Exposure Management (only the status):</mark></p>
<figure><img
    class="my-0 rounded-md"
    loading="lazy"
    decoding="async"
    fetchpriority="auto"
    alt=""
    width="1848"
    height="993"
    src="https://www.modernsecurity.nl/microsoft-sentinel-xdr-data-lake-guide/image-6_hu_17a9770d1b6c8615.webp"
   
   
    data-zoom-src="https://www.modernsecurity.nl/microsoft-sentinel-xdr-data-lake-guide/image-6.webp"></figure>
<h2 class="relative group">Retention configuration and management
    <div id="retention-configuration-and-management" class="anchor"></div>
    
</h2>

<h2 class="relative group">Understanding data mirroring behavior
    <div id="understanding-data-mirroring-behavior" class="anchor"></div>
    
</h2>
<p>When you enable data lake, automatic mirroring begins for all tables from the onboarding point forward with these characteristics:</p>
<ul>
<li><strong>Forward-looking only:</strong> Historical data existing before onboarding is not mirrored</li>
<li><strong>Automatic mirroring:</strong> All existing connectors automatically mirror data to data lake</li>
<li><strong>Consistent retention initially:</strong> Data lake tier matches analytics tier retention settings</li>
<li><strong>Single copy architecture:</strong> Same data serves both tiers without duplication</li>
</ul>

<h2 class="relative group">The Data lake retention model
    <div id="the-data-lake-retention-model" class="anchor"></div>
    
</h2>
<p>As covered earlier, Data Lake uses a two-tier model:</p>

<div class="ms-table" role="region" aria-label="Table" tabindex="0">
  <table>
      <thead>
          <tr>
              <th>Tier</th>
              <th>Default retention</th>
              <th>Maximum retention</th>
              <th>Purpose</th>
          </tr>
      </thead>
    <tbody>
        <tr>
            <td><strong>Analytics tier (hot)</strong></td>
            <td>30 days</td>
            <td>2 years</td>
            <td>Real-time detection, hunting, analytics</td>
        </tr>
        <tr>
            <td><strong>Data lake tier (cold)</strong></td>
            <td>Mirrors analytics</td>
            <td>12 years</td>
            <td>Long-term compliance, historical analysis</td>
        </tr>
    </tbody>
  </table>
</div>
<p><strong>Key cost insight:</strong> For <strong>Sentinel solution tables</strong>, 90 days of analytics tier storage is free (you only pay ingestion). For <strong>XDR tables</strong>, only 30 days is included in the XDR license. Data lake storage beyond analytics retention incurs additional costs.</p>

<h2 class="relative group">Special case: XDR tables and data lake
    <div id="special-case-xdr-tables-and-data-lake" class="anchor"></div>
    
</h2>
<p>XDR tables behave fundamentally differently than regular Sentinel solution tables, particularly around costs and retention:</p>

<h3 class="relative group">Understanding XDR table tiers:
    <div id="understanding-xdr-table-tiers" class="anchor"></div>
    
</h3>
<p>Before they’re ingested into your Sentinel workspace, XDR tables exist in what’s called the <strong>“XDR default tier”</strong> – essentially a 30-day buffer managed by the Defender XDR service. This data is:</p>
<ul>
<li>Included in your Defender XDR license (already paid for)</li>
<li>Available via Advanced Hunting in Defender portal</li>
<li>View-only and doesn’t participate in the data lake architecture</li>
<li><strong>Not</strong> ingested into Sentinel (so no Sentinel ingestion costs)</li>
</ul>
<figure><img
    class="my-0 rounded-md"
    loading="lazy"
    decoding="async"
    fetchpriority="auto"
    alt=""
    width="2000"
    height="777"
    src="https://www.modernsecurity.nl/microsoft-sentinel-xdr-data-lake-guide/tiers-retention-defender-portal-1_hu_570eb0d4dfa3f3f2.webp"
   
   
    data-zoom-src="https://www.modernsecurity.nl/microsoft-sentinel-xdr-data-lake-guide/tiers-retention-defender-portal-1.webp"></figure>
<div class="ms-table" role="region" aria-label="Table" tabindex="0">
  <table>
      <thead>
          <tr>
              <th>Table type</th>
              <th>Minimum analytics</th>
              <th>Can use data lake?</th>
              <th>Note</th>
          </tr>
      </thead>
    <tbody>
        <tr>
            <td><strong>Sentinel/Custom</strong></td>
            <td>30 days</td>
            <td>✅ Yes</td>
            <td>Standard data lake behavior, 90 days free storage</td>
        </tr>
        <tr>
            <td><strong>XDR (not ingested)</strong></td>
            <td>N/A (30-day XDR default)</td>
            <td>❌ No</td>
            <td>Must ingest first by setting retention &gt; 30 days</td>
        </tr>
        <tr>
            <td><strong>XDR (ingested)</strong></td>
            <td>30 days minimum</td>
            <td>✅ Yes</td>
            <td>Now follows standard data lake model <strong>with costs</strong></td>
        </tr>
    </tbody>
  </table>
</div>

<h3 class="relative group">Two methods for extending XDR table retention:
    <div id="two-methods-for-extending-xdr-table-retention" class="anchor"></div>
    
</h3>
<p><strong>Method 1: Standard ingestion (covered in this section)</strong></p>
<ul>
<li>Set analytics retention &gt; 30 days in Defender portal</li>
<li>XDR data ingests into Sentinel Analytics tier (<strong>expensive ingestion costs</strong>)</li>
<li>Then automatically mirrors to data lake</li>
</ul>
<p><strong>Method 2: DCR transformation (cost-optimized)</strong></p>
<ul>
<li>Bypass expensive Analytics tier ingestion entirely</li>
<li>Route XDR data directly to data lake using custom tables</li>
<li>Massive cost savings for compliance/archival scenarios</li>
<li><strong>Covered in next section:</strong> “Optimizing XDR costs with DCR transformations”</li>
</ul>

<h2 class="relative group">How to check current retention configuration
    <div id="how-to-check-current-retention-configuration" class="anchor"></div>
    
</h2>

<h3 class="relative group">Step 1: Navigate to table management
    <div id="step-1-navigate-to-table-management" class="anchor"></div>
    
</h3>
<p>Open <strong>Microsoft Defender Portal</strong> → <strong>Microsoft Sentinel</strong> → <strong>Configuration</strong> → <strong>Tables</strong></p>
<p>You’ll see a list of all tables with their current retention settings</p>
<figure><img
    class="my-0 rounded-md"
    loading="lazy"
    decoding="async"
    fetchpriority="auto"
    alt=""
    width="1853"
    height="999"
    src="https://www.modernsecurity.nl/microsoft-sentinel-xdr-data-lake-guide/image-17_hu_ff287d9def39e06c.webp"
   
   
    data-zoom-src="https://www.modernsecurity.nl/microsoft-sentinel-xdr-data-lake-guide/image-17.webp"></figure>
<h3 class="relative group">Step 2: Review retention overview
    <div id="step-2-review-retention-overview" class="anchor"></div>
    
</h3>
<p>The table list displays key information:</p>

<div class="ms-table" role="region" aria-label="Table" tabindex="0">
  <table>
      <thead>
          <tr>
              <th>Column</th>
              <th>Description</th>
          </tr>
      </thead>
    <tbody>
        <tr>
            <td><strong>Table name</strong></td>
            <td>Name of the table</td>
        </tr>
        <tr>
            <td><strong>Workspace</strong></td>
            <td>Which Log Analytics workspace</td>
        </tr>
        <tr>
            <td><strong>Tier</strong></td>
            <td>Analytics, Data Lake, or XDR default</td>
        </tr>
        <tr>
            <td><strong>Analytics retention</strong></td>
            <td>Hot storage duration</td>
        </tr>
        <tr>
            <td><strong>Total retention</strong></td>
            <td>Analytics + data lake combined</td>
        </tr>
    </tbody>
  </table>
</div>

<h3 class="relative group">Step 3: Check detailed retention for a specific table
    <div id="step-3-check-detailed-retention-for-a-specific-table" class="anchor"></div>
    
</h3>
<ol>
<li>Click on any table name</li>
<li>A details panel opens on the right showing:
<ul>
<li>Current tier (Analytics, data lake, or XDR default)</li>
<li>Analytics retention period</li>
<li>Total retention period</li>
</ul>
</li>
</ol>
<figure><img
    class="my-0 rounded-md"
    loading="lazy"
    decoding="async"
    fetchpriority="auto"
    alt=""
    width="1855"
    height="999"
    src="https://www.modernsecurity.nl/microsoft-sentinel-xdr-data-lake-guide/image-18_hu_e9afd34993783297.webp"
   
   
    data-zoom-src="https://www.modernsecurity.nl/microsoft-sentinel-xdr-data-lake-guide/image-18.webp"></figure>
<h2 class="relative group">How to change retention configuration
    <div id="how-to-change-retention-configuration" class="anchor"></div>
    
</h2>

<h3 class="relative group">For Sentinel and custom tables:
    <div id="for-sentinel-and-custom-tables" class="anchor"></div>
    
</h3>
<p><strong>Step 1:</strong> Navigate to <strong>Microsoft Defender Portal</strong> → <strong>Microsoft Sentinel</strong> → <strong>Configuration</strong> → <strong>Tables</strong></p>
<p><strong>Step 2:</strong> Click on your table → Click <strong>Manage table</strong></p>
<p><strong>Step 3:</strong> Configure retention:</p>
<ul>
<li><strong>Analytics retention:</strong> 30 days to 2 years (hot storage)</li>
<li><strong>Total retention:</strong> Equal to or greater than analytics, max 12 years (hot + cold)</li>
</ul>
<p><strong>Step 4:</strong> Click <strong>Save</strong></p>

<h4 class="relative group">Example configuration:
    <div id="example-configuration" class="anchor"></div>
    
</h4>
<p><strong>Scenario:</strong> Need 1 year total retention for a Sentinel solution table</p>
<p><strong>Configuration:</strong></p>
<ul>
<li>Analytics retention: <strong>90 days</strong> (free for Sentinel tables)</li>
<li>Total retention: <strong>1 year</strong> (365 days)</li>
</ul>
<p><strong>Result:</strong> 90 days in analytics + 275 days in data lake</p>
<p><strong>Cost:</strong> Only data lake storage for days 91-365 (analytics storage is free)</p>
<figure><img
    class="my-0 rounded-md"
    loading="lazy"
    decoding="async"
    fetchpriority="auto"
    alt=""
    width="1569"
    height="922"
    src="https://www.modernsecurity.nl/microsoft-sentinel-xdr-data-lake-guide/image-19_hu_3cc3847d45588786.webp"
   
   
    data-zoom-src="https://www.modernsecurity.nl/microsoft-sentinel-xdr-data-lake-guide/image-19.webp"></figure><p><strong>Cost tip:</strong> You can also fully skip the analytics tier for some tables – this results in lower cost, but loses real-time analytics features like alerting, hunting queries, and analytics rules. Make sure you understand what functionality breaks before doing this:</p>
<figure><img
    class="my-0 rounded-md"
    loading="lazy"
    decoding="async"
    fetchpriority="auto"
    alt=""
    width="1569"
    height="921"
    src="https://www.modernsecurity.nl/microsoft-sentinel-xdr-data-lake-guide/image-20_hu_54f3652d6c11dfa.webp"
   
   
    data-zoom-src="https://www.modernsecurity.nl/microsoft-sentinel-xdr-data-lake-guide/image-20.webp"></figure>
<h3 class="relative group">For XDR tables (enabling data lake – standard method):
    <div id="for-xdr-tables-enabling-data-lake-standard-method" class="anchor"></div>
    
</h3>
<p><mark><strong>IMPORTANT COST NOTICE:</strong> This method incurs significant Analytics tier ingestion costs. XDR tables only have 30 days included in your license (not 90 like Sentinel tables). Every day beyond 30 requires paying full Sentinel ingestion rates before data reaches the data lake. See the next section for a cost-optimized alternative via DCR.</mark></p>
<p><strong>Step 1:</strong> Navigate to <strong>Tables</strong> → Locate XDR table showing “XDR default tier”</p>
<p>Examples: DeviceEvents, EmailEvents, IdentityInfo, AlertEvidence, DeviceProcessEvents</p>
<p><strong>Step 2:</strong> Click on the XDR table → Click <strong>Manage table</strong></p>
<p><strong>Step 3:</strong> Set analytics retention &gt; 30 days</p>
<p><strong>This triggers ingestion into Sentinel and incurs expensive ingestion costs</strong><br>
Common values: 60, 90, 180, 365 days (preferable 90 days if using standard method)</p>
<p><strong>Step 4:</strong> Set total retention (equal to or greater than analytics)</p>
<p>Example: 365 days for 1-year compliance</p>
<p><strong>Step 5:</strong> Review cost warnings → Click <strong>Save</strong></p>
<figure><img
    class="my-0 rounded-md"
    loading="lazy"
    decoding="async"
    fetchpriority="auto"
    alt=""
    width="1570"
    height="921"
    src="https://www.modernsecurity.nl/microsoft-sentinel-xdr-data-lake-guide/image-21_hu_b75b4682b9c569cc.webp"
   
   
    data-zoom-src="https://www.modernsecurity.nl/microsoft-sentinel-xdr-data-lake-guide/image-21.webp"></figure><figure><img
    class="my-0 rounded-md"
    loading="lazy"
    decoding="async"
    fetchpriority="auto"
    alt=""
    width="1567"
    height="920"
    src="https://www.modernsecurity.nl/microsoft-sentinel-xdr-data-lake-guide/image-22_hu_3ac74b2848596fb8.webp"
   
   
    data-zoom-src="https://www.modernsecurity.nl/microsoft-sentinel-xdr-data-lake-guide/image-22.webp"></figure>
<h4 class="relative group">What happens:
    <div id="what-happens" class="anchor"></div>
    
</h4>
<ul>
<li>Ingestion begins immediately (<strong>costs start here</strong>)</li>
<li>Data flows: XDR → Sentinel Analytics tier (<strong>expensive</strong>) → Data lake mirror</li>
<li>Table type changes from “XDR default” to “Microsoft Sentinel”</li>
<li>You’re now paying for both Analytics ingestion + any data lake storage beyond analytics retention</li>
</ul>
<p><strong>To stop ingestion:</strong> Set both Analytics and Total retention back to 30 days</p>

<h4 class="relative group">Cost breakdown example for XDR tables:
    <div id="cost-breakdown-example-for-xdr-tables" class="anchor"></div>
    
</h4>

<div class="ms-table" role="region" aria-label="Table" tabindex="0">
  <table>
      <thead>
          <tr>
              <th>Scenario</th>
              <th>Analytics</th>
              <th>Total</th>
              <th>Cost structure</th>
          </tr>
      </thead>
    <tbody>
        <tr>
            <td>Stay in XDR default</td>
            <td>30 days</td>
            <td>30 days</td>
            <td><strong>$0</strong> – Included in license</td>
        </tr>
        <tr>
            <td>Standard method</td>
            <td>90 days</td>
            <td>90 days</td>
            <td><strong>Analytics ingestion for 90 days</strong> (expensive)</td>
        </tr>
        <tr>
            <td>Standard + compliance</td>
            <td>90 days</td>
            <td>1 year</td>
            <td><strong>Analytics ingestion for 90 days</strong> + Data lake storage (days 91-365)</td>
        </tr>
    </tbody>
  </table>
</div>
<p><strong>Next section:</strong> Learn how to bypass these expensive ingestion costs using DCR transformations to send XDR data directly to data lake tier (<em><strong>especially handy for noisy tables</strong></em>).</p>

<h2 class="relative group">Recommended retention configurations
    <div id="recommended-retention-configurations" class="anchor"></div>
    
</h2>

<div class="ms-table" role="region" aria-label="Table" tabindex="0">
  <table>
      <thead>
          <tr>
              <th>Scenario</th>
              <th>Analytics</th>
              <th>Total</th>
              <th>Use case</th>
          </tr>
      </thead>
    <tbody>
        <tr>
            <td><strong>Standard operations</strong></td>
            <td>90 days</td>
            <td>90 days</td>
            <td>Active security operations, no extended compliance</td>
        </tr>
        <tr>
            <td><strong>Balanced approach</strong></td>
            <td>90 days</td>
            <td>365 days</td>
            <td>Operations with 1-year compliance</td>
        </tr>
        <tr>
            <td><strong>Extended compliance</strong></td>
            <td>90 days</td>
            <td>2-7 years</td>
            <td>Regulatory requirements (GDPR, HIPAA)</td>
        </tr>
        <tr>
            <td><strong>Cost-optimized</strong></td>
            <td>30 days</td>
            <td>365 days – 7 years</td>
            <td>Minimal hot storage, extended cold storage</td>
        </tr>
    </tbody>
  </table>
</div>

<h2 class="relative group">Optimizing XDR costs with DCR transformations
    <div id="optimizing-xdr-costs-with-dcr-transformations" class="anchor"></div>
    
</h2>

<h3 class="relative group">The cost problem
    <div id="the-cost-problem" class="anchor"></div>
    
</h3>
<p>As we explored in the previous section, extending XDR table retention beyond 30 days using the standard method triggers expensive Analytics tier ingestion. The warning dialog makes this clear: increasing retention moves your XDR data to Sentinel and incurs ingestion costs.</p>
<p><strong>The impact:</strong> 1TB/day of XDR data = ~$96,000/month in ingestion costs alone. For many organizations, this makes long-term retention financially prohibitive, even when required for compliance.</p>

<h3 class="relative group">Understanding the optimization approach
    <div id="understanding-the-optimization-approach" class="anchor"></div>
    
</h3>
<p>The key insight is that XDR data already exists for free in your environment – it’s included in your Defender XDR license and available via Advanced Hunting for 30 days. The problem is the expensive journey it takes when you need to keep it longer.</p>
<p><strong>Standard flow (expensive):</strong></p>
<div class="highlight-wrapper"><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="cl">XDR Advanced Hunting (30d free) → Analytics Tier Ingestion ($$$) → Data Lake Mirror</span></span></code></pre></div></div>
<p><strong>Optimized flow (cost-effective):</strong></p>
<div class="highlight-wrapper"><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="cl">XDR Advanced Hunting (30d free) → Workspace DCR Transformation → Custom Data Lake Tables ($)</span></span></code></pre></div></div>
<p>By using Data Collection Rules (DCR) with workspace transformations, we can route XDR data directly to custom tables in the data lake tier, completely bypassing expensive Analytics tier ingestion. This is a legitimate Microsoft-supported feature that’s just not widely documented for this use case, but got inspired by Jeffrey Appel his approach for this.</p>
<figure><img
    class="my-0 rounded-md"
    loading="lazy"
    decoding="async"
    fetchpriority="low"
    alt="Workspace transformation DCR"
    src="https://learn.microsoft.com/en-us/azure/azure-monitor/data-collection/media/data-collection-transformations/workspace-transformation-dcr.png"
    ></figure>
<h3 class="relative group">Key benefits and trade-offs
    <div id="key-benefits-and-trade-offs" class="anchor"></div>
    
</h3>
<p><strong>Benefits:</strong></p>
<ul>
<li>Eliminate Analytics tier ingestion costs entirely</li>
<li>Keep 30 days free in XDR Advanced Hunting for real-time detection</li>
<li>Store years of data in low-cost data lake tier</li>
<li>Perfect for compliance and historical analysis</li>
<li>Single DCR handles multiple tables</li>
</ul>
<p><strong>Trade-offs:</strong></p>
<ul>
<li>No real-time alerting or analytics rules on custom tables</li>
<li>Slower queries compared to Analytics tier</li>
<li>Requires initial setup and ongoing management</li>
<li>Custom tables have limited feature support</li>
</ul>
<p><strong>Critical decision:</strong> Only use this method for XDR data needed for compliance/historical purposes. If you need real-time detection beyond 30 days, keep those tables in Analytics tier. Many organizations use a hybrid approach.</p>

<h3 class="relative group">Choosing which tables to optimize
    <div id="choosing-which-tables-to-optimize" class="anchor"></div>
    
</h3>
<p>Not all XDR tables are equal candidates. Base your decision on volume, analytical needs, and compliance requirements.</p>

<div class="ms-table" role="region" aria-label="Table" tabindex="0">
  <table>
      <thead>
          <tr>
              <th>XDR Table</th>
              <th>Volume</th>
              <th>Recommendation</th>
              <th>Reasoning</th>
          </tr>
      </thead>
    <tbody>
        <tr>
            <td>DeviceProcessEvents</td>
            <td>Very High</td>
            <td>Optimize</td>
            <td>Highest volume, mostly needed for forensics</td>
        </tr>
        <tr>
            <td>DeviceNetworkEvents</td>
            <td>Very High</td>
            <td>Optimize</td>
            <td>High noise-to-signal ratio</td>
        </tr>
        <tr>
            <td>DeviceFileEvents</td>
            <td>High</td>
            <td>Optimize</td>
            <td>Primarily used for investigations</td>
        </tr>
        <tr>
            <td>CloudAppEvents</td>
            <td>Medium</td>
            <td>Consider</td>
            <td>Depends on detection requirements</td>
        </tr>
        <tr>
            <td>EmailEvents</td>
            <td>Medium</td>
            <td>Consider</td>
            <td>May need for phishing detection</td>
        </tr>
        <tr>
            <td>AlertEvidence</td>
            <td>Low</td>
            <td>Keep in Analytics</td>
            <td>Critical for investigations</td>
        </tr>
        <tr>
            <td>IdentityInfo</td>
            <td>Very Low</td>
            <td>Keep in Analytics</td>
            <td>Required for UEBA</td>
        </tr>
    </tbody>
  </table>
</div>
<p><strong>Optimize when:</strong></p>
<ul>
<li>High-volume, low-value data (verbose logs)</li>
<li>Compliance retention only</li>
<li>Historical analysis and forensics needs</li>
</ul>
<p><strong>Keep in Analytics when:</strong></p>
<ul>
<li>Real-time alerting required</li>
<li>UEBA or behavioral analytics needed</li>
<li>Active detection rules depend on the data</li>
</ul>

<h3 class="relative group">Prerequisites and tools
    <div id="prerequisites-and-tools" class="anchor"></div>
    
</h3>
<p>Before implementing this optimization, you’ll need a few things in place.</p>

<h4 class="relative group">1. Marko Lauren’s Table Creator Tool
    <div id="1-marko-laurens-table-creator-tool" class="anchor"></div>
    
</h4>
<p>The tool is essential because Azure Data Lake tables (Auxiliary tier) don’t natively support dynamic data types, which many XDR tables use. Marko’s tool solves this by automating the table creation process and handling the schema complexity.</p>
<p><strong>GitHub</strong> <a href="https://github.com/markolauren/sentinel/tree/main/tableCreator%20tool"  target="_blank" rel="noreferrer">link</a></p>
<p><strong>What it does:</strong></p>
<ul>
<li>Reads source table schema from your workspace</li>
<li>Creates matching custom table with correct structure</li>
<li>Handles dynamic fields via Analytics tier workaround</li>
<li>Enables seamless switching to Data Lake tier</li>
</ul>
<p>The workaround: Create tables in Analytics tier first (which supports dynamic types), then switch to Data Lake tier via the portal. This preserves the dynamic field support.</p>

<h4 class="relative group">2. Azure access requirements
    <div id="2-azure-access-requirements" class="anchor"></div>
    
</h4>
<ul>
<li>Contributor or Owner permissions on Log Analytics workspace</li>
<li>Ability to deploy ARM templates</li>
<li>Access to Azure Portal and Defender portal</li>
</ul>

<h4 class="relative group">3. Optimization scope decision
    <div id="3-optimization-scope-decision" class="anchor"></div>
    
</h4>
<p>Identify which XDR tables to optimize based on current ingestion volumes, real-time analytics requirements, compliance needs, and detection rule dependencies. Start with your highest-volume tables for maximum impact.</p>

<h3 class="relative group">Implementation guide
    <div id="implementation-guide" class="anchor"></div>
    
</h3>
<p>The implementation follows three main steps: creating custom tables, configuring the DCR, and verifying data flow. Let’s walk through each one.</p>

<h4 class="relative group">Step 1: Create custom data lake tables
    <div id="step-1-create-custom-data-lake-tables" class="anchor"></div>
    
</h4>
<p>We’ll use Marko Lauren’s <code>tableCreator.ps1</code> script to automate the table creation process and avoid schema issues.</p>

<h4 class="relative group">Download the tool
    <div id="download-the-tool" class="anchor"></div>
    
</h4>
<p>Download <code>tableCreator.ps1</code> from the GitHub repository:</p>
<p><strong>GitHub</strong> <a href="https://github.com/markolauren/sentinel/tree/main/tableCreator%20tool"  target="_blank" rel="noreferrer">link</a></p>

<h4 class="relative group">Run the table creator
    <div id="run-the-table-creator" class="anchor"></div>
    
</h4>
<p>The tool uses command-line parameters. Execute it via Azure CLI with your workspace details:</p>
<div class="highlight-wrapper"><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="cl"># Login to Azure
</span></span><span class="line"><span class="cl">az login
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"># Run the table creator script with parameters
</span></span><span class="line"><span class="cl">.\tableCreator.ps1 -tableName DeviceProcessEvents -newTableName DeviceProcessEventsLake_CL -type analytics -retention 30 -totalRetention 365</span></span></code></pre></div></div>
<figure><img
    class="my-0 rounded-md"
    loading="lazy"
    decoding="async"
    fetchpriority="auto"
    alt=""
    width="1183"
    height="607"
    src="https://www.modernsecurity.nl/microsoft-sentinel-xdr-data-lake-guide/image-24_hu_c546e902f9250ac7.webp"
   
   
    data-zoom-src="https://www.modernsecurity.nl/microsoft-sentinel-xdr-data-lake-guide/image-24.webp"></figure><p><strong>Parameter explanation:</strong></p>

<div class="ms-table" role="region" aria-label="Table" tabindex="0">
  <table>
      <thead>
          <tr>
              <th>Parameter</th>
              <th>Value</th>
              <th>Description</th>
          </tr>
      </thead>
    <tbody>
        <tr>
            <td><code>-tableName</code></td>
            <td><code>DeviceProcessEvents</code></td>
            <td>Existing XDR table to replicate</td>
        </tr>
        <tr>
            <td><code>-newTableName</code></td>
            <td><code>DeviceProcessEventsLake_CL</code></td>
            <td>New custom table name (must end with <code>_CL</code>)</td>
        </tr>
        <tr>
            <td><code>-type</code></td>
            <td><code>analytics</code></td>
            <td>Start with analytics, not datalake/auxiliary</td>
        </tr>
        <tr>
            <td><code>-retention</code></td>
            <td><code>365</code></td>
            <td>Total retention in days</td>
        </tr>
        <tr>
            <td><code>-ConvertToString</code></td>
            <td>(optional)</td>
            <td>Use if you get dynamic type errors</td>
        </tr>
        <tr>
            <td><code>-TenantId</code></td>
            <td>(optional)</td>
            <td>Specify if multi-tenant environment</td>
        </tr>
    </tbody>
  </table>
</div>
<figure><img
    class="my-0 rounded-md"
    loading="lazy"
    decoding="async"
    fetchpriority="auto"
    alt=""
    width="1568"
    height="920"
    src="https://www.modernsecurity.nl/microsoft-sentinel-xdr-data-lake-guide/image-25_hu_f55cc0ec7bd047ac.webp"
   
   
    data-zoom-src="https://www.modernsecurity.nl/microsoft-sentinel-xdr-data-lake-guide/image-25.webp"></figure><p><strong>Why <code>-type analytics</code> first?</strong> Even though our final destination is Data Lake, we must create the table as analytics type initially to preserve dynamic field support. We’ll switch it to Data Lake tier in the next step.</p>
<figure><img
    class="my-0 rounded-md"
    loading="lazy"
    decoding="async"
    fetchpriority="auto"
    alt=""
    width="1183"
    height="607"
    src="https://www.modernsecurity.nl/microsoft-sentinel-xdr-data-lake-guide/image-23_hu_84a9ed66292d46bd.webp"
   
   
    data-zoom-src="https://www.modernsecurity.nl/microsoft-sentinel-xdr-data-lake-guide/image-23.webp"></figure>
<h4 class="relative group">Switch table to data lake tier
    <div id="switch-table-to-data-lake-tier" class="anchor"></div>
    
</h4>
<p>Now that the table exists with the correct schema including dynamic fields, switch it to data Lake tier:</p>
<p>Navigate to <strong>Microsoft Defender Portal</strong> → <strong>Microsoft Sentinel</strong> → <strong>Configuration</strong> → <strong>Tables</strong></p>
<ol>
<li>Locate your custom table (<code>DeviceProcessEventsLake_CL</code>)</li>
<li>Click on the table → Click <strong>Manage table</strong></li>
<li>Under table tier options, select <strong>data lake tier only</strong></li>
<li>Configure retention (e.g., 1 year for compliance)</li>
<li>Click <strong>Save</strong></li>
</ol>
<figure><img
    class="my-0 rounded-md"
    loading="lazy"
    decoding="async"
    fetchpriority="auto"
    alt=""
    width="1851"
    height="994"
    src="https://www.modernsecurity.nl/microsoft-sentinel-xdr-data-lake-guide/image-26_hu_c70ec54465e90fde.webp"
   
   
    data-zoom-src="https://www.modernsecurity.nl/microsoft-sentinel-xdr-data-lake-guide/image-26.webp"></figure><p>Your table is now in the Auxiliary (data lake) tier with full dynamic field support, ready to receive data.</p>
<figure><img
    class="my-0 rounded-md"
    loading="lazy"
    decoding="async"
    fetchpriority="auto"
    alt=""
    width="1852"
    height="995"
    src="https://www.modernsecurity.nl/microsoft-sentinel-xdr-data-lake-guide/image-28_hu_feba210b8b3c41b6.webp"
   
   
    data-zoom-src="https://www.modernsecurity.nl/microsoft-sentinel-xdr-data-lake-guide/image-28.webp"></figure>
<h4 class="relative group">Create additional tables
    <div id="create-additional-tables" class="anchor"></div>
    
</h4>
<p>Repeat this process for each XDR table you want to optimize:</p>

<div class="ms-table" role="region" aria-label="Table" tabindex="0">
  <table>
      <thead>
          <tr>
              <th>Source Table</th>
              <th>Custom Table Name</th>
              <th>Use Case</th>
          </tr>
      </thead>
    <tbody>
        <tr>
            <td>DeviceProcessEvents</td>
            <td>DeviceProcessEventsLake_CL</td>
            <td>Process execution history</td>
        </tr>
        <tr>
            <td>DeviceNetworkEvents</td>
            <td>DeviceNetworkEventsLake_CL</td>
            <td>Network connection logs</td>
        </tr>
        <tr>
            <td>DeviceFileEvents</td>
            <td>DeviceFileEventsLake_CL</td>
            <td>File activity forensics</td>
        </tr>
        <tr>
            <td>CloudAppEvents</td>
            <td>CloudAppEventsLake_CL</td>
            <td>Cloud application activity</td>
        </tr>
        <tr>
            <td>EmailEvents</td>
            <td>EmailEventsLake_CL</td>
            <td>Email flow history</td>
        </tr>
    </tbody>
  </table>
</div>
<figure><img
    class="my-0 rounded-md"
    loading="lazy"
    decoding="async"
    fetchpriority="auto"
    alt=""
    width="1852"
    height="995"
    src="https://www.modernsecurity.nl/microsoft-sentinel-xdr-data-lake-guide/image-36_hu_f9b97d27311c066f.webp"
   
   
    data-zoom-src="https://www.modernsecurity.nl/microsoft-sentinel-xdr-data-lake-guide/image-36.webp"></figure>
<h3 class="relative group">Step 2: Create workspace transformation DCR
    <div id="step-2-create-workspace-transformation-dcr" class="anchor"></div>
    
</h3>
<p>Now we’ll create the Data Collection Rule that routes XDR data from original tables to your custom Data Lake tables. This is where the magic happens.</p>

<h4 class="relative group">Initial DCR creation via portal
    <div id="initial-dcr-creation-via-portal" class="anchor"></div>
    
</h4>
<p>Start by creating the basic DCR structure through the Azure Portal:</p>
<p>Navigate to <strong>Azure Portal</strong> → <strong>Log Analytics workspaces</strong> → Select your workspace → <strong>Tables</strong></p>
<ol>
<li>Locate any source XDR table (e.g., <code>DeviceProcessEvents</code>)</li>
<li>Click on the table → Click <strong>Create transformation</strong></li>
<li>Configure the DCR:</li>
</ol>

<div class="ms-table" role="region" aria-label="Table" tabindex="0">
  <table>
      <thead>
          <tr>
              <th>Field</th>
              <th>Value</th>
              <th>Note</th>
          </tr>
      </thead>
    <tbody>
        <tr>
            <td>DCR name</td>
            <td><code>dcr-sentinel-workspace-xdr-lake-routing</code></td>
            <td>Use descriptive name</td>
        </tr>
        <tr>
            <td>Resource group</td>
            <td>Same as workspace</td>
            <td>Keep together</td>
        </tr>
        <tr>
            <td>Region</td>
            <td>Same as workspace</td>
            <td>Performance</td>
        </tr>
        <tr>
            <td>Description</td>
            <td>Routes XDR data to Data Lake custom tables</td>
            <td>Clear purpose</td>
        </tr>
    </tbody>
  </table>
</div>
<ol start="4">
<li>Click <strong>Create</strong></li>
</ol>
<figure><img
    class="my-0 rounded-md"
    loading="lazy"
    decoding="async"
    fetchpriority="auto"
    alt=""
    width="1852"
    height="999"
    src="https://www.modernsecurity.nl/microsoft-sentinel-xdr-data-lake-guide/image-29_hu_33d7239c26d08851.webp"
   
   
    data-zoom-src="https://www.modernsecurity.nl/microsoft-sentinel-xdr-data-lake-guide/image-29.webp"></figure><figure><img
    class="my-0 rounded-md"
    loading="lazy"
    decoding="async"
    fetchpriority="auto"
    alt=""
    width="1853"
    height="996"
    src="https://www.modernsecurity.nl/microsoft-sentinel-xdr-data-lake-guide/image-30_hu_4b2ada3fa423d5c5.webp"
   
   
    data-zoom-src="https://www.modernsecurity.nl/microsoft-sentinel-xdr-data-lake-guide/image-30.webp"></figure><figure><img
    class="my-0 rounded-md"
    loading="lazy"
    decoding="async"
    fetchpriority="auto"
    alt=""
    width="1852"
    height="996"
    src="https://www.modernsecurity.nl/microsoft-sentinel-xdr-data-lake-guide/image-31_hu_d81dd451ca240696.webp"
   
   
    data-zoom-src="https://www.modernsecurity.nl/microsoft-sentinel-xdr-data-lake-guide/image-31.webp"></figure><figure><img
    class="my-0 rounded-md"
    loading="lazy"
    decoding="async"
    fetchpriority="auto"
    alt=""
    width="1849"
    height="998"
    src="https://www.modernsecurity.nl/microsoft-sentinel-xdr-data-lake-guide/image-32_hu_d859603c54452fd.webp"
   
   
    data-zoom-src="https://www.modernsecurity.nl/microsoft-sentinel-xdr-data-lake-guide/image-32.webp"></figure><p>This creates a Workspace Transformation DCR (Kind: <code>WorkspaceTransforms</code>) that’s automatically associated with your workspace.</p>
<p><strong>Important limitation:</strong> You can only have one Workspace Transformation DCR per workspace, but this single DCR can handle all your table routing.</p>

<h4 class="relative group">Configure DCR via ARM template
    <div id="configure-dcr-via-arm-template" class="anchor"></div>
    
</h4>
<p>The portal UI only allows configuring one table at a time. To efficiently route multiple XDR tables, we’ll edit the DCR’s ARM template directly.</p>
<p>Navigate to <strong>Azure Portal</strong> → <strong>Data Collection Rules</strong> → Locate your DCR</p>
<ol>
<li>Verify <strong>Kind</strong> shows <code>WorkspaceTransforms</code> in the Overview</li>
<li>Click <strong>Export template</strong> → <strong>Deploy</strong> → <strong>Edit template</strong></li>
</ol>
<figure><img
    class="my-0 rounded-md"
    loading="lazy"
    decoding="async"
    fetchpriority="auto"
    alt=""
    width="1850"
    height="996"
    src="https://www.modernsecurity.nl/microsoft-sentinel-xdr-data-lake-guide/image-33_hu_1ffa37396df93669.webp"
   
   
    data-zoom-src="https://www.modernsecurity.nl/microsoft-sentinel-xdr-data-lake-guide/image-33.webp"></figure><figure><img
    class="my-0 rounded-md"
    loading="lazy"
    decoding="async"
    fetchpriority="auto"
    alt=""
    width="1851"
    height="995"
    src="https://www.modernsecurity.nl/microsoft-sentinel-xdr-data-lake-guide/image-34_hu_c1c722698fabdf15.webp"
   
   
    data-zoom-src="https://www.modernsecurity.nl/microsoft-sentinel-xdr-data-lake-guide/image-34.webp"></figure><figure><img
    class="my-0 rounded-md"
    loading="lazy"
    decoding="async"
    fetchpriority="auto"
    alt=""
    width="1850"
    height="995"
    src="https://www.modernsecurity.nl/microsoft-sentinel-xdr-data-lake-guide/image-35_hu_eb0e8860b89a5cd7.webp"
   
   
    data-zoom-src="https://www.modernsecurity.nl/microsoft-sentinel-xdr-data-lake-guide/image-35.webp"></figure><ol start="3">
<li>Write down the name from the workspaceresourceId (under LogAnalytics):</li>
</ol>
<div class="highlight-wrapper"><div class="highlight"><div class="ms-code-label">JSON</div><pre tabindex="0" class="chroma"><code class="language-json" data-lang="json"><span class="line"><span class="cl">        <span class="p">{</span>
</span></span><span class="line"><span class="cl">            <span class="nt">&#34;type&#34;</span><span class="p">:</span> <span class="s2">&#34;Microsoft.Insights/dataCollectionRules&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">            <span class="nt">&#34;apiVersion&#34;</span><span class="p">:</span> <span class="s2">&#34;2023-03-11&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">            <span class="nt">&#34;name&#34;</span><span class="p">:</span> <span class="s2">&#34;[parameters(&#39;dataCollectionRules_dcr_sentinel_workspace_xdr_lake_routing_name&#39;)]&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">            <span class="nt">&#34;location&#34;</span><span class="p">:</span> <span class="s2">&#34;westeurope&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">            <span class="nt">&#34;kind&#34;</span><span class="p">:</span> <span class="s2">&#34;WorkspaceTransforms&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">            <span class="nt">&#34;properties&#34;</span><span class="p">:</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">                <span class="nt">&#34;dataSources&#34;</span><span class="p">:</span> <span class="p">{},</span>
</span></span><span class="line"><span class="cl">                <span class="nt">&#34;destinations&#34;</span><span class="p">:</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">                    <span class="nt">&#34;logAnalytics&#34;</span><span class="p">:</span> <span class="p">[</span>
</span></span><span class="line"><span class="cl">                        <span class="p">{</span>
</span></span><span class="line"><span class="cl">                            <span class="nt">&#34;workspaceResourceId&#34;</span><span class="p">:</span> <span class="s2">&#34;[parameters(&#39;workspaces_sec_management_siemlog_prd_001_externalid&#39;)]&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">                            <span class="nt">&#34;name&#34;</span><span class="p">:</span> <span class="s2">&#34;5511c2c9b1764fed860fa62716b60686&#34;</span>
</span></span><span class="line"><span class="cl">                        <span class="p">}</span>
</span></span><span class="line"><span class="cl">                    <span class="p">]</span>
</span></span><span class="line"><span class="cl">                <span class="p">},</span></span></span></code></pre></div></div>
<ol start="3">
<li>Replace the template content (dataFlows-part) with the configuration below. The template configures data flows for multiple XDR tables simultaneously:</li>
</ol>
<div class="highlight-wrapper"><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="cl">&#34;dataFlows&#34;: [
</span></span><span class="line"><span class="cl">  {
</span></span><span class="line"><span class="cl">    &#34;streams&#34;: [
</span></span><span class="line"><span class="cl">      &#34;Microsoft-Table-DeviceProcessEvents&#34;
</span></span><span class="line"><span class="cl">    ],
</span></span><span class="line"><span class="cl">    &#34;destinations&#34;: [
</span></span><span class="line"><span class="cl">      &#34;5511c2c9b1764fed860fa62716b60686&#34;
</span></span><span class="line"><span class="cl">    ],
</span></span><span class="line"><span class="cl">    &#34;outputStream&#34;: &#34;Custom-DeviceProcessEventsLake_CL&#34;
</span></span><span class="line"><span class="cl">  },
</span></span><span class="line"><span class="cl">  {
</span></span><span class="line"><span class="cl">    &#34;streams&#34;: [
</span></span><span class="line"><span class="cl">      &#34;Microsoft-Table-DeviceNetworkEvents&#34;
</span></span><span class="line"><span class="cl">    ],
</span></span><span class="line"><span class="cl">    &#34;destinations&#34;: [
</span></span><span class="line"><span class="cl">      &#34;5511c2c9b1764fed860fa62716b60686&#34;
</span></span><span class="line"><span class="cl">    ],
</span></span><span class="line"><span class="cl">    &#34;outputStream&#34;: &#34;Custom-DeviceNetworkEventsLake_CL&#34;
</span></span><span class="line"><span class="cl">  },
</span></span><span class="line"><span class="cl">  {
</span></span><span class="line"><span class="cl">    &#34;streams&#34;: [
</span></span><span class="line"><span class="cl">      &#34;Microsoft-Table-DeviceFileEvents&#34;
</span></span><span class="line"><span class="cl">    ],
</span></span><span class="line"><span class="cl">    &#34;destinations&#34;: [
</span></span><span class="line"><span class="cl">      &#34;5511c2c9b1764fed860fa62716b60686&#34;
</span></span><span class="line"><span class="cl">    ],
</span></span><span class="line"><span class="cl">    &#34;outputStream&#34;: &#34;Custom-DeviceFileEventsLake_CL&#34;
</span></span><span class="line"><span class="cl">  },
</span></span><span class="line"><span class="cl">  {
</span></span><span class="line"><span class="cl">    &#34;streams&#34;: [
</span></span><span class="line"><span class="cl">      &#34;Microsoft-Table-CloudAppEvents&#34;
</span></span><span class="line"><span class="cl">    ],
</span></span><span class="line"><span class="cl">    &#34;destinations&#34;: [
</span></span><span class="line"><span class="cl">      &#34;5511c2c9b1764fed860fa62716b60686&#34;
</span></span><span class="line"><span class="cl">    ],
</span></span><span class="line"><span class="cl">    &#34;outputStream&#34;: &#34;Custom-CloudAppEventsLake_CL&#34;
</span></span><span class="line"><span class="cl">  },
</span></span><span class="line"><span class="cl">  {
</span></span><span class="line"><span class="cl">    &#34;streams&#34;: [
</span></span><span class="line"><span class="cl">      &#34;Microsoft-Table-EmailEvents&#34;
</span></span><span class="line"><span class="cl">    ],
</span></span><span class="line"><span class="cl">    &#34;destinations&#34;: [
</span></span><span class="line"><span class="cl">      &#34;5511c2c9b1764fed860fa62716b60686&#34;
</span></span><span class="line"><span class="cl">    ],
</span></span><span class="line"><span class="cl">    &#34;outputStream&#34;: &#34;Custom-EmailEventsLake_CL&#34;
</span></span><span class="line"><span class="cl">  }
</span></span><span class="line"><span class="cl">]</span></span></code></pre></div></div>
<p>You will end up with a template like this:</p>
<div class="highlight-wrapper"><div class="highlight"><div class="ms-code-label">JSON</div><pre tabindex="0" class="chroma"><code class="language-json" data-lang="json"><span class="line"><span class="cl"><span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="nt">&#34;$schema&#34;</span><span class="p">:</span> <span class="s2">&#34;https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="nt">&#34;contentVersion&#34;</span><span class="p">:</span> <span class="s2">&#34;1.0.0.0&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="nt">&#34;parameters&#34;</span><span class="p">:</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="nt">&#34;dataCollectionRules_dcr_sentinel_workspace_xdr_lake_routing_name&#34;</span><span class="p">:</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">            <span class="nt">&#34;defaultValue&#34;</span><span class="p">:</span> <span class="s2">&#34;dcr-sentinel-workspace-xdr-lake-routing&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">            <span class="nt">&#34;type&#34;</span><span class="p">:</span> <span class="s2">&#34;String&#34;</span>
</span></span><span class="line"><span class="cl">        <span class="p">},</span>
</span></span><span class="line"><span class="cl">        <span class="nt">&#34;workspaces_sec_management_siemlog_prd_001_externalid&#34;</span><span class="p">:</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">            <span class="nt">&#34;defaultValue&#34;</span><span class="p">:</span> <span class="s2">&#34;/subscriptions/xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx/resourceGroups/sec-management-siemlog-prd-001/providers/microsoft.operationalinsights/workspaces/sec-management-siemlog-prd-001&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">            <span class="nt">&#34;type&#34;</span><span class="p">:</span> <span class="s2">&#34;String&#34;</span>
</span></span><span class="line"><span class="cl">        <span class="p">}</span>
</span></span><span class="line"><span class="cl">    <span class="p">},</span>
</span></span><span class="line"><span class="cl">    <span class="nt">&#34;variables&#34;</span><span class="p">:</span> <span class="p">{},</span>
</span></span><span class="line"><span class="cl">    <span class="nt">&#34;resources&#34;</span><span class="p">:</span> <span class="p">[</span>
</span></span><span class="line"><span class="cl">        <span class="p">{</span>
</span></span><span class="line"><span class="cl">            <span class="nt">&#34;type&#34;</span><span class="p">:</span> <span class="s2">&#34;Microsoft.Insights/dataCollectionRules&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">            <span class="nt">&#34;apiVersion&#34;</span><span class="p">:</span> <span class="s2">&#34;2023-03-11&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">            <span class="nt">&#34;name&#34;</span><span class="p">:</span> <span class="s2">&#34;[parameters(&#39;dataCollectionRules_dcr_sentinel_workspace_xdr_lake_routing_name&#39;)]&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">            <span class="nt">&#34;location&#34;</span><span class="p">:</span> <span class="s2">&#34;westeurope&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">            <span class="nt">&#34;kind&#34;</span><span class="p">:</span> <span class="s2">&#34;WorkspaceTransforms&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">            <span class="nt">&#34;properties&#34;</span><span class="p">:</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">                <span class="nt">&#34;description&#34;</span><span class="p">:</span> <span class="s2">&#34;Routes XDR tables directly to Data Lake custom tables, bypassing Analytics tier ingestion costs&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">                <span class="nt">&#34;dataSources&#34;</span><span class="p">:</span> <span class="p">{},</span>
</span></span><span class="line"><span class="cl">                <span class="nt">&#34;destinations&#34;</span><span class="p">:</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">                    <span class="nt">&#34;logAnalytics&#34;</span><span class="p">:</span> <span class="p">[</span>
</span></span><span class="line"><span class="cl">                        <span class="p">{</span>
</span></span><span class="line"><span class="cl">                            <span class="nt">&#34;workspaceResourceId&#34;</span><span class="p">:</span> <span class="s2">&#34;[parameters(&#39;workspaces_sec_management_siemlog_prd_001_externalid&#39;)]&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">                            <span class="nt">&#34;name&#34;</span><span class="p">:</span> <span class="s2">&#34;5511c2c9b1764fed860fa62716b60686&#34;</span>
</span></span><span class="line"><span class="cl">                        <span class="p">}</span>
</span></span><span class="line"><span class="cl">                    <span class="p">]</span>
</span></span><span class="line"><span class="cl">                <span class="p">},</span>
</span></span><span class="line"><span class="cl">                <span class="nt">&#34;dataFlows&#34;</span><span class="p">:</span> <span class="p">[</span>
</span></span><span class="line"><span class="cl">                    <span class="p">{</span>
</span></span><span class="line"><span class="cl">                        <span class="nt">&#34;streams&#34;</span><span class="p">:</span> <span class="p">[</span>
</span></span><span class="line"><span class="cl">                            <span class="s2">&#34;Microsoft-Table-DeviceProcessEvents&#34;</span>
</span></span><span class="line"><span class="cl">                        <span class="p">],</span>
</span></span><span class="line"><span class="cl">                        <span class="nt">&#34;destinations&#34;</span><span class="p">:</span> <span class="p">[</span>
</span></span><span class="line"><span class="cl">                            <span class="s2">&#34;5511c2c9b1764fed860fa62716b60686&#34;</span>
</span></span><span class="line"><span class="cl">                        <span class="p">],</span>
</span></span><span class="line"><span class="cl">                        <span class="nt">&#34;outputStream&#34;</span><span class="p">:</span> <span class="s2">&#34;Custom-DeviceProcessEventsLake_CL&#34;</span>
</span></span><span class="line"><span class="cl">                    <span class="p">},</span>
</span></span><span class="line"><span class="cl">                    <span class="p">{</span>
</span></span><span class="line"><span class="cl">                        <span class="nt">&#34;streams&#34;</span><span class="p">:</span> <span class="p">[</span>
</span></span><span class="line"><span class="cl">                            <span class="s2">&#34;Microsoft-Table-DeviceNetworkEvents&#34;</span>
</span></span><span class="line"><span class="cl">                        <span class="p">],</span>
</span></span><span class="line"><span class="cl">                        <span class="nt">&#34;destinations&#34;</span><span class="p">:</span> <span class="p">[</span>
</span></span><span class="line"><span class="cl">                            <span class="s2">&#34;5511c2c9b1764fed860fa62716b60686&#34;</span>
</span></span><span class="line"><span class="cl">                        <span class="p">],</span>
</span></span><span class="line"><span class="cl">                        <span class="nt">&#34;outputStream&#34;</span><span class="p">:</span> <span class="s2">&#34;Custom-DeviceNetworkEventsLake_CL&#34;</span>
</span></span><span class="line"><span class="cl">                    <span class="p">},</span>
</span></span><span class="line"><span class="cl">                    <span class="p">{</span>
</span></span><span class="line"><span class="cl">                        <span class="nt">&#34;streams&#34;</span><span class="p">:</span> <span class="p">[</span>
</span></span><span class="line"><span class="cl">                            <span class="s2">&#34;Microsoft-Table-DeviceFileEvents&#34;</span>
</span></span><span class="line"><span class="cl">                        <span class="p">],</span>
</span></span><span class="line"><span class="cl">                        <span class="nt">&#34;destinations&#34;</span><span class="p">:</span> <span class="p">[</span>
</span></span><span class="line"><span class="cl">                            <span class="s2">&#34;5511c2c9b1764fed860fa62716b60686&#34;</span>
</span></span><span class="line"><span class="cl">                        <span class="p">],</span>
</span></span><span class="line"><span class="cl">                        <span class="nt">&#34;outputStream&#34;</span><span class="p">:</span> <span class="s2">&#34;Custom-DeviceFileEventsLake_CL&#34;</span>
</span></span><span class="line"><span class="cl">                    <span class="p">},</span>
</span></span><span class="line"><span class="cl">                    <span class="p">{</span>
</span></span><span class="line"><span class="cl">                        <span class="nt">&#34;streams&#34;</span><span class="p">:</span> <span class="p">[</span>
</span></span><span class="line"><span class="cl">                            <span class="s2">&#34;Microsoft-Table-CloudAppEvents&#34;</span>
</span></span><span class="line"><span class="cl">                        <span class="p">],</span>
</span></span><span class="line"><span class="cl">                        <span class="nt">&#34;destinations&#34;</span><span class="p">:</span> <span class="p">[</span>
</span></span><span class="line"><span class="cl">                            <span class="s2">&#34;5511c2c9b1764fed860fa62716b60686&#34;</span>
</span></span><span class="line"><span class="cl">                        <span class="p">],</span>
</span></span><span class="line"><span class="cl">                        <span class="nt">&#34;outputStream&#34;</span><span class="p">:</span> <span class="s2">&#34;Custom-CloudAppEventsLake_CL&#34;</span>
</span></span><span class="line"><span class="cl">                    <span class="p">},</span>
</span></span><span class="line"><span class="cl">                    <span class="p">{</span>
</span></span><span class="line"><span class="cl">                        <span class="nt">&#34;streams&#34;</span><span class="p">:</span> <span class="p">[</span>
</span></span><span class="line"><span class="cl">                            <span class="s2">&#34;Microsoft-Table-EmailEvents&#34;</span>
</span></span><span class="line"><span class="cl">                        <span class="p">],</span>
</span></span><span class="line"><span class="cl">                        <span class="nt">&#34;destinations&#34;</span><span class="p">:</span> <span class="p">[</span>
</span></span><span class="line"><span class="cl">                            <span class="s2">&#34;5511c2c9b1764fed860fa62716b60686&#34;</span>
</span></span><span class="line"><span class="cl">                        <span class="p">],</span>
</span></span><span class="line"><span class="cl">                        <span class="nt">&#34;outputStream&#34;</span><span class="p">:</span> <span class="s2">&#34;Custom-EmailEventsLake_CL&#34;</span>
</span></span><span class="line"><span class="cl">                    <span class="p">}</span>
</span></span><span class="line"><span class="cl">                <span class="p">]</span>
</span></span><span class="line"><span class="cl">            <span class="p">}</span>
</span></span><span class="line"><span class="cl">        <span class="p">}</span>
</span></span><span class="line"><span class="cl">    <span class="p">]</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span></span></span></code></pre></div></div>
<p><strong>Understanding the template:</strong></p>
<p>Each <code>dataFlow</code> entry routes data from a source stream to a destination table. The <code>streams</code> value must match Microsoft’s exact naming (e.g., <code>Microsoft-Table-DeviceProcessEvents</code>). The <code>outputStream</code> must include the <code>Custom-</code> prefix for custom tables. The <code>transformKql</code> value of <code>&quot;source&quot;</code> means no filtering – all data passes through. You can add KQL filtering here if needed (covered later).</p>
<p>Click <strong>Save</strong> → <strong>Review + create</strong> → <strong>Create</strong> to deploy the DCR</p>

<h3 class="relative group">Step 3: Verify data flow
    <div id="step-3-verify-data-flow" class="anchor"></div>
    
</h3>
<p>After deploying the DCR, data should start flowing to your custom tables within 15-30 minutes. Let’s verify everything is working correctly.</p>
<p><strong>Check 1: Original table status</strong></p>
<div class="highlight-wrapper"><div class="highlight"><div class="ms-code-label">KQL</div><pre tabindex="0" class="chroma"><code class="language-kql" data-lang="kql">DeviceProcessEvents
<span class="o">|</span> <span class="k">take</span> 10</code></pre></div>
</div>
<p>Expected: Low count or zero (data is being routed to the custom table)</p>
<p><strong>Check 2: Custom table receiving data</strong></p>
<div class="highlight-wrapper"><div class="highlight"><div class="ms-code-label">KQL</div><pre tabindex="0" class="chroma"><code class="language-kql" data-lang="kql">DeviceProcessEventsLake_CL
<span class="o">|</span> <span class="k">take</span> 10</code></pre></div>
</div>
<figure><img
    class="my-0 rounded-md"
    loading="lazy"
    decoding="async"
    fetchpriority="auto"
    alt="Datalake Microsoft Sentinel XDR"
    width="1850"
    height="995"
    src="https://www.modernsecurity.nl/microsoft-sentinel-xdr-data-lake-guide/image-38_hu_c7b8d63cbd989fc5.webp"
   
   
    data-zoom-src="https://www.modernsecurity.nl/microsoft-sentinel-xdr-data-lake-guide/image-38.webp"></figure><p>Expected: Data flowing with proper schema</p>

<h4 class="relative group">Monitor cost savings
    <div id="monitor-cost-savings" class="anchor"></div>
    
</h4>
<p>Track the effectiveness of your optimization with these queries:</p>
<p><strong>Volume comparison:</strong></p>
<div class="highlight-wrapper"><div class="highlight"><div class="ms-code-label">KQL</div><pre tabindex="0" class="chroma"><code class="language-kql" data-lang="kql"><span class="k">let</span> OriginalVolume = <span class="k">toscalar</span>(DeviceProcessEvents <span class="o">|</span> <span class="k">where</span> TimeGenerated <span class="o">&gt;</span> <span class="nf">ago</span>(24h) <span class="o">|</span> <span class="k">count</span>);
<span class="k">let</span> OptimizedVolume = <span class="k">toscalar</span>(DeviceProcessEventsLake_CL <span class="o">|</span> <span class="k">where</span> TimeGenerated <span class="o">&gt;</span> <span class="nf">ago</span>(24h) <span class="o">|</span> <span class="k">count</span>);
<span class="k">print</span> 
    OriginalTableEvents = OriginalVolume,
    DataLakeTableEvents = OptimizedVolume,
    RoutingSuccess = <span class="nf">iff</span>(OptimizedVolume <span class="o">&gt;</span> OriginalVolume, <span class="s">&#34;Working&#34;</span>, <span class="s">&#34;Check DCR&#34;</span>)</code></pre></div>
</div>
<figure><img
    class="my-0 rounded-md"
    loading="lazy"
    decoding="async"
    fetchpriority="auto"
    alt=""
    width="1852"
    height="999"
    src="https://www.modernsecurity.nl/microsoft-sentinel-xdr-data-lake-guide/image-43_hu_3d47b88ff4f54a0f.webp"
   
   
    data-zoom-src="https://www.modernsecurity.nl/microsoft-sentinel-xdr-data-lake-guide/image-43.webp"></figure><p><strong>Cost savings estimate KQL example:</strong></p>
<div class="highlight-wrapper"><div class="highlight"><div class="ms-code-label">KQL</div><pre tabindex="0" class="chroma"><code class="language-kql" data-lang="kql"><span class="k">let</span> DailyVolumeGB = <span class="k">toscalar</span>(
    DeviceProcessEventsLake_CL
    <span class="o">|</span> <span class="k">where</span> TimeGenerated <span class="o">&gt;</span> <span class="nf">ago</span>(24h)
    <span class="o">|</span> <span class="k">extend</span> DataSizeBytes = <span class="nf">estimate_data_size</span>(*)
    <span class="o">|</span> <span class="k">summarize</span> TotalBytes = <span class="nf">sum</span>(DataSizeBytes)
    <span class="o">|</span> <span class="k">extend</span> GB = TotalBytes / 1024 / 1024 / 1024
    <span class="o">|</span> <span class="k">project</span> GB
);
<span class="c1">// Updated costs for 2025 GA pricing (East US region)</span>
<span class="k">let</span> AnalyticsIngestionCost = 4.30;  <span class="c1">// Per GB (updated from $3.207)</span>
<span class="k">let</span> DataLakeIngestionCost = 0.05;    <span class="c1">// Per GB</span>
<span class="k">let</span> DataLakeProcessingCost = 0.10;   <span class="c1">// Per GB</span>
<span class="k">let</span> DataLakeStorageCost = 0.02;      <span class="c1">// Per GB per month (compressed)</span>
<span class="c1">// Calculate monthly costs</span>
<span class="k">let</span> StandardMethodCost = DailyVolumeGB * 30 * AnalyticsIngestionCost;
<span class="k">let</span> OptimizedMethodCost = (DailyVolumeGB * 30 * (DataLakeIngestionCost + DataLakeProcessingCost)) + (DailyVolumeGB * 30 * DataLakeStorageCost);
<span class="k">let</span> MonthlySavings = StandardMethodCost - OptimizedMethodCost;
<span class="k">print</span> 
    DailyVolumeGB = <span class="nf">round</span>(DailyVolumeGB, 2),
    MonthlyVolumeTB = <span class="nf">round</span>((DailyVolumeGB * 30) / 1024, 2),
    StandardMethodCost = <span class="nf">strcat</span>(<span class="s">&#34;$&#34;</span>, <span class="nf">round</span>(StandardMethodCost, 2)),
    OptimizedMethodCost = <span class="nf">strcat</span>(<span class="s">&#34;$&#34;</span>, <span class="nf">round</span>(OptimizedMethodCost, 2)),
    EstimatedMonthlySavings = <span class="nf">strcat</span>(<span class="s">&#34;$&#34;</span>, <span class="nf">round</span>(MonthlySavings, 2)),
    SavingsPercentage = <span class="nf">strcat</span>(<span class="nf">round</span>((MonthlySavings / StandardMethodCost) * 100, 1), <span class="s">&#34;%&#34;</span>)</code></pre></div>
</div>

<h3 class="relative group">Optional: Advanced filtering with transformKql
    <div id="optional-advanced-filtering-with-transformkql" class="anchor"></div>
    
</h3>
<p>The examples (template) above don’t use <code>&quot;transformKql&quot;: &quot;source&quot;</code> which routes all data without filtering. You can add KQL transformations to filter data before ingestion, providing even more cost savings.</p>
<p>Filtering at the DCR level provides maximum savings because filtered data never reaches your workspace. However, ensure you’re not filtering out data needed for compliance or future investigations. When in doubt, keep everything and filter during queries instead.</p>

<h2 class="relative group">Data analysis and operations
    <div id="data-analysis-and-operations" class="anchor"></div>
    
</h2>

<h3 class="relative group">Data lake exploration with KQL
    <div id="data-lake-exploration-with-kql" class="anchor"></div>
    
</h3>
<p><strong>Accessing data lake exploration interface</strong></p>
<figure><img
    class="my-0 rounded-md"
    loading="lazy"
    decoding="async"
    fetchpriority="auto"
    alt=""
    width="1851"
    height="995"
    src="https://www.modernsecurity.nl/microsoft-sentinel-xdr-data-lake-guide/image-37_hu_812a03870c1f4d53.webp"
   
   
    data-zoom-src="https://www.modernsecurity.nl/microsoft-sentinel-xdr-data-lake-guide/image-37.webp"></figure><p><strong>Navigation steps:</strong></p>
<ol>
<li>Navigate to <strong>Microsoft Defender Portal</strong> → <strong>Microsoft Sentinel</strong> → <strong>Data lake exploration</strong></li>
<li>Select target workspace from dropdown menu</li>
<li>Configure appropriate time range for analysis</li>
<li>Begin KQL query development and execution</li>
</ol>

<h3 class="relative group">Query capabilities and limitations
    <div id="query-capabilities-and-limitations" class="anchor"></div>
    
</h3>
<p><strong>Supported KQL control commands:</strong> Microsoft’s data lake documentation shows the following control commands are currently supported:</p>
<div class="highlight-wrapper"><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="cl">.show version
</span></span><span class="line"><span class="cl">.show databases
</span></span><span class="line"><span class="cl">.show databases entities
</span></span><span class="line"><span class="cl">.show database</span></span></code></pre></div></div>
<p><strong>Performance and functional limitations:</strong></p>

<div class="ms-table" role="region" aria-label="Table" tabindex="0">
  <table>
      <thead>
          <tr>
              <th>Limitation category</th>
              <th>Specification</th>
              <th>Recommended workaround</th>
          </tr>
      </thead>
    <tbody>
        <tr>
            <td><strong>Query timeout</strong></td>
            <td>8 minutes maximum</td>
            <td>Use time-based filtering and sampling techniques</td>
        </tr>
        <tr>
            <td><strong>Result size</strong></td>
            <td>500,000 rows or 64MB</td>
            <td>Implement summarization and aggregation</td>
        </tr>
        <tr>
            <td><strong>Concurrent queries</strong></td>
            <td>45 per minute per workspace</td>
            <td>Plan and stagger query execution schedules</td>
        </tr>
        <tr>
            <td><strong>Query scope</strong></td>
            <td>Single workspace per query</td>
            <td>Design workspace-specific analysis approaches</td>
        </tr>
    </tbody>
  </table>
</div>

<h3 class="relative group">Sample queries and optimization
    <div id="sample-queries-and-optimization" class="anchor"></div>
    
</h3>
<p><strong>Suspicious travel activity analysis:</strong></p>
<div class="highlight-wrapper"><div class="highlight"><div class="ms-code-label">KQL</div><pre tabindex="0" class="chroma"><code class="language-kql" data-lang="kql">SigninLogs
<span class="o">|</span> <span class="k">where</span> TimeGenerated <span class="o">&gt;=</span> <span class="nf">ago</span>(180d)
<span class="o">|</span> <span class="k">where</span> ResultType <span class="o">==</span> 0
<span class="o">|</span> <span class="k">summarize</span> CountriesAccessed = <span class="nf">make_set</span>(Location) <span class="k">by</span> UserPrincipalName
<span class="o">|</span> <span class="k">where</span> <span class="nf">array_length</span>(CountriesAccessed) <span class="o">&gt;</span> 3  <span class="c1">// Adjust threshold as needed</span></code></pre></div>
</div>
<p><strong>Time-first filtering approach:</strong></p>
<div class="highlight-wrapper"><div class="highlight"><div class="ms-code-label">KQL</div><pre tabindex="0" class="chroma"><code class="language-kql" data-lang="kql"><span class="c1">// Efficient query pattern leveraging time partitioning</span>
SecurityEvent
<span class="o">|</span> <span class="k">where</span> TimeGenerated <span class="o">&gt;</span> <span class="nf">ago</span>(7d)     <span class="c1">// Partition elimination first</span>
<span class="o">|</span> <span class="k">where</span> Computer <span class="k">startswith</span> <span class="s">&#34;DC&#34;</span>    <span class="c1">// Apply specific filters second</span>
<span class="o">|</span> <span class="k">where</span> EventID <span class="k">in</span> (4624, 4625)     <span class="c1">// Multiple conditions last</span>
<span class="o">|</span> <span class="k">summarize</span> <span class="k">count</span>() <span class="k">by</span> Computer</code></pre></div>
</div>

<h3 class="relative group">Jupyter notebooks for security analytics
    <div id="jupyter-notebooks-for-security-analytics" class="anchor"></div>
    
</h3>
<p><strong>Step 1: Install and configure VS Code extension</strong></p>
<figure><img
    class="my-0 rounded-md"
    loading="lazy"
    decoding="async"
    fetchpriority="auto"
    alt=""
    width="1920"
    height="1140"
    src="https://www.modernsecurity.nl/microsoft-sentinel-xdr-data-lake-guide/image-40_hu_757356b702b4c24f.webp"
   
   
    data-zoom-src="https://www.modernsecurity.nl/microsoft-sentinel-xdr-data-lake-guide/image-40.webp"></figure><p><strong>Required components:</strong></p>
<ol>
<li><strong>Visual Studio Code</strong> (latest version)</li>
<li><strong>Microsoft Sentinel extension</strong> for VS Code</li>
<li><strong>Python environment</strong> with appropriate packages</li>
</ol>
<p><strong>Installation process:</strong></p>
<ol>
<li>Open Visual Studio Code</li>
<li>Navigate to Extensions (Ctrl+Shift+X)</li>
<li>Search for “Microsoft Sentinel”</li>
<li>Click <strong>Install</strong> on the Microsoft Sentinel extension</li>
<li>Microsoft Sentinel shield icon appears in left toolbar</li>
</ol>
<p><strong>Step 2: Configure compute resources</strong></p>
<figure><img
    class="my-0 rounded-md"
    loading="lazy"
    decoding="async"
    fetchpriority="low"
    alt="Select runtime"
    src="https://learn.microsoft.com/en-us/azure/sentinel/datalake/media/notebooks/select-runtime.png"
    ></figure><p><strong>Runtime pool options:</strong></p>

<div class="ms-table" role="region" aria-label="Table" tabindex="0">
  <table>
      <thead>
          <tr>
              <th>Pool size</th>
              <th>Compute resources</th>
              <th>Memory</th>
              <th>Recommended use cases</th>
              <th>Cost considerations</th>
          </tr>
      </thead>
    <tbody>
        <tr>
            <td><strong>Small</strong></td>
            <td>4 cores</td>
            <td>8GB</td>
            <td>Basic analytics, data exploration, development</td>
            <td>Lower cost, suitable for small datasets</td>
        </tr>
        <tr>
            <td><strong>Medium</strong></td>
            <td>8 cores</td>
            <td>16GB</td>
            <td>Standard security analytics, reporting</td>
            <td>Moderate cost, production workloads</td>
        </tr>
        <tr>
            <td><strong>Large</strong></td>
            <td>16 cores</td>
            <td>32GB</td>
            <td>ML models, complex analysis, large datasets</td>
            <td>Higher cost, resource-intensive operations</td>
        </tr>
    </tbody>
  </table>
</div>
<p>Microsoft’s billing documentation shows compute hours are calculated by multiplying the number of cores with session time, affecting Advanced Data Insights billing.</p>
<figure><img
    class="my-0 rounded-md"
    loading="lazy"
    decoding="async"
    fetchpriority="auto"
    alt=""
    width="1920"
    height="1140"
    src="https://www.modernsecurity.nl/microsoft-sentinel-xdr-data-lake-guide/image-39_hu_a5934259b24d6fbe.webp"
   
   
    data-zoom-src="https://www.modernsecurity.nl/microsoft-sentinel-xdr-data-lake-guide/image-39.webp"></figure><p><strong>Step 3: Develop security analytics workflows</strong></p>
<p><strong>Basic data exploration example:</strong></p>
<div class="highlight-wrapper"><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="cl">from sentinel_lake.providers import MicrosoftSentinelProvider
</span></span><span class="line"><span class="cl">import pandas as pd
</span></span><span class="line"><span class="cl">import matplotlib.pyplot as plt
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"># Initialize data provider
</span></span><span class="line"><span class="cl">data_provider = MicrosoftSentinelProvider(spark)
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"># Read data from custom data lake table
</span></span><span class="line"><span class="cl">df = data_provider.read_table(&#34;DeviceNetworkEventsLake_CL&#34;)
</span></span><span class="line"><span class="cl">df.select(&#34;TimeGenerated&#34;, &#34;DeviceName&#34;, &#34;ProcessName&#34;, &#34;ProcessCommandLine&#34;).show(10)</span></span></code></pre></div></div>

<h3 class="relative group">Automated jobs and scheduling
    <div id="automated-jobs-and-scheduling" class="anchor"></div>
    
</h3>
<p><strong>Understanding data lake jobs</strong></p>
<p>Microsoft’s job documentation shows that jobs enable automated analysis and data promotion between tiers. Two primary job types are supported:</p>
<ol>
<li><strong>KQL jobs</strong>: Query-based analytics using KQL syntax</li>
<li><strong>Notebook jobs</strong>: Python/Spark analytics using Jupyter notebooks</li>
</ol>
<p><strong>Creating and managing KQL jobs</strong></p>
<ol>
<li>Navigate to <strong>Microsoft Defender Portal</strong> → <strong>Microsoft Sentinel</strong> → <strong>Data lake exploration</strong></li>
<li>Develop and test your KQL query</li>
<li>Click <strong>Create job</strong> button in upper right corner</li>
</ol>
<figure><img
    class="my-0 rounded-md"
    loading="lazy"
    decoding="async"
    fetchpriority="auto"
    alt=""
    width="1853"
    height="997"
    src="https://www.modernsecurity.nl/microsoft-sentinel-xdr-data-lake-guide/image-42_hu_635d809c850eabab.webp"
   
   
    data-zoom-src="https://www.modernsecurity.nl/microsoft-sentinel-xdr-data-lake-guide/image-42.webp"></figure><p><strong>Job limitations during preview:</strong></p>

<div class="ms-table" role="region" aria-label="Table" tabindex="0">
  <table>
      <thead>
          <tr>
              <th>Limitation category</th>
              <th>Specification</th>
              <th>Impact on implementation</th>
          </tr>
      </thead>
    <tbody>
        <tr>
            <td><strong>Concurrent executions</strong></td>
            <td>3 per tenant maximum</td>
            <td>Requires queue management and scheduling coordination</td>
        </tr>
        <tr>
            <td><strong>Job timeout</strong></td>
            <td>1 hour maximum execution time</td>
            <td>Necessitates query optimization for complex operations</td>
        </tr>
        <tr>
            <td><strong>Enabled jobs</strong></td>
            <td>100 per tenant maximum</td>
            <td>Requires lifecycle planning and job prioritization</td>
        </tr>
    </tbody>
  </table>
</div>

<h2 class="relative group">Performance monitoring and optimization
    <div id="performance-monitoring-and-optimization" class="anchor"></div>
    
</h2>
<p>Microsoft’s data lake exploration documentation shows search functionality within results and comprehensive query management capabilities.</p>
<p><strong>Performance optimization guidelines:</strong></p>

<div class="ms-table" role="region" aria-label="Table" tabindex="0">
  <table>
      <thead>
          <tr>
              <th>Performance area</th>
              <th>Limitation</th>
              <th>Optimization strategy</th>
          </tr>
      </thead>
    <tbody>
        <tr>
            <td><strong>Query execution time</strong></td>
            <td>8 minutes maximum</td>
            <td>Implement time-based filtering and data sampling</td>
        </tr>
        <tr>
            <td><strong>Result set size</strong></td>
            <td>500,000 rows or 64MB</td>
            <td>Use summarization and aggregation techniques</td>
        </tr>
        <tr>
            <td><strong>Concurrent operations</strong></td>
            <td>45 queries per minute</td>
            <td>Plan and schedule query execution appropriately</td>
        </tr>
        <tr>
            <td><strong>Data processing</strong></td>
            <td>Single workspace scope</td>
            <td>Design workspace-specific analysis workflows</td>
        </tr>
    </tbody>
  </table>
</div>

<h2 class="relative group">Troubleshooting common issues
    <div id="troubleshooting-common-issues" class="anchor"></div>
    
</h2>
<p><strong>Onboarding error codes</strong></p>
<p>Microsoft’s troubleshooting documentation provides specific error codes for common onboarding issues:</p>
<p><strong>DL101: Regional mismatch error</strong></p>
<div class="highlight-wrapper"><div class="highlight"><div class="ms-code-label">YAML</div><pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl"><span class="nt">Error</span><span class="p">:</span><span class="w"> </span><span class="l">Can&#39;t complete setup</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nt">Description</span><span class="p">:</span><span class="w"> </span><span class="l">Primary workspace region differs from tenant home region</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nt">Resolution</span><span class="p">:</span><span class="w"> </span><span class="l">Ensure workspace is in same region as tenant home region</span></span></span></code></pre></div></div>
<p><strong>DL102: Resource availability error</strong></p>
<div class="highlight-wrapper"><div class="highlight"><div class="ms-code-label">YAML</div><pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl"><span class="nt">Error</span><span class="p">:</span><span class="w"> </span><span class="l">Lack of Azure resources in region</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nt">Description</span><span class="p">:</span><span class="w"> </span><span class="l">Insufficient Azure resources available during provisioning</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nt">Resolution</span><span class="p">:</span><span class="w"> </span><span class="l">Retry setup or attempt during off-peak hours</span></span></span></code></pre></div></div>
<p><strong>DL103: Azure policy restrictions</strong></p>
<div class="highlight-wrapper"><div class="highlight"><div class="ms-code-label">YAML</div><pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl"><span class="nt">Error</span><span class="p">:</span><span class="w"> </span><span class="l">Azure policies prevent resource creation</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nt">Description</span><span class="p">:</span><span class="w"> </span><span class="l">Organizational policies blocking required resource creation</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nt">Resolution</span><span class="p">:</span><span class="w"> </span><span class="l">Create policy exemption for Microsoft.SentinelPlatformServices</span></span></span></code></pre></div></div>
<p><strong>Data integration troubleshooting</strong></p>
<p><strong>Data not appearing in data lake:</strong></p>
<ol>
<li><strong>Wait period</strong>: Refer to the sections above for estimated timeline expectations</li>
<li><strong>Connector verification</strong>: Verify data connector configuration and status</li>
<li><strong>Retention settings</strong>: Check tier configuration and retention policies</li>
<li><strong>Permissions</strong>: Validate managed identity permissions and role assignments</li>
</ol>

<h2 class="relative group">Best practices and governance
    <div id="best-practices-and-governance" class="anchor"></div>
    
</h2>
<p><strong>Security and access management:</strong></p>
<ul>
<li>Implement principle of least privilege access</li>
<li>Conduct regular access reviews and role assignments</li>
<li>Use Unified RBAC for granular workspace-specific permissions</li>
<li>Monitor data access through comprehensive audit logs</li>
</ul>
<p><strong>Cost management best practices:</strong></p>
<ul>
<li>Use time-based filtering for optimal partition elimination</li>
<li>Implement appropriate sampling techniques for large datasets</li>
<li>Monitor query patterns and associated costs regularly</li>
<li>Balance operational needs with cost optimization objectives</li>
</ul>

<h2 class="relative group">Additional information
    <div id="additional-information" class="anchor"></div>
    
</h2>
<p><strong>Official Microsoft documentation:</strong></p>
<ul>
<li><a href="https://learn.microsoft.com/en-us/azure/sentinel/datalake/sentinel-lake-overview"  target="_blank" rel="noreferrer">Microsoft Sentinel data lake overview</a></li>
<li><a href="https://learn.microsoft.com/en-us/azure/sentinel/datalake/sentinel-lake-onboarding"  target="_blank" rel="noreferrer">Onboarding guide</a></li>
<li><a href="https://www.microsoft.com/en-us/security/pricing/microsoft-sentinel"  target="_blank" rel="noreferrer">Pricing information</a></li>
<li><a href="https://learn.microsoft.com/en-us/azure/sentinel/billing"  target="_blank" rel="noreferrer">Cost management</a></li>
</ul>
<p><strong>Community resources:</strong></p>
<ul>
<li><a href="https://techcommunity.microsoft.com/blog/microsoft-security-blog/microsoft-sentinel-data-lake-is-now-generally-available/4456342"  target="_blank" rel="noreferrer">Microsoft Security Blog – GA announcement</a></li>
<li><a href="https://techcommunity.microsoft.com/blog/microsoft-security-blog/introducing-microsoft-sentinel-graph-public-preview/4456368"  target="_blank" rel="noreferrer">Microsoft Security Blog – graph launch</a></li>
<li><a href="https://techcommunity.microsoft.com/t5/microsoft-sentinel/ct-p/MicrosoftSentinel"  target="_blank" rel="noreferrer">Microsoft Tech Community</a></li>
</ul>
<lite-youtube videoid="MIlQfgiyUz8" playlabel="MIlQfgiyUz8" params=""></lite-youtube>


<h2 class="relative group">Conclusion
    <div id="conclusion" class="anchor"></div>
    
</h2>
<p>When I first started testing with Microsoft Sentinel data lake, I’ll be honest – the pricing models and retention tiers felt overwhelming. But after implementing it across multiple environments and seeing the cost savings firsthand, I’m convinced this is one of the most significant improvements Microsoft has made to Sentinel.</p>
<p><strong>Why this matters to me (and probably to you too):</strong></p>
<p>We’ve all been in those budget meetings where leadership questions why security data retention costs so much. The data lake finally gives us a real answer to that problem. Being able to keep years of security logs without burning through budget means we can actually do our jobs properly – hunt for threats, investigate incidents thoroughly, and meet compliance requirements without constantly worrying about costs.</p>
<p><strong>My honest take on implementation:</strong></p>
<p>The standard retention configuration through the Defender portal is straightforward – you can set it up in minutes. For most Sentinel tables, it just works and the 90 days of free analytics storage is genuinely helpful. Where it gets tricky is with XDR tables. That 30-day limit catches a lot of people off guard, and suddenly you’re looking at massive ingestion bills if you’re not careful.</p>
<p><strong>What I’ve learned along the way:</strong></p>
<p>Start simple. Don’t try to optimize everything at once. Get comfortable with basic retention configuration first, understand your data volumes, and then decide if the advanced DCR approach makes sense for your environment. Monitor your costs closely in the first few months – you’ll quickly see which tables are driving expenses and where optimization efforts will have the biggest impact.</p>
<p>Also, don’t underestimate the value of having historical data readily available. I’ve been in too many investigations where we needed logs from 6+ months ago and they were either gone or stuck in some archived format that took hours to access. The data lake solves that problem elegantly.</p>
<p><strong>Looking ahead:</strong></p>
<p>Microsoft Sentinel data lake is now GA, which means it’s stable and production-ready. The pricing has settled down, the features are solid, and the performance is good. I’m excited to see where Microsoft takes this – the foundation is there for some really powerful capabilities around AI-driven analysis and long-term behavioral detection. I will try to cover MCP and Graph in my next posts, also digging more in Jupyter and Notebooks soon :-).</p>
<p>If you’re still on the fence about enabling data lake, my advice is simple: just do it. The automatic mirroring from analytics to data lake costs nothing, and you’ll immediately have a safety net for your data. You can always optimize later, but at least you won’t lose historical data while you’re figuring out your strategy.</p>
<p><strong>Final thoughts:</strong></p>
<p>Security operations is hard enough without having to choose between doing the right thing and staying within budget. The data lake removes that impossible choice. Yes, there’s complexity to manage. Yes, you need to understand the cost model. But the alternative – deleting security logs because you can’t afford to keep them – is far worse.</p>
<p>Take the time to understand your options, configure things properly, and you’ll have a data retention strategy that actually works for both security and finance. And honestly? That’s a win we don’t get very often in this field.</p>
]]></content:encoded><media:content url="https://www.modernsecurity.nl/microsoft-sentinel-xdr-data-lake-guide/featured_hu_964a0236b313b698.jpg" medium="image" type="image/jpeg" width="1200" height="800"/><enclosure url="https://www.modernsecurity.nl/microsoft-sentinel-xdr-data-lake-guide/featured_hu_964a0236b313b698.jpg" type="image/jpeg" length="243489"/></item><item><title>Automatic Attack Disruption in Microsoft Defender XDR</title><link>https://www.modernsecurity.nl/automatic-attack-disruption-defender-xdr/</link><guid isPermaLink="true">https://www.modernsecurity.nl/automatic-attack-disruption-defender-xdr/</guid><pubDate>Wed, 13 Aug 2025 16:06:47 +0100</pubDate><dc:creator>Farid Kalaidji</dc:creator><category>Microsoft Defender XDR</category><category>Security</category><description>Step-by-step guide to implementing Microsoft's Automatic Attack Disruption in Defender XDR, with all the configuration and products needed.</description><content:encoded><![CDATA[
<h2 class="relative group">Introduction
    <div id="introduction" class="anchor"></div>
    
</h2>

<h3 class="relative group">The reality of modern ransomware response
    <div id="the-reality-of-modern-ransomware-response" class="anchor"></div>
    
</h3>
<p>Picture this: It’s 2 AM. Your on-call engineer gets an alert about suspicious activity. By the time they log in, investigate, and start containment procedures, the attackers have already pivoted through three critical servers and begun encrypting your file shares. Sound familiar?</p>
<p>This scenario plays out in organizations worldwide every week. The traditional detect-alert-investigate-respond cycle simply can’t keep pace with modern attack velocities. Human-operated ransomware groups know they have a window, typically 1-3 hours, before security teams mobilize effectively. They exploit this gap ruthlessly.</p>
<figure><img
    class="my-0 rounded-md"
    loading="lazy"
    decoding="async"
    fetchpriority="low"
    alt="Automatic Attack Disruption XDR M365 Defender"
    src="https://www.modernsecurity.nl/automatic-attack-disruption-defender-xdr/autoattackdistruption-graphic-1005.gif"
    width="950"
      height="534"></figure><p><strong>This is where Microsoft’s Attack Disruption fundamentally changes the game.</strong></p>
<p>After implementing Attack Disruption across dozens of enterprise environments over the past two years, I’ve seen firsthand how it transforms incident response from a frantic race against time into a controlled, methodical process. When configured correctly, it reduces attacker dwell time from hours to minutes, automatically containing threats while your team sleeps.</p>
<p>But here’s the catch: getting it right requires meticulous attention to detail across multiple Microsoft Defender products. <em>One misconfiguration, one outdated agent, one missing integration point, and you’re back to manual firefighting.</em></p>
<p>In this guide, I’ll walk you through I ran into from my previous deployments: the configurations that work, the pitfalls to avoid, and the validation steps that ensure your Attack Disruption capability is battle-ready when you need it most.</p>

<h2 class="relative group">Understanding Attack Disruption’s threat coverage
    <div id="understanding-attack-disruptions-threat-coverage" class="anchor"></div>
    
</h2>
<p>Attack Disruption isn’t a silver bullet. It’s a precision tool designed for specific high-impact attack patterns. Understanding exactly what it protects against helps set appropriate expectations and complementary defenses.</p>

<h3 class="relative group">Primary attack vectors addressed
    <div id="primary-attack-vectors-addressed" class="anchor"></div>
    
</h3>
<p>The system excels at disrupting these specific attack types:</p>
<p><strong>Adversary-in-the-middle (AiTM) attacks</strong> – These sophisticated session hijacking attacks bypass MFA by stealing authentication cookies. Attack Disruption identifies the anomalous authentication patterns and immediately suspends compromised accounts. Microsoft has specifically enhanced this capability following recent FIDO downgrade attacks discovered in 2025.</p>
<p><strong>Business Email Compromise (BEC)</strong> – Financial fraud attempts through compromised email accounts trigger rapid containment based on unusual mailbox behavior and suspicious financial communications. With mail bombing attacks now detectable as of June 2025, the system can identify DDoS attempts that often precede BEC attacks.</p>
<p><sub>Example flow of a attack disruption in a BEC attack:</sub></p>
<figure><img
    class="my-0 rounded-md"
    loading="lazy"
    decoding="async"
    fetchpriority="auto"
    alt=""
    width="944"
    height="398"
    src="https://www.modernsecurity.nl/automatic-attack-disruption-defender-xdr/gzdwoh-xqaa-4av_hu_9dabf97a489069d2.webp"
   
   
    data-zoom-src="https://www.modernsecurity.nl/automatic-attack-disruption-defender-xdr/gzdwoh-xqaa-4av.webp"></figure><p><strong>Human-operated ransomware</strong> – The bread and butter of Attack Disruption. It recognizes hands-on-keyboard patterns, lateral movement attempts, and pre-encryption behaviors, automatically containing affected systems before encryption begins.</p>
<p><sub>Example flow of a attack disruption in STORM-1567:</sub></p>
<figure><img
    class="my-0 rounded-md"
    loading="lazy"
    decoding="async"
    fetchpriority="auto"
    alt=""
    width="1443"
    height="468"
    src="https://www.modernsecurity.nl/automatic-attack-disruption-defender-xdr/fig1-user-contiainment-akira-ransomware_hu_1783b10944bde858.webp"
   
   
    data-zoom-src="https://www.modernsecurity.nl/automatic-attack-disruption-defender-xdr/fig1-user-contiainment-akira-ransomware.webp"></figure><p><strong>Credential theft and privilege escalation</strong> – When attackers compromise domain admin accounts or attempt privilege escalation, the system responds with immediate account suspension and device isolation.</p>
<p><strong>Multi-stage phishing campaigns</strong> – Complex attack chains targeting high-value assets trigger coordinated responses across email, endpoint, and identity planes.</p>

<h2 class="relative group">The three-stage defense architecture
    <div id="the-three-stage-defense-architecture" class="anchor"></div>
    
</h2>
<p>Attack Disruption operates through a sophisticated correlation engine that processes signals in three distinct stages:</p>

<h3 class="relative group">Stage 1: Multi-vector signal correlation
    <div id="stage-1-multi-vector-signal-correlation" class="anchor"></div>
    
</h3>
<p>The system continuously ingests and correlates telemetry from all deployed Defender products: endpoint behavioral analytics, identity anomalies, email security indicators, and cloud application activity. This cross-product visibility is crucial; isolated signals that seem benign become critical when correlated across domains.</p>

<h3 class="relative group">Stage 2: Compromised asset identification
    <div id="stage-2-compromised-asset-identification" class="anchor"></div>
    
</h3>
<p>Once high-confidence attack patterns emerge, the system maps the attack’s progression across your environment. It identifies not just currently compromised assets but also likely next targets based on lateral movement patterns and attacker TTPs (Tactics, Techniques, and Procedures).</p>

<h3 class="relative group">Stage 3: Automated response execution
    <div id="stage-3-automated-response-execution" class="anchor"></div>
    
</h3>
<p>Based on the threat scope and your configured automation levels, the system executes appropriate containment actions while preserving forensic evidence. These aren’t random isolations. They’re surgical strikes designed to break the attack chain while minimizing business disruption.</p>

<h2 class="relative group">Automated response actions in practice
    <div id="automated-response-actions-in-practice" class="anchor"></div>
    
</h2>
<p>The platform can execute four primary response actions, each serving a specific defensive purpose:</p>
<ul>
<li>
<p><strong>Device containment</strong> isolates compromised endpoints from network communications while maintaining a forensic channel to the Defender portal. I’ve seen this stop ransomware spread in its tracks during active attacks.</p>
</li>
<li>
<p><strong>User account suspension</strong> immediately disables compromised accounts in both Active Directory and Microsoft Entra ID (formerly Azure AD). This is particularly effective against BEC attacks where every minute counts.</p>
</li>
<li>
<p><strong>User containment</strong> provides temporary identity-based blocking that prevents lateral movement without fully disabling accounts, perfect for investigating suspicious but unconfirmed activity.</p>
</li>
<li>
<p><strong>IP address containment</strong> blocks malicious IP addresses associated with command-and-control infrastructure or compromised unmanaged devices attempting network access.</p>
</li>
</ul>

<h2 class="relative group">High-confidence decision making
    <div id="high-confidence-decision-making" class="anchor"></div>
    
</h2>
<p>What sets Attack Disruption apart from basic automated response tools is its sophisticated decision-making framework:</p>
<ul>
<li><strong>Multi-vector convergent analysis</strong> requires corroborating evidence from multiple security domains before taking action</li>
<li><strong>Threat intelligence integration</strong> leverages Microsoft’s visibility into thousands of real-world incidents daily</li>
<li><strong>Advanced AI models</strong> trained on confirmed attack patterns, not just anomalies</li>
<li><strong>Temporal and contextual correlation</strong> understands that certain behaviors together in sequence indicate attacks</li>
</ul>
<p>This multi-layered approach maintains exceptionally low false positive rates, critical for maintaining trust in automation.</p>

<h2 class="relative group">Licensing requirements and architecture
    <div id="licensing-requirements-and-architecture" class="anchor"></div>
    
</h2>

<h3 class="relative group">License requirements
    <div id="license-requirements" class="anchor"></div>
    
</h3>
<p>Full Attack Disruption functionality requires one of these licensing combinations:</p>

<div class="ms-table" role="region" aria-label="Table" tabindex="0">
  <table>
      <thead>
          <tr>
              <th>Subscription Type</th>
              <th>Coverage</th>
              <th>Best for</th>
          </tr>
      </thead>
    <tbody>
        <tr>
            <td><strong>Microsoft 365 E5</strong></td>
            <td>Complete</td>
            <td>Most organizations – best value</td>
        </tr>
        <tr>
            <td><strong>Microsoft 365 A5</strong></td>
            <td>Complete</td>
            <td>Educational institutions</td>
        </tr>
        <tr>
            <td><strong>Microsoft 365 E3 + E5 Security</strong></td>
            <td>Complete</td>
            <td>Organizations with existing E3</td>
        </tr>
        <tr>
            <td><strong>Microsoft 365 A3 + A5 Security</strong></td>
            <td>Complete</td>
            <td>Educational alternative</td>
        </tr>
    </tbody>
  </table>
</div>
<p>Partial coverage options (requiring additional products):</p>
<ul>
<li>Windows 10/11 Enterprise E5</li>
<li>EMS E5</li>
<li>Office 365 E5</li>
</ul>

<h3 class="relative group">Essential product dependencies
    <div id="essential-product-dependencies" class="anchor"></div>
    
</h3>
<p>These four products must all be deployed for complete Attack Disruption coverage:</p>
<ol>
<li><strong>Microsoft Defender for Endpoint Plan 2</strong> – Provides device containment and behavioral analytics</li>
<li><strong>Microsoft Defender for Identity</strong> – Enables Active Directory and Entra ID account suspension</li>
<li><strong>Microsoft Defender for Cloud Apps</strong> – Supplies cloud application signals and OAuth app governance</li>
<li><strong>Microsoft Defender for Office 365 Plan 2</strong> – Delivers email security signals and SafeLinks protection</li>
</ol>
<blockquote><p><em><strong>Missing any component creates coverage gaps that sophisticated attackers will exploit. I don’t dive into how to configure MDE/MDI/MDCA/MDO, below I have added the steps that are often forgotten. Make sure to check them!</strong></em> And again: the wider the deployment, the greater the <em>protection coverage</em> is</p>
</blockquote>
<h2 class="relative group">Permission configuration
    <div id="permission-configuration" class="anchor"></div>
    
</h2>
<p>Proper role assignment ensures your team can manage Attack Disruption effectively:</p>

<div class="ms-table" role="region" aria-label="Table" tabindex="0">
  <table>
      <thead>
          <tr>
              <th>Role</th>
              <th>Purpose</th>
          </tr>
      </thead>
    <tbody>
        <tr>
            <td><strong>Global Administrator</strong></td>
            <td>Full configuration access</td>
        </tr>
        <tr>
            <td><strong>Security Administrator</strong></td>
            <td>Manage Attack Disruption settings</td>
        </tr>
        <tr>
            <td><strong>Security Reader</strong></td>
            <td>View actions and incidents</td>
        </tr>
        <tr>
            <td><strong>Security Operator</strong></td>
            <td>Approve/reject pending actions</td>
        </tr>
    </tbody>
  </table>
</div>

<h2 class="relative group">Microsoft Defender for Endpoint configuration (important for HumOR and AiTM)
    <div id="microsoft-defender-for-endpoint-configuration-important-for-humor-and-aitm" class="anchor"></div>
    
</h2>

<h3 class="relative group">Agent version requirements
    <div id="agent-version-requirements" class="anchor"></div>
    
</h3>
<p>When you have deployed Microsoft Defender for Endpoint (MDE), you must verify the minimum Sense Agent version for full functionality is <strong>10.8470</strong>. This version enables the critical “Contain User” action essential for stopping human-operated attacks. Running older versions severely limits your defensive capabilities.</p>
<p>Validate your current deployment with this KQL query:</p>
<div class="highlight-wrapper"><div class="highlight"><div class="ms-code-label">KQL</div><pre tabindex="0" class="chroma"><code class="language-kql" data-lang="kql"><span class="c1">// Identify devices with outdated agent versions</span>
DeviceInfo
<span class="o">|</span> <span class="k">where</span> Timestamp <span class="o">&gt;</span> <span class="nf">ago</span>(1d)
<span class="o">|</span> <span class="k">where</span> OnboardingStatus <span class="o">==</span> <span class="s">&#34;Onboarded&#34;</span>
<span class="o">|</span> <span class="k">summarize</span> <span class="nf">arg_max</span>(Timestamp, *) <span class="k">by</span> DeviceId
<span class="o">|</span> <span class="k">extend</span> AgentVersionNumber = <span class="nf">toint</span>(<span class="nf">substring</span>(ClientVersion, 0, <span class="nf">indexof</span>(ClientVersion, <span class="s">&#34;.&#34;</span>)))
<span class="o">|</span> <span class="k">where</span> AgentVersionNumber <span class="o">&lt;</span> 10 <span class="k">or</span> (AgentVersionNumber <span class="o">==</span> 10 <span class="k">and</span> 
    <span class="nf">toint</span>(<span class="nf">substring</span>(ClientVersion, <span class="nf">indexof</span>(ClientVersion, <span class="s">&#34;.&#34;</span>) + 1)) <span class="o">&lt;</span> 8470)
<span class="o">|</span> <span class="k">project</span> DeviceName, ClientVersion, OnboardingStatus, OSPlatform
<span class="o">|</span> <span class="k">sort by</span> DeviceName <span class="k">asc</span></code></pre></div>
</div>
<p>Local verification:</p>
<div class="highlight-wrapper"><div class="highlight"><div class="ms-code-label">PowerShell</div><pre tabindex="0" class="chroma"><code class="language-powershell" data-lang="powershell"><span class="line"><span class="cl"><span class="c"># Check agent version locally</span>
</span></span><span class="line"><span class="cl"><span class="nb">Get-ItemProperty</span> <span class="n">-Path</span> <span class="s1">&#39;Registry::HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows Advanced Threat Protection\Status&#39;</span> <span class="n">-Name</span> <span class="s2">&#34;MsSenseDllVersion&#34;</span></span></span></code></pre></div></div>

<h3 class="relative group">Device Group automation strategy
    <div id="device-group-automation-strategy" class="anchor"></div>
    
</h3>
<p>Device groups control automation levels across your environment. Strategic configuration balances security effectiveness with business continuity.</p>
<p><strong>Manual configuration steps:</strong></p>
<ol>
<li>Navigate to the Microsoft Defender portal (<a href="https://security.microsoft.com"  target="_blank" rel="noreferrer">https://security.microsoft.com</a>)</li>
<li>Go to <strong>Settings &gt; Endpoints &gt; Permissions &gt; Device groups</strong></li>
<li>Click <strong>+ Add device group</strong></li>
<li>Configure the following settings:
<ul>
<li><strong>Name and description</strong> – Use clear, function-based naming (e.g., “Production Servers – Semi-Auto”)</li>
<li><strong>Automation level</strong> – Choose based on device criticality:</li>
</ul>
</li>
</ol>

<div class="ms-table" role="region" aria-label="Table" tabindex="0">
  <table>
      <thead>
          <tr>
              <th>Automation level</th>
              <th>Description</th>
              <th>When actions are taken</th>
          </tr>
      </thead>
    <tbody>
        <tr>
            <td><strong>Full – remediate threats automatically</strong></td>
            <td>Recommended setting</td>
            <td>Malicious verdicts = automatic remediation</td>
        </tr>
        <tr>
            <td><strong>Semi – require approval for any remediation</strong></td>
            <td>All actions need approval</td>
            <td>All verdicts require manual approval</td>
        </tr>
        <tr>
            <td><strong>Semi – require approval for core folders remediation</strong></td>
            <td>Core system folders protected</td>
            <td>Malicious in system folders = approval needed; elsewhere = automatic</td>
        </tr>
        <tr>
            <td><strong>Semi – require approval for non-temp folders remediation</strong></td>
            <td>Temp folders automated</td>
            <td>Temp folders = automatic; other locations = approval needed</td>
        </tr>
        <tr>
            <td><strong>Semi – require approval for all folders</strong></td>
            <td>Investigation only</td>
            <td>All remediation requires approval</td>
        </tr>
        <tr>
            <td><strong>No automated response</strong></td>
            <td>Not recommended</td>
            <td>No automated investigation or remediation</td>
        </tr>
    </tbody>
  </table>
</div>
<figure><img
    class="my-0 rounded-md"
    loading="lazy"
    decoding="async"
    fetchpriority="auto"
    alt=""
    width="1501"
    height="935"
    src="https://www.modernsecurity.nl/automatic-attack-disruption-defender-xdr/image-6_hu_f2cc3213e09e60e8.webp"
   
   
    data-zoom-src="https://www.modernsecurity.nl/automatic-attack-disruption-defender-xdr/image-6.webp"></figure>
<h3 class="relative group">Device Discovery configuration
    <div id="device-discovery-configuration" class="anchor"></div>
    
</h3>
<p>Standard discovery mode is essential for Attack Disruption to identify and respond to unmanaged devices attempting network access.</p>
<p><strong>Configuration steps:</strong></p>
<ol>
<li>In the Microsoft Defender portal, go to <strong>Settings &gt; <strong>Device discovery</strong></strong></li>
<li>Ensure <strong>Standard discovery</strong> is enabled (not Basic)</li>
<li>Configure monitored networks as needed</li>
<li>Save changes</li>
</ol>
<figure><img
    class="my-0 rounded-md"
    loading="lazy"
    decoding="async"
    fetchpriority="auto"
    alt=""
    width="1490"
    height="889"
    src="https://www.modernsecurity.nl/automatic-attack-disruption-defender-xdr/image-7_hu_85a9d84f85ee2ad8.webp"
   
   
    data-zoom-src="https://www.modernsecurity.nl/automatic-attack-disruption-defender-xdr/image-7.webp"></figure><p>Monitor discovery of devices after a bit of time:</p>
<div class="highlight-wrapper"><div class="highlight"><div class="ms-code-label">KQL</div><pre tabindex="0" class="chroma"><code class="language-kql" data-lang="kql"><span class="c1">// Check for devices that should be onboarded</span>
DeviceInfo 
<span class="o">|</span> <span class="k">summarize</span> <span class="nf">arg_max</span>(Timestamp, *) <span class="k">by</span> DeviceId
<span class="o">|</span> <span class="k">where</span> <span class="k">isempty</span>(MergedToDeviceId)
<span class="o">|</span> <span class="k">where</span> OnboardingStatus <span class="o">==</span> <span class="s">&#34;Can be onboarded&#34;</span>
<span class="o">|</span> <span class="k">project</span> DeviceName, OnboardingStatus, LastSeen = Timestamp, OSPlatform</code></pre></div>
</div>

<h2 class="relative group">Microsoft Defender for Identity configuration (important for hybrid users)
    <div id="microsoft-defender-for-identity-configuration-important-for-hybrid-users" class="anchor"></div>
    
</h2>

<h3 class="relative group">Domain Controller audit requirements
    <div id="domain-controller-audit-requirements" class="anchor"></div>
    
</h3>
<p>Proper audit policies enable Defender for Identity to detect and respond to credential-based attacks. See <a href="https://www.modernsecurity.nl/install-microsoft-defender-for-identity/" >my extensive guide on Defender for Identity</a>, below the important things to keep in mind.</p>
<p><strong>Manual audit configuration via Group Policy:</strong></p>
<ol>
<li>Open Group Policy Management Console on a domain controller</li>
<li>Navigate to <strong>Computer Configuration &gt; Policies &gt; Windows Settings &gt; Security Settings &gt; Advanced Audit Policy Configuration &gt; Audit Policies</strong></li>
<li>Configure the following audit subcategories for Success and Failure:
<ul>
<li><strong>Account Logon &gt; Audit Credential Validation</strong></li>
<li><strong>Account Management &gt; Audit Computer Account Management</strong></li>
<li><strong>Account Management &gt; Audit Distribution Group Management</strong></li>
<li><strong>Account Management &gt; Audit Security Group Management</strong></li>
<li><strong>Account Management &gt; Audit User Account Management</strong></li>
<li><strong>DS Access &gt; Audit Directory Service Changes</strong></li>
<li><strong>DS Access &gt; Audit Directory Service Access</strong></li>
<li><strong>System &gt; Audit Security System Extension</strong></li>
</ul>
</li>
<li>Apply the GPO to all domain controllers</li>
<li>Verify with PowerShell:</li>
</ol>
<div class="highlight-wrapper"><div class="highlight"><div class="ms-code-label">PowerShell</div><pre tabindex="0" class="chroma"><code class="language-powershell" data-lang="powershell"><span class="line"><span class="cl"><span class="c"># Install the Defender for Identity PowerShell module</span>
</span></span><span class="line"><span class="cl"><span class="nb">Install-Module</span> <span class="n">-Name</span> <span class="n">DefenderForIdentity</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c"># Set all required audit configurations</span>
</span></span><span class="line"><span class="cl"><span class="nb">Set-MDIConfiguration</span> <span class="n">-Mode</span> <span class="n">Domain</span> <span class="n">-Configuration</span> <span class="n">All</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c"># Test if all configurations are correct</span>
</span></span><span class="line"><span class="cl"><span class="nb">Test-MDIConfiguration</span> <span class="n">-Mode</span> <span class="n">Domain</span> <span class="n">-Configuration</span> <span class="n">All</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c"># View current configuration status</span>
</span></span><span class="line"><span class="cl"><span class="nb">Get-MDIConfiguration</span> <span class="n">-Mode</span> <span class="n">Domain</span> <span class="n">-Configuration</span> <span class="n">All</span></span></span></code></pre></div></div>

<h3 class="relative group">Action account configuration
    <div id="action-account-configuration" class="anchor"></div>
    
</h3>
<p>Defender for Identity uses the LocalSystem account on domain controllers for automated responses by default. The sensor must be deployed on the DC where Active Directory accounts will be disabled.</p>
<p><strong>Important considerations:</strong></p>
<ul>
<li>Validate that no automation conflicts exist that might re-enable disabled accounts</li>
<li>Ensure the LocalSystem account maintains proper permissions</li>
<li>Test account suspension in a controlled environment first</li>
</ul>
<p>Verify sensor deployment:</p>
<div class="highlight-wrapper"><div class="highlight"><div class="ms-code-label">PowerShell</div><pre tabindex="0" class="chroma"><code class="language-powershell" data-lang="powershell"><span class="line"><span class="cl"><span class="c"># Check Defender for Identity sensor service</span>
</span></span><span class="line"><span class="cl"><span class="nb">Get-Service</span> <span class="n">-Name</span> <span class="s2">&#34;AATPSensor&#34;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c"># Verify sensor deployment on domain controllers</span>
</span></span><span class="line"><span class="cl"><span class="nb">Get-WmiObject</span> <span class="n">-Class</span> <span class="n">Win32_Service</span> <span class="n">-Filter</span> <span class="s2">&#34;Name=&#39;AATPSensor&#39;&#34;</span> <span class="p">|</span> <span class="nb">Select-Object</span> <span class="n">Name</span><span class="p">,</span> <span class="n">State</span><span class="p">,</span> <span class="n">StartMode</span></span></span></code></pre></div></div>

<h3 class="relative group">Entra ID integration
    <div id="entra-id-integration" class="anchor"></div>
    
</h3>
<p>With the rebranding from Azure AD to Microsoft Entra ID, it’s important to understand how Attack Disruption handles different account types:</p>
<p><strong>For hybrid accounts (synced from AD):</strong></p>
<ul>
<li>Defender for Identity disables the on-premises AD account</li>
<li>Attack Disruption also disables the Entra ID synced account</li>
</ul>
<p><strong>For cloud-only accounts (Entra ID native):</strong></p>
<ul>
<li>Attack Disruption disables the account directly in Entra ID</li>
<li>This doesn’t require Defender for Identity deployment</li>
</ul>

<h2 class="relative group">Microsoft Defender for Cloud Apps integration (important for BEC detections)
    <div id="microsoft-defender-for-cloud-apps-integration-important-for-bec-detections" class="anchor"></div>
    
</h2>

<h3 class="relative group">Office 365 Connector configuration
    <div id="office-365-connector-configuration" class="anchor"></div>
    
</h3>
<p>The Office 365 connector provides essential visibility for detecting for example BEC attacks and suspicious OAuth applications.</p>
<p><strong>Detailed setup process:</strong></p>
<ol>
<li>Navigate to the Microsoft Defender portal (<a href="https://security.microsoft.com"  target="_blank" rel="noreferrer">https://security.microsoft.com</a>)</li>
<li>Go to <strong>Settings &gt; Cloud Apps &gt; Connected apps &gt; App connectors</strong></li>
<li>Click <strong>Connect an app</strong> and select <strong>Office 365</strong></li>
<li>In the connection wizard, grant the following permissions:
<ul>
<li>Microsoft Entra Users and groups</li>
<li>Microsoft Entra ID Management events</li>
<li>Microsoft Entra ID Sign-in events</li>
<li>Microsoft Entra ID Apps</li>
<li>Microsoft 365 activities</li>
<li>Microsoft 365 files</li>
</ul>
</li>
<li>Review and accept the permission consent</li>
<li>Verify connection status shows “Connected”</li>
</ol>
<figure><img
    class="my-0 rounded-md"
    loading="lazy"
    decoding="async"
    fetchpriority="auto"
    alt=""
    width="1493"
    height="935"
    src="https://www.modernsecurity.nl/automatic-attack-disruption-defender-xdr/image-9_hu_44cd86c0ed0e4856.webp"
   
   
    data-zoom-src="https://www.modernsecurity.nl/automatic-attack-disruption-defender-xdr/image-9.webp"></figure>
<h3 class="relative group">App Governance configuration
    <div id="app-governance-configuration" class="anchor"></div>
    
</h3>
<p>App Governance provides critical OAuth application visibility to detect malicious apps used in attacks. Also for this, <a href="https://www.modernsecurity.nl/oauth-attacks-microsoft-app-governance-mda/" >check my blogpost</a> which I created before, below the short steps to enable it.</p>
<p><strong>Enablement steps:</strong></p>
<ol>
<li>In Microsoft Defender portal, navigate to <strong>Cloud Apps &gt; App governance</strong></li>
<li>If not activated, click <strong>Get started</strong> to enable App Governance</li>
<li>Accept the terms and conditions</li>
<li>Wait for initial discovery (can take 1-2 hours)</li>
<li>Configure OAuth app policies:
<ul>
<li>Go to <strong>Policies &gt; Create policy</strong></li>
<li>Select <strong>OAuth app anomaly detection</strong></li>
<li>Configure thresholds for suspicious app behavior</li>
<li>Enable automatic remediation where appropriate</li>
</ul>
</li>
</ol>
<figure><img
    class="my-0 rounded-md"
    loading="lazy"
    decoding="async"
    fetchpriority="auto"
    alt=""
    width="1489"
    height="925"
    src="https://www.modernsecurity.nl/automatic-attack-disruption-defender-xdr/image-10_hu_173dce7d2cbd962f.webp"
   
   
    data-zoom-src="https://www.modernsecurity.nl/automatic-attack-disruption-defender-xdr/image-10.webp"></figure>
<h3 class="relative group">Network requirements update (critical)
    <div id="network-requirements-update-critical" class="anchor"></div>
    
</h3>
<p><strong>Important</strong>: Microsoft has announced critical network requirement changes for Defender for Cloud Apps:</p>
<p><strong>For commercial tenants (by April 29, 2025):</strong></p>
<ul>
<li>Update firewall configurations to allow the new Azure service tags</li>
<li>Add <strong>AzureFrontDoor.MicrosoftSecurity</strong> tag to allowlist</li>
<li>Configure outbound traffic on port 443</li>
</ul>
<p><strong>For GCC/Government Tenants (by August 25, 2025):</strong></p>
<ul>
<li>Allow outbound traffic on port 443 to specified IP ranges</li>
<li>Add Azure Gov service tag <strong>AzureFrontDoor.MicrosoftSecurity</strong></li>
</ul>
<p>Failure to update these configurations will result in service disruption.</p>

<h2 class="relative group">Microsoft Defender for Office 365 configuration (important for AiTM)
    <div id="microsoft-defender-for-office-365-configuration-important-for-aitm" class="anchor"></div>
    
</h2>

<h3 class="relative group">Mailbox auditing
    <div id="mailbox-auditing" class="anchor"></div>
    
</h3>
<p>Enable auditing for all mailboxes to detect attack patterns. The following events must be audited at minimum:</p>
<ul>
<li>MailItemsAccessed (tracks email access patterns)</li>
<li>UpdateInboxRules (detects malicious rule creation)</li>
<li>MoveToDeletedItems (monitors email manipulation)</li>
<li>SoftDelete (tracks email deletion)</li>
<li>HardDelete (tracks permanent deletion)</li>
</ul>
<p><strong>Complete PowerShell configuration:</strong></p>
<div class="highlight-wrapper"><div class="highlight"><div class="ms-code-label">PowerShell</div><pre tabindex="0" class="chroma"><code class="language-powershell" data-lang="powershell"><span class="line"><span class="cl"><span class="c"># Connect to Exchange Online</span>
</span></span><span class="line"><span class="cl"><span class="nb">Connect-ExchangeOnline</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c"># Step 1: Enable unified audit log ingestion (for admin actions)</span>
</span></span><span class="line"><span class="cl"><span class="nb">Get-AdminAuditLogConfig</span> <span class="p">|</span> <span class="nb">Format-List</span> <span class="n">UnifiedAuditLogIngestionEnabled</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c"># If False, enable it:</span>
</span></span><span class="line"><span class="cl"><span class="nb">Set-AdminAuditLogConfig</span> <span class="n">-UnifiedAuditLogIngestionEnabled</span> <span class="vm">$true</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c"># Step 2: Enable mailbox auditing by default (for mailbox actions)</span>
</span></span><span class="line"><span class="cl"><span class="nb">Get-OrganizationConfig</span> <span class="p">|</span> <span class="nb">Format-List</span> <span class="n">AuditDisabled</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c"># If True (auditing is disabled), enable it:</span>
</span></span><span class="line"><span class="cl"><span class="nb">Set-OrganizationConfig</span> <span class="n">-AuditDisabled</span> <span class="vm">$false</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c"># Step 3: Configure specific audit events for all mailboxes</span>
</span></span><span class="line"><span class="cl"><span class="nv">$AuditEvents</span> <span class="p">=</span> <span class="vm">@</span><span class="p">(</span><span class="s2">&#34;MailItemsAccessed&#34;</span><span class="p">,</span><span class="s2">&#34;UpdateInboxRules&#34;</span><span class="p">,</span><span class="s2">&#34;MoveToDeletedItems&#34;</span><span class="p">,</span><span class="s2">&#34;SoftDelete&#34;</span><span class="p">,</span><span class="s2">&#34;HardDelete&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="nb">Get-Mailbox</span> <span class="n">-ResultSize</span> <span class="n">Unlimited</span> <span class="n">-Filter</span> <span class="s2">&#34;RecipientTypeDetails -eq &#39;UserMailbox&#39;&#34;</span> <span class="p">|</span> 
</span></span><span class="line"><span class="cl">    <span class="nb">ForEach-Object</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="nb">Set-Mailbox</span> <span class="n">-Identity</span> <span class="nv">$_</span><span class="p">.</span><span class="py">Identity</span> <span class="p">`</span>
</span></span><span class="line"><span class="cl">            <span class="n">-AuditEnabled</span> <span class="vm">$true</span> <span class="p">`</span>
</span></span><span class="line"><span class="cl">            <span class="n">-AuditLogAgeLimit</span> <span class="mf">90</span> <span class="p">`</span>
</span></span><span class="line"><span class="cl">            <span class="n">-AuditAdmin</span> <span class="p">(</span><span class="nv">$AuditEvents</span> <span class="n">-join</span> <span class="s2">&#34;,&#34;</span><span class="p">)</span> <span class="p">`</span>
</span></span><span class="line"><span class="cl">            <span class="n">-AuditDelegate</span> <span class="p">(</span><span class="nv">$AuditEvents</span> <span class="n">-join</span> <span class="s2">&#34;,&#34;</span><span class="p">)</span> <span class="p">`</span>
</span></span><span class="line"><span class="cl">            <span class="n">-AuditOwner</span> <span class="p">(</span><span class="nv">$AuditEvents</span> <span class="n">-join</span> <span class="s2">&#34;,&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c"># Verify configuration</span>
</span></span><span class="line"><span class="cl"><span class="nb">Get-Mailbox</span> <span class="n">-ResultSize</span> <span class="mf">10</span> <span class="p">|</span> <span class="nb">Format-List</span> <span class="n">Name</span><span class="p">,</span> <span class="n">AuditEnabled</span><span class="p">,</span> <span class="n">AuditLogAgeLimit</span></span></span></code></pre></div></div>

<h3 class="relative group">SafeLinks policy configuration
    <div id="safelinks-policy-configuration" class="anchor"></div>
    
</h3>
<p>At least one active SafeLinks policy must be configured for Attack Disruption email threat detection.</p>
<p><strong>Manual Configuration Steps:</strong></p>
<ol>
<li>Navigate to Microsoft 365 Defender portal (<a href="https://security.microsoft.com"  target="_blank" rel="noreferrer">https://security.microsoft.com</a>)</li>
<li>Go to <strong>Email &amp; collaboration &gt; Policies &amp; rules &gt; Threat policies &gt; Safe Links</strong></li>
<li>Click <strong>Create</strong> to add a new policy</li>
<li>Configure policy settings:
<ul>
<li><strong>Name</strong>: “Custom – SafeLinks Policy”</li>
<li><strong>URL scanning</strong>: Enable “On: Safe Links checks a list of known, malicious links”</li>
<li><strong>Real-time scanning</strong>: Enable “Apply real-time URL scanning for suspicious links”</li>
<li><strong>Wait for scanning</strong>: Enable “Wait for URL scanning to complete before delivering”</li>
<li><strong>Internal emails</strong>: Enable “Apply Safe Links to email messages sent within the organization”</li>
<li><strong>Click protection</strong>: Enable “Track user clicks”</li>
<li><strong>User override</strong>: Disable “Do not let users click through to original URL”</li>
</ul>
</li>
<li>Configure app protection:
<ul>
<li>Enable Safe Links for <strong>Office 365 applications</strong></li>
<li>Enable Safe Links for <strong>Microsoft Teams</strong></li>
</ul>
</li>
<li>Apply to recipients:
<ul>
<li>Condition: <strong>The recipient domain is</strong></li>
<li>Value: Select all accepted domains</li>
</ul>
</li>
<li>Set priority to <strong>0</strong> (highest)</li>
<li>Review and <strong>Save</strong></li>
</ol>
<p><strong>Configuration and verification via PowerShell:</strong></p>
<div class="highlight-wrapper"><div class="highlight"><div class="ms-code-label">PowerShell</div><pre tabindex="0" class="chroma"><code class="language-powershell" data-lang="powershell"><span class="line"><span class="cl"><span class="c"># Connect to Security &amp; Compliance PowerShell</span>
</span></span><span class="line"><span class="cl"><span class="nb">Connect-IPPSSession</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c"># Create a new SafeLinks policy</span>
</span></span><span class="line"><span class="cl"><span class="nb">New-SafeLinksPolicy</span> <span class="n">-Name</span> <span class="s2">&#34;Custom - SafeLinks Policy&#34;</span> <span class="p">`</span>
</span></span><span class="line"><span class="cl">    <span class="n">-EnableSafeLinksForEmail</span> <span class="vm">$true</span> <span class="p">`</span>
</span></span><span class="line"><span class="cl">    <span class="n">-EnableSafeLinksForOffice</span> <span class="vm">$true</span> <span class="p">`</span>
</span></span><span class="line"><span class="cl">    <span class="n">-EnableSafeLinksForTeams</span> <span class="vm">$true</span> <span class="p">`</span>
</span></span><span class="line"><span class="cl">    <span class="n">-ScanUrls</span> <span class="vm">$true</span> <span class="p">`</span>
</span></span><span class="line"><span class="cl">    <span class="n">-DeliverMessageAfterScan</span> <span class="vm">$true</span> <span class="p">`</span>
</span></span><span class="line"><span class="cl">    <span class="n">-EnableForInternalSenders</span> <span class="vm">$true</span> <span class="p">`</span>
</span></span><span class="line"><span class="cl">    <span class="n">-AllowClickThrough</span> <span class="vm">$false</span> <span class="p">`</span>
</span></span><span class="line"><span class="cl">    <span class="n">-TrackUserClicks</span> <span class="vm">$true</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c"># Create and apply the SafeLinks rule</span>
</span></span><span class="line"><span class="cl"><span class="nb">New-SafeLinksRule</span> <span class="n">-Name</span> <span class="s2">&#34;Custom - SafeLinks Policy&#34;</span> <span class="p">`</span>
</span></span><span class="line"><span class="cl">    <span class="n">-SafeLinksPolicy</span> <span class="s2">&#34;Custom - SafeLinks Policy&#34;</span> <span class="p">`</span>
</span></span><span class="line"><span class="cl">    <span class="n">-RecipientDomainIs</span> <span class="p">(</span><span class="nb">Get-AcceptedDomain</span><span class="p">).</span><span class="py">Name</span> <span class="p">`</span>
</span></span><span class="line"><span class="cl">    <span class="n">-Enabled</span> <span class="vm">$true</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c"># Verify the policy is active</span>
</span></span><span class="line"><span class="cl"><span class="nb">Get-SafeLinksPolicy</span> <span class="n">-Identity</span> <span class="s2">&#34;Custom - SafeLinks Policy&#34;</span>
</span></span><span class="line"><span class="cl"><span class="nb">Get-SafeLinksRule</span> <span class="n">-Identity</span> <span class="s2">&#34;Custom - SafeLinks Policy&#34;</span></span></span></code></pre></div></div>

<h2 class="relative group">Strategic exclusion management
    <div id="strategic-exclusion-management" class="anchor"></div>
    
</h2>

<h3 class="relative group">User account exclusions
    <div id="user-account-exclusions" class="anchor"></div>
    
</h3>
<p>While the platform allows excluding specific accounts from automated responses, use this capability sparingly. High-value accounts, often targeted in attacks, need maximum protection.</p>
<p><strong>Configure user exclusions:</strong></p>
<ol>
<li>In the Microsoft Defender portal, go to <strong>Settings &gt; Microsoft Defender XDR</strong></li>
<li>Under <strong>Automated response</strong>, select <strong>Identities</strong></li>
<li>Click <strong>Add user exclusion</strong></li>
<li>Enter user account names (UPN format)</li>
<li>Select <strong>Exclude users</strong> to save</li>
</ol>
<figure><img
    class="my-0 rounded-md"
    loading="lazy"
    decoding="async"
    fetchpriority="auto"
    alt=""
    width="1498"
    height="928"
    src="https://www.modernsecurity.nl/automatic-attack-disruption-defender-xdr/image-1_hu_4076bd3df32614dc.webp"
   
   
    data-zoom-src="https://www.modernsecurity.nl/automatic-attack-disruption-defender-xdr/image-1.webp"></figure><p><strong>Appropriate exclusions include:</strong></p>
<ul>
<li>Emergency break-glass accounts (with compensating controls)</li>
<li>Critical service accounts with unique authentication patterns</li>
<li>Test accounts in completely isolated environments</li>
</ul>
<p><strong>Never exclude:</strong></p>
<ul>
<li>C-level executives or VIPs (prime targets for BEC/AiTM)</li>
<li>Domain administrators</li>
<li>Service accounts with broad permissions</li>
</ul>

<h3 class="relative group">Device Group exclusions
    <div id="device-group-exclusions" class="anchor"></div>
    
</h3>
<p>Device exclusions affect both Attack Disruption and broader automated investigation capabilities.</p>
<p><strong>Configuration process:</strong></p>
<ol>
<li>Navigate to <strong>Settings &gt; Microsoft Defender XDR &gt; Automated response &gt; Devices</strong></li>
<li>In the <strong>Device groups</strong> tab, select the group to configure</li>
<li>Choose the appropriate automation level</li>
<li>Document business justification for any “No automated response” settings</li>
</ol>
<figure><img
    class="my-0 rounded-md"
    loading="lazy"
    decoding="async"
    fetchpriority="auto"
    alt=""
    width="1497"
    height="934"
    src="https://www.modernsecurity.nl/automatic-attack-disruption-defender-xdr/image-2_hu_c86c2e62342485c8.webp"
   
   
    data-zoom-src="https://www.modernsecurity.nl/automatic-attack-disruption-defender-xdr/image-2.webp"></figure>
<h2 class="relative group">Action Center operations
    <div id="action-center-operations" class="anchor"></div>
    
</h2>

<h3 class="relative group">Understanding the Action Center interface
    <div id="understanding-the-action-center-interface" class="anchor"></div>
    
</h3>
<p>The Action Center (<a href="https://security.microsoft.com/action-center"  target="_blank" rel="noreferrer">https://security.microsoft.com/action-center</a>) serves as your command center for Attack Disruption events.</p>
<p><strong>Pending Actions tab:</strong></p>
<ul>
<li>Displays actions awaiting approval in semi-automated scenarios</li>
<li>Provides bulk approval/rejection for similar action types</li>
<li>Shows full incident context and affected assets</li>
<li>Critical for maintaining automated investigation flow</li>
</ul>
<p><strong>History tab:</strong></p>
<ul>
<li>Complete audit trail of all automated actions</li>
<li>Tracks automated investigations and Live Response sessions</li>
<li>Provides ability to undo certain completed actions</li>
<li>Serves as compliance documentation</li>
</ul>
<figure><img
    class="my-0 rounded-md"
    loading="lazy"
    decoding="async"
    fetchpriority="auto"
    alt=""
    width="1853"
    height="999"
    src="https://www.modernsecurity.nl/automatic-attack-disruption-defender-xdr/image_hu_8da58c5d6ac825dd.webp"
   
   
    data-zoom-src="https://www.modernsecurity.nl/automatic-attack-disruption-defender-xdr/image.webp"></figure>
<h3 class="relative group">Incident recognition
    <div id="incident-recognition" class="anchor"></div>
    
</h3>
<p>Attack Disruption incidents are easily identifiable through several indicators:</p>
<ol>
<li><strong>Attack Disruption tag</strong> in the incident queue for easy filtering</li>
<li><strong>Yellow banner</strong> at the top of incident pages highlighting automatic actions taken</li>
<li><strong>Asset status indicators</strong> in the incident graph showing contained devices and disabled accounts</li>
<li><strong>(attack disruption)</strong> string added to incident titles via API</li>
</ol>
<figure><img
    class="my-0 rounded-md"
    loading="lazy"
    decoding="async"
    fetchpriority="auto"
    alt=""
    width="1274"
    height="768"
    src="https://www.modernsecurity.nl/automatic-attack-disruption-defender-xdr/fig1-auto-attack-disruption_hu_f4a4d5f8ff9910be.webp"
   
   
    data-zoom-src="https://www.modernsecurity.nl/automatic-attack-disruption-defender-xdr/fig1-auto-attack-disruption.webp"></figure>
<h3 class="relative group">Managing automated responses
    <div id="managing-automated-responses" class="anchor"></div>
    
</h3>
<p>When investigations confirm threats have been remediated, contained assets can be released:</p>
<p><strong>Device release process:</strong></p>
<ol>
<li>Navigate to the incident page or Action Center</li>
<li>Locate the contained device in the incident graph</li>
<li>Click on the device to open asset details</li>
<li>Select <strong>“Release from containment”</strong></li>
<li>Provide business justification</li>
<li>Confirm the release action</li>
</ol>
<p><strong>User account re-enablement:</strong></p>
<ol>
<li>Locate the disabled user account in incident details</li>
<li>Click on the user account</li>
<li>Select <strong>“Enable user”</strong></li>
<li>Provide justification for enablement</li>
<li>Confirm the action</li>
</ol>

<h2 class="relative group">Advanced Monitoring queries
    <div id="advanced-monitoring-queries" class="anchor"></div>
    
</h2>

<h3 class="relative group">Attack Disruption effectiveness
    <div id="attack-disruption-effectiveness" class="anchor"></div>
    
</h3>
<p>List compromised accounts</p>
<div class="highlight-wrapper"><div class="highlight"><div class="ms-code-label">KQL</div><pre tabindex="0" class="chroma"><code class="language-kql" data-lang="kql">kql
DisruptionAndResponseEvents
<span class="o">|</span> <span class="k">where</span> <span class="k">isnotempty</span>( CompromisedAccountCount)</code></pre></div>
</div>
<p>Show policies applied</p>
<div class="highlight-wrapper"><div class="highlight"><div class="ms-code-label">KQL</div><pre tabindex="0" class="chroma"><code class="language-kql" data-lang="kql">kql
DisruptionAndResponseEvents
<span class="o">|</span> <span class="k">distinct</span> PolicyName</code></pre></div>
</div>
<p>Show unique ActionTypes</p>
<div class="highlight-wrapper"><div class="highlight"><div class="ms-code-label">KQL</div><pre tabindex="0" class="chroma"><code class="language-kql" data-lang="kql">kql
DisruptionAndResponseEvents
<span class="o">|</span> <span class="k">distinct</span> ActionType</code></pre></div>
</div>

<h2 class="relative group">Additional resources
    <div id="additional-resources" class="anchor"></div>
    
</h2>
<p><a href="https://learn.microsoft.com/en-us/defender-xdr/automatic-attack-disruption"  target="_blank" rel="noreferrer">https://learn.microsoft.com/en-us/defender-xdr/automatic-attack-disruption</a></p>
<lite-youtube videoid="kH2f8PdDj7A" playlabel="kH2f8PdDj7A" params=""></lite-youtube>


<h2 class="relative group">Conclusion
    <div id="conclusion" class="anchor"></div>
    
</h2>
<p>Attack Disruption represents a paradigm shift in automated threat response. When properly deployed with all components, Microsoft Entra ID integration, complete Defender product suite, proper network configurations, and comprehensive auditing, it transforms your security posture from reactive to preemptive, containing sophisticated attacks in minutes rather than hours.</p>
<p>Success requires more than just turning on features. It demands:</p>
<ul>
<li>Comprehensive product deployment across all four Defender products</li>
<li>Minimum configuration must contain at least Entra ID data, mailbox auditing, and SafeLinks</li>
<li>Thoughtful automation level selection balancing security and operations</li>
<li>Continuous optimization based on real-world performance</li>
<li>Regular updates to meet evolving network and security requirements</li>
</ul>
<p>The organizations I’ve worked with report dramatic improvements after full implementation: ransomware attacks contained before encryption, BEC attempts stopped before wire transfers, AiTM attacks disrupted before token theft, and lateral movement halted at the first compromised credential.</p>
<p>But perhaps most importantly, their security teams can focus on threat hunting and strategic improvements rather than fighting fires. In an era where attackers operate 24/7 with increasing sophistication, Attack Disruption serves as your organization’s immune system: always on, constantly learning, and ready to respond automatically when threats strike.</p>
<p>As the threat landscape evolves, from FIDO downgrade attacks to OAuth app exploitation, Microsoft continues enhancing Attack Disruption capabilities. Stay engaged with the security community, monitor Microsoft’s security updates, and continuously refine your implementation.</p>
<p>Remember: <em>Attack Disruption isn’t just another security tool. It’s your organization’s automatic defense system, ready to protect your environment when every second counts. Configure it thoughtfully, monitor it diligently, and trust it to protect your organization during those critical moments when human response simply isn’t fast enough.</em></p>
]]></content:encoded><media:content url="https://www.modernsecurity.nl/automatic-attack-disruption-defender-xdr/featured_hu_b9a1436ff814a875.jpg" medium="image" type="image/jpeg" width="1200" height="723"/><enclosure url="https://www.modernsecurity.nl/automatic-attack-disruption-defender-xdr/featured_hu_b9a1436ff814a875.jpg" type="image/jpeg" length="78563"/></item><item><title>Selective Isolation in Defender for Endpoint – Combining tools like Velociraptor for DFIR</title><link>https://www.modernsecurity.nl/mde-selective-isolation-velociraptor/</link><guid isPermaLink="true">https://www.modernsecurity.nl/mde-selective-isolation-velociraptor/</guid><pubDate>Sun, 13 Jul 2025 16:05:03 +0100</pubDate><dc:creator>Farid Kalaidji</dc:creator><category>Microsoft Defender for Endpoint</category><category>Microsoft Defender XDR</category><category>Security</category><description>Use Microsoft Defender for Endpoint's Selective Isolation with Velociraptor to investigate compromised endpoints remotely, full DFIR without losing access.</description><content:encoded><![CDATA[
<h2 class="relative group">Introduction
    <div id="introduction" class="anchor"></div>
    
</h2>
<p>With the <a href="https://techcommunity.microsoft.com/blog/microsoftdefenderatpblog/maintain-connectivity-for-essential-services-with-selective-network-isolation/4422938"  target="_blank" rel="noreferrer">introduction of Selective Isolation</a>, Microsoft Defender for Endpoint has taken a significant step toward more flexible incident response. Instead of fully isolating an endpoint from the network, security teams can now allow specific outbound connections, enabling secure communication with approved services such as a forensic server or response platform.</p>
<p>This development removes a critical blocker for incident responders: the trade-off between containment and investigation. Defender’s own investigation tools, including Live Response and Timeline, provide powerful capabilities. But for deeper forensics, with tools like Velociraptor still offer value: especially in scenarios involving memory analysis, persistence detection, or large-scale artifact collection.</p>
<p>In this article, we explore how Selective Isolation works, what <a href="https://www.modernsecurity.nl/microsoft-defender-for-endpoint/" >Microsoft Defender for Endpoint (MDE)</a> can offer natively, how it can be extended with Velociraptor, and what a modern DFIR process looks like when combining containment with full investigative access.</p>

<h2 class="relative group">Native Defender for Endpoint capabilities
    <div id="native-defender-for-endpoint-capabilities" class="anchor"></div>
    
</h2>
<p>Before considering third-party tooling, it is important to recognize that Microsoft Defender for Endpoint already includes a mature and evolving set of response and investigation capabilities. When a device is onboarded, the following functions become available to security analysts:</p>
<ul>
<li><strong>Device Timeline</strong>: Provides detailed visibility into process execution, file creation, registry activity, and more.</li>
<li><strong>Alert Storyline</strong>: Automatically correlates signals from various components to show attack progression.</li>
<li><strong>Advanced Hunting</strong>: Allows threat analysts to write custom KQL queries across telemetry.</li>
<li><strong>Live Response</strong>: A remote PowerShell-based shell that can retrieve files, kill processes, and execute scripts.</li>
<li><strong>Investigation Graph</strong>: Visualizes relationships between alerts, identities, devices, and evidence.</li>
<li><strong>File and Registry Evidence</strong>: Enables analysts to isolate and inspect malicious binaries and registry modifications.</li>
<li><strong>Integration across XDR</strong>: Correlation with signals from Defender for Identity, Cloud Apps, and Office 365.</li>
</ul>
<p>However, during an active DFIR case, you may encounter situations where critical visibility is missing, and physically retrieving the device is not a viable option when remote investigation is possible. Traditionally, isolating a device for containment meant losing remote access, and the Investigation Package alone was often insufficient. Selective Isolation addresses this limitation by allowing secure connectivity to approved forensic tools during containment.</p>

<h2 class="relative group">Selective Isolation: overview and modes
    <div id="selective-isolation-overview-and-modes" class="anchor"></div>
    
</h2>
<p>Selective Isolation is a network containment feature within Defender for Endpoint that allows administrators to restrict all outbound traffic <strong>except</strong> specific destinations required for investigation or remediation.</p>
<p>Unlike traditional full isolation, which only permits communication with Microsoft security services, Selective Isolation introduces configurable allowlists for IP addresses <a href="https://learn.microsoft.com/en-us/defender-endpoint/isolation-exclusions"  target="_blank" rel="noreferrer">and more</a>.</p>
<p>Microsoft formally introduced Selective Isolation in June 2025 in public preview, and it is available to all customers with Microsoft Defender for Endpoint Plan 2 or via Microsoft 365 E5 licensing.</p>

<h2 class="relative group">Supported modes
    <div id="supported-modes" class="anchor"></div>
    
</h2>
<p>There are currently two modes of network isolation available:</p>
<ul>
<li><strong>Full Isolation</strong>: All outbound traffic is blocked except communication with Microsoft Defender backend services.</li>
<li><strong>Selective Isolation</strong>: Communication is blocked except to destinations defined by the organization in an isolation exclusion profile.</li>
</ul>
<p>Selective Isolation enables secure interaction with:</p>
<ul>
<li>Internal forensic servers (e.g., Velociraptor)</li>
<li>SOAR or IR orchestration platforms</li>
<li>Secure file repositories or cloud storage</li>
<li>Internal services such as revocation servers or proxies</li>
</ul>

<h2 class="relative group">Configuration and application of Selective Isolation
    <div id="configuration-and-application-of-selective-isolation" class="anchor"></div>
    
</h2>
<p>Implementing Selective Isolation requires a small number of preparatory steps. Once configured, it becomes an operational tool during containment or escalation procedures.</p>

<h3 class="relative group">Step 1: Enable Isolation exclusion rules
    <div id="step-1-enable-isolation-exclusion-rules" class="anchor"></div>
    
</h3>
<ol>
<li>Log into the <strong>Microsoft 365 Defender portal</strong></li>
<li>Navigate to <strong>Settings → Endpoints → Advanced Features</strong></li>
<li>Enable <strong>Isolation Exclusion Rules</strong> and <strong>Live Response unsigned script execution</strong> (or else you have to sign the PS1 files later on – which is better ofcourse 🙁 )</li>
</ol>
<figure><img
    class="my-0 rounded-md"
    loading="lazy"
    decoding="async"
    fetchpriority="auto"
    alt="Selective Isolation Velociraptor MDE Defender for Endpoint"
    width="2000"
    height="1082"
    src="https://www.modernsecurity.nl/mde-selective-isolation-velociraptor/image-1_hu_b3425c188dd21115.webp"
   
   
    data-zoom-src="https://www.modernsecurity.nl/mde-selective-isolation-velociraptor/image-1.webp"></figure><p>This enables the option to apply Selective Isolation and define custom allowlists.</p>

<h3 class="relative group">Step 2: Create an exclusion profile
    <div id="step-2-create-an-exclusion-profile" class="anchor"></div>
    
</h3>
<ol>
<li>Navigate to <strong>Settings → Endpoints → Isolation Exclusion</strong> <strong>Rules</strong></li>
<li>Click <strong>Add device isolation exclusion</strong> (make sure to add an inbound and outbound rule to your server IP which we create in the steps below)</li>
<li>Provide a clear name (e.g., <code>velociraptor-access-policy</code>)</li>
<li>Define one or more destinations:
<ul>
<li>IP addresses (e.g., <code>10.1.2.10</code>)</li>
</ul>
</li>
<li>Save the policy</li>
</ol>
<figure><img
    class="my-0 rounded-md"
    loading="lazy"
    decoding="async"
    fetchpriority="auto"
    alt=""
    width="2000"
    height="1078"
    src="https://www.modernsecurity.nl/mde-selective-isolation-velociraptor/image-2_hu_231e2a311f7cde21.webp"
   
   
    data-zoom-src="https://www.modernsecurity.nl/mde-selective-isolation-velociraptor/image-2.webp"></figure><figure><img
    class="my-0 rounded-md"
    loading="lazy"
    decoding="async"
    fetchpriority="auto"
    alt=""
    width="2000"
    height="1079"
    src="https://www.modernsecurity.nl/mde-selective-isolation-velociraptor/image-3_hu_472e4c8d360a1b72.webp"
   
   
    data-zoom-src="https://www.modernsecurity.nl/mde-selective-isolation-velociraptor/image-3.webp"></figure>
<h3 class="relative group">Step 3: Apply isolation with exclusion
    <div id="step-3-apply-isolation-with-exclusion" class="anchor"></div>
    
</h3>
<ol>
<li>Go to <strong>Device inventory</strong> and select the affected endpoint</li>
<li>Choose <strong>Isolate Device</strong> from the action menu</li>
<li>Select <strong>Isolation</strong> <strong>Exclusions</strong> to be allowed</li>
<li>Confirm</li>
</ol>
<figure><img
    class="my-0 rounded-md"
    loading="lazy"
    decoding="async"
    fetchpriority="auto"
    alt=""
    width="2000"
    height="1078"
    src="https://www.modernsecurity.nl/mde-selective-isolation-velociraptor/image-4_hu_42c61f8bc0cc54c8.webp"
   
   
    data-zoom-src="https://www.modernsecurity.nl/mde-selective-isolation-velociraptor/image-4.webp"></figure><figure><img
    class="my-0 rounded-md"
    loading="lazy"
    decoding="async"
    fetchpriority="auto"
    alt=""
    width="2000"
    height="1081"
    src="https://www.modernsecurity.nl/mde-selective-isolation-velociraptor/image-5_hu_d48bb7ceef6151f.webp"
   
   
    data-zoom-src="https://www.modernsecurity.nl/mde-selective-isolation-velociraptor/image-5.webp"></figure><p>The device will be isolated from all other network activity except the explicitly defined destinations.</p>

<h3 class="relative group">Step 4: Validate behavior
    <div id="step-4-validate-behavior" class="anchor"></div>
    
</h3>
<p>Once isolated, validate the configuration:</p>
<ul>
<li>The device will appear as <strong>Isolated</strong></li>
<li>Live Response remains available</li>
<li>Connectivity to defined destinations should succeed</li>
<li>Other network activity will be blocked</li>
</ul>
<p>This isolation mode preserves investigation access without allowing lateral movement or external communication.</p>

<h2 class="relative group">Extending DFIR with Velociraptor
    <div id="extending-dfir-with-velociraptor" class="anchor"></div>
    
</h2>
<p>Velociraptor is an open-source DFIR platform that complements Defender for Endpoint by providing deep forensic visibility. It enables memory acquisition, advanced artifact collection, and persistent hunt capability at scale.</p>
<figure><img
    class="my-0 rounded-md"
    loading="lazy"
    decoding="async"
    fetchpriority="auto"
    alt=""
    width="1024"
    height="1024"
    src="https://www.modernsecurity.nl/mde-selective-isolation-velociraptor/image-10_hu_13965c91718285cd.webp"
   
   
    data-zoom-src="https://www.modernsecurity.nl/mde-selective-isolation-velociraptor/image-10.webp"><figcaption>Yeah lets post a stupid AI picture too</figcaption></figure><p>While Defender for Endpoint offers excellent detection and triage, Velociraptor adds:</p>
<ul>
<li>Memory dumps and YARA scanning</li>
<li>Collection of Amcache, Prefetch, MFT, and Registry artifacts</li>
<li>In-memory malware detection and process forensics</li>
<li>Live artifact scheduling across multiple endpoints</li>
<li>Persistence across reboots and sessions</li>
</ul>
<p>When paired with Selective Isolation, Velociraptor can continue to operate securely on an endpoint under containment.</p>

<h2 class="relative group">Deploying Velociraptor for use with isolated endpoints
    <div id="deploying-velociraptor-for-use-with-isolated-endpoints" class="anchor"></div>
    
</h2>
<p>There are several ways to deploy Velociraptor in a secure and scalable manner. One notable example is a project by <strong>Eric Mannon</strong>, who developed a clean and efficient Azure-based Velociraptor deployment method that avoids the need for a persistent VM.</p>
<p>This approach is ideal for scalable and ephemeral deployments in modern cloud environments. You can even use his <a href="https://github.com/msdirtbag/MDEAutomator"  target="_blank" rel="noreferrer">MDEAutomator</a> to push the files to Live Response.</p>
<p>More information can be found on his GitHub repository and LinkedIn article:</p>
<ul>
<li><strong>GitHub</strong>: <a href="https://github.com/msdirtbag/azurevelo"  target="_blank" rel="noreferrer">link</a></li>
<li><strong>LinkedIn:</strong> <a href="https://www.linkedin.com/posts/ericmanon_velociraptor-dfir-azure-activity-7178038809747333120-xpB9/"  target="_blank" rel="noreferrer">link</a></li>
</ul>
<p>In this blog, however, I will do a traditional legacy lame VM-based deployment. That can be used for environments that require or prefer direct control over server infrastructure.</p>

<h2 class="relative group">Server Deployment
    <div id="server-deployment" class="anchor"></div>
    
</h2>
<ol>
<li>Deploy a Linux virtual machine (tested with Ubuntu 24.10)</li>
<li>Paste the script below and make sure to chmod +x it and run (beware I <em>hardcoded</em> the lastest version as of per july 2025)</li>
</ol>
<div class="highlight-wrapper"><div class="highlight"><div class="ms-code-label">Bash</div><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="cp">#!/usr/bin/env bash
</span></span></span><span class="line"><span class="cl"><span class="nb">set</span> -euo pipefail
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="nv">VR_BIN</span><span class="o">=</span><span class="s2">&#34;/usr/local/bin/velociraptor&#34;</span>
</span></span><span class="line"><span class="cl"><span class="nv">VR_USER</span><span class="o">=</span><span class="s2">&#34;velociraptor&#34;</span>
</span></span><span class="line"><span class="cl"><span class="nv">VR_CONFIG</span><span class="o">=</span><span class="s2">&#34;/etc/velociraptor/server.config.yaml&#34;</span>
</span></span><span class="line"><span class="cl"><span class="nv">VR_SERVICE</span><span class="o">=</span><span class="s2">&#34;/etc/systemd/system/velociraptor.service&#34;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="nb">echo</span> <span class="s2">&#34;[+] Installing curl&#34;</span>
</span></span><span class="line"><span class="cl">apt-get update -y
</span></span><span class="line"><span class="cl">apt-get install -y curl
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="nb">echo</span> <span class="s2">&#34;[+] Creating Velociraptor user if not exists&#34;</span>
</span></span><span class="line"><span class="cl">id -u <span class="s2">&#34;</span><span class="nv">$VR_USER</span><span class="s2">&#34;</span> <span class="p">&amp;</span>&gt;/dev/null <span class="o">||</span> useradd -r -s /usr/sbin/nologin <span class="s2">&#34;</span><span class="nv">$VR_USER</span><span class="s2">&#34;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="nb">echo</span> <span class="s2">&#34;[+] Downloading Velociraptor v0.74.5&#34;</span>
</span></span><span class="line"><span class="cl">curl -L -o <span class="s2">&#34;</span><span class="nv">$VR_BIN</span><span class="s2">&#34;</span> https://github.com/Velocidex/velociraptor/releases/download/v0.74/velociraptor-v0.74.5-linux-amd64
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="nb">echo</span> <span class="s2">&#34;[+] Validating binary&#34;</span>
</span></span><span class="line"><span class="cl"><span class="k">if</span> ! file <span class="s2">&#34;</span><span class="nv">$VR_BIN</span><span class="s2">&#34;</span> <span class="p">|</span> grep -q <span class="s2">&#34;ELF 64-bit&#34;</span><span class="p">;</span> <span class="k">then</span>
</span></span><span class="line"><span class="cl">    <span class="nb">echo</span> <span class="s2">&#34;[✗] Invalid Velociraptor binary&#34;</span>
</span></span><span class="line"><span class="cl">    rm -f <span class="s2">&#34;</span><span class="nv">$VR_BIN</span><span class="s2">&#34;</span>
</span></span><span class="line"><span class="cl">    <span class="nb">exit</span> <span class="m">1</span>
</span></span><span class="line"><span class="cl"><span class="k">fi</span>
</span></span><span class="line"><span class="cl">chmod <span class="m">755</span> <span class="s2">&#34;</span><span class="nv">$VR_BIN</span><span class="s2">&#34;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="nb">echo</span> <span class="s2">&#34;[+] Generating server config&#34;</span>
</span></span><span class="line"><span class="cl">mkdir -p <span class="s2">&#34;</span><span class="k">$(</span>dirname <span class="s2">&#34;</span><span class="nv">$VR_CONFIG</span><span class="s2">&#34;</span><span class="k">)</span><span class="s2">&#34;</span>
</span></span><span class="line"><span class="cl"><span class="s2">&#34;</span><span class="nv">$VR_BIN</span><span class="s2">&#34;</span> config generate &gt; <span class="s2">&#34;</span><span class="nv">$VR_CONFIG</span><span class="s2">&#34;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="nb">echo</span> <span class="s2">&#34;[+] Setting permissions&#34;</span>
</span></span><span class="line"><span class="cl">chown -R <span class="s2">&#34;</span><span class="nv">$VR_USER</span><span class="s2">:</span><span class="nv">$VR_USER</span><span class="s2">&#34;</span> /etc/velociraptor
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="nb">echo</span> <span class="s2">&#34;[+] Creating systemd service&#34;</span>
</span></span><span class="line"><span class="cl">cat &gt;<span class="s2">&#34;</span><span class="nv">$VR_SERVICE</span><span class="s2">&#34;</span> <span class="s">&lt;&lt;EOF
</span></span></span><span class="line"><span class="cl"><span class="s">[Unit]
</span></span></span><span class="line"><span class="cl"><span class="s">Description=Velociraptor DFIR Server
</span></span></span><span class="line"><span class="cl"><span class="s">After=network.target
</span></span></span><span class="line"><span class="cl"><span class="s">
</span></span></span><span class="line"><span class="cl"><span class="s">[Service]
</span></span></span><span class="line"><span class="cl"><span class="s">Type=simple
</span></span></span><span class="line"><span class="cl"><span class="s">User=$VR_USER
</span></span></span><span class="line"><span class="cl"><span class="s">Group=$VR_USER
</span></span></span><span class="line"><span class="cl"><span class="s">ExecStart=$VR_BIN -c $VR_CONFIG frontend -v
</span></span></span><span class="line"><span class="cl"><span class="s">Restart=on-failure
</span></span></span><span class="line"><span class="cl"><span class="s">LimitNOFILE=20000
</span></span></span><span class="line"><span class="cl"><span class="s">
</span></span></span><span class="line"><span class="cl"><span class="s">[Install]
</span></span></span><span class="line"><span class="cl"><span class="s">WantedBy=multi-user.target
</span></span></span><span class="line"><span class="cl"><span class="s">EOF</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="nb">echo</span> <span class="s2">&#34;[+] Starting Velociraptor&#34;</span>
</span></span><span class="line"><span class="cl">systemctl daemon-reload
</span></span><span class="line"><span class="cl">systemctl <span class="nb">enable</span> --now velociraptor
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="nb">echo</span>
</span></span><span class="line"><span class="cl"><span class="nb">echo</span> <span class="s2">&#34;[✓] Velociraptor is running!&#34;</span>
</span></span><span class="line"><span class="cl"><span class="nb">echo</span> <span class="s2">&#34;    Web UI (no TLS): http://</span><span class="k">$(</span>hostname -I <span class="p">|</span> awk <span class="s1">&#39;{print $1}&#39;</span><span class="k">)</span><span class="s2">:8889&#34;</span>
</span></span><span class="line"><span class="cl"><span class="nb">echo</span> <span class="s2">&#34;    Agent check-in:  http://</span><span class="k">$(</span>hostname -I <span class="p">|</span> awk <span class="s1">&#39;{print $1}&#39;</span><span class="k">)</span><span class="s2">:8000&#34;</span></span></span></code></pre></div></div>
<ol start="3">
<li>Edit the Config yaml: <code>nano /etc/velociraptor/server.config.yaml</code></li>
<li>Configure GUI and Frontend <code>bind_address</code> to <code>0.0.0.0</code> and change the <code>bind_</code>port to 8443 (I had to change the default port for a specific reason – you can leave as default too)</li>
<li>Change the Client <code>server_urls</code> to your URL and check if the correct port is used too (8443 in my case)</li>
<li><a href="https://docs.velociraptor.app/blog/2024/2024-07-22-how-to-use-your-own-certificates/"  target="_blank" rel="noreferrer">Define custom SSL certificates and change it too as per following link</a> (by default you get a self signed SSL)</li>
<li>Save the yaml file</li>
<li>Add an admin account: <code>./velociraptor --config server.config.yaml user add admin P@ss123 --role administrator</code></li>
<li>Restart Velociraptor: <code>sudo systemctl restart velociraptor</code></li>
<li>Check the logs in case Velociraptor can’t run: <code>/usr/local/bin/velociraptor -c /etc/velociraptor/server.config.yaml frontend -v</code></li>
</ol>

<h2 class="relative group">Agent Deployment (on isolated device)
    <div id="agent-deployment-on-isolated-device" class="anchor"></div>
    
</h2>
<p>Follow the steps below to manually install the agent on the isolated endpoint. For an automated approach you can use the <a href="https://learn.microsoft.com/en-us/defender-endpoint/api/run-live-response"  target="_blank" rel="noreferrer">Live Response API</a> too.</p>
<ol>
<li>First grab the client.root.config.yaml from the Velociraptor portal, by logging in with the admin account created above and save the config as client.config.yaml:</li>
</ol>
<figure><img
    class="my-0 rounded-md"
    loading="lazy"
    decoding="async"
    fetchpriority="auto"
    alt=""
    width="2000"
    height="1076"
    src="https://www.modernsecurity.nl/mde-selective-isolation-velociraptor/image_hu_4c44ad38cd25a726.webp"
   
   
    data-zoom-src="https://www.modernsecurity.nl/mde-selective-isolation-velociraptor/image.webp"></figure><ol start="2">
<li>Download the corresponding .msi file (<a href="https://github.com/Velocidex/velociraptor/releases/download/v0.74/velociraptor-v0.74.5-windows-amd64.msi"  target="_blank" rel="noreferrer">velociraptor-vx.xx.x-windows-amd64.msi</a>) <a href="https://github.com/Velocidex/velociraptor/releases"  target="_blank" rel="noreferrer">from here</a> and save it as velociraptor.msi (you can also wrap a bundle yourself through <a href="https://docs.velociraptor.app/docs/deployment/clients/"  target="_blank" rel="noreferrer">this link</a>)</li>
<li>Create a fresh powershell and name it like install_velociraptor.ps1 with the code below:</li>
</ol>
<div class="highlight-wrapper"><div class="highlight"><div class="ms-code-label">PowerShell</div><pre tabindex="0" class="chroma"><code class="language-powershell" data-lang="powershell"><span class="line"><span class="cl"><span class="c"># Paths</span>
</span></span><span class="line"><span class="cl"><span class="nv">$MsiPath</span> <span class="p">=</span> <span class="s2">&#34;C:\ProgramData\Microsoft\Windows Defender Advanced Threat Protection\Downloads\velociraptor.msi&#34;</span>
</span></span><span class="line"><span class="cl"><span class="nv">$ConfigPath</span> <span class="p">=</span> <span class="s2">&#34;C:\ProgramData\Microsoft\Windows Defender Advanced Threat Protection\Downloads\client.config.yaml&#34;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="nb">Write-Output</span> <span class="s2">&#34;---- Velociraptor MSI installation initiated ----&#34;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c"># Step 1: Copy config to the expected location</span>
</span></span><span class="line"><span class="cl"><span class="nv">$ConfigDest</span> <span class="p">=</span> <span class="s2">&#34;C:\Program Files\Velociraptor\client.config.yaml&#34;</span>
</span></span><span class="line"><span class="cl"><span class="k">if</span> <span class="p">(!(</span><span class="nb">Test-Path</span> <span class="s2">&#34;C:\Program Files\Velociraptor&#34;</span><span class="p">))</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="nb">New-Item</span> <span class="n">-Path</span> <span class="s2">&#34;C:\Program Files\Velociraptor&#34;</span> <span class="n">-ItemType</span> <span class="n">Directory</span> <span class="n">-Force</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span><span class="line"><span class="cl"><span class="nb">Copy-Item</span> <span class="n">-Path</span> <span class="nv">$ConfigPath</span> <span class="n">-Destination</span> <span class="nv">$ConfigDest</span> <span class="n">-Force</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c"># Step 2: Install the MSI silently</span>
</span></span><span class="line"><span class="cl"><span class="nb">Start-Process</span> <span class="n">msiexec</span><span class="p">.</span><span class="py">exe</span> <span class="n">-ArgumentList</span> <span class="s2">&#34;/i </span><span class="se">`&#34;</span><span class="nv">$MsiPath</span><span class="se">`&#34;</span><span class="s2"> /qn&#34;</span> <span class="n">-Wait</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c"># Step 3: Start the service</span>
</span></span><span class="line"><span class="cl"><span class="nb">Start-Service</span> <span class="n">-Name</span> <span class="n">velociraptor</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="nb">Write-Output</span> <span class="s2">&#34;Velociraptor installed and service started.&#34;</span></span></span></code></pre></div></div>
<ol start="4">
<li>Now upload the install_velociraptor.ps1, client.config.yaml and velociraptor.msi via Live Response and submit:</li>
</ol>
<figure><img
    class="my-0 rounded-md"
    loading="lazy"
    decoding="async"
    fetchpriority="auto"
    alt=""
    width="2000"
    height="1077"
    src="https://www.modernsecurity.nl/mde-selective-isolation-velociraptor/image-6_hu_a2674abf80dea468.webp"
   
   
    data-zoom-src="https://www.modernsecurity.nl/mde-selective-isolation-velociraptor/image-6.webp"></figure><ol start="5">
<li><a href="https://learn.microsoft.com/en-us/defender-endpoint/live-response-command-examples"  target="_blank" rel="noreferrer">Start a Live Response session</a> and type putfile and the filenames, to download them onto the device:</li>
</ol>
<div class="highlight-wrapper"><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="cl">putfile velociraptor.msi
</span></span><span class="line"><span class="cl">putfile client.config.yaml
</span></span><span class="line"><span class="cl">putfile install_velociraptor.ps1</span></span></code></pre></div></div>
<ol start="6">
<li>Now start the Powershell file to install the MSI (I’m using the MSI to be able to install the service and gain persistency):</li>
</ol>
<figure><img
    class="my-0 rounded-md"
    loading="lazy"
    decoding="async"
    fetchpriority="auto"
    alt=""
    width="2000"
    height="222"
    src="https://www.modernsecurity.nl/mde-selective-isolation-velociraptor/image-7_hu_19ab19f6c0ccc7a6.webp"
   
   
    data-zoom-src="https://www.modernsecurity.nl/mde-selective-isolation-velociraptor/image-7.webp"></figure><ol start="7">
<li>At this point if you check the Timeline in MDE, the events start popping up:</li>
</ol>
<figure><img
    class="my-0 rounded-md"
    loading="lazy"
    decoding="async"
    fetchpriority="auto"
    alt=""
    width="1729"
    height="197"
    src="https://www.modernsecurity.nl/mde-selective-isolation-velociraptor/image-8_hu_ab3709ce036ad17b.webp"
   
   
    data-zoom-src="https://www.modernsecurity.nl/mde-selective-isolation-velociraptor/image-8.webp"></figure><ol start="8">
<li>From my setup I can interact with my isolated endpoint and do all the fancy stuff now 🙂</li>
</ol>
<figure><img
    class="my-0 rounded-md"
    loading="lazy"
    decoding="async"
    fetchpriority="auto"
    alt=""
    width="2000"
    height="1079"
    src="https://www.modernsecurity.nl/mde-selective-isolation-velociraptor/image-9_hu_c7cc1fff704c1723.webp"
   
   
    data-zoom-src="https://www.modernsecurity.nl/mde-selective-isolation-velociraptor/image-9.webp"></figure>
<h2 class="relative group">Using Velociraptor
    <div id="using-velociraptor" class="anchor"></div>
    
</h2>
<p>I’m not going to dive in how you can use Velociraptor, I recommend going through these docs and video:</p>
<p><a href="https://training.velociraptor.app"  target="_blank" rel="noreferrer">https://training.velociraptor.app</a></p>
<p>And make sure to <a href="https://github.com/EricZimmerman/KapeFiles"  target="_blank" rel="noreferrer">check KAPE too</a></p>
<lite-youtube videoid="ibl4-MzW-KI" playlabel="ibl4-MzW-KI" params=""></lite-youtube>


<h2 class="relative group">Practical use cases
    <div id="practical-use-cases" class="anchor"></div>
    
</h2>

<div class="ms-table" role="region" aria-label="Table" tabindex="0">
  <table>
      <thead>
          <tr>
              <th>Scenario</th>
              <th>MDE + Live Response</th>
              <th>Velociraptor</th>
          </tr>
      </thead>
    <tbody>
        <tr>
            <td>Memory dump</td>
            <td>✖</td>
            <td>✔</td>
        </tr>
        <tr>
            <td>Shimcache, Amcache</td>
            <td>✖</td>
            <td>✔</td>
        </tr>
        <tr>
            <td>YARA scan (memory/disk)</td>
            <td>✖</td>
            <td>✔</td>
        </tr>
        <tr>
            <td>Registry and autoruns</td>
            <td>✔ (limited)</td>
            <td>✔</td>
        </tr>
        <tr>
            <td>Event log timeline</td>
            <td>✔</td>
            <td>✔</td>
        </tr>
        <tr>
            <td>Multi-endpoint hunt</td>
            <td>✔ (AH)</td>
            <td>✔</td>
        </tr>
        <tr>
            <td>Persistent session (DFIR)</td>
            <td>✖</td>
            <td>✔</td>
        </tr>
    </tbody>
  </table>
</div>
<p>Combined, these tools provide layered insight without lifting containment.</p>

<h2 class="relative group">Conclusion
    <div id="conclusion" class="anchor"></div>
    
</h2>
<p>Selective Isolation introduces a meaningful improvement to containment and investigation in Microsoft Defender for Endpoint. Where previously an isolated endpoint was also inaccessible to responders, we now have the ability to safely maintain access to critical tools such as Velociraptor or Live Response.</p>
<p>Security operations teams can confidently apply isolation without compromising forensic capability. Defender provides strong triage and analysis features natively, while Velociraptor extends the response lifecycle into memory analysis, execution tracing, and attacker behavior correlation.</p>
<p>For organizations dealing with modern threats, this combination enables rapid containment, effective root cause investigation, and informed remediation, without delay or exposure.</p>
]]></content:encoded><media:content url="https://www.modernsecurity.nl/mde-selective-isolation-velociraptor/featured_hu_d4429d58fad27cfb.jpg" medium="image" type="image/jpeg" width="1200" height="800"/><enclosure url="https://www.modernsecurity.nl/mde-selective-isolation-velociraptor/featured_hu_d4429d58fad27cfb.jpg" type="image/jpeg" length="70940"/></item><item><title>Integrating Microsoft Defender EASM with Exposure Management</title><link>https://www.modernsecurity.nl/integrate-defender-easm-exposure-management/</link><guid isPermaLink="true">https://www.modernsecurity.nl/integrate-defender-easm-exposure-management/</guid><pubDate>Mon, 23 Jun 2025 10:40:15 +0100</pubDate><dc:creator>Farid Kalaidji</dc:creator><category>Security</category><category>Microsoft Defender XDR</category><description>Integrate Microsoft Defender EASM with Exposure Management to enrich attack paths with external risk data and strengthen your posture.</description><content:encoded><![CDATA[
<h2 class="relative group">Introduction
    <div id="introduction" class="anchor"></div>
    
</h2>
<p>Microsoft has taken another step in closing the gap between internal risk and external exposure. With the June 2025 public preview release of <strong>Microsoft Defender External Attack Surface Management (EASM)</strong> integration into <strong>Defender Exposure Management</strong>, organizations can now analyze attacker pathways that begin <em>outside</em> the enterprise perimeter.</p>
<figure><img
    class="my-0 rounded-md"
    loading="lazy"
    decoding="async"
    fetchpriority="auto"
    alt=""
    width="1920"
    height="1080"
    src="https://www.modernsecurity.nl/integrate-defender-easm-exposure-management/external-attack-tbmnl-en-us_hu_c3892487a8bf819c.webp"
   
   
    data-zoom-src="https://www.modernsecurity.nl/integrate-defender-easm-exposure-management/external-attack-tbmnl-en-us.webp"></figure><p>This addition enables a more realistic, end-to-end understanding of exploitable risks, bringing external visibility directly into the risk modeling engine of Microsoft Defender XDR. In this guide, in addition to my earlier posts about <a href="https://www.modernsecurity.nl/microsoft-external-attack-surface-management/" >Defender EASM</a> and <a href="https://www.modernsecurity.nl/microsoft-security-exposure-management/" >Exposure Management</a>, I walk through how this integration works, what it unlocks, how to enable it, and what to look out for when validating the setup.</p>

<h2 class="relative group">From internal misconfigurations to external threat vectors
    <div id="from-internal-misconfigurations-to-external-threat-vectors" class="anchor"></div>
    
</h2>
<p>Traditional exposure management has largely focused on the internal environment: devices, identities, configurations, and software vulnerabilities. While these remain foundational, the increasing complexity of digital footprints means that <strong>external exposures</strong>, publicly accessible assets, misconfigured services, and shadow IT, pose an equally significant risk.</p>
<p>Microsoft Defender EASM is designed to continuously discover and monitor an organization’s public-facing assets, such as:</p>
<ul>
<li>Untracked or legacy subdomains</li>
<li>Exposed endpoints (e.g., RDP, VPN, or admin portals)</li>
<li>Expired or weak TLS certificates</li>
<li>Public cloud assets or services configured without proper access control</li>
</ul>
<p>By integrating this data into <strong>Defender Exposure Management</strong>, security teams gain the ability to <strong>prioritize and remediate exposures</strong> that attackers are most likely to exploit.</p>

<h2 class="relative group">What this integration enables
    <div id="what-this-integration-enables" class="anchor"></div>
    
</h2>
<p>The integration between EASM and Exposure Management introduces several critical capabilities:</p>
<ul>
<li>
<p><strong>Unified visibility across surfaces</strong><br>
Previously siloed views of internal and external risk are now converged in a single pane of glass, enabling defenders to take action with complete context.</p>
</li>
<li>
<p><strong>Attack Path enrichment</strong><br>
External assets discovered by EASM are now included in attack path modeling within Defender Exposure Management. This allows for the identification of realistic exploitation scenarios beginning from internet-facing infrastructure.</p>
</li>
<li>
<p><strong>Risk-based prioritization</strong><br>
Exposure paths involving externally accessible services, especially those lacking MFA, endpoint protection, or conditional access, are now scored with higher severity, ensuring the most exploitable risks are surfaced.</p>
</li>
</ul>

<h2 class="relative group">How it works: a technical perspective
    <div id="how-it-works-a-technical-perspective" class="anchor"></div>
    
</h2>
<p>At the core of this integration is Microsoft’s threat intelligence pipeline, which now ingests telemetry from Defender EASM and correlates it with internal signals across Entra ID, Defender for Endpoint, and Microsoft 365.</p>
<p>The process is fully automated:</p>
<ol>
<li><strong>EASM continuously discovers external assets</strong> using DNS resolution, certificate analysis, and passive fingerprinting.</li>
<li><strong>Exposure Management ingests EASM findings</strong> into its graph-based risk engine.</li>
<li><strong>Correlations are established</strong> between public-facing assets and internal objects (identities, devices, configurations).</li>
<li><strong>Attack paths are recalculated</strong> to reflect real-world attacker entry points.</li>
</ol>
<p>No additional agents, scripts, or connectors are required.</p>

<h2 class="relative group">Licensing and prerequisites
    <div id="licensing-and-prerequisites" class="anchor"></div>
    
</h2>
<p>Before you begin, ensure the following conditions are met:</p>

<div class="ms-table" role="region" aria-label="Table" tabindex="0">
  <table>
      <thead>
          <tr>
              <th>Requirement</th>
              <th>Description</th>
          </tr>
      </thead>
    <tbody>
        <tr>
            <td><strong>Microsoft Defender EASM</strong></td>
            <td>Active EASM workspace with validated domains and discovered assets</td>
        </tr>
        <tr>
            <td><strong>Microsoft Defender XDR</strong></td>
            <td>Exposure Management (Preview) must be enabled in the tenant</td>
        </tr>
        <tr>
            <td><strong>License requirements</strong></td>
            <td>Microsoft 365 E5 + EASM (standalone or bundled license)</td>
        </tr>
        <tr>
            <td><strong>Same tenant</strong></td>
            <td>EASM workspace must be associated with the same Entra tenant as Defender XDR</td>
        </tr>
        <tr>
            <td><strong>Public preview availability</strong></td>
            <td>Feature is available in supported regions as of June 2025</td>
        </tr>
    </tbody>
  </table>
</div>

<h2 class="relative group">Step-by-step guide
    <div id="step-by-step-guide" class="anchor"></div>
    
</h2>
<p>This guide explains how to integrate your Microsoft Defender EASM workspace into the Exposure Management experience in Microsoft Defender XDR.</p>

<h3 class="relative group">Step 1 – Open Exposure Management in Defender XDR
    <div id="step-1-open-exposure-management-in-defender-xdr" class="anchor"></div>
    
</h3>
<ol>
<li>Go to the <a href="https://security.microsoft.com/"  target="_blank" rel="noreferrer">Microsoft 365 Defender portal</a></li>
<li>In the left-hand menu, select <strong>Exposure management</strong></li>
<li>Under <strong>Key initiatives</strong>, locate <strong>External Attack Surface Protection</strong></li>
<li>Click <strong>Open initiative page</strong></li>
</ol>
<figure><img
    class="my-0 rounded-md"
    loading="lazy"
    decoding="async"
    fetchpriority="auto"
    alt=""
    width="1827"
    height="975"
    src="https://www.modernsecurity.nl/integrate-defender-easm-exposure-management/image-4_hu_d1b5a83eb5e52f8e.webp"
   
   
    data-zoom-src="https://www.modernsecurity.nl/integrate-defender-easm-exposure-management/image-4.webp"></figure>
<h3 class="relative group">Step 2 – Connect EASM data to the initiative
    <div id="step-2-connect-easm-data-to-the-initiative" class="anchor"></div>
    
</h3>
<ol>
<li>In the initiative view, click <strong>Connect data to see initiative details</strong></li>
<li>Choose one of the following options:
<ul>
<li><strong>Connect your MDEASM workspace</strong></li>
<li><strong>Search for your organization’s pre-built footprint</strong></li>
</ul>
</li>
</ol>
<figure><img
    class="my-0 rounded-md"
    loading="lazy"
    decoding="async"
    fetchpriority="auto"
    alt="EASM  Exposure Management"
    width="1829"
    height="975"
    src="https://www.modernsecurity.nl/integrate-defender-easm-exposure-management/image-5_hu_4ec69d2209f963bc.webp"
   
   
    data-zoom-src="https://www.modernsecurity.nl/integrate-defender-easm-exposure-management/image-5.webp"></figure>
<h3 class="relative group">Step 3 – Fill in workspace details (if applicable)
    <div id="step-3-fill-in-workspace-details-if-applicable" class="anchor"></div>
    
</h3>
<p>If you choose to connect a workspace:</p>
<ul>
<li>Enter the following:
<ul>
<li><strong>Resource name</strong> (e.g., <code>secmanagementeasmprd001</code>)</li>
<li><strong>Subscription ID</strong></li>
<li><strong>Resource group name</strong></li>
<li><strong>Region</strong></li>
</ul>
</li>
</ul>
<figure><img
    class="my-0 rounded-md"
    loading="lazy"
    decoding="async"
    fetchpriority="auto"
    alt=""
    width="1827"
    height="975"
    src="https://www.modernsecurity.nl/integrate-defender-easm-exposure-management/image-6_hu_e71d94e8f7f48932.webp"
   
   
    data-zoom-src="https://www.modernsecurity.nl/integrate-defender-easm-exposure-management/image-6.webp"></figure><p>If using the pre-built option:</p>
<ul>
<li>Enter your organization’s name</li>
</ul>
<p>Click <strong>Connect</strong> to finalize the integration</p>

<h3 class="relative group">Step 4 – Wait for data ingestion
    <div id="step-4-wait-for-data-ingestion" class="anchor"></div>
    
</h3>
<ul>
<li>A notification will confirm the configuration was successful</li>
<li>It may take up to <strong>32 hours</strong> for data to populate within the initiative</li>
</ul>
<figure><img
    class="my-0 rounded-md"
    loading="lazy"
    decoding="async"
    fetchpriority="auto"
    alt=""
    width="878"
    height="417"
    src="https://www.modernsecurity.nl/integrate-defender-easm-exposure-management/image-7_hu_eb6afdb7ee31bf0f.webp"
   
   
    data-zoom-src="https://www.modernsecurity.nl/integrate-defender-easm-exposure-management/image-7.webp"></figure><ul>
<li>Once complete, EASM data will enrich the <strong>External Attack Surface Protection</strong> dashboard with information:</li>
</ul>
<figure><img
    class="my-0 rounded-md"
    loading="lazy"
    decoding="async"
    fetchpriority="auto"
    alt=""
    width="1932"
    height="1122"
    src="https://www.modernsecurity.nl/integrate-defender-easm-exposure-management/image-8_hu_fb52feb8f7c7044a.webp"
   
   
    data-zoom-src="https://www.modernsecurity.nl/integrate-defender-easm-exposure-management/image-8.webp"></figure>
<h3 class="relative group">Step 5 – Review security metrics
    <div id="step-5-review-security-metrics" class="anchor"></div>
    
</h3>
<ol>
<li>In the <strong>External Attack Surface Protection</strong> initiative, go to the <strong>Security metrics</strong> tab</li>
<li>Review metrics such as:
<ul>
<li>Assets allowing remote access</li>
<li>Recently expired SSL certificates</li>
<li>Expired domains</li>
<li>Internet-facing assets with critical CVEs</li>
</ul>
</li>
</ol>
<figure><img
    class="my-0 rounded-md"
    loading="lazy"
    decoding="async"
    fetchpriority="auto"
    alt=""
    width="1932"
    height="1122"
    src="https://www.modernsecurity.nl/integrate-defender-easm-exposure-management/image-9_hu_baf2a93b99c63677.webp"
   
   
    data-zoom-src="https://www.modernsecurity.nl/integrate-defender-easm-exposure-management/image-9.webp"></figure><p>Each metric will show progress, affected asset count, and remediation state</p>

<h3 class="relative group">Step 6 – Check security recommendations
    <div id="step-6-check-security-recommendations" class="anchor"></div>
    
</h3>
<ol>
<li>Navigate to the <strong>Security recommendations</strong> tab</li>
<li>Review actionable recommendations such as:
<ul>
<li>Replace weak certificates (e.g., SHA1)</li>
<li>Reclaim expired domains</li>
<li>Remove public remote access</li>
<li>Remediate exposed high-severity CVEs</li>
</ul>
</li>
</ol>
<p>Click on any recommendation for remediation steps and affected asset details</p>
<figure><img
    class="my-0 rounded-md"
    loading="lazy"
    decoding="async"
    fetchpriority="auto"
    alt=""
    width="1932"
    height="1122"
    src="https://www.modernsecurity.nl/integrate-defender-easm-exposure-management/image-10_hu_8fc5ec76e397618f.webp"
   
   
    data-zoom-src="https://www.modernsecurity.nl/integrate-defender-easm-exposure-management/image-10.webp"></figure>
<h3 class="relative group">Step 7 – View affected assets
    <div id="step-7-view-affected-assets" class="anchor"></div>
    
</h3>
<ol>
<li>From any metric or recommendation, switch to the <strong>Affected assets</strong> tab</li>
<li>Confirm:
<ul>
<li>Asset type (e.g., IP address, domain)</li>
<li>Last seen timestamp</li>
<li>Severity and impact</li>
</ul>
</li>
</ol>
<figure><img
    class="my-0 rounded-md"
    loading="lazy"
    decoding="async"
    fetchpriority="auto"
    alt=""
    width="1932"
    height="1122"
    src="https://www.modernsecurity.nl/integrate-defender-easm-exposure-management/image-11_hu_132e9722cc0bd604.webp"
   
   
    data-zoom-src="https://www.modernsecurity.nl/integrate-defender-easm-exposure-management/image-11.webp"></figure><p>You can export this list or use it to plan mitigation</p>

<h2 class="relative group">Attack Paths and example scenarios enabled by the integration
    <div id="attack-paths-and-example-scenarios-enabled-by-the-integration" class="anchor"></div>
    
</h2>

<h3 class="relative group">Explore Attack Paths
    <div id="explore-attack-paths" class="anchor"></div>
    
</h3>
<ol>
<li>Go to <strong>Exposure management &gt; Attack paths</strong> (outside the initiative page)</li>
<li>Filter by:
<ul>
<li>Entry point: External</li>
<li>Signal source: External Attack Surface Management</li>
</ul>
</li>
<li>Identify if any paths link:
<ul>
<li>External assets → exposed service → identity → privilege escalation</li>
</ul>
</li>
</ol>
<p>Here are some realistic use cases that become visible after the integration:</p>

<div class="ms-table" role="region" aria-label="Table" tabindex="0">
  <table>
      <thead>
          <tr>
              <th>Scenario</th>
              <th>Description</th>
          </tr>
      </thead>
    <tbody>
        <tr>
            <td><strong>Legacy web admin portal</strong></td>
            <td>An untracked admin subdomain is publicly exposed. The linked service uses an expired TLS cert and leads to a backend server with no endpoint protection</td>
        </tr>
        <tr>
            <td><strong>Unmanaged cloud asset</strong></td>
            <td>A forgotten Azure Web App is exposed via a verified domain and linked to an Entra ID identity without Conditional Access</td>
        </tr>
        <tr>
            <td><strong>Shadow IT domain</strong></td>
            <td>EASM discovers a new subdomain with an open port. That system communicates with internal infrastructure and can be reached without authentication</td>
        </tr>
        <tr>
            <td><strong>Guest user access</strong></td>
            <td>A guest account in Entra has permissions on an externally accessible application discovered by EASM</td>
        </tr>
    </tbody>
  </table>
</div>

<h2 class="relative group">Known limitations (preview)
    <div id="known-limitations-preview" class="anchor"></div>
    
</h2>
<p>As of the June 2025 public preview, note the following:</p>

<div class="ms-table" role="region" aria-label="Table" tabindex="0">
  <table>
      <thead>
          <tr>
              <th>Limitation</th>
              <th>Detail</th>
          </tr>
      </thead>
    <tbody>
        <tr>
            <td><strong>Partial regional availability</strong></td>
            <td>Not all tenants may have access immediately</td>
        </tr>
        <tr>
            <td><strong>UI improvements ongoing</strong></td>
            <td>Path visualizations are improving but may not show full context in all cases</td>
        </tr>
        <tr>
            <td><strong>Asset linking</strong></td>
            <td>Some public assets may not resolve correctly if ownership or DNS metadata is incomplete</td>
        </tr>
        <tr>
            <td><strong>No backfill</strong></td>
            <td>EASM data is used prospectively. It does not retroactively enrich old attack paths</td>
        </tr>
    </tbody>
  </table>
</div>

<h2 class="relative group">Extra resources
    <div id="extra-resources" class="anchor"></div>
    
</h2>
<p><a href="https://learn.microsoft.com/en-us/security-exposure-management/whats-new"  target="_blank" rel="noreferrer">https://learn.microsoft.com/en-us/security-exposure-management/whats-new</a></p>
<p><a href="https://learn.microsoft.com/en-us/security-exposure-management/external-attack-surface-management-initiative"  target="_blank" rel="noreferrer">https://learn.microsoft.com/en-us/security-exposure-management/external-attack-surface-management-initiative</a></p>
<p><a href="https://learn.microsoft.com/en-us/security-exposure-management/integration-licensing"  target="_blank" rel="noreferrer">https://learn.microsoft.com/en-us/security-exposure-management/integration-licensing</a></p>
<p><a href="https://www.modernsecurity.nl/integrate-defender-easm-exposure-management/microsoft-security-insider-cyberthreat-minute-infographic-9-1-22.pdf" >Download</a></p>

<h2 class="relative group">Final thoughts
    <div id="final-thoughts" class="anchor"></div>
    
</h2>
<p>As someone who regularly advises organizations on exposure management, this integration is the most strategic improvement Microsoft has released this year. It aligns your visibility with the attacker’s perspective and moves beyond the internal bubble most tooling still lives in.</p>
<p>For security teams working with Defender XDR and EASM, enabling this is low-effort and high-impact. And if you haven’t explored Microsoft Exposure Management yet, this is a compelling reason to start. Seeing your attack surface as an attacker would is no longer optional. It’s foundational :).</p>
]]></content:encoded><media:content url="https://www.modernsecurity.nl/integrate-defender-easm-exposure-management/featured_hu_435e6b2a34f94737.jpg" medium="image" type="image/jpeg" width="1200" height="697"/><enclosure url="https://www.modernsecurity.nl/integrate-defender-easm-exposure-management/featured_hu_435e6b2a34f94737.jpg" type="image/jpeg" length="79881"/></item></channel></rss>