MITRE ATT&CK Technique: T1552.001 (Unsecured Credentials: Credentials in Files)
CVE: N/A (Configuration-based vulnerability)
Platforms: Microsoft 365 (M365)
Severity: CRITICAL
Viability: ACTIVE
| Author | SERVTEP – Artur Pchelnikau |
MIP (Microsoft Information Protection) master key theft is a critical credential access attack that exploits weakly protected encryption keys used to decrypt sensitive organizational data. Threat actors who obtain MIP tenant keys, encryption keys from Azure Key Vault, or signing keys can forge access tokens, decrypt protected documents, and impersonate users across Microsoft 365 services. The Storm-0558 incident (July 2023) demonstrated real-world exploitation, where Chinese threat actors compromised an MSA signing key and accessed Exchange Online for 25+ organizations. This module covers detection, response, and mitigation strategies specific to M365 environments.
Stage 1: Initial Access & Reconnaissance
Stage 2: Key Extraction
Stage 3: Token Forging & Lateral Movement
Stage 4: Persistence & Data Exfiltration
Timeline:
Attack Characteristics:
| Key Type | Owner | Use Case | Viability | Detection Difficulty |
|---|---|---|---|---|
| Tenant Root Key (Microsoft-managed) | Microsoft | Default encryption for all MIP data | ACTIVE | Medium |
| BYOK (Customer-managed in Key Vault) | Customer | High compliance requirements (GDPR, HIPAA) | ACTIVE | Hard |
| DKE (Double Key Encryption) | Customer + Microsoft | Dual control / zero-knowledge encryption | ACTIVE | Very Hard |
| AD RMS TPD Keys | Legacy / On-premises | Migrated from on-premises AD RMS | DEPRECATED | Medium |
| Application Signing Keys | Microsoft / Customer | OAuth2 token validation | ACTIVE | Medium |
Azure Key Vault (Cloud-based BYOK):
/subscriptions/{subscription}/resourcegroups/{resource-group}/providers/microsoft.keyvault/vaults/{vault-name}
Key names: ContosoRmsKey, ContosoEncryptionKey
Key versions: Multiple (rotation tracked by version GUID)
On-Premises HSM (nCipher, Luna, Thales):
HSM Slot: 0, 1, 2 (depends on hardware configuration)
Key Labels: AIP-Master-Key, RMS-Encryption-Key-2024
Backup: Tokenized key files + security world files
Windows Registry (Legacy/Cached):
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\MSIPC\ServiceLocation
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\MSIPC\OFFLINE_KEY
HKEY_CURRENT_USER\Software\Microsoft\Office\16.0\Outlook\Security
Azure Rights Management Service Storage:
Service Fabric encrypted storage
Key identifiers: <GUID-format>
Metadata: Key creation date, rotation schedule, dependent applications
Method 1: Azure Key Vault Export (Requires “Get”, “UnwrapKey” Permissions)
# Attacker with Key Vault access
$key = Get-AzKeyVaultKey -VaultName "production-keyvault" -Name "MIP-Master-Key"
$key | Export-AzKeyVaultKey -Destination "C:\stolen-key.pfx"
# Result: Plaintext key exported to attackable location
Method 2: Azure RMS Super User Bypass
# If attacker enables super user feature
Enable-AipServiceSuperUserFeature
Add-AipServiceSuperUser -EmailAddress attacker@domain.com
# Attacker can now decrypt any document in tenant
Method 3: BYOK Access During Transfer
Method 4: Service Principal Credential Theft
# Stolen service principal with Microsoft.KeyVault/vaults/keys/read permission
$credential = Get-AzAccessToken -ResourceUrl "https://vault.azure.net"
# Use token to query Key Vault API for key material
Technique: T1552.001 - Unsecured Credentials: Credentials in Files
Tactics Executed:
Sub-techniques Associated:
Related Techniques:
| Tool | Purpose | ViabilityStatus | Download URL |
|---|---|---|---|
| LaZagne | Credential harvesting from browsers, email, cloud apps | ACTIVE | https://github.com/AlessandroZ/LaZagne |
| Mimikatz | LSASS memory credential dumping | ACTIVE | https://github.com/gentilkiwi/mimikatz |
| SessionGopher | PowerShell session history + WinRM credential extraction | ACTIVE | https://github.com/Arvanaghi/SessionGopher |
| Snaffler | Network share enumeration for credential files | ACTIVE | https://github.com/SnaffCon/Snaffler |
| WinPwn | Integrated toolkit for sensitive file discovery | ACTIVE | https://github.com/S3cur3Th1sSh1t/WinPwn |
| Az.KeyVault Module | PowerShell key export (if permissions exist) | ACTIVE | Built-in to Azure PowerShell |
| Get-AipServiceKeys | Query MIP tenant keys | ACTIVE | AIPService PowerShell module |
Supported Platforms: Windows, macOS, Linux
| Test Name | Command | Executor | Detection Trigger |
|---|---|---|---|
| Find AWS credentials | find / -name "credentials" -type f |
bash/sh | File enumeration, process execution |
| Extract with LaZagne | python2 laZagne.py all |
bash | Child process creation, network calls |
| Extract with grep | grep -ri password / |
sh | Recursive file search, process execution |
| Extracting with findstr | findstr /si pass *.xml *.doc *.txt |
PowerShell | File system enumeration |
| Access unattend.xml | type C:\Windows\Panther\unattend.xml |
cmd.exe | Registry/file access audit |
| Find GitHub credentials | find /home -name .netrc |
bash | Sensitive file access |
| WinPwn sensitivefiles | IEX + sensitivefiles function | PowerShell | Command-line logging, network downloads |
| WinPwn Snaffler | IEX + Snaffler function | PowerShell | Network share enumeration logs |
| List Credential Files | Get-ChildItem -Hidden C:\Users\*\AppData\Roaming\Microsoft\Credentials |
PowerShell | Registry + file system auditing |
| Find Azure credentials | find / -name "msal_token_cache.json" |
bash | Token file access logging |
| Find GCP credentials | find / -path "*/.config/gcloud" |
bash | Config file enumeration |
Execution Example:
# Atomic test execution
Invoke-AtomicTest T1552.001 -TestName "Extracting passwords with findstr"
# Expected telemetry:
# - Process: PowerShell.exe (PID: 4521)
# - CommandLine: findstr /si pass *.xml *.doc *.txt
# - Target files: web.config, machine.config, connection strings
| Registry Path | Event ID | Significance | Attacker Indicator |
|---|---|---|---|
HKLM\SOFTWARE\Microsoft\Cryptography |
4657, 4663 | Crypto provider status | Unusual read access frequency |
HKEY_LOCAL_MACHINE\SECURITY\Policy\Secrets\* |
4657 | LSA secrets (DPAPI-encrypted) | Privilege elevation for access |
HKCU\Software\Microsoft\MSIPC\ServiceLocation |
4657 | MIP service endpoint config | Modification = suspicious |
HKCU\Software\Microsoft\Office\16.0\Outlook\Outlook Security |
4657 | Outlook encryption settings | Disablement of security features |
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System\CredentialsDom |
4657 | Credential delegation policy | Relaxed policy = attack precondition |
HKCU\Software\Microsoft\Windows\CurrentVersion\Explorer\RecentDocs |
4663 | Recently accessed files | Encryption keys or config files |
| Artifact Path | Artifact Type | Significance |
|---|---|---|
%APPDATA%\Microsoft\Credentials\* |
Binary files | Windows Credential Manager encrypted credentials |
%LOCALAPPDATA%\Microsoft\Credentials\* |
Binary files | Additional credential storage |
C:\Users\%USERNAME%\.azure\msal_token_cache.json |
JSON | Azure CLI/PowerShell token cache |
C:\Users\%USERNAME%\.config\gcloud\ |
Directory | GCP credentials (if multi-cloud environment) |
C:\Users\%USERNAME%\.aws\credentials |
Text file (plaintext) | AWS access key storage |
/home/*/.netrc |
Text file (plaintext) | GitHub/FTP credentials (Unix-like) |
C:\Windows\Panther\unattend.xml |
XML | Installation credentials (legacy) |
C:\Users\%USERNAME%\AppData\Local\Microsoft\OneDrive\settings\Personal |
Registry hive | OneDrive encryption keys |
C:\Program Files\Microsoft Azure AD Connect\Data\ |
Directory | Azure AD Connect sync keys |
| Event ID | Log Source | Significance | Detection Condition |
|---|---|---|---|
| 4657 | Security | Audit Registry Value Modified | REG_SZ or REG_BINARY changes to crypto paths |
| 4663 | Security | Audit File/Object Access | Read access to %APPDATA%\Microsoft\Credentials |
| 4768 | Security | Kerberos TGT Granted | Forged token detection requires E5 audit logs |
| 4769 | Security | Kerberos Service Ticket Granted | Unusual service principal requests |
| 5136 | Directory Services | Active Directory Object Changed | Replication metadata tampering |
| 4688 | Security | Process Creation | Child processes spawned by suspicious tools |
| 17 | Sysmon | PipeEvent | Named pipe connections to elevated processes |
| 12-14 | Sysmon | RegistryEvent | Registry operations on key material paths |
| 10 | Sysmon | ProcessAccess | LSASS access attempts for credential dumping |
| 23 | Sysmon | FileDelete | Deletion of audit logs or key backups |
azure:aad:audit, o365:management:activity, wineventlog:security, XmlWinEventLog:Microsoft-Windows-Sysmon/OperationalDetection Type: Anomaly Detection
Alert Severity: HIGH
Frequency: Every 5 minutes
Applies To: Azure Subscriptions with Key Vault resources
Splunk Query:
index=azure sourcetype=azure:aad:audit operationName IN ("Decrypt Key", "Get Key", "Get Key Versions", "Export Key", "Backup Key", "Restore Key")
| stats count, values(initiatedBy.user.userPrincipalName) as User, values(resourceDisplayName) as KeyName, values(result) as Result by correlationId
| where count > 5
| eval RiskScore=case(
Result=="Failure" AND count>10, 95,
operationName=="Export Key" AND count>=1, 98,
User LIKE "%service%", 85,
1=1, 70
)
| where RiskScore > 80
What This Detects:
Alert Action: Create incident, notify security team, initiate Key Vault access review
Detection Type: Behavioral Anomaly
Alert Severity: CRITICAL
Frequency: Real-time
Splunk Query:
index=azure sourcetype=azure:aad:audit operationName IN ("Enable-AipServiceSuperUserFeature", "Add-AipServiceSuperUser", "Set-AipServiceSuperUserGroup") result=success
| dedup correlationId
| table creationTime, initiatedBy.user.userPrincipalName, operationName, targetResources
| eval SuspiciousRoleAssignment=if(match(initiatedBy.user.userPrincipalName, "(?i)(svc_|robot|automation|service)"), 1, 0)
| where SuspiciousRoleAssignment=1 OR operationName="Enable-AipServiceSuperUserFeature"
False Positive Analysis:
Tuning:
index=azure sourcetype=azure:aad:audit operationName="Enable-AipServiceSuperUserFeature"
| where NOT (initiatedBy.user.userPrincipalName IN ("compliance@domain.com", "ediscovery-svc@domain.com"))
Detection Type: TTP Detection
Alert Severity: CRITICAL
Applies To: Organizations using BYOK
Splunk Query:
index=azure sourcetype=o365:management:activity Workload=AzureRMS Operation IN ("ExportTenantKey", "DownloadTemplate", "Get-AipServiceKeys")
| lookup builtin_list result as IsAuthorized
| where IsAuthorized=false
| stats count by UserId, Operation, ClientIP, UserAgent
| eval RiskIndicator=if(ClientIP NOT IN ("10.0.0.0/8", "172.16.0.0/12"), "External IP", "Internal IP")
| where RiskIndicator="External IP" OR count > 2
Forensic Pivot:
index=azure sourcetype=o365:management:activity Operation="ExportTenantKey"
| search UserId=attacker@domain.com
| transaction UserId clientIP
| where duration > 300
| table UserId, Operation, ClientIP, UsageLocation, TimeGenerated
Detection Type: Host-based Detection
Alert Severity: HIGH
Requires: Sysmon Event Logs from client/server machines
Splunk Query:
index=windows source=XmlWinEventLog:Microsoft-Windows-Sysmon/Operational EventCode IN (12, 13, 14)
| regex TargetObject="(?i)(MSIPC|CredentialsDom|Outlook.*Security)"
| stats count, values(Image) as Process, values(User) as User by Computer, TargetObject
| where count > 10
| eval Severity=case(
Image LIKE "%powershell%", "High",
Image LIKE "%cmd.exe%", "Medium",
Image LIKE "%explorer.exe%", "Low",
1=1, "Medium"
)
Detection Condition:
HKLM\SOFTWARE\Microsoft\MSIPC\*HKCU\Software\Microsoft\Office\16.0\Outlook\SecurityRule Configuration:
KQL Query:
AuditLogs
| where OperationName in ("Decrypt Key", "Get Key", "Export Key", "ExportTenantKey", "Download Template")
and Result == "Success"
| extend InitiatedByUser = tostring(InitiatedBy.user.userPrincipalName)
| extend TargetKeyName = tostring(TargetResources[0].displayName)
| extend OperationTime = TimeGenerated
| summarize KeyAccessCount = dcount(OperationName), AccessedKeys = make_set(TargetKeyName),
UniqueInitiators = dcount(InitiatedByUser) by InitiatedByUser, ClientIP = InitiatedBy.user.ipAddress, tostring(UserAgent)
| where KeyAccessCount > 3
or AccessedKeys has "MasterKey"
or AccessedKeys has "RmsKey"
| extend RiskScore =
case(
InitiatedByUser matches regex @"(svc_|service|robot|automation)" , 75,
KeyAccessCount > 10, 90,
ClientIP startswith "192.168" or ClientIP startswith "10.", 40,
1=1, 60
)
| where RiskScore >= 75
| project TimeGenerated, InitiatedByUser, ClientIP, KeyAccessCount, AccessedKeys, RiskScore, OperationName
What This Detects:
Manual Configuration Steps (Azure Portal):
Detect MIP Master Key Export AttemptsCritical5 minutes1 hourManual Configuration Steps (PowerShell):
# Connect to Sentinel workspace
Connect-AzAccount
$ResourceGroup = "YourResourceGroup"
$WorkspaceName = "YourSentinelWorkspace"
# Create the analytics rule
New-AzSentinelAlertRule -ResourceGroupName $ResourceGroup -WorkspaceName $WorkspaceName `
-DisplayName "Detect MIP Master Key Export Attempts" `
-Query @"
AuditLogs
| where OperationName in ("Decrypt Key", "Get Key", "Export Key")
| where Result == "Success"
| extend InitiatedByUser = tostring(InitiatedBy.user.userPrincipalName)
| summarize KeyAccessCount = count() by InitiatedByUser
| where KeyAccessCount > 3
"@ `
-Severity "Critical" `
-Enabled $true `
-SuppressionDuration (New-TimeSpan -Hours 1) `
-Frequency (New-TimeSpan -Minutes 5) `
-Period (New-TimeSpan -Hours 1)
Source: Microsoft Sentinel GitHub - Entra ID Detection Rules
Rule Configuration:
KQL Query:
SigninLogs
| where ServicePrincipalName != ""
| where ResultType == 0 // Successful logon
| extend ServicePrincipalId = ServicePrincipalId
| join kind=inner (
AuditLogs
| where OperationName in ("Get Key", "Decrypt Key", "List Keys")
| extend ServicePrincipalId = extractjson("$.TargetResources[0].id", tostring(TargetResources))
) on ServicePrincipalId
| summarize SigninCount = count(), KeyOpsCount = dcount(OperationName) by ServicePrincipalName, ClientIP, TimeGenerated
| where KeyOpsCount >= 5 and SigninCount >= 2
| extend AnomalyScore = (KeyOpsCount * SigninCount) / 10
| where AnomalyScore > 1.5
What This Detects:
Log Source: Security
Trigger: Modification to Registry values under HKLM\SOFTWARE\Microsoft\MSIPC or HKCU\Office encryption paths
Filter: Object Name contains “MSIPC” or “Outlook” and “Security”
Applies To Versions: Server 2016+, Windows 10+
Manual Configuration Steps (Group Policy):
gpupdate /force on target machinesForensic Query (PowerShell):
$StartTime = (Get-Date).AddHours(-24)
Get-WinEvent -FilterHashtable @{
LogName = "Security"
Id = 4657
StartTime = $StartTime
} | Where-Object {
$_.Properties[10].Value -match "MSIPC|Outlook" -and
$_.Properties[13].Value -ne "%%1900" # Not System account
} | Select-Object TimeCreated, @{N="User";E={$_.Properties[1].Value}},
@{N="Registry Path";E={$_.Properties[10].Value}},
@{N="Old Value";E={$_.Properties[14].Value}},
@{N="New Value";E={$_.Properties[15].Value}}
Log Source: Security
Trigger: Read access to credential files in %APPDATA%\Microsoft\Credentials
Applies To Versions: Server 2016+
Manual Configuration Steps (Local Policy):
auditpol /set /subcategory:"File System" /success:enable /failure:enableLog Source: Directory Services
Trigger: Replication metadata changes indicating key rollover or breach response
Applies To: Domain Controllers
Example: Azure AD Connect sync key rotation
Detection (PowerShell):
Get-WinEvent -FilterHashtable @{
LogName = "Directory Service"
Id = 5136
StartTime = (Get-Date).AddHours(-24)
} | Where-Object {
$_.Message -match "(msDS-KeyVersionNumber|msDS-EncodedRDN)" -and
$_.Message -match "Attribute Modification"
} | Measure-Object
Minimum Sysmon Version: 13.0+
Supported Platforms: Windows 10, Windows Server 2016+
Sysmon Event IDs to Monitor:
Sysmon XML Configuration:
<Sysmon schemaversion="4.22">
<HashAlgorithms>md5,sha256</HashAlgorithms>
<!-- Detect Registry Access to Encryption Key Paths -->
<RegistryEvent onmatch="include">
<TargetObject condition="contains">MSIPC</TargetObject>
<TargetObject condition="contains">Outlook\Security</TargetObject>
<TargetObject condition="contains">Office\16.0\Encryption</TargetObject>
</RegistryEvent>
<!-- Detect LSASS Access (Credential Dumping) -->
<ProcessAccess onmatch="include">
<TargetImage condition="image">lsass.exe</TargetImage>
<GrantedAccess condition="is">0x1438</GrantedAccess>
<GrantedAccess condition="is">0x1400</GrantedAccess>
<GrantedAccess condition="is">0x1010</GrantedAccess>
</ProcessAccess>
<!-- Detect Key Export/Backup File Creation -->
<FileCreate onmatch="include">
<TargetFilename condition="contains">\.pfx</TargetFilename>
<TargetFilename condition="contains">\.pem</TargetFilename>
<TargetFilename condition="contains">\.key</TargetFilename>
<TargetFilename condition="contains">backup</TargetFilename>
<Image condition="is">powershell.exe</Image>
</FileCreate>
<!-- Detect Malicious Credential Harvesting Tools -->
<ProcessCreate onmatch="include">
<CommandLine condition="contains">LaZagne</CommandLine>
<CommandLine condition="contains">SessionGopher</CommandLine>
<CommandLine condition="contains">Snaffler</CommandLine>
</ProcessCreate>
</Sysmon>
Manual Configuration Steps:
sysmon-mip-config.xml with XML abovesysmon64.exe -accepteula -i sysmon-mip-config.xml
Get-Service Sysmon64
Get-WinEvent -LogName "Microsoft-Windows-Sysmon/Operational" -MaxEvents 10
Alert Name: KeyVaultSuspiciousAccess
Severity: High
Description: Microsoft Defender for Cloud detects multiple failed key retrieval attempts followed by a successful export operation, indicating potential key theft via brute force or compromised credentials
Applies To: All subscriptions with Defender for Cloud enabled + Key Vault resources
Remediation:
Manual Configuration Steps (Enable Defender for Cloud):
Reference: Microsoft Defender for Cloud Alerts - Key Vault
Operation: GetAipServiceKeys, AddAipServiceSuperUser, ExportTenantKey
Workload: Azure Active Directory, AzureRMS
Details: Monitor AuditData JSON blob for key export events
PowerShell Query:
Search-UnifiedAuditLog `
-Operations "Get Key", "Export Key", "Decrypt Key", "Enable-AipServiceSuperUserFeature" `
-StartDate (Get-Date).AddDays(-7) `
-EndDate (Get-Date) `
-FreeText "MIP" `
-ResultSize 10000 | Select-Object CreationDate, UserIds, Operations, AuditData |
Export-Csv -Path "C:\MIP-Key-Audit.csv"
Manual Configuration Steps (Enable Unified Audit Log):
Manual Configuration Steps (Search Audit Logs):
Export Tenant KeyGet KeyDecrypt KeyEnable Super User FeaturePowerShell Alternative:
Connect-ExchangeOnline
Search-UnifiedAuditLog -StartDate "01/01/2024" -EndDate "12/31/2024" -Operations "Get Key", "Export Key" |
Select-Object CreationDate, UserIds, ClientIP, ObjectId, AuditData |
Export-Csv -Path "C:\AuditExport.csv" -NoTypeInformation
T+0 (Detection):
T+15 minutes:
T+1 hour:
T+4 hours:
T+24 hours:
1.1 Enable Azure Key Vault Purge Protection & Soft Delete
Rationale: Prevents attackers from permanently deleting keys after compromise; enforces recovery window
Applies To Versions: All Azure Key Vault versions
Manual Steps (Azure Portal):
Manual Steps (PowerShell):
# Enable purge protection on Key Vault
Update-AzKeyVault -ResourceGroupName "MyResourceGroup" -VaultName "MyKeyVault" `
-EnablePurgeProtection $true
# Verify configuration
Get-AzKeyVault -ResourceGroupName "MyResourceGroup" -VaultName "MyKeyVault" |
Select-Object EnablePurgeProtection, EnableSoftDelete
Verification:
Get-AzKeyVault -ResourceGroupName "MyResourceGroup" |
Select-Object VaultName, EnablePurgeProtection, EnableSoftDelete,
@{N="SoftDeleteRetentionDays";E={$_.SoftDeleteRetentionInDays}}
1.2 Implement Azure Key Vault RBAC with Least Privilege
Rationale: Restrict key access to named individuals; prevent overprivileged service accounts
Applies To: BYOK customers
Manual Steps (Azure Portal):
Key Vault Crypto User (read-only access to keys)Key Vault Contributor or Owner roles for routine key accessManual Steps (PowerShell):
# Assign minimal Key Vault role to user
$PrincipalId = (Get-AzADUser -UserPrincipalName "user@domain.com").Id
New-AzRoleAssignment -ObjectId $PrincipalId `
-RoleDefinitionName "Key Vault Crypto User" `
-Scope "/subscriptions/SUBSCRIPTION_ID/resourcegroups/RESOURCE_GROUP/providers/Microsoft.KeyVault/vaults/VAULT_NAME"
# Verify role assignment
Get-AzRoleAssignment -Scope "/subscriptions/SUBSCRIPTION_ID/resourcegroups/RESOURCE_GROUP/providers/Microsoft.KeyVault/vaults/VAULT_NAME" |
Where-Object RoleDefinitionName -Match "Crypto"
Forbidden Roles (Audit & Remove):
# Identify overprivileged users
Get-AzRoleAssignment -Scope "/subscriptions/SUBSCRIPTION_ID" |
Where-Object RoleDefinitionName -In @("Owner", "Key Vault Contributor", "Contributor") |
Select-Object DisplayName, RoleDefinitionName, Scope
1.3 Enable Azure Key Vault Diagnostic Logging
Rationale: Audit all key access for incident investigation; detect unauthorized operations
Manual Steps (Azure Portal):
KeyVaultAuditLoggingAuditEventSend to Log Analytics workspaceManual Steps (PowerShell):
# Enable diagnostic logging
$ResourceGroupName = "MyResourceGroup"
$VaultName = "MyKeyVault"
$WorkspaceId = "/subscriptions/SUBSCRIPTION_ID/resourcegroups/RESOURCE_GROUP/providers/microsoft.operationalinsights/workspaces/WORKSPACE_NAME"
New-AzDiagnosticSetting -Name "KeyVaultDiagnostics" `
-ResourceId "/subscriptions/SUBSCRIPTION_ID/resourcegroups/$ResourceGroupName/providers/Microsoft.KeyVault/vaults/$VaultName" `
-WorkspaceId $WorkspaceId `
-Enabled $true `
-Category AuditEvent
# Verify
Get-AzDiagnosticSetting -ResourceId "/subscriptions/SUBSCRIPTION_ID/resourcegroups/$ResourceGroupName/providers/Microsoft.KeyVault/vaults/$VaultName"
1.4 Rotate MIP Tenant Key Immediately After Suspected Breach
Rationale: Invalidates stolen keys; ensures future data is encrypted with new key material
Applies To: Both Microsoft-managed and BYOK topologies
Manual Steps (PowerShell - Microsoft-managed):
# Connect to AIP Service
Connect-AipService
# Identify current active key
Get-AipServiceKeys | Where-Object IsPrimary -EQ $true |
Select-Object KeyId, CreationTime
# Create new key (if BYOK)
# Or select existing Microsoft-managed key to activate
$NewKey = Get-AipServiceKeys | Sort-Object CreationTime -Descending | Select-Object -First 1 -Skip 1
# Set as primary (rekey operation)
Set-AipServiceKeyProperties -KeyId $NewKey.KeyId -IsPrimary $true
# Verification
Get-AipServiceKeys | Select-Object KeyId, CreationTime, IsPrimary
Manual Steps (PowerShell - BYOK Rekey):
# Identify new Azure Key Vault key
$NewKeyVaultKey = Get-AzKeyVaultKey -VaultName "MyKeyVault" -Name "NewMIPKey"
# Authorize AIP Service to use key vault
Set-AzKeyVaultAccessPolicy -VaultName "MyKeyVault" `
-ServicePrincipalName "00000012-0000-0000-c000-000000000000" `
-PermissionsToKeys get, decrypt, unwrapKey, wrapKey
# Configure new key for AIP Service
Use-AipServiceKeyVaultKey -KeyVaultKey $NewKeyVaultKey
# Activate as primary tenant key
Set-AipServiceKeyProperties -KeyId $NewKeyVaultKey.KeyIdentifier -IsPrimary $true
Impact Assessment:
2.1 Disable Azure RMS Super User Feature (if not required)
Rationale: Super users can decrypt all tenant data; restricts attack surface
Manual Steps (PowerShell):
# Check super user status
Get-AipServiceSuperUser
# If feature not required, disable
Disable-AipServiceSuperUserFeature
# Verification
Get-AipServiceSuperUserFeature | Select-Object Enabled
Operational Impact: eDiscovery and DLP may require re-enabling; requires case-by-case approval
2.2 Implement Multi-Factor Authentication (MFA) for All Administrative Roles
Manual Steps (Azure Portal - Entra ID):
Manual Steps (PowerShell):
# Check current MFA enforcement
Get-MsolCompanyInformation | Select-Object StrongAuthenticationPolicy
# Enforce MFA for all users
$MFAUsers = Get-MsolUser -All | Where-Object {$_.IsLicensed -eq $true}
foreach ($User in $MFAUsers) {
Set-MsolUser -UserPrincipalName $User.UserPrincipalName `
-StrongAuthenticationRequirements @(New-Object `
-TypeName Microsoft.Online.Administration.StrongAuthenticationRequirement)
}
2.3 Enable Conditional Access Policy to Require Compliant Devices
Manual Steps (Azure Portal):
Require Compliant Device for Key Vault Access4 hoursManual Steps (PowerShell):
# Create Conditional Access policy
$PolicyName = "Require Compliant Device for Key Vault Access"
$AppId = "00000012-0000-0000-c000-000000000000" # Azure Key Vault
# Policy creation via Microsoft Graph PowerShell
Connect-MgGraph -Scopes "Policy.ReadWrite.ConditionalAccess"
$policy = @{
displayName = $PolicyName
state = "enabled"
conditions = @{
applications = @{
includeApplications = @($AppId)
}
users = @{
includeUsers = @("All")
}
}
grantControls = @{
operator = "AND"
builtInControls = @("compliantDevice", "mfa")
}
}
New-MgIdentityConditionalAccessPolicy -BodyParameter $policy
| Compliance Framework | Control ID | Requirement | Mitigation |
|---|---|---|---|
| NIST 800-53 | SC-12 | Cryptographic Key Establishment and Management | Enable Key Vault diagnostic logging; implement RBAC; rotate keys annually |
| CIS Microsoft 365 v6.0 | 5.1 | Encryption at Rest with Strong Ciphers | Use RSA-3072 or AES-256; enable DKE for highly sensitive data |
| DISA STIG (Office 365) | SRG-APP-000014 | Cryptographic Mechanisms | Enforce BYOK with HSM protection; require MFA for key operations |
| ISO 27001:2022 | A.10.1.1 | Policy on the Use of Cryptographic Controls | Document key lifecycle; implement automated rotation |
| GDPR Article 32 | Encryption of Data | Protective Measures in Transit and at Rest | Enable encryption with customer-managed keys; maintain access logs |
| DORA (EU) | Article 17 | ICT Cryptographic Security | Implement FIPS 140-3 validation; enable HSM-based protection |
| NIS2 Directive | 4.2.1 | Technical Security Measures | Enable audit logging; implement threat detection; conduct quarterly reviews |
Assume Breach Timeline:
Containment Actions:
# Step 1: Immediately revoke compromised account
$CompromisedUser = "attacker@domain.com"
Set-AzADUser -ObjectId (Get-AzADUser -UserPrincipalName $CompromisedUser).Id -AccountEnabled $false
# Step 2: Invalidate all refresh tokens for compromised user
Revoke-AzureADUserAllRefreshToken -ObjectId (Get-AzADUser -UserPrincipalName $CompromisedUser).Id
# Step 3: Reset MFA devices for account
Set-AzureADUser -ObjectId (Get-AzADUser -UserPrincipalName $CompromisedUser).Id -StrongAuthenticationPhoneNumber ""
# Step 4: Disable all service principals with elevated Key Vault access
Get-AzADServicePrincipal | Where-Object { # Check for suspicious creation dates } |
ForEach-Object { Disable-AzADServicePrincipal -ObjectId $_.Id }
# Step 5: Revoke all active Key Vault access tokens
Get-AzKeyVault -ResourceGroupName "Prod" |
ForEach-Object { Update-AzKeyVaultNetworkRuleSet -VaultName $_.VaultName `
-DefaultAction "Deny" -Bypass "None" }