Rules
Rules are the heart of CFRipper. When running CFRipper the CloudFormation stack will be checked against each rule and the results combined.
Available Rules¶
CloudFormationAuthenticationRule¶
Checks that any AWS::CloudFormation::Authentication
resource does not contain plain text credentials.
Severity: Medium
Defaults to monitor mode (rule not enforced)
Risk¶
Secrets are stored in clear text and printed in clear text in the AWS console.
Fix¶
Do not store credentials in CloudFormation files, use parameters.
Code for fix¶
Parameters: PasswordAuth: NoEcho: true Description: Some cool password MinLength: 8 Type: String ... Resources: AWS::CloudFormation::Authentication: ... password: Ref: "PasswordAuth" ...
CrossAccountCheckingRule¶
Base class not intended to be instantiated, but inherited from. This class provides common methods used to detect access permissions from other accounts.
Severity: Medium
CrossAccountTrustRule¶
Checks if the trust policy of a role grants permissions to principals from other accounts. Do not use whole accounts as principals.
Severity: Medium
Risk¶
It might allow other AWS identities to escalate privileges.
Fix¶
If cross account permissions are required, the stack should be added to the whitelist for this rule. Otherwise, the access should be removed from the CloudFormation definition.
EBSVolumeHasSSERule¶
Checks that server side encryption is enabled for all EBS volumes.
Severity: Medium
Defaults to monitor mode (rule not enforced)
Risk¶
Data that is not encrypted at rest could breach regulatory compliance and allow easier access for an attacker to view any instace storage data of your EC2 instance.
Fix¶
Enable server-side encryption on EBS volumes.
Code for fix¶
{ "Type" : "AWS::EC2::Volume", "Properties" : { ... "Encrypted" : true, ... } }
FullWildcardPrincipalRule¶
Checks for any wildcard principals defined in any statements.
Severity: High
Risk¶
It might allow other AWS identities to escalate privileges.
Fix¶
Where possible, restrict the access to only the required resources.
For example, instead of Principal: "*"
, include a list of the roles that need access.
HardcodedRDSPasswordRule¶
Checks that any RDS clusters or instances aren't exposing their passwords.
The rule forbids default password parameters and any missing NoEcho
for RDS passwords.
Severity: Medium
Risk¶
Not setting this correctly can lead to malicious agents attempting to gain access to your
RDS instaces with a default password, or by reading the value that will be printed in plain
text in the AWS console and logs if NoEcho
is not set.
Fix¶
When defining a password do not use the default value. If you specify a default password and you don’t provide a parameter, it will use the default which can be found clear text in the CloudFormation file.
Code for fix¶
Parameters: MasterUserPassword: NoEcho: true Description: The database admin account password MinLength: 8 Type: String ... Resources: RDSCluster: Type: AWS::RDS::DBCluster DeletionPolicy: "Snapshot" Properties: ... MasterUserPassword: !Ref 'MasterUserPassword' ...
IAMRoleWildcardActionOnPolicyRule¶
Checks for use of wildcard characters in all IAM Role policies (including AssumeRolePolicyDocument) and AWS Managed Policies (https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies_managed-vs-inline.html).
Severity: Medium
Defaults to debug mode (rule not enforced)
IAMRolesOverprivilegedRule¶
Rule that checks for wildcards in resources for a set of actions and restricts managed policies.
Severity: Medium
KMSKeyCrossAccountTrustRule¶
Checks for KMS keys that allow cross-account principals to get access to the key.
Severity: Medium
Risk¶
It might allow other AWS identities to read/modify the secrets.
Fix¶
If cross account permissions are required for KMS access, the stack should be added to the whitelist for this rule. Otherwise, the access should be removed from the CloudFormation definition.
KMSKeyWildcardPrincipal¶
Check for wildcards in principals in KMS Policies.
Severity: Medium
ManagedPolicyOnUserRule¶
Checks if any IAM managed policy is applied to a group and not a user.
Severity: Medium
Defaults to monitor mode (rule not enforced)
PartialWildcardPrincipalRule¶
Checks for any wildcard or account-wide principals defined in any statements. This rule will flag
as non-compliant any principals where root
or *
are included at the end of the value, for
example, arn:aws:iam:12345:12345*
.
Severity: Medium
Defaults to monitor mode (rule not enforced)
Risk¶
It might allow other AWS identities or the root access of the account to escalate privileges.
Fix¶
Where possible, restrict the access to only the required resources.
For example, instead of Principal: "*"
, include a list of the roles that need access.
PolicyOnUserRule¶
Checks if any IAM policy is applied to a group and not a user.
Severity: Medium
Defaults to monitor mode (rule not enforced)
PrincipalCheckingRule¶
Abstract class for rules that check principals
Severity: Medium
PrivilegeEscalationRule¶
Checks for any dangerous IAM actions that could allow privilege escalation and potentially represent a large security risk. See current blacklisted IAM actions.
Severity: Medium
Fix¶
Unless strictly necessary, do not use actions in the IAM action blacklist. CloudFormation files that do require these actions should be added to the whitelist.
S3BucketPolicyPrincipalRule¶
Checks for non-whitelisted principals in S3 bucket policies.
Severity: High
Risk¶
This is designed to block unintended access from third party accounts to your buckets.
Fix¶
All principals connected to S3 Bucket Policies should be known. CFRipper checks that all principals meet
the requirements expected. The list of valid accounts is defined in valid_principals
, which is set in the config.
S3BucketPolicyWildcardActionRule¶
Checks for use of the wildcard *
character in the Actions of Policy Documents of S3 Bucket Policies.
This rule is a subclass of GenericWildcardPolicyRule
.
Severity: Medium
Defaults to debug mode (rule not enforced)
S3BucketPublicReadAclAndListStatementRule¶
Checks if any S3 bucket policy has a public read ACL and List
permission in the bucket policy.
Severity: Medium
Defaults to debug mode (rule not enforced)
Fix¶
Unless the bucket is hosting static content and needs to be accessed publicly, these bucket policies should be locked down.
S3BucketPublicReadWriteAclRule¶
Checks if any S3 bucket policy has access control set to PublicReadWrite
.
Severity: High
S3CrossAccountTrustRule¶
Check for cross account access in S3 bucket policies. Cross account access by default should not be allowed.
Severity: Medium
Risk¶
It might allow other AWS identities to access/modify content of the bucket.
Fix¶
If cross account permissions are required for S3 access, the stack should be added to the whitelist for this rule. Otherwise, the access should be removed from the CloudFormation definition.
SNSTopicPolicyNotPrincipalRule¶
Checks if an SNS topic policy has an Allow + a NotPrincipal (exclusive principal).
Severity: Medium
Defaults to monitor mode (rule not enforced)
SNSTopicPolicyWildcardActionRule¶
Checks for use of the wildcard *
character in the Actions of Policy Documents of SQS Queue Policies.
This rule is a subclass of GenericWildcardPolicyRule
.
Severity: Medium
Defaults to debug mode (rule not enforced)
SQSQueuePolicyNotPrincipalRule¶
Checks if an SQS Queue policy has an Allow + a NotPrincipal (exclusive principal).
Severity: Medium
Defaults to monitor mode (rule not enforced)
SQSQueuePolicyPublicRule¶
Checks for wildcard principals in Allow statements in an SQS Queue Policy.
Severity: High
Risk¶
This is deemed a potential security risk as anyone would be able to interact with your queue.
SQSQueuePolicyWildcardActionRule¶
Checks for use of the wildcard *
character in the Actions of Policy Documents of SQS Queue Policies.
This rule is a subclass of GenericWildcardPolicyRule
.
Severity: Medium
Defaults to debug mode (rule not enforced)
SecurityGroupIngressOpenToWorld¶
Checks if a security group has a CIDR open to world on ingress.
Severity: Medium
Fix¶
Unless required, do not use 0.0.0.0/0 as an ingress rule in your Security group. This is a security risk as your resource will be publicly available.
SecurityGroupMissingEgressRule¶
Checks that Security Groups are defined with an egress policy, even if this is still allowing all outbound traffic.
Severity: Medium
Defaults to debug mode (rule not enforced)
Risk¶
If no egress rule is specified, the default is to open all outbound traffic to the world. Whilst some services may need this, it is usually the case that the security group can be locked down more. A NAT instance for example may require a completely open egress policy.
Allowing unrestricted (0.0.0.0/0 or ::/0) outbound/egress access can increase opportunities for malicious activity such as such as Denial of Service (DoS) attacks or Distributed Denial of Service (DDoS) attacks.
Fix¶
Explicitly defining the egress policy for the security group.
Code for fix¶
Even in the example below, the egress rule added will allow HTTP traffic out to the world. However, this will pass the rule.
// example from https://stelligent.com/2016/04/07/finding-security-problems-early-in-the-development-process-of-a-cloudformation-template-with-cfn-nag/ { "Resources": { "sg": { "Type": "AWS::EC2::SecurityGroup", "Properties": { "GroupDescription": "some_group_desc", "SecurityGroupIngress": { "CidrIp": "10.1.2.3/32", "FromPort": 34, "ToPort": 34, "IpProtocol": "tcp" }, // addition of egress to the `sg` resource "SecurityGroupEgress": { "CidrIp": "0.0.0.0/0", "FromPort": 80, "ToPort": 80, "IpProtocol": "tcp" }, "VpcId": "vpc-12345678" } } } }
SecurityGroupOpenToWorldRule¶
Checks if security groups have an ingress rule of /0 for ports other than 80 and 443. All other ports should be closed off from public access to prevent a serious security misconfiguration.
Severity: Medium
Fix¶
Most security groups only need to be access privately, and this can typically be done by specifying
the CIDR of a Security Group's ingress to 10.0.0.0/8
or similar (https://en.wikipedia.org/wiki/Private_network).
Code for fix¶
{ "AWSTemplateFormatVersion": "2010-09-09", "Resources": { "SecurityGroup": { "Type": "AWS::EC2::SecurityGroup", "Properties": { "GroupDescription": "description", "SecurityGroupIngress": [ // this is compliant. Port 22 (typically SSH) is accessible from the private network only. { "IpProtocol": "tcp", "CidrIp": "10.0.0.0/8", "FromPort": 22, "ToPort": 22 }, // this is not compliant. Anyone with the IP for this EC2 instance can connect on port 9090. { "IpProtocol": "tcp", "CidrIp": "0.0.0.0/0", "FromPort": 9090, "ToPort": 9090 } ] } } } }
Custom Rules¶
To add custom rules first extend the Rule
class. Then implement the invoke
method by adding your logic.
@abstractmethod def invoke(self, cfmodel: CFModel, extras: Optional[Dict] = None) -> Result: pass
CFRipper uses pycfmodel to create a Python model of the CloudFormation script.
This model is passed to the invoke
function as the cfmodel
parameter. You can use the model's iterate through the
resources and other objects of the model and use the helper functions to perform various checks. Look at the
current rules for examples.
class S3CrossAccountTrustRule(CrossAccountCheckingRule): """ Check for cross account access in S3 bucket policies. Cross account access by default should not be allowed. Risk: It might allow other AWS identities to access/modify content of the bucket. Fix: If cross account permissions are required for S3 access, the stack should be added to the whitelist for this rule. Otherwise, the access should be removed from the CloudFormation definition. """ REASON = "{} has forbidden cross-account policy allow with {} for an S3 bucket." def invoke(self, cfmodel: CFModel, extras: Optional[Dict] = None) -> Result: result = Result() for logical_id, resource in cfmodel.Resources.items(): if isinstance(resource, S3BucketPolicy): for statement in resource.Properties.PolicyDocument._statement_as_list(): self._do_statement_check(result, logical_id, statement) return result
Monitor Mode¶
By default, each rule has MONITOR_MODE
set to false. Monitor model will return the failed rules in another field in the
response, instead in the main "failed rules". This way new rules can be tested before they are removed from monitor
mode and start triggering alarms.