Skip to content

Commit 11969d2

Browse files
committed
feat: Add MT.1123 - BitLocker encryption policy check (#intune)
1 parent 332dfa7 commit 11969d2

File tree

6 files changed

+308
-0
lines changed

6 files changed

+308
-0
lines changed

powershell/Maester.psd1

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -181,6 +181,7 @@
181181
'Test-MtAppleVolumePurchaseProgramToken',
182182
'Test-MtCertificateConnectors', 'Test-MtFeatureUpdatePolicy',
183183
'Test-MtIntuneDiagnosticSettings', 'Test-MtIntuneRbacGroupsProtected',
184+
'Test-MtBitLockerFullDiskEncryption',
184185
'Test-MtMdmAuthority', 'Test-MtMobileThreatDefenseConnectors',
185186
'Test-MtTenantCustomization', 'Test-MtWindowsDataProcessor',
186187
'Test-MtXspmCriticalCredsOnDevicesWithNonCriticalAccounts',
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
Ensure at least one Intune Disk Encryption policy enforces BitLocker with **full disk encryption type**.
2+
3+
BitLocker Drive Encryption protects data on Windows devices by encrypting the disk.
4+
However, BitLocker supports two encryption types that have very different security implications:
5+
6+
- **Full disk encryption** — encrypts the entire drive including free space. This is the recommended and secure option.
7+
- **Used space only encryption** — only encrypts sectors currently holding data. **This is dangerous on drives that previously contained unencrypted data**, because previously deleted files remain as raw data in unencrypted free space. This data can be recovered using commonly available data recovery software (e.g., Recuva, PhotoRec, or forensic imaging tools). NTFS marks deleted file sectors as "free" but does not zero them out — the original bytes stay on disk until overwritten by new data.
8+
9+
**Bottom line:** If BitLocker is enabled with "Used space only" on a drive that already had data on it before encryption was turned on, that pre-existing deleted data is fully recoverable. Only "Full disk encryption" guarantees that the entire drive surface is protected.
10+
11+
This test queries the Intune **Endpoint Security > Disk Encryption** policies via the `configurationPolicies` Graph API and inspects the BitLocker CSP settings to verify that **Enforce drive encryption type** is set to **Full encryption** for OS drives.
12+
13+
#### Remediation action:
14+
15+
1. Navigate to [Microsoft Intune admin center](https://intune.microsoft.com).
16+
2. Go to **Endpoint security** > **Disk encryption**.
17+
3. Click **+ Create policy**.
18+
4. Set **Platform** to **Windows 10 and later** and **Profile** to **BitLocker**.
19+
5. Enter a policy name (e.g., "BitLocker - Full Disk Encryption").
20+
6. Configure the following settings:
21+
- **Require Device Encryption**: **Enabled**
22+
- **Allow Warning For Other Disk Encryption**: **Disabled** (enables silent encryption)
23+
- **Allow Standard User Encryption**: **Enabled**
24+
- **Enforce drive encryption type on operating system drives**: **Enabled**, set to **Full encryption**
25+
- **Enforce drive encryption type on fixed data drives**: **Enabled**, set to **Full encryption**
26+
- **Choose drive encryption method and cipher strength**: **Enabled**
27+
- OS drives: **XTS-AES 256-bit**
28+
- Fixed data drives: **XTS-AES 256-bit**
29+
- Removable data drives: **AES-CBC 256-bit**
30+
- **Require additional authentication at startup**: **Enabled**, with **Require TPM**
31+
- **Choose how BitLocker-protected OS drives can be recovered**: **Enabled**, with backup to Entra ID
32+
7. Assign the policy to your device groups and click **Create**.
33+
34+
#### Related links
35+
36+
- [Microsoft Intune - Endpoint Security Disk Encryption](https://intune.microsoft.com/#view/Microsoft_Intune_Workflows/SecurityManagementMenu/~/diskEncryption)
37+
- [Microsoft Learn - Encrypt devices with BitLocker in Intune](https://learn.microsoft.com/en-us/mem/intune/protect/encrypt-devices)
38+
- [Microsoft Learn - BitLocker CSP reference](https://learn.microsoft.com/en-us/windows/client-management/mdm/bitlocker-csp)
39+
- [CIS Benchmark - Ensure BitLocker is enabled on all Windows devices](https://www.cisecurity.org/benchmark/microsoft_intune_for_windows)
40+
41+
<!--- Results --->
42+
%TestResult%
Lines changed: 212 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,212 @@
1+
function Test-MtBitLockerFullDiskEncryption {
2+
<#
3+
.SYNOPSIS
4+
Ensure at least one Intune Disk Encryption policy enforces BitLocker with full disk encryption type.
5+
6+
.DESCRIPTION
7+
Checks Intune Endpoint Security Disk Encryption policies (configurationPolicies API) for BitLocker
8+
profiles that enforce full disk encryption rather than "Used space only" encryption.
9+
10+
BitLocker supports two encryption types with very different security implications:
11+
- "Full disk encryption" — encrypts the entire drive including free space. This is the secure option.
12+
- "Used space only encryption" — only encrypts sectors currently holding data. Previously deleted
13+
files that were written before encryption was enabled remain in unencrypted free space and can be
14+
recovered using data recovery software (e.g., Recuva, PhotoRec, or forensic tools). This is because
15+
NTFS marks sectors as free but does not zero them out — the raw data stays on disk until overwritten.
16+
17+
This test queries the configurationPolicies Graph API (used by Endpoint Security > Disk Encryption)
18+
which exposes the actual BitLocker CSP settings including:
19+
- SystemDrivesEncryptionType (OS drive encryption type: full vs used space only)
20+
- FixedDrivesEncryptionType (fixed drive encryption type: full vs used space only)
21+
- RequireDeviceEncryption (require BitLocker encryption)
22+
- EncryptionMethodByDriveType (cipher strength: XTS-AES 128/256, AES-CBC 128/256)
23+
24+
The test passes only if at least one BitLocker Disk Encryption policy has the OS drive encryption
25+
type set to "Full encryption". It fails if no policies exist, if encryption type is set to
26+
"Used space only", or if the encryption type setting is not configured.
27+
28+
.EXAMPLE
29+
Test-MtBitLockerFullDiskEncryption
30+
31+
Returns true if at least one Disk Encryption policy enforces full disk encryption for OS drives.
32+
33+
.LINK
34+
https://maester.dev/docs/commands/Test-MtBitLockerFullDiskEncryption
35+
#>
36+
[CmdletBinding()]
37+
[OutputType([bool])]
38+
param()
39+
40+
if (-not (Get-MtLicenseInformation -Product Intune)) {
41+
Add-MtTestResultDetail -SkippedBecause NotLicensedIntune
42+
return $null
43+
}
44+
45+
try {
46+
# Query Endpoint Security Disk Encryption policies (configurationPolicies API)
47+
$policies = Invoke-MtGraphRequest -RelativeUri 'deviceManagement/configurationPolicies' -ApiVersion beta
48+
49+
# Filter to BitLocker Disk Encryption policies by template family
50+
$bitLockerPolicies = $policies | Where-Object {
51+
$_.templateReference.templateFamily -eq 'endpointSecurityDiskEncryption' -and
52+
$_.templateReference.templateDisplayName -eq 'BitLocker'
53+
}
54+
55+
if (-not $bitLockerPolicies -or $bitLockerPolicies.Count -eq 0) {
56+
$testResultMarkdown = "No Endpoint Security Disk Encryption (BitLocker) policies found in Intune.`n`n"
57+
$testResultMarkdown += "Create a BitLocker policy under **Endpoint Security > Disk Encryption** with "
58+
$testResultMarkdown += "**Enforce drive encryption type** set to **Full encryption** for OS and fixed data drives."
59+
Add-MtTestResultDetail -Result $testResultMarkdown
60+
return $false
61+
}
62+
63+
# Setting definition IDs for BitLocker CSP settings
64+
$osEncryptionTypeId = 'device_vendor_msft_bitlocker_systemdrivesencryptiontype'
65+
$osEncryptionTypeDropdownId = 'device_vendor_msft_bitlocker_systemdrivesencryptiontype_osencryptiontypedropdown_name'
66+
$fixedEncryptionTypeId = 'device_vendor_msft_bitlocker_fixeddrivesencryptiontype'
67+
$fixedEncryptionTypeDropdownId = 'device_vendor_msft_bitlocker_fixeddrivesencryptiontype_fdeencryptiontypedropdown_name'
68+
$requireEncryptionId = 'device_vendor_msft_bitlocker_requiredeviceencryption'
69+
$encryptionMethodId = 'device_vendor_msft_bitlocker_encryptionmethodbydrivetype'
70+
$osEncryptionMethodDropdownId = 'device_vendor_msft_bitlocker_encryptionmethodbydrivetype_encryptionmethodwithxtsosdropdown_name'
71+
72+
# Encryption type value suffixes: _0 = Allow user to choose, _1 = Full encryption, _2 = Used Space Only
73+
$encryptionTypeLabels = @{
74+
'_0' = 'Allow user to choose'
75+
'_1' = 'Full encryption'
76+
'_2' = 'Used Space Only'
77+
}
78+
79+
# Encryption method value suffixes: _3=AES-CBC 128, _4=AES-CBC 256, _6=XTS-AES 128, _7=XTS-AES 256
80+
$encryptionMethodLabels = @{
81+
'_3' = 'AES-CBC 128-bit'
82+
'_4' = 'AES-CBC 256-bit'
83+
'_6' = 'XTS-AES 128-bit'
84+
'_7' = 'XTS-AES 256-bit'
85+
}
86+
87+
$policyResults = @()
88+
$hasFullEncryption = $false
89+
90+
foreach ($policy in $bitLockerPolicies) {
91+
# Fetch settings for this policy with definitions expanded
92+
$settingsUri = "deviceManagement/configurationPolicies('$($policy.id)')/settings?`$expand=settingDefinitions&top=1000"
93+
$settingsResponse = Invoke-MtGraphRequest -RelativeUri $settingsUri -ApiVersion beta
94+
95+
$policyDetail = @{
96+
Name = $policy.name
97+
RequireEncryption = 'Not configured'
98+
OsEncryptionType = 'Not configured'
99+
FixedEncryptionType = 'Not configured'
100+
OsEncryptionMethod = 'Not configured'
101+
}
102+
103+
foreach ($setting in $settingsResponse) {
104+
$defId = $setting.settingInstance.settingDefinitionId
105+
106+
# Check RequireDeviceEncryption
107+
if ($defId -eq $requireEncryptionId) {
108+
$val = $setting.settingInstance.choiceSettingValue.value
109+
if ($val -like '*_1') {
110+
$policyDetail.RequireEncryption = 'Enabled'
111+
} else {
112+
$policyDetail.RequireEncryption = 'Disabled'
113+
}
114+
}
115+
116+
# Check OS drive encryption type (SystemDrivesEncryptionType)
117+
if ($defId -eq $osEncryptionTypeId) {
118+
$parentVal = $setting.settingInstance.choiceSettingValue.value
119+
if ($parentVal -like '*_1') {
120+
# Enabled — check the child dropdown for the actual encryption type
121+
$children = $setting.settingInstance.choiceSettingValue.children
122+
foreach ($child in $children) {
123+
if ($child.settingDefinitionId -eq $osEncryptionTypeDropdownId) {
124+
$dropdownVal = $child.choiceSettingValue.value
125+
foreach ($suffix in $encryptionTypeLabels.Keys) {
126+
if ($dropdownVal -like "*$suffix") {
127+
$policyDetail.OsEncryptionType = $encryptionTypeLabels[$suffix]
128+
if ($suffix -eq '_1') { $hasFullEncryption = $true }
129+
}
130+
}
131+
}
132+
}
133+
} else {
134+
$policyDetail.OsEncryptionType = 'Disabled'
135+
}
136+
}
137+
138+
# Check Fixed drive encryption type (FixedDrivesEncryptionType)
139+
if ($defId -eq $fixedEncryptionTypeId) {
140+
$parentVal = $setting.settingInstance.choiceSettingValue.value
141+
if ($parentVal -like '*_1') {
142+
$children = $setting.settingInstance.choiceSettingValue.children
143+
foreach ($child in $children) {
144+
if ($child.settingDefinitionId -eq $fixedEncryptionTypeDropdownId) {
145+
$dropdownVal = $child.choiceSettingValue.value
146+
foreach ($suffix in $encryptionTypeLabels.Keys) {
147+
if ($dropdownVal -like "*$suffix") {
148+
$policyDetail.FixedEncryptionType = $encryptionTypeLabels[$suffix]
149+
}
150+
}
151+
}
152+
}
153+
} else {
154+
$policyDetail.FixedEncryptionType = 'Disabled'
155+
}
156+
}
157+
158+
# Check encryption method (cipher strength)
159+
if ($defId -eq $encryptionMethodId) {
160+
$parentVal = $setting.settingInstance.choiceSettingValue.value
161+
if ($parentVal -like '*_1') {
162+
$children = $setting.settingInstance.choiceSettingValue.children
163+
foreach ($child in $children) {
164+
if ($child.settingDefinitionId -eq $osEncryptionMethodDropdownId) {
165+
$methodVal = $child.choiceSettingValue.value
166+
foreach ($suffix in $encryptionMethodLabels.Keys) {
167+
if ($methodVal -like "*$suffix") {
168+
$policyDetail.OsEncryptionMethod = $encryptionMethodLabels[$suffix]
169+
}
170+
}
171+
}
172+
}
173+
}
174+
}
175+
}
176+
177+
$policyResults += $policyDetail
178+
}
179+
180+
# Build result markdown
181+
$testResultMarkdown = "Found $($bitLockerPolicies.Count) BitLocker Disk Encryption policy/policies in Intune.`n`n"
182+
$testResultMarkdown += "| Policy | Require Encryption | OS Encryption Type | Fixed Encryption Type | OS Cipher |`n"
183+
$testResultMarkdown += "| --- | --- | --- | --- | --- |`n"
184+
foreach ($p in $policyResults) {
185+
$testResultMarkdown += "| $($p.Name) | $($p.RequireEncryption) | $($p.OsEncryptionType) | $($p.FixedEncryptionType) | $($p.OsEncryptionMethod) |`n"
186+
}
187+
188+
if ($hasFullEncryption) {
189+
$testResultMarkdown += "`n**Result:** At least one BitLocker policy enforces **Full encryption** for OS drives."
190+
191+
# Warn if any policy uses Used Space Only
192+
$usedSpaceOnly = $policyResults | Where-Object { $_.OsEncryptionType -eq 'Used Space Only' }
193+
if ($usedSpaceOnly) {
194+
$testResultMarkdown += "`n`n> **Warning:** $($usedSpaceOnly.Count) policy/policies use **Used Space Only** encryption. "
195+
$testResultMarkdown += "Previously deleted data remains recoverable from unencrypted free space on those devices."
196+
}
197+
198+
Add-MtTestResultDetail -Result $testResultMarkdown
199+
return $true
200+
} else {
201+
$testResultMarkdown += "`n**Result:** No BitLocker policy enforces **Full encryption** for OS drives.`n`n"
202+
$testResultMarkdown += "> **Risk:** If 'Used space only' encryption is configured (or encryption type is not enforced), "
203+
$testResultMarkdown += "data written to the disk before BitLocker was enabled remains as raw unencrypted data in free space "
204+
$testResultMarkdown += "and can be recovered using commonly available data recovery tools (Recuva, PhotoRec, forensic imaging)."
205+
Add-MtTestResultDetail -Result $testResultMarkdown
206+
return $false
207+
}
208+
} catch {
209+
Add-MtTestResultDetail -SkippedBecause Error -SkippedError $_
210+
return $null
211+
}
212+
}

tests/Maester/Intune/Test-MtIntunePlatform.Tests.ps1

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,4 +61,11 @@ Describe "Maester/Intune" -Tag "Maester", "Intune" {
6161
$result | Should -Be $true -Because "MDM Authority is set to Intune."
6262
}
6363
}
64+
65+
It "MT.1123: Ensure BitLocker full disk encryption is configured" -Tag "MT.1123" {
66+
$result = Test-MtBitLockerFullDiskEncryption
67+
if ($null -ne $result) {
68+
$result | Should -Be $true -Because "at least one Intune Endpoint Protection profile enforces BitLocker full disk encryption."
69+
}
70+
}
6471
}

tests/maester-config.json

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1349,6 +1349,11 @@
13491349
"Severity": "Medium",
13501350
"Title": "AI agents should not have orphaned ownership"
13511351
},
1352+
{
1353+
"Id": "MT.1123",
1354+
"Severity": "High",
1355+
"Title": "Ensure BitLocker full disk encryption is configured via Intune"
1356+
},
13521357
{
13531358
"Id": "ORCA.100",
13541359
"Severity": "Medium",
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
---
2+
title: MT.1123 - Ensure BitLocker full disk encryption is configured via Intune
3+
description: Checks if at least one Intune Endpoint Protection profile enforces BitLocker full disk encryption for OS and fixed data drives.
4+
slug: /tests/MT.1123
5+
sidebar_class_name: hidden
6+
---
7+
8+
# Ensure BitLocker full disk encryption is configured via Intune
9+
10+
## Description
11+
12+
BitLocker Drive Encryption protects data on Windows devices, but the **encryption type** setting is critical:
13+
14+
- **Full disk encryption** — encrypts the entire drive including free space. This is the secure option.
15+
- **Used space only encryption** — only encrypts sectors currently holding data. Previously deleted files that existed before encryption was enabled remain as raw data in unencrypted free space and **can be recovered using data recovery software** (e.g., Recuva, PhotoRec, forensic imaging tools). This happens because NTFS marks deleted sectors as "free" but does not zero them — the original bytes persist on disk until overwritten.
16+
17+
This test checks that at least one Windows 10/11 Endpoint Protection configuration profile exists in Intune with BitLocker settings configured. It inspects `bitLockerEncryptDevice`, `bitLockerSystemDrivePolicy`, and `bitLockerFixedDrivePolicy` via the Graph API.
18+
19+
> **Note:** The Endpoint Protection Graph API does not expose the "encryption type" (full disk vs used space only) setting. That is controlled via the BitLocker CSP (`SystemDrivesEncryptionType` / `FixedDrivesEncryptionType`), configured through Intune **Settings Catalog** or **Disk Encryption** profiles. When BitLocker is detected, the test outputs a warning to verify full disk encryption is enforced.
20+
21+
## How to fix
22+
23+
1. Navigate to [Microsoft Intune admin center](https://intune.microsoft.com).
24+
2. Click **Devices** > **Manage devices** > **Configuration**.
25+
3. Click **+ Create** > **New policy**.
26+
4. Set **Platform** to **Windows 10 and later**.
27+
5. Set **Profile type** to **Templates** > **Endpoint protection**.
28+
6. Under **Windows Encryption**, configure:
29+
- **Encrypt devices**: **Require**
30+
- **BitLocker OS drive settings**: Enable, set **Encryption method** to **XTS-AES 256-bit**
31+
- **BitLocker fixed drive settings**: Enable, set **Encryption method** to **XTS-AES 256-bit**
32+
7. **Additionally**, create a **Settings Catalog** or **Disk Encryption** profile to set:
33+
- **Enforce drive encryption type on operating system drives**: **Full encryption**
34+
- **Enforce drive encryption type on fixed data drives**: **Full encryption**
35+
8. Assign both profiles to your device groups.
36+
37+
## Learn more
38+
39+
- [Microsoft Intune - Device Configuration](https://intune.microsoft.com/#view/Microsoft_Intune_DeviceSettings/DevicesMenu/~/configuration)
40+
- [Microsoft Learn - Encrypt devices with BitLocker in Intune](https://learn.microsoft.com/en-us/mem/intune/protect/encrypt-devices)
41+
- [Microsoft Learn - BitLocker settings reference](https://learn.microsoft.com/en-us/mem/intune/protect/endpoint-protection-windows-10#windows-settings)

0 commit comments

Comments
 (0)