Skip to content

Commit 268e813

Browse files
andoniafclaude
andcommitted
feat(m365): add defender_atp_safe_attachments_policy_enabled security check
Add new security check defender_atp_safe_attachments_policy_enabled for m365 provider. Includes check implementation, metadata, and unit tests. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
1 parent f39a82f commit 268e813

File tree

7 files changed

+497
-0
lines changed

7 files changed

+497
-0
lines changed

prowler/CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ All notable changes to the **Prowler SDK** are documented in this file.
2424
- CIS 6.0 for M365 provider [(#9779)](https://github.com/prowler-cloud/prowler/pull/9779)
2525
- CIS 5.0 compliance framework for the Azure provider [(#9777)](https://github.com/prowler-cloud/prowler/pull/9777)
2626
- `Cloudflare` Bot protection, WAF, Privacy, Anti-Scraping and Zone configuration checks [(#9425)](https://github.com/prowler-cloud/prowler/pull/9425)
27+
- `defender_atp_safe_attachments_policy_enabled` check for m365 provider [(#9837)](https://github.com/prowler-cloud/prowler/pull/9837)
2728

2829
### Changed
2930
- Update AWS Step Functions service metadata to new format [(#9432)](https://github.com/prowler-cloud/prowler/pull/9432)

prowler/providers/m365/lib/powershell/m365_powershell.py

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -823,6 +823,29 @@ def get_sharing_policy(self) -> dict:
823823
"Get-SharingPolicy | ConvertTo-Json -Depth 10", json_parse=True
824824
)
825825

826+
def get_atp_policy_for_o365(self) -> dict:
827+
"""
828+
Get ATP Policy for Office 365.
829+
830+
Retrieves the current ATP (Advanced Threat Protection) policy settings for Office 365,
831+
including Safe Attachments for SharePoint, OneDrive, and Teams, and Safe Documents settings.
832+
833+
Returns:
834+
dict: ATP policy settings in JSON format.
835+
836+
Example:
837+
>>> get_atp_policy_for_o365()
838+
{
839+
"Identity": "Default",
840+
"EnableATPForSPOTeamsODB": true,
841+
"EnableSafeDocs": true,
842+
"AllowSafeDocsOpen": false
843+
}
844+
"""
845+
return self.execute(
846+
"Get-AtpPolicyForO365 | ConvertTo-Json -Depth 10", json_parse=True
847+
)
848+
826849
def get_user_account_status(self) -> dict:
827850
"""
828851
Get User Account Status.

prowler/providers/m365/services/defender/defender_atp_safe_attachments_policy_enabled/__init__.py

Whitespace-only changes.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
{
2+
"Provider": "m365",
3+
"CheckID": "defender_atp_safe_attachments_policy_enabled",
4+
"CheckTitle": "ATP Safe Attachments policy has Safe Documents enabled and click-through blocked for SharePoint, OneDrive, and Microsoft Teams",
5+
"CheckType": [],
6+
"ServiceName": "defender",
7+
"SubServiceName": "",
8+
"ResourceIdTemplate": "",
9+
"Severity": "medium",
10+
"ResourceType": "Defender ATP Policy",
11+
"ResourceGroup": "security",
12+
"Description": "Safe Attachments for SharePoint, OneDrive, and Microsoft Teams protects organizations from inadvertently sharing malicious files. When enabled, files identified as malicious are blocked and cannot be opened, copied, moved, or shared until further actions are taken by the organization's security team.",
13+
"Risk": "Without Safe Attachments enabled, users may download, sync, or access malicious files from SharePoint, OneDrive, or Teams, potentially leading to malware infections across the organization. If Safe Documents is disabled or users can bypass Protected View, malicious content in Office documents may execute and compromise endpoints.",
14+
"RelatedUrl": "",
15+
"AdditionalURLs": [
16+
"https://learn.microsoft.com/en-us/defender-office-365/safe-attachments-about",
17+
"https://learn.microsoft.com/en-us/defender-office-365/safe-documents-in-e5-plus-security-about"
18+
],
19+
"Remediation": {
20+
"Code": {
21+
"CLI": "Set-AtpPolicyForO365 -EnableATPForSPOTeamsODB $true -EnableSafeDocs $true -AllowSafeDocsOpen $false",
22+
"NativeIaC": "",
23+
"Other": "1. Navigate to Microsoft 365 Defender portal at https://security.microsoft.com.\n2. Go to Email & Collaboration > Policies & Rules > Threat policies.\n3. Under Policies, select Safe Attachments.\n4. Click on Global settings.\n5. Enable Turn on Defender for Office 365 for SharePoint, OneDrive, and Microsoft Teams.\n6. Enable Turn on Safe Documents for Office clients.\n7. Disable Allow people to click through Protected View even if Safe Documents identified the file as malicious.\n8. Click Save.",
24+
"Terraform": ""
25+
},
26+
"Recommendation": {
27+
"Text": "Enable Safe Attachments for SharePoint, OneDrive, and Microsoft Teams along with Safe Documents to protect users from malicious files. Block users from bypassing Protected View warnings for files identified as malicious to maintain defense-in-depth.",
28+
"Url": "https://hub.prowler.com/check/defender_atp_safe_attachments_policy_enabled"
29+
}
30+
},
31+
"Categories": [
32+
"e5"
33+
],
34+
"DependsOn": [],
35+
"RelatedTo": [],
36+
"Notes": "This check requires Microsoft Defender for Office 365 Plan 1 or Plan 2 (included in E5 license). Safe Documents specifically requires Microsoft 365 E5 or Microsoft 365 E5 Security."
37+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
from typing import List
2+
3+
from prowler.lib.check.models import Check, CheckReportM365
4+
from prowler.providers.m365.services.defender.defender_client import defender_client
5+
6+
7+
class defender_atp_safe_attachments_policy_enabled(Check):
8+
"""
9+
Check if Safe Attachments for SharePoint, OneDrive, and Teams is properly configured.
10+
11+
This check verifies that the ATP (Advanced Threat Protection) policy for Office 365 has:
12+
- EnableATPForSPOTeamsODB = True (Safe Attachments enabled for SPO/OneDrive/Teams)
13+
- EnableSafeDocs = True (Safe Documents enabled)
14+
- AllowSafeDocsOpen = False (Users cannot bypass Protected View for malicious files)
15+
16+
- PASS: All three settings are properly configured.
17+
- FAIL: One or more settings are not properly configured.
18+
"""
19+
20+
def execute(self) -> List[CheckReportM365]:
21+
"""
22+
Execute the check to verify Safe Attachments ATP policy configuration.
23+
24+
Returns:
25+
List[CheckReportM365]: A list of reports containing the result of the check.
26+
"""
27+
findings = []
28+
29+
if defender_client.atp_policy_for_o365:
30+
policy = defender_client.atp_policy_for_o365
31+
32+
report = CheckReportM365(
33+
metadata=self.metadata(),
34+
resource=policy,
35+
resource_name=policy.identity,
36+
resource_id=policy.identity,
37+
)
38+
39+
# Check all three required settings
40+
is_atp_enabled = policy.enable_atp_for_spo_teams_odb
41+
is_safe_docs_enabled = policy.enable_safe_docs
42+
is_safe_docs_open_blocked = not policy.allow_safe_docs_open
43+
44+
if is_atp_enabled and is_safe_docs_enabled and is_safe_docs_open_blocked:
45+
report.status = "PASS"
46+
report.status_extended = f"ATP policy {policy.identity} has Safe Attachments for SharePoint, OneDrive, and Teams properly configured with Safe Documents enabled and click-through blocked."
47+
else:
48+
report.status = "FAIL"
49+
issues = []
50+
if not is_atp_enabled:
51+
issues.append("Safe Attachments for SPO/OneDrive/Teams is disabled")
52+
if not is_safe_docs_enabled:
53+
issues.append("Safe Documents is disabled")
54+
if not is_safe_docs_open_blocked:
55+
issues.append("users can bypass Protected View for malicious files")
56+
report.status_extended = f"ATP policy {policy.identity} is not properly configured: {'; '.join(issues)}."
57+
58+
findings.append(report)
59+
60+
return findings

prowler/providers/m365/services/defender/defender_service.py

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,34 @@
88

99

1010
class Defender(M365Service):
11+
"""
12+
Microsoft 365 Defender service class.
13+
14+
This class provides methods to retrieve and manage Microsoft Defender for Office 365
15+
security policies and configurations, including malware filters, spam policies,
16+
anti-phishing settings, and ATP (Advanced Threat Protection) policies.
17+
18+
Attributes:
19+
malware_policies (list): List of malware filter policies.
20+
outbound_spam_policies (dict): Dictionary of outbound spam filter policies.
21+
outbound_spam_rules (dict): Dictionary of outbound spam filter rules.
22+
antiphishing_policies (dict): Dictionary of anti-phishing policies.
23+
antiphishing_rules (dict): Dictionary of anti-phishing rules.
24+
connection_filter_policy: Connection filter policy configuration.
25+
dkim_configurations (list): List of DKIM signing configurations.
26+
inbound_spam_policies (list): List of inbound spam filter policies.
27+
inbound_spam_rules (dict): Dictionary of inbound spam filter rules.
28+
report_submission_policy: Report submission policy configuration.
29+
atp_policy_for_o365: ATP policy for Office 365 configuration.
30+
"""
31+
1132
def __init__(self, provider: M365Provider):
33+
"""
34+
Initialize the Defender service.
35+
36+
Args:
37+
provider (M365Provider): The Microsoft 365 provider instance.
38+
"""
1239
super().__init__(provider)
1340
self.malware_policies = []
1441
self.outbound_spam_policies = {}
@@ -20,6 +47,7 @@ def __init__(self, provider: M365Provider):
2047
self.inbound_spam_policies = []
2148
self.inbound_spam_rules = {}
2249
self.report_submission_policy = None
50+
self.atp_policy_for_o365 = None
2351
if self.powershell:
2452
if self.powershell.connect_exchange_online():
2553
self.malware_policies = self._get_malware_filter_policy()
@@ -33,6 +61,7 @@ def __init__(self, provider: M365Provider):
3361
self.inbound_spam_policies = self._get_inbound_spam_filter_policy()
3462
self.inbound_spam_rules = self._get_inbound_spam_filter_rule()
3563
self.report_submission_policy = self._get_report_submission_policy()
64+
self.atp_policy_for_o365 = self._get_atp_policy_for_o365()
3665
self.powershell.close()
3766

3867
def _get_malware_filter_policy(self):
@@ -350,6 +379,12 @@ def _get_inbound_spam_filter_rule(self):
350379
return inbound_spam_rules
351380

352381
def _get_report_submission_policy(self):
382+
"""
383+
Get the Defender report submission policy.
384+
385+
Returns:
386+
ReportSubmissionPolicy: The report submission policy configuration.
387+
"""
353388
logger.info("Microsoft365 - Getting Defender report submission policy...")
354389
report_submission_policy = None
355390
try:
@@ -387,6 +422,35 @@ def _get_report_submission_policy(self):
387422
)
388423
return report_submission_policy
389424

425+
def _get_atp_policy_for_o365(self):
426+
"""
427+
Get the ATP (Advanced Threat Protection) policy for Office 365.
428+
429+
Retrieves the ATP policy settings including Safe Attachments for SharePoint,
430+
OneDrive, and Teams, as well as Safe Documents configuration.
431+
432+
Returns:
433+
AtpPolicyForO365: The ATP policy configuration for Office 365.
434+
"""
435+
logger.info("Microsoft365 - Getting ATP policy for Office 365...")
436+
atp_policy = None
437+
try:
438+
policy = self.powershell.get_atp_policy_for_o365()
439+
if policy:
440+
atp_policy = AtpPolicyForO365(
441+
identity=policy.get("Identity", "Default"),
442+
enable_atp_for_spo_teams_odb=policy.get(
443+
"EnableATPForSPOTeamsODB", False
444+
),
445+
enable_safe_docs=policy.get("EnableSafeDocs", False),
446+
allow_safe_docs_open=policy.get("AllowSafeDocsOpen", True),
447+
)
448+
except Exception as error:
449+
logger.error(
450+
f"{error.__class__.__name__}[{error.__traceback__.tb_lineno}]: {error}"
451+
)
452+
return atp_policy
453+
390454

391455
class MalwarePolicy(BaseModel):
392456
enable_file_filter: bool
@@ -470,6 +534,8 @@ class InboundSpamRule(BaseModel):
470534

471535

472536
class ReportSubmissionPolicy(BaseModel):
537+
"""Model for Defender report submission policy configuration."""
538+
473539
report_junk_to_customized_address: bool
474540
report_not_junk_to_customized_address: bool
475541
report_phish_to_customized_address: bool
@@ -478,3 +544,22 @@ class ReportSubmissionPolicy(BaseModel):
478544
report_phish_addresses: list[str]
479545
report_chat_message_enabled: bool
480546
report_chat_message_to_customized_address_enabled: bool
547+
548+
549+
class AtpPolicyForO365(BaseModel):
550+
"""
551+
Model for ATP (Advanced Threat Protection) policy for Office 365.
552+
553+
Attributes:
554+
identity: The identity of the ATP policy.
555+
enable_atp_for_spo_teams_odb: Whether Safe Attachments is enabled for
556+
SharePoint, OneDrive, and Microsoft Teams.
557+
enable_safe_docs: Whether Safe Documents is enabled for clients in Protected View.
558+
allow_safe_docs_open: Whether users can click through Protected View
559+
even if Safe Documents identifies the file as malicious.
560+
"""
561+
562+
identity: str
563+
enable_atp_for_spo_teams_odb: bool
564+
enable_safe_docs: bool
565+
allow_safe_docs_open: bool

0 commit comments

Comments
 (0)