turbot/steampipe-mod-azure-compliance

Control: 7.2 Ensure that SSH access from the Internet is evaluated and restricted

Description

Network security groups should be periodically evaluated for port misconfigurations. Where SSH is not explicitly required and narrowly configured for resources attached to a network security group, Internet-level access to Azure resources should be restricted or eliminated.

The potential security problem with using SSH over the Internet is that attackers can use various brute force techniques to gain access to Azure Virtual Machines. Once the attackers gain access, they can use a virtual machine as a launch point for compromising other machines on the Azure Virtual Network or even attack networked devices outside of Azure.

Remediation

Remediate from Azure Portal

  1. Go to Network security groups.
  2. Click the name of a network security group.
  3. Under Settings, click Inbound security rules.
  4. Check the box next to any inbound security rule matching:
    • Port: 22 or range including 22
    • Protocol: TCP or Any
    • Source: 0.0.0.0/0, Internet, or Any
    • Action: Allow
  5. Click Delete.
  6. Click Yes.
  7. Repeat steps 1-6 for each network security group requiring remediation

Remediate from Azure CLI

For each network security group rule requiring remediation, run the following command to delete the rule:

az network nsg rule delete --resource-group <resource-group> --nsg-name <network-security-group> --name <rule>

Default Value

By default, SSH access from internet is not enabled.

Usage

Run the control in your terminal:

powerpipe control run azure_compliance.control.cis_v500_7_2

Snapshot and share results via Turbot Pipes:

powerpipe login
powerpipe control run azure_compliance.control.cis_v500_7_2 --share

SQL

This control uses a named query:

with network_sg as (
select
distinct name sg_name
from
azure_network_security_group nsg,
jsonb_array_elements(security_rules) sg,
jsonb_array_elements_text(sg -> 'properties' -> 'destinationPortRanges' || (sg -> 'properties' -> 'destinationPortRange') :: jsonb) dport,
jsonb_array_elements_text(sg -> 'properties' -> 'sourceAddressPrefixes' || (sg -> 'properties' -> 'sourceAddressPrefix') :: jsonb) sip
where
sg -> 'properties' ->> 'access' = 'Allow'
and sg -> 'properties' ->> 'direction' = 'Inbound'
and (sg -> 'properties' ->> 'protocol' ilike 'TCP' or sg -> 'properties' ->> 'protocol' = '*')
and sip in ('*', '0.0.0.0', '0.0.0.0/0', 'Internet', 'any', '<nw>/0', '/0')
and (
dport in ('22', '*')
or (
dport like '%-%'
and split_part(dport, '-', 1) :: integer <= 22
and split_part(dport, '-', 2) :: integer >= 22
)
)
)
select
sg.id resource,
case
when nsg.sg_name is null then 'ok'
else 'alarm'
end as status,
case
when nsg.sg_name is null
then sg.title || ' restricts SSH access from internet.'
else sg.title || ' allows SSH access from internet.'
end as reason
, sg.resource_group as resource_group
, sub.display_name as subscription
from
azure_network_security_group sg
left join network_sg nsg on nsg.sg_name = sg.name
left join azure_subscription sub on sub.subscription_id = sg.subscription_id;

Tags