This check flags Network Security Group rules that allow inbound SMB (TCP 445) from public internet sources like 0.0.0.0/0 or Internet. SMB exposed to the world is a magnet for ransomware and credential attacks. Fix it by scoping the rule to known private ranges or removing it entirely, and front file shares with a VPN or Private Endpoint.
Port 445 has one of the worst reputations in networking, and it earned it. SMB (Server Message Block) is the protocol Windows uses for file and printer sharing, and it has been the entry point for some of the most damaging malware campaigns on record. When a Network Security Group (NSG) in Azure permits SMB traffic from the public internet, you have effectively opened a door that attackers actively and continuously scan for.
The nsg_opensmb check looks at your NSG rules and raises a finding whenever an inbound rule allows TCP port 445 from a public source. This post covers what that means, why it is dangerous, and exactly how to close the gap.
What this check detects
Lensix evaluates each NSG inbound security rule and flags it when all of the following are true:
- The rule direction is Inbound.
- The access is Allow.
- The protocol is TCP (or *, which includes TCP).
- The destination port range includes 445 (directly, as part of a range, or via
*). - The source is a public value such as
0.0.0.0/0,Internet,*, or any other CIDR that covers public address space.
Note: NSGs use source * and the service tag Internet interchangeably for "anything outside your virtual network." Both count as public exposure here, as does any broad CIDR like 0.0.0.0/0 or large public ranges.
A typical offending rule looks like this when you pull it via the CLI:
{
"name": "AllowSMB",
"direction": "Inbound",
"access": "Allow",
"protocol": "Tcp",
"sourceAddressPrefix": "*",
"sourcePortRange": "*",
"destinationAddressPrefix": "*",
"destinationPortRange": "445",
"priority": 1000
}
Why it matters
SMB was designed for trusted internal networks, not the open internet. Exposing it publicly creates several concrete risks.
Ransomware and wormable exploits
The most infamous example is WannaCry in 2017, which used the EternalBlue exploit (CVE-2017-0144) against SMBv1 to spread across hundreds of thousands of machines worldwide. NotPetya followed the same path weeks later. Both relied on reachable SMB endpoints. More recently, SMBGhost (CVE-2020-0796) targeted SMBv3 compression. New SMB vulnerabilities surface regularly, and a publicly reachable port 445 turns each one into an immediate, exploitable threat the moment it is disclosed.
Credential brute forcing and relay attacks
Even without a memory-corruption bug, an exposed SMB endpoint lets attackers attempt password spraying against Windows accounts, harvest NTLM hashes, and run relay attacks. Automated botnets scan the entire IPv4 space for open 445 within hours, so this is not a question of whether you will be probed but how soon.
Data exposure
If the exposed host has file shares, attackers who get in can read or encrypt your data directly. Azure file shares accessed over the public internet without proper controls are a common source of leaks.
Danger: Many ISPs and cloud providers block outbound 445 specifically because it is so heavily abused. If you find an Allow rule for public SMB, treat it as an active incident risk, not a low-priority cleanup item. Check NSG flow logs for unexpected inbound connections before you assume nothing has happened.
How to fix it
The goal is simple: SMB should never be reachable from the public internet. Pick the option that matches your situation.
Step 1: Find the offending rule
List inbound rules for the NSG and look for port 445 from a public source:
az network nsg rule list \
--resource-group myResourceGroup \
--nsg-name myNsg \
--query "[?direction=='Inbound' && access=='Allow'].{name:name, port:destinationPortRange, source:sourceAddressPrefix, priority:priority}" \
--output table
Step 2: Restrict the source to known private ranges
If you genuinely need SMB across networks (for example, a hybrid file share reachable from your corporate network), scope the rule to a specific trusted CIDR instead of the internet:
az network nsg rule update \
--resource-group myResourceGroup \
--nsg-name myNsg \
--name AllowSMB \
--source-address-prefixes 10.20.0.0/16 \
--destination-port-ranges 445
Warning: Updating an in-use rule can immediately drop connections from any source that no longer matches the new prefix. Confirm which clients legitimately need SMB before narrowing the range, and roll out during a maintenance window if the share is in active use.
Step 3: Or delete the rule entirely
If nothing should reach this host over SMB from outside the VNet, remove the rule. Within a single virtual network, traffic flows without an explicit Allow rule (subject to the default rules), so you usually do not need a public SMB rule at all.
Danger: Deleting an NSG rule is immediate and affects every resource associated with the NSG. Make sure no production workload depends on this rule before running the command below.
az network nsg rule delete \
--resource-group myResourceGroup \
--nsg-name myNsg \
--name AllowSMB
Step 4: Use the right access pattern instead
If users or apps need file share access from outside the VNet, route it through a secure channel rather than the open internet:
- Azure VPN Gateway or ExpressRoute for site-to-site or point-to-site access, so SMB only travels over a private tunnel.
- Private Endpoints for Azure Files, which give the storage account a private IP inside your VNet and keep traffic off the public internet entirely.
- Azure Bastion for administrative access to VMs, removing the need to expose management or file ports.
For Azure Files specifically, disable public network access on the storage account and add a private endpoint:
# Lock the storage account to private access only
az storage account update \
--resource-group myResourceGroup \
--name mystorageacct \
--public-network-access Disabled
# Create a private endpoint for the file service
az network private-endpoint create \
--resource-group myResourceGroup \
--name files-pe \
--vnet-name myVnet \
--subnet myPrivateSubnet \
--private-connection-resource-id $(az storage account show -g myResourceGroup -n mystorageacct --query id -o tsv) \
--group-id file \
--connection-name files-connection
How to prevent it from happening again
Manual cleanup fixes today's problem. To stop the rule from reappearing, push the control left into your provisioning pipeline and your policy layer.
Azure Policy to deny public SMB
Azure Policy can block the creation of NSG rules that expose 445. Here is a policy definition that denies inbound Allow rules for port 445 from internet sources:
{
"policyRule": {
"if": {
"allOf": [
{ "field": "type", "equals": "Microsoft.Network/networkSecurityGroups/securityRules" },
{ "field": "Microsoft.Network/networkSecurityGroups/securityRules/direction", "equals": "Inbound" },
{ "field": "Microsoft.Network/networkSecurityGroups/securityRules/access", "equals": "Allow" },
{ "field": "Microsoft.Network/networkSecurityGroups/securityRules/destinationPortRange", "equals": "445" },
{
"field": "Microsoft.Network/networkSecurityGroups/securityRules/sourceAddressPrefix",
"in": [ "*", "0.0.0.0/0", "Internet" ]
}
]
},
"then": { "effect": "deny" }
}
}
Assign it at the subscription or management group level so it covers everything, including resources created outside your IaC.
Note: The example above matches a single port value. Real rules sometimes express 445 as part of a range like 440-450 or as *. Add destinationPortRanges array checks and range logic, or use the built-in initiative for network hardening, to catch those variants.
Catch it in CI/CD with IaC scanning
If you provision NSGs with Terraform or Bicep, scan the plan before it applies. Tools like Checkov, tfsec, and Trivy flag SMB exposure out of the box. A minimal GitHub Actions step:
- name: Scan IaC for public SMB exposure
run: |
pip install checkov
checkov -d ./infra --framework terraform \
--check CKV_AZURE_10 # restrict SMB access from the internet
Tip: Write your Terraform so that NSG sources come from a variable that defaults to your private CIDR, never 0.0.0.0/0. Make a wide-open source require an explicit, reviewed override. That way the safe path is also the easy path, and exceptions show up clearly in pull requests.
Define safe rules in Terraform
resource "azurerm_network_security_rule" "smb_internal" {
name = "AllowSMBInternal"
priority = 1000
direction = "Inbound"
access = "Allow"
protocol = "Tcp"
source_port_range = "*"
destination_port_range = "445"
source_address_prefix = "10.20.0.0/16"
destination_address_prefix = "*"
resource_group_name = azurerm_resource_group.main.name
network_security_group_name = azurerm_network_security_group.main.name
}
Best practices
- Never expose SMB to the internet. There is no legitimate scenario where port 445 should accept connections from
0.0.0.0/0. Treat any such rule as a finding to remediate, not a configuration to tune. - Disable SMBv1 everywhere. Even on internal networks, SMBv1 is obsolete and carries the EternalBlue exposure. Enforce SMBv3 with encryption.
- Default to deny. Build NSGs that explicitly allow only what is needed and rely on the implicit deny for everything else. Avoid broad rules that allow ranges spanning sensitive ports.
- Enable NSG flow logs. Send them to a Log Analytics workspace so you have visibility into what is actually hitting your SMB ports and can detect scanning or brute-force attempts.
- Use Private Endpoints for Azure Files. Keep file share traffic on the Microsoft backbone instead of the public internet.
- Audit continuously. One-time cleanup decays. Continuous checks like Lensix nsg_opensmb catch drift the moment a well-meaning engineer opens a port to debug a problem and forgets to close it.
Public SMB exposure is one of the highest-signal findings you can get, because the fix is unambiguous and the risk is severe. Close the port, route legitimate access through a private channel, and gate the change in policy so it stays closed.

