How Can AWS IAM Access Analyzer Help You Improve Security Checks in Your CI/CD Pipeline?
Tags: aws, security, cicd, privesc
Published: 2024-03-31 17:30:40

Recently I was working on improving a client's CI/CD Pipeline security and one of the aspects I wanted to explore was how to use AWS native tools to identify over-permissive IAM policies or detect privilege escalation possibilities. In this article I would like to have a look at what the AWS IAM Access Analyzer has to offer with its policy validation feature. Apart from checking policy grammar, it can also raise a security finding if the "[policy provides access that AWS considers a security risk because the access is overly permissive](https://docs.aws.amazon.com/IAM/latest/UserGuide/access-analyzer-policy-validation.html)". Or can it?

## Let's Get the Basics Right

Privilege escalation is the act of exploiting a flaw to gain elevated access to resources that normally shouldn't be accessible to you. In AWS it is done by (enumerating and) abusing permissions assigned to your principal or to the principal the attacker gained access to. The permissions are assigned to principals using IAM policies. In turn, the policies are made of one or more statements, each statement containing a tuple of action, resource, effect and optionally a condition.

## How Does Privilege Escalation Work?

In terms of privilege escalation, it boils down to the individual IAM actions in the statement or their combination. At the time of writing the article, AWS provided [whopping 16458](https://www.awsiamactions.io/) individual IAM actions. The most critical area are the IAM actions related to the IAM service itself. Filtering only IAM actions, we still get [171](https://www.awsiamactions.io/?a=iam%3A) actions that could be potentially dangerous. Obviously we can't deny all those IAM actions for everyone in our AWS account or AWS Organization e.g. by a Service Control Policy as that would render the AWS pretty unusable. For example you wouldn't be able to assign an EC2 instance an IAM role allowing it to put items in DynamoDB or read data from an S3 bucket or make any other services talk to each other. 

So, which actions really pose a threat? A great security researcher [Nick Frichette](https://frichetten.com/) (worth following on social networks) and his project [https://hackingthe.cloud](https://hackingthe.cloud) identified [37 ways](https://hackingthe.cloud/aws/exploitation/iam_privilege_escalation/) how an IAM policy can be abused to gain more privileges. Some of them are quite surprising, e.g. DetachRolePolicy which sounds counterintuitive, but if the policy being detached contains a Deny statement, then detaching it can in fact allow you to perform more actions which is considered privilege escalation.

Looking at the checks performed by the IAM Access Analyzer, we can see some resemblance with the list at https://hackingthe.cloud, however both lists look at the problem from a slightly different perspective. 


![Available Checks](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/hj7xxk3ook9cupnzw7nw.png)

Whereas the Hacking The Cloud approach leans more towards auditing and penetration testing by looking for real exploitation possibilities thanks to a combination of permissions for multiple AWS services, the Access Analyzer looks more at prevention and mostly misuse of the `iam:PassRole` permission. A good explanation of why the iam:PassRole permission can be dangerous is explained in detail for example [here](https://ermetic.com/blog/aws/auditing-passrole-a-problematic-privilege-escalation-permission/).

## How Can AWS IAM Access Analyzer Help?

Based on the observations above, the best place for such checks would be a CI/CD pipeline where the Access Analyzer can check IAM policies before they are deployed to AWS and identify possible security issues. Usually, the IAM policies are part of Infrastructure as Code templates such as Cloud Formation or Terraform. That's where the first problem arises. The input for the `aws iam accessaanalyzer validate` command is NOT a CloudFormation template or a Terraform plan file, but a JSON document containing the policy. It looks something like this:

```
aws accessanalyzer validate-policy
    --policy-document file://myfile.json
    --policy-type IDENTITY_POLICY
```

The second problem is that CloudFormation templates and the IAM policies in the templates more often than not contain also intrinsic functions, such `Fn::Join` or `Fn::Sub` to join or substitute values which might not be known by simply parsing the template as a JSON or YAML file. This might not be the case though in case of scanning Terraform plan files where the variables are already replaced with the respective values. 
So, how to deal with a template looking like this?


```
AWSTemplateFormatVersion: '2010-09-09'
Resources:
  BobUser:
    Type: AWS::IAM::User
    Properties:
      UserName: Bob

  BobPolicy:
    Type: AWS::IAM::Policy
    Properties:
      PolicyName: BobEC2Policy
      PolicyDocument:
        Version: '2012-10-17'
        Statement:
          - Effect: Allow
            Action:
              - "ec2:RunInstances"
              - !Join
                - ""
                - - "iam:"
                  - "PassRole"
            Resource: "*"
      Users:
        - Ref: BobUser

  BobPolicyAttachment:
    Type: AWS::IAM::UserPolicyAttachment
    Properties:
      UserName: !Ref BobUser
      PolicyArn: !Ref BobPolicy
```

The critical `iam:PassRole` action is constructed here by joining the two parts of the action together using the `Fn::Join` intrinsic function. 

Luckily, AWS provides a solution called [cfn-policy-validator](https://github.com/awslabs/aws-cloudformation-iam-policy-validator) which can parse CloudFormation templates and uses IAM Access Analyzer in the background. (There is also [a version of the tool for Terraform](https://github.com/awslabs/terraform-iam-policy-validator)). It can be installed by simply running:

```
pip install cfn-policy-validator
```

Then the actual check of a CloudFormation template is performed by running

```
cfn-policy-validator validate --template-path DangerousTemplate.yaml --region eu-central-1
```
**Note:** The command requires valid AWS credentials with permissions to run AWS IAM Access Analyzer checks.

Running it against the template above, we get a JSON document as a result correctly identifying the dangerous action `iam:PassRole` with `*` as a Resource, meaning the user Bob could pass any IAM role and possibly escalate his privileges.


```
{
    "BlockingFindings": [
        {
            "findingType": "SECURITY_WARNING",
            "code": "PASS_ROLE_WITH_STAR_IN_RESOURCE",
            "message": "Using the iam:PassRole action with wildcards (*) in the resource can be overly permissive because it allows iam:PassRole permissions on multiple resources. We recommend that you specify resource ARNs or add the iam:PassedToService condition key to your statement.",
            "resourceName": "Bob",
            "policyName": "BobEC2Policy",
            "details": {
                "findingDetails": "Using the iam:PassRole action with wildcards (*) in the resource can be overly permissive because it allows iam:PassRole permissions on multiple resources. We recommend that you specify resource ARNs or add the iam:PassedToService condition key to your statement.",
                "findingType": "SECURITY_WARNING",
                "issueCode": "PASS_ROLE_WITH_STAR_IN_RESOURCE",
                "learnMoreLink": "https://docs.aws.amazon.com/IAM/latest/UserGuide/access-analyzer-reference-policy-checks.html#access-analyzer-reference-policy-checks-security-warning-pass-role-with-star-in-resource",
                "locations": [
                    {
                        "path": [
                            {
                                "value": "Statement"
                            },
                            {
                                "index": 0
                            },
                            {
                                "value": "Action"
                            },
                            {
                                "index": 1
                            }
                        ],
                        "span": {
                            "start": {
                                "line": 1,
                                "column": 91,
                                "offset": 91
                            },
                            "end": {
                                "line": 1,
                                "column": 105,
                                "offset": 105
                            }
                        }
                    },
                    {
                        "path": [
                            {
                                "value": "Statement"
                            },
                            {
                                "index": 0
                            },
                            {
                                "value": "Resource"
                            }
                        ],
                        "span": {
                            "start": {
                                "line": 1,
                                "column": 120,
                                "offset": 120
                            },
                            "end": {
                                "line": 1,
                                "column": 123,
                                "offset": 123
                            }
                        }
                    }
                ]
            }
        }
    ],
    "NonBlockingFindings": []
}

```


Checking the return code by running
```
$?
```
we get a non-zero code, 2 in this case. 

## Conclusion

The Validate feature of AWS IAM Access Analyzer is certainly not an almighty tool but I think it has its place in the CI/CD tooling and beside security findings it also provides other warnings and suggestions possibly pointing out an unintentional mistake in IAM policies. Besides IAM policies it also supports resource policies and service control policies. 
The checks are free of charge and together with the cfn-policy-validator it is surprisingly easy to integrate into CI/CD pipelines and provides an easy-to-parse output and decision-making. Furthermore, it has further capabilities how to treat findings, so you can treat certain findings or resources as non-blocking. Overall, it seems to be a versatile tool and was worth checking. 

How about privilege escalation though? Besides detecting some `iam:PassRole` related dangerous policies, it doesn't provide much in this area, but then again it's not the main purpose of the service. When it comes to detecting overly permissive statements as stated in the feature description of the feature, the tool does the job just fine.
If you are interested in finding or exploiting the privilege escalation possibilities, there are multiple great write-ups and tools, such as: https://rhinosecuritylabs.com/aws/aws-privilege-escalation-methods-mitigation/ and their pentesting tool [pacu](https://rhinosecuritylabs.com/aws/pacu-open-source-aws-exploitation-framework/), or https://bishopfox.com/blog/privilege-escalation-in-aws and their tool [IAM Vulnerable](https://github.com/BishopFox/iam-vulnerable).