You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
In the example security ingress/egress rules, the only CIDR range that will flag as "open to the world" is the exact string of 0.0.0.0/0. For example, 1.0.0.0/0 is also open to the world, but if I process my template where that's the ingress CIDR, I see:
I am pretty sure if you change the ingress test case to 1.0.0.0/0 it will pass the test when it should fail. EC2/VPC are perfectly happy to accept that as a CIDR, because it is valid syntactically. They will create an ingress CIDR range that, when you do describe-security-groups will show as 0.0.0.0/0.
The same is probably true for IPv6 CIDR ranges (I haven't tested) because it looks like string matching on ::0.
Expected behavior
If we must treat IPv4 CIDRs as strings, can we just match strings that end with /0? That would be be a wee bit more robust.
Ideally we should parse CIDRs as data structures, extract the netmask as an integer, and complain on small numbers like 8 or less.
The text was updated successfully, but these errors were encountered:
Hello @pacohope! Sorry for the very late reply. A lot has changed since 2021 so I figured I'd drop in with a suggestion to remedy this using regex:
let sg_resources = Resources.*[
Type == "AWS::EC2::SecurityGroup"
]
rule prevent_outbound_access_to_any_ip when %sg_resources !empty {
# select egress rules that are strings
let egress = %sg_resources.Properties.SecurityGroupEgress[
CidrIp is_string or
CidrIpv6 is_string
]
when %egress !empty {
%egress.CidrIp != /^(?:\d{1,3}\.){3}\d{1,3}\/0$/ <<IPv4 address cannot be open to the world (e.g., any CIDR ending in /0)>> or
%egress.CidrIpv6 != /^::\/0$/ <<IPv6 address cannot be open to the world (e.g., CIDR ::/0)>>
}
}
rule prevent_inbound_access_to_any_ip when %sg_resources !empty {
let ingress = %sg_resources.Properties.SecurityGroupIngress[
CidrIp is_string or
CidrIpv6 is_string
]
when %ingress !empty {
%ingress.CidrIp != /^(?:\d{1,3}\.){3}\d{1,3}\/0$/ <<IPv4 address cannot be open to the world (e.g., any CIDR ending in /0)>> or
%ingress.CidrIpv6 != /^::\/0$/ <<IPv6 address cannot be open to the world (e.g., CIDR ::/0)>>
}
}
When checking locally and applying your suggested reproduce steps I am able to have the test fail as expected. Please let me know if this is a viable solution for you. Thanks!
This pattern match will accurately pluck off the netmask part of a CIDR range, so it won't be fooled by 1.1.1.1/0. It is still treating the netmask as a string, and it's only matching the string "0". It's not considering the netmask as a number. And if you consider how much IPv6 space is allowed when the CIDR range is ::/1, it's still pretty bad. This regular expression will catch all the CIDRs that are literally 0 in the netmask, but I'm arguing that that is insufficient. For an IPv4 netmask, less than 8 is probably worth alerting (heck, imagine someone tried to type /24 and they typoed /2). For an IPv6 range, I think less than 32 is probably worth alerting (again, imagine someone meant to type ::/64 and accidentally typed ::/6).
My point was that CIDR ranges and netmasks are numbers, not strings. So string matching doesn't get it done because string matching doesn't do math.
Describe the bug
In the example security ingress/egress rules, the only CIDR range that will flag as "open to the world" is the exact string of
0.0.0.0/0
. For example,1.0.0.0/0
is also open to the world, but if I process my template where that's the ingress CIDR, I see:To Reproduce
I am pretty sure if you change the ingress test case to
1.0.0.0/0
it will pass the test when it should fail. EC2/VPC are perfectly happy to accept that as a CIDR, because it is valid syntactically. They will create an ingress CIDR range that, when you dodescribe-security-groups
will show as0.0.0.0/0
.The same is probably true for IPv6 CIDR ranges (I haven't tested) because it looks like string matching on
::0
.Expected behavior
If we must treat IPv4 CIDRs as strings, can we just match strings that end with
/0
? That would be be a wee bit more robust.Ideally we should parse CIDRs as data structures, extract the netmask as an integer, and complain on small numbers like
8
or less.The text was updated successfully, but these errors were encountered: