Automatically block open RDP/SSH in Azure

3 minutes, 4 seconds Read

I’ve been working with Microsoft Azure recently and looking for ways to implement some basic security hygiene and automate controls.

Most ransomware cases today are caused by some common threat vectors; phishing, vulnerable web apps and brute force attempts against RDP/SSH on ports 3389 and 22.

We can use Azure policy to enforce rules on Azure resources.

Azure Policy

Azure Policy is a service in Azure that you can use to create, assign, and manage policies. Policies are rules and guidelines that you can set for your resources to ensure that they meet certain requirements.

For example, we can set a rule that says any resource that is created must have a tag called owner.

Blocking open RDP/SSH with Azure Policy

Navigate to the Azure Policy console and select Definitions.

Click the + icon

Enter your defined location (ideally at the root level), a name, description and category. For the policy rule, copy in the JSON below.

Note: This will deny any network security rule from being created that allows management port access from the Internet – including port 3389 (RDP) and 22 (SSH). You can expand the ports you’re concerned about under the Ports section and the IPs within the Microsoft.Network/networkSecurityGroups/securityRules/destinationPortRange.

For example, you could create the rule to only allow these ports to be open from a specific IP.

{
    "name": "Deny-MgmtPorts-From-Internet",
    "type": "Microsoft.Authorization/policyDefinitions",
    "apiVersion": "2021-06-01",
    "scope": null,
    "properties": {
        "policyType": "Custom",
        "mode": "All",
        "displayName": "Management port access from the Internet should be blocked",
        "description": "This policy denies any network security rule that allows management port access from the Internet",
        "metadata": {
            "version": "2.0.0",
            "category": "Network",
            "source": "https://github.com/Azure/Enterprise-Scale/",
            "alzCloudEnvironments": [
                "AzureCloud",
                "AzureChinaCloud",
                "AzureUSGovernment"
            ]
        },
        "parameters": {
            "effect": {
                "type": "String",
                "metadata": {
                    "displayName": "Effect",
                    "description": "Enable or disable the execution of the policy"
                },
                "allowedValues": [
                    "Audit",
                    "Deny",
                    "Disabled"
                ],
                "defaultValue": "Deny"
            },
            "ports": {
                "type": "Array",
                "metadata": {
                    "displayName": "Ports",
                    "description": "Ports to be blocked"
                },
                "defaultValue": [
                    "22",
                    "3389"
                ]
            }
        },
        "policyRule": {
            "if": {
                "allOf": [
                    {
                        "field": "type",
                        "equals": "Microsoft.Network/networkSecurityGroups/securityRules"
                    },
                    {
                        "allOf": [
                            {
                                "field": "Microsoft.Network/networkSecurityGroups/securityRules/access",
                                "equals": "Allow"
                            },
                            {
                                "field": "Microsoft.Network/networkSecurityGroups/securityRules/direction",
                                "equals": "Inbound"
                            },
                            {
                                "anyOf": [
                                    {
                                        "field": "Microsoft.Network/networkSecurityGroups/securityRules/destinationPortRange",
                                        "equals": "*"
                                    },
                                    {
                                        "field": "Microsoft.Network/networkSecurityGroups/securityRules/destinationPortRange",
                                        "in": "[[parameters('ports')]"
                                    },
                                    {
                                        "count": {
                                            "value": "[[parameters('ports')]",
                                            "where": {
                                                "value": "[[if(and(not(empty(field('Microsoft.Network/networkSecurityGroups/securityRules/destinationPortRange'))), contains(field('Microsoft.Network/networkSecurityGroups/securityRules/destinationPortRange'),'-')), and(lessOrEquals(int(first(split(field('Microsoft.Network/networkSecurityGroups/securityRules/destinationPortRange'), '-'))),int(current())),greaterOrEquals(int(last(split(field('Microsoft.Network/networkSecurityGroups/securityRules/destinationPortRange'), '-'))),int(current()))), 'false')]",
                                                "equals": "true"
                                            }
                                        },
                                        "greater": 0
                                    },
                                    {
                                        "count": {
                                            "value": "[[parameters('ports')]",
                                            "name": "ports",
                                            "where": {
                                                "count": {
                                                    "field": "Microsoft.Network/networkSecurityGroups/securityRules/destinationPortRanges[*]",
                                                    "where": {
                                                        "value": "[[if(and(not(empty(first(field('Microsoft.Network/networkSecurityGroups/securityRules/destinationPortRanges[*]')))), contains(first(field('Microsoft.Network/networkSecurityGroups/securityRules/destinationPortRanges[*]')),'-')), and(lessOrEquals(int(first(split(first(field('Microsoft.Network/networkSecurityGroups/securityRules/destinationPortRanges[*]')), '-'))),int(current('ports'))),greaterOrEquals(int(last(split(first(field('Microsoft.Network/networkSecurityGroups/securityRules/destinationPortRanges[*]')), '-'))),int(current('ports')))) , 'false')]",
                                                        "equals": "true"
                                                    }
                                                },
                                                "greater": 0
                                            }
                                        },
                                        "greater": 0
                                    },
                                    {
                                        "not": {
                                            "field": "Microsoft.Network/networkSecurityGroups/securityRules/destinationPortRanges[*]",
                                            "notEquals": "*"
                                        }
                                    },
                                    {
                                        "not": {
                                            "field": "Microsoft.Network/networkSecurityGroups/securityRules/destinationPortRanges[*]",
                                            "notIn": "[[parameters('ports')]"
                                        }
                                    }
                                ]
                            },
                            {
                                "anyOf": [
                                    {
                                        "field": "Microsoft.Network/networkSecurityGroups/securityRules/sourceAddressPrefix",
                                        "equals": "*"
                                    },
                                    {
                                        "field": "Microsoft.Network/networkSecurityGroups/securityRules/sourceAddressPrefix",
                                        "equals": "Internet"
                                    },
                                    {
                                        "not": {
                                            "field": "Microsoft.Network/networkSecurityGroups/securityRules/sourceAddressPrefixes[*]",
                                            "notEquals": "*"
                                        }
                                    },
                                    {
                                        "not": {
                                            "field": "Microsoft.Network/networkSecurityGroups/securityRules/sourceAddressPrefixes[*]",
                                            "notEquals": "Internet"
                                        }
                                    }
                                ]
                            }
                        ]
                    }
                ]
            },
            "then": {
                "effect": "[[parameters('effect')]"
            }
        }
    }
}

Other examples of Azure Policies:

  • Azure Security Center should be enabled for all virtual machines.
  • Virtual machines should be deployed in a specific region or list of regions.
  • All public IP addresses should be denied at the network security group level.
  • Virtual Network Service Endpoints should be used for Azure SQL Databases.
  • Require multi-factor authentication for administrative access to the Azure portal.

A recommended resource is AzAdvertizer: https://www.azadvertizer.net/index.html

Similar Posts