fix(azure): require all SMB channel encryption algorithms to be secure (storage_smb_channel_encryption_with_secure_algorithm) (#11327)

Co-authored-by: Daniel Barranquero <danielbo2001@gmail.com>
This commit is contained in:
Hugo Pereira BritoandDaniel Barranquero authored and GitHub committed 2026-05-25 18:28:21 +02:00
1 parent 6ca8e726f7
commit 4c59af93eb
7 files changed
+184 -20

No files matched your search

@@ -91,6 +91,7 @@ The following list includes all the Azure checks with configurable variables tha
| `sqlserver_recommended_minimal_tls_version` | `recommended_minimal_tls_versions` | List of Strings |
| `vm_sufficient_daily_backup_retention_period` | `vm_backup_min_daily_retention_days` | Integer |
| `vm_desired_sku_size` | `desired_vm_sku_sizes` | List of Strings |
| `storage_smb_channel_encryption_with_secure_algorithm` | `recommended_smb_channel_encryption_algorithms` | List of Strings |
| `defender_attack_path_notifications_properly_configured` | `defender_attack_path_minimal_risk_level` | String |
| `apim_threat_detection_llm_jacking` | `apim_threat_detection_llm_jacking_threshold` | Float |
| `apim_threat_detection_llm_jacking` | `apim_threat_detection_llm_jacking_minutes` | Integer |
@@ -534,6 +535,18 @@ azure:
"1.3"
]
# Azure Storage
# azure.storage_smb_channel_encryption_with_secure_algorithm
# List of SMB channel encryption algorithms allowed on file shares. A storage
# account passes only if every enabled algorithm is in this list. Defaults to
# the value required by CIS (AES-256-GCM only, excluding weaker AES-128 ciphers).
recommended_smb_channel_encryption_algorithms:
[
"AES-256-GCM",
# "AES-128-CCM",
# "AES-128-GCM",
]
# Azure Virtual Machines
# azure.vm_desired_sku_size
# List of desired VM SKU sizes that are allowed in the organization
+8
View File
@@ -10,6 +10,14 @@ All notable changes to the **Prowler SDK** are documented in this file.
---
## [5.28.1] (Prowler v5.28.1)
### 🐞 Fixed
- `storage_smb_channel_encryption_with_secure_algorithm` check for Azure provider no longer passes when a storage account allows a weak SMB channel encryption algorithm (e.g. `AES-128-CCM`/`AES-128-GCM`) alongside `AES-256-GCM`; it now requires every enabled algorithm to be in the recommended list, configurable via `azure.recommended_smb_channel_encryption_algorithms` (defaults to `AES-256-GCM` only, as required by CIS) [(#11327)](https://github.com/prowler-cloud/prowler/pull/11327)
---
## [5.28.0] (Prowler v5.28.0)
### 🚀 Added
+12
View File
@@ -467,6 +467,18 @@ azure:
"1.3",
]
# Azure Storage
# azure.storage_smb_channel_encryption_with_secure_algorithm
# List of SMB channel encryption algorithms allowed on file shares. A storage
# account passes only if every enabled algorithm is in this list. Defaults to
# the value required by CIS (AES-256-GCM only, excluding weaker AES-128 ciphers).
recommended_smb_channel_encryption_algorithms:
[
"AES-256-GCM",
# "AES-128-CCM",
# "AES-128-GCM",
]
# Azure Virtual Machines
# azure.vm_desired_sku_size
# List of desired VM SKU sizes that are allowed in the organization
@@ -34,5 +34,5 @@
],
"DependsOn": [],
"RelatedTo": [],
"Notes": "This check passes if SMB channel encryption is set to a secure algorithm."
"Notes": "This check passes only if every SMB channel encryption algorithm allowed on the file shares is in the recommended list, which is configurable via azure.recommended_smb_channel_encryption_algorithms and defaults to AES-256-GCM only, as required by CIS."
}
@@ -1,32 +1,38 @@
from prowler.lib.check.models import Check, Check_Report_Azure
from prowler.providers.azure.services.storage.storage_client import storage_client
SECURE_ENCRYPTION_ALGORITHMS = ["AES-256-GCM"]
DEFAULT_SECURE_ENCRYPTION_ALGORITHMS = ["AES-256-GCM"]
class storage_smb_channel_encryption_with_secure_algorithm(Check):
"""
Ensure SMB channel encryption for file shares is set to the recommended algorithm (AES-256-GCM or higher).
Ensure SMB channel encryption for file shares only allows secure algorithms (AES-256-GCM or higher by default).
The list of allowed algorithms is configurable via
azure.recommended_smb_channel_encryption_algorithms in the Prowler configuration file.
This check evaluates whether SMB file shares are configured to use only the recommended SMB channel encryption algorithms.
- PASS: Storage account has the recommended SMB channel encryption (AES-256-GCM or higher) enabled for file shares.
- FAIL: Storage account does not have the recommended SMB channel encryption enabled for file shares or uses an unsupported algorithm.
- PASS: Storage account only allows secure SMB channel encryption algorithms for file shares.
- FAIL: Storage account does not have SMB channel encryption enabled, or it allows at least one algorithm that is not in the recommended list.
"""
def execute(self) -> list[Check_Report_Azure]:
findings = []
secure_encryption_algorithms = storage_client.audit_config.get(
"recommended_smb_channel_encryption_algorithms",
DEFAULT_SECURE_ENCRYPTION_ALGORITHMS,
)
for subscription, storage_accounts in storage_client.storage_accounts.items():
subscription_name = storage_client.subscriptions.get(
subscription, subscription
)
for account in storage_accounts:
if account.file_service_properties:
channel_encryption = (
account.file_service_properties.smb_protocol_settings.channel_encryption
)
pretty_current_algorithms = (
", ".join(
account.file_service_properties.smb_protocol_settings.channel_encryption
)
if account.file_service_properties.smb_protocol_settings.channel_encryption
else "none"
", ".join(channel_encryption) if channel_encryption else "none"
)
report = Check_Report_Azure(
metadata=self.metadata(),
@@ -35,20 +41,18 @@ class storage_smb_channel_encryption_with_secure_algorithm(Check):
report.subscription = subscription
report.resource_name = account.name
if (
not account.file_service_properties.smb_protocol_settings.channel_encryption
):
if not channel_encryption:
report.status = "FAIL"
report.status_extended = f"Storage account {account.name} from subscription {subscription_name} ({subscription}) does not have SMB channel encryption enabled for file shares."
elif any(
algorithm in SECURE_ENCRYPTION_ALGORITHMS
for algorithm in account.file_service_properties.smb_protocol_settings.channel_encryption
elif all(
algorithm in secure_encryption_algorithms
for algorithm in channel_encryption
):
report.status = "PASS"
report.status_extended = f"Storage account {account.name} from subscription {subscription_name} ({subscription}) has a secure algorithm for SMB channel encryption ({', '.join(SECURE_ENCRYPTION_ALGORITHMS)}) enabled for file shares since it supports {pretty_current_algorithms}."
report.status_extended = f"Storage account {account.name} from subscription {subscription_name} ({subscription}) only allows secure algorithms for SMB channel encryption on file shares since it supports {pretty_current_algorithms}."
else:
report.status = "FAIL"
report.status_extended = f"Storage account {account.name} from subscription {subscription_name} ({subscription}) does not have SMB channel encryption with a secure algorithm for file shares since it supports {pretty_current_algorithms}."
report.status_extended = f"Storage account {account.name} from subscription {subscription_name} ({subscription}) allows insecure algorithms for SMB channel encryption on file shares since it supports {pretty_current_algorithms} and only {', '.join(secure_encryption_algorithms)} is recommended."
findings.append(report)
return findings
@@ -86,6 +86,7 @@ class TestAzureProvider:
"python_latest_version": "3.12",
"java_latest_version": "17",
"recommended_minimal_tls_versions": ["1.2", "1.3"],
"recommended_smb_channel_encryption_algorithms": ["AES-256-GCM"],
"vm_backup_min_daily_retention_days": 7,
"desired_vm_sku_sizes": [
"Standard_A8_v2",
@@ -20,6 +20,7 @@ class Test_storage_smb_channel_encryption_with_secure_algorithm:
def test_no_storage_accounts(self):
storage_client = mock.MagicMock()
storage_client.subscriptions = {AZURE_SUBSCRIPTION_ID: AZURE_SUBSCRIPTION_NAME}
storage_client.audit_config = {}
storage_client.storage_accounts = {}
with (
mock.patch(
@@ -44,6 +45,7 @@ class Test_storage_smb_channel_encryption_with_secure_algorithm:
storage_account_name = "Test Storage Account"
storage_client = mock.MagicMock()
storage_client.subscriptions = {AZURE_SUBSCRIPTION_ID: AZURE_SUBSCRIPTION_NAME}
storage_client.audit_config = {}
storage_client.storage_accounts = {
AZURE_SUBSCRIPTION_ID: [
Account(
@@ -97,6 +99,7 @@ class Test_storage_smb_channel_encryption_with_secure_algorithm:
)
storage_client = mock.MagicMock()
storage_client.subscriptions = {AZURE_SUBSCRIPTION_ID: AZURE_SUBSCRIPTION_NAME}
storage_client.audit_config = {}
storage_client.storage_accounts = {
AZURE_SUBSCRIPTION_ID: [
Account(
@@ -154,6 +157,7 @@ class Test_storage_smb_channel_encryption_with_secure_algorithm:
)
storage_client = mock.MagicMock()
storage_client.subscriptions = {AZURE_SUBSCRIPTION_ID: AZURE_SUBSCRIPTION_NAME}
storage_client.audit_config = {}
storage_client.storage_accounts = {
AZURE_SUBSCRIPTION_ID: [
Account(
@@ -194,7 +198,7 @@ class Test_storage_smb_channel_encryption_with_secure_algorithm:
assert len(result) == 1
assert result[0].status == "FAIL"
assert result[0].status_extended == (
f"Storage account {storage_account_name} from subscription {AZURE_SUBSCRIPTION_DISPLAY} does not have SMB channel encryption with a secure algorithm for file shares since it supports AES-128-GCM."
f"Storage account {storage_account_name} from subscription {AZURE_SUBSCRIPTION_DISPLAY} allows insecure algorithms for SMB channel encryption on file shares since it supports AES-128-GCM and only AES-256-GCM is recommended."
)
def test_recommended_encryption(self):
@@ -211,6 +215,7 @@ class Test_storage_smb_channel_encryption_with_secure_algorithm:
)
storage_client = mock.MagicMock()
storage_client.subscriptions = {AZURE_SUBSCRIPTION_ID: AZURE_SUBSCRIPTION_NAME}
storage_client.audit_config = {}
storage_client.storage_accounts = {
AZURE_SUBSCRIPTION_ID: [
Account(
@@ -251,5 +256,126 @@ class Test_storage_smb_channel_encryption_with_secure_algorithm:
assert len(result) == 1
assert result[0].status == "PASS"
assert result[0].status_extended == (
f"Storage account {storage_account_name} from subscription {AZURE_SUBSCRIPTION_DISPLAY} has a secure algorithm for SMB channel encryption (AES-256-GCM) enabled for file shares since it supports AES-256-GCM."
f"Storage account {storage_account_name} from subscription {AZURE_SUBSCRIPTION_DISPLAY} only allows secure algorithms for SMB channel encryption on file shares since it supports AES-256-GCM."
)
def test_recommended_algorithm_mixed_with_weak_algorithm(self):
storage_account_id = str(uuid4())
storage_account_name = "Test Storage Account"
file_service_properties = FileServiceProperties(
id="id1",
name="fs1",
type="type1",
share_delete_retention_policy=DeleteRetentionPolicy(enabled=True, days=7),
smb_protocol_settings=SMBProtocolSettings(
channel_encryption=["AES-128-CCM", "AES-256-GCM"], supported_versions=[]
),
)
storage_client = mock.MagicMock()
storage_client.subscriptions = {AZURE_SUBSCRIPTION_ID: AZURE_SUBSCRIPTION_NAME}
storage_client.audit_config = {}
storage_client.storage_accounts = {
AZURE_SUBSCRIPTION_ID: [
Account(
id=storage_account_id,
name=storage_account_name,
resouce_group_name="rg",
enable_https_traffic_only=False,
infrastructure_encryption=False,
allow_blob_public_access=False,
network_rule_set=NetworkRuleSet(
bypass="AzureServices", default_action="Allow"
),
encryption_type="None",
minimum_tls_version="TLS1_2",
key_expiration_period_in_days=None,
location="westeurope",
private_endpoint_connections=[],
file_service_properties=file_service_properties,
)
]
}
with (
mock.patch(
"prowler.providers.common.provider.Provider.get_global_provider",
return_value=set_mocked_azure_provider(),
),
mock.patch(
"prowler.providers.azure.services.storage.storage_smb_channel_encryption_with_secure_algorithm.storage_smb_channel_encryption_with_secure_algorithm.storage_client",
new=storage_client,
),
):
from prowler.providers.azure.services.storage.storage_smb_channel_encryption_with_secure_algorithm.storage_smb_channel_encryption_with_secure_algorithm import (
storage_smb_channel_encryption_with_secure_algorithm,
)
check = storage_smb_channel_encryption_with_secure_algorithm()
result = check.execute()
assert len(result) == 1
assert result[0].status == "FAIL"
assert result[0].status_extended == (
f"Storage account {storage_account_name} from subscription {AZURE_SUBSCRIPTION_DISPLAY} allows insecure algorithms for SMB channel encryption on file shares since it supports AES-128-CCM, AES-256-GCM and only AES-256-GCM is recommended."
)
def test_custom_recommended_algorithms_from_config(self):
storage_account_id = str(uuid4())
storage_account_name = "Test Storage Account"
file_service_properties = FileServiceProperties(
id="id1",
name="fs1",
type="type1",
share_delete_retention_policy=DeleteRetentionPolicy(enabled=True, days=7),
smb_protocol_settings=SMBProtocolSettings(
channel_encryption=["AES-128-GCM", "AES-256-GCM"], supported_versions=[]
),
)
storage_client = mock.MagicMock()
storage_client.subscriptions = {AZURE_SUBSCRIPTION_ID: AZURE_SUBSCRIPTION_NAME}
storage_client.audit_config = {
"recommended_smb_channel_encryption_algorithms": [
"AES-128-GCM",
"AES-256-GCM",
]
}
storage_client.storage_accounts = {
AZURE_SUBSCRIPTION_ID: [
Account(
id=storage_account_id,
name=storage_account_name,
resouce_group_name="rg",
enable_https_traffic_only=False,
infrastructure_encryption=False,
allow_blob_public_access=False,
network_rule_set=NetworkRuleSet(
bypass="AzureServices", default_action="Allow"
),
encryption_type="None",
minimum_tls_version="TLS1_2",
key_expiration_period_in_days=None,
location="westeurope",
private_endpoint_connections=[],
file_service_properties=file_service_properties,
)
]
}
with (
mock.patch(
"prowler.providers.common.provider.Provider.get_global_provider",
return_value=set_mocked_azure_provider(),
),
mock.patch(
"prowler.providers.azure.services.storage.storage_smb_channel_encryption_with_secure_algorithm.storage_smb_channel_encryption_with_secure_algorithm.storage_client",
new=storage_client,
),
):
from prowler.providers.azure.services.storage.storage_smb_channel_encryption_with_secure_algorithm.storage_smb_channel_encryption_with_secure_algorithm import (
storage_smb_channel_encryption_with_secure_algorithm,
)
check = storage_smb_channel_encryption_with_secure_algorithm()
result = check.execute()
assert len(result) == 1
assert result[0].status == "PASS"
assert result[0].status_extended == (
f"Storage account {storage_account_name} from subscription {AZURE_SUBSCRIPTION_DISPLAY} only allows secure algorithms for SMB channel encryption on file shares since it supports AES-128-GCM, AES-256-GCM."
)