Skip to content

Commit a0c3fd0

Browse files
Add 'EC2 sensitive port publicly exposed' query for CloudFormation (#1642)
* Closes #1634 * simplifying query * splitting into UDP and TCP queries * removing comments * fixing integration tests * fixing unit tests * fixing integration tests
1 parent fef9fcf commit a0c3fd0

File tree

10 files changed

+418
-0
lines changed

10 files changed

+418
-0
lines changed
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
{
2+
"id": "ec2_sensitive_tcp_port_is_publicly_exposed",
3+
"queryName": "EC2 Sensitive TCP Port Is Publicly Exposed",
4+
"severity": "HIGH",
5+
"category": "Network Ports Security",
6+
"descriptionText": "The EC2 instance has a sensitive port connection exposed to the entire internet.",
7+
"descriptionUrl": "https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-ec2-security-group.html"
8+
}
Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
package Cx
2+
3+
getIngress(securityGroup) = ingress {
4+
ingress = securityGroup.Properties.SecurityGroupIngress
5+
}
6+
7+
isAccessibleFromEntireNetwork(ingress) {
8+
endswith(ingress.CidrIp, "/0")
9+
}
10+
11+
CxPolicy [ result ] {
12+
############# inputs
13+
# List of ports
14+
portNumbers = {
15+
22: "SSH",
16+
23: "Telnet",
17+
25: "SMTP",
18+
110: "POP3",
19+
135: "MSSQL Debugger",
20+
137: "NetBIOS Name Service",
21+
138: "NetBIOS Datagram Service",
22+
139: "NetBIOS Session Service",
23+
389: "LDAP",
24+
445: "Microsoft-DS",
25+
636: "LDAP SSL",
26+
1433: "MSSQL Server",
27+
1434: "MSSQL Browser",
28+
1521: "Oracl DB",
29+
2382: "SQL Server Analysis",
30+
2383: "SQL Server Analysis",
31+
2483: "Oracle DB SSL",
32+
2484: "Oracle DB SSL",
33+
3000: "Prevalent known internal port",
34+
3020: "CIFS / SMB",
35+
3306: "MySQL",
36+
3389: "Remote Desktop",
37+
4505: "SaltStack Master",
38+
4506: "SaltStack Master",
39+
5432: "PostgreSQL",
40+
5500: "VNC Listener",
41+
5900: "VNC Server",
42+
6379: "Redis",
43+
7000: "Cassandra Internode Communication",
44+
7001: "Cassandra",
45+
7199: "Cassandra Monitoring",
46+
8000: "Known internal web port",
47+
8080: "Known internal web port",
48+
8140: "Puppet Master",
49+
8888: "Cassandra OpsCenter Website",
50+
9000: "Hadoop Name Node",
51+
9042: "Cassandra Client",
52+
9090: "CiscoSecure: WebSM",
53+
9160: "Cassandra Thrift",
54+
9200: "Elastic Search",
55+
9300: "Elastic Search",
56+
11211: "Memcached",
57+
11214: "Memcached SSL",
58+
11215: "Memcached SSL",
59+
27017: "Mongo",
60+
27018: "Mongo Web Portal",
61+
61620: "Cassandra OpsCenter",
62+
61621: "Cassandra OpsCenter"
63+
}
64+
65+
############# document and resource
66+
allResources := input.document[i].Resources
67+
securityGroupName = [key | secGroup := allResources[key]; secGroup.Type == "AWS::EC2::SecurityGroup"; count(secGroup.Properties.SecurityGroupIngress) > 0][m]
68+
securityGroup = allResources[securityGroupName]
69+
ingress := getIngress(securityGroup)[n]
70+
71+
############# get relevant fields
72+
upper(ingress.IpProtocol) == "TCP"
73+
74+
############# Checks
75+
isAccessibleFromEntireNetwork(ingress)
76+
portRange := numbers.range(ingress.FromPort, ingress.ToPort)
77+
portNumbers[portRange[idx]]
78+
portNumber = portRange[idx]
79+
portName := portNumbers[portNumber]
80+
81+
############# Result
82+
result := {
83+
"documentId": input.document[i].id,
84+
"searchKey": sprintf("Resources.%s.SecurityGroupIngress", [securityGroupName]),
85+
"issueType": "IncorrectValue",
86+
"keyExpectedValue": sprintf("%s (%s:%d) should not be allowed in EC2 security group for instance", [portName, "TCP", portNumber]),
87+
"keyActualValue": sprintf("%s (%s:%d) is allowed in EC2 security group for instance", [portName, "TCP", portNumber])
88+
}
89+
}
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
AWSTemplateFormatVersion: 2010-09-09T00:00:00Z
2+
Resources:
3+
SafeSecGroup:
4+
Type: AWS::EC2::SecurityGroup
5+
Properties:
6+
SecurityGroupEgress:
7+
- IpProtocol: tcp
8+
FromPort: 22
9+
ToPort: 22
10+
CidrIp: 127.0.0.1/32
11+
GroupDescription: Allow http and ssh
12+
VpcId: my-vpc
13+
SecurityGroupIngress:
14+
- FromPort: 80
15+
ToPort: 80
16+
CidrIp: 127.0.0.1/32
17+
IpProtocol: tcp
18+
- ToPort: 77
19+
CidrIp: 127.0.0.1/32
20+
IpProtocol: all
21+
FromPort: 77
22+
MyNegativeEC2Instance:
23+
Type: AWS::EC2::Instance
24+
Properties:
25+
SecurityGroups:
26+
- SafeSecGroup
27+
KeyName: my-new-rsa-key
28+
ImageId: ami-79fd7eee
29+
InstanceType: t3.medium
Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
AWSTemplateFormatVersion: 2010-09-09T00:00:00Z
2+
Resources:
3+
UnsafeSecGroup01:
4+
Type: AWS::EC2::SecurityGroup
5+
Properties:
6+
GroupDescription: Allow http and ssh
7+
VpcId: my-vpc
8+
SecurityGroupIngress:
9+
- FromPort: 8080
10+
ToPort: 8080
11+
CidrIp: 127.0.0.1/32
12+
IpProtocol: tcp
13+
- IpProtocol: tcp
14+
FromPort: 6379
15+
ToPort: 6379
16+
CidrIp: 127.0.0.1/0
17+
SecurityGroupEgress:
18+
- FromPort: 22
19+
ToPort: 22
20+
CidrIp: 0.0.0.0/0
21+
IpProtocol: tcp
22+
EC2Instance01:
23+
Type: AWS::EC2::Instance
24+
Properties:
25+
ImageId: ami-79fd7eee
26+
InstanceType: t3.medium
27+
SecurityGroups:
28+
- UnsafeSecGroup01
29+
KeyName: my-new-rsa-key
30+
---
31+
AWSTemplateFormatVersion: 2010-09-09T00:00:00Z
32+
Resources:
33+
UnsafeSecGroup02:
34+
Type: AWS::EC2::SecurityGroup
35+
Properties:
36+
GroupDescription: Allow http and ssh
37+
VpcId: my-vpc
38+
SecurityGroupIngress:
39+
- IpProtocol: tcp
40+
FromPort: 80
41+
ToPort: 80
42+
CidrIp: 127.0.0.1/32
43+
- ToPort: 1434
44+
CidrIp: 127.0.0.1/0
45+
IpProtocol: tcp
46+
FromPort: 1433
47+
- IpProtocol: tcp
48+
FromPort: 150
49+
ToPort: 180
50+
CidrIp: 127.0.0.1/0
51+
SecurityGroupEgress:
52+
- IpProtocol: tcp
53+
FromPort: 22
54+
ToPort: 22
55+
CidrIp: 0.0.0.0/0
56+
EC2Instance02:
57+
Type: AWS::EC2::Instance
58+
Properties:
59+
InstanceType: t3.medium
60+
SecurityGroups:
61+
- UnsafeSecGroup02
62+
KeyName: my-new-rsa-key
63+
ImageId: ami-79fd7eee
64+
---
65+
AWSTemplateFormatVersion: 2010-09-09T00:00:00Z
66+
Resources:
67+
UnsafeSecGroup03:
68+
Type: AWS::EC2::SecurityGroup
69+
Properties:
70+
SecurityGroupEgress:
71+
- IpProtocol: tcp
72+
FromPort: 22
73+
ToPort: 22
74+
CidrIp: 0.0.0.0/0
75+
GroupDescription: Allow http and ssh
76+
VpcId: my-vpc
77+
SecurityGroupIngress:
78+
- ToPort: 80
79+
CidrIp: 0.0.0.0/0
80+
IpProtocol: tcp
81+
FromPort: 80
82+
- ToPort: 9000
83+
CidrIp: 127.0.0.1/0
84+
IpProtocol: tcp
85+
FromPort: 9000
86+
EC2Instance03:
87+
Type: AWS::EC2::Instance
88+
Properties:
89+
SecurityGroups:
90+
- UnsafeSecGroup03
91+
KeyName: my-new-rsa-key
92+
ImageId: ami-79fd7eee
93+
InstanceType: t3.medium
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
[
2+
{
3+
"queryName": "EC2 Sensitive TCP Port Is Publicly Exposed",
4+
"severity": "HIGH",
5+
"line": 8
6+
},
7+
{
8+
"queryName": "EC2 Sensitive TCP Port Is Publicly Exposed",
9+
"severity": "HIGH",
10+
"line": 38
11+
},
12+
{
13+
"queryName": "EC2 Sensitive TCP Port Is Publicly Exposed",
14+
"severity": "HIGH",
15+
"line": 38
16+
},
17+
{
18+
"queryName": "EC2 Sensitive TCP Port Is Publicly Exposed",
19+
"severity": "HIGH",
20+
"line": 77
21+
}
22+
]
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
{
2+
"id": "ec2_sensitive_udp_port_is_publicly_exposed",
3+
"queryName": "EC2 Sensitive UDP Port Is Publicly Exposed",
4+
"severity": "HIGH",
5+
"category": "Network Ports Security",
6+
"descriptionText": "The EC2 instance has a sensitive port connection exposed to the entire internet.",
7+
"descriptionUrl": "https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-ec2-security-group.html"
8+
}
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
package Cx
2+
3+
getIngress(securityGroup) = ingress {
4+
ingress = securityGroup.Properties.SecurityGroupIngress
5+
}
6+
7+
isAccessibleFromEntireNetwork(ingress) {
8+
endswith(ingress.CidrIp, "/0")
9+
}
10+
11+
containsDestinationPort(port, ingress) {
12+
ingress.FromPort == 0
13+
ingress.ToPort == 0
14+
} else {
15+
port == numbers.range(ingress.FromPort, ingress.ToPort)[_]
16+
}
17+
18+
CxPolicy [ result ] {
19+
############# inputs
20+
# List of ports
21+
portNumbers = [
22+
[53, "DNS"],
23+
[137, "NetBIOS Name Service"],
24+
[138, "NetBIOS Datagram Service"],
25+
[139, "NetBIOS Session Service"],
26+
[161, "SNMP"],
27+
[389, "LDAP"],
28+
[1434, "MSSQL Browser"],
29+
[2483, "Oracle DB SSL"],
30+
[2484, "Oracle DB SSL"],
31+
[5432, "PostgreSQL"],
32+
[11211, "Memcached"],
33+
[11214, "Memcached SSL"],
34+
[11215, "Memcached SSL"]
35+
]
36+
37+
############# document and resource
38+
allResources := input.document[i].Resources
39+
securityGroupName = [key | secGroup := allResources[key]; secGroup.Type == "AWS::EC2::SecurityGroup"; count(secGroup.Properties.SecurityGroupIngress) > 0][m]
40+
securityGroup = allResources[securityGroupName]
41+
ingress := getIngress(securityGroup)[n]
42+
43+
############# get relevant fields
44+
portNumber = portNumbers[j][0]
45+
portName = portNumbers[j][1]
46+
upper(ingress.IpProtocol) == "UDP"
47+
48+
############# Checks
49+
isAccessibleFromEntireNetwork(ingress)
50+
containsDestinationPort(portNumber, ingress)
51+
52+
############# Result
53+
result := {
54+
"documentId": input.document[i].id,
55+
"searchKey": sprintf("Resources.%s.SecurityGroupIngress", [securityGroupName]),
56+
"issueType": "IncorrectValue",
57+
"keyExpectedValue": sprintf("%s (%s:%d) should not be allowed in EC2 security group for instance", [portName, "UDP", portNumber]),
58+
"keyActualValue": sprintf("%s (%s:%d) is allowed in EC2 security group for instance", [portName, "UDP", portNumber])
59+
}
60+
}
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
AWSTemplateFormatVersion: 2010-09-09T00:00:00Z
2+
Resources:
3+
SafeSecGroup:
4+
Type: AWS::EC2::SecurityGroup
5+
Properties:
6+
SecurityGroupEgress:
7+
- IpProtocol: tcp
8+
FromPort: 22
9+
ToPort: 22
10+
CidrIp: 127.0.0.1/32
11+
GroupDescription: Allow http and ssh
12+
VpcId: my-vpc
13+
SecurityGroupIngress:
14+
- FromPort: 53
15+
ToPort: 53
16+
CidrIp: 127.0.0.1/32
17+
IpProtocol: udp
18+
- ToPort: 77
19+
CidrIp: 127.0.0.1/32
20+
IpProtocol: udp
21+
FromPort: 77
22+
MyNegativeEC2Instance:
23+
Type: AWS::EC2::Instance
24+
Properties:
25+
SecurityGroups:
26+
- SafeSecGroup
27+
KeyName: my-new-rsa-key
28+
ImageId: ami-79fd7eee
29+
InstanceType: t3.medium

0 commit comments

Comments
 (0)