Passed roles

When a CloudFormation stack is created, there is the option to pass an IAM role to it for the deployment process. If a role is passed, the stack will be created using that role, but if a role is not passed, then CloudFormation just uses the current user privileges to deploy the stack. This opens the possibility of privilege escalation through stacks that have already been passed roles when they were created.

Let's say that a user we compromised has "cloudformation:*" permissions, but not "iam:PassRole". This means that we cannot escalate our privileges by creating a new stack and passing it a role with higher privileges than what we have (because that requires the "iam:PassRole" permission), but it does mean that we can modify existing stacks.

To determine which, if any, CloudFormation stacks have had roles passed to them, we can go back to the output from the DescribeStacks command. If a stack has the "RoleARN" key with the value of an IAM role's ARN, then that stack has been passed a role. If that key does not show up, then that stack was not passed a role when it was created. The demo stack we created was passed a role.

Now, if we have the necessary IAM permissions, we could use the IAM API to figure out what permissions the role passed to that stack has, but if we don't, we can infer based off a few different things. First, the name of the role could be a small hint, such as if it includes "EC2FullAccessForCloudFormation", it is safe to assume the role has full access to EC2. The more reliable, but not necessarily complete, set of permissions can be assumed based on what resources the stack deployed. If a certain stack deployed an EC2 instance, created a security group for it, created an S3 bucket, and set up an RDS database, it would be safe to assume that the role has access to do all of those things. In our case, that's more access to the AWS APIs than just "cloudformation:*", so we could abuse that stack to gain further access to the environment.

There are a few ways we can check that, including just looking at the raw CloudFormation template we looked at earlier, or we can use the DescribeStackResources command to list out what resources were created by that stack, then make our access assumptions from there. This can be done by running the following command from the AWS CLI:

aws cloudformation describe-stack-resources --stack-name Test-Lamp-Stack --region us-west-2

The output from our demo stack looks like this:

{
"StackResources": [
{
"StackName": "Test-Lamp-Stack",
"StackId": "arn:aws:cloudformation:us-west-2:000000000000:stack/Deleted-Test-Lamp-Stack/23801r22-906h-53a0-pao3-74yre1420836",
"LogicalResourceId": "WebServerInstance",
"PhysicalResourceId": "i-0caa63d9f77b06d90",
"ResourceType": "AWS::EC2::Instance",
"Timestamp": "2018-12-26T18:55:59.189Z",
"ResourceStatus": "CREATE_COMPLETE",
"DriftInformation": {
"StackResourceDriftStatus": "NOT_CHECKED"
}
},
{
"StackName": "Test-Lamp-Stack",
"StackId": "arn:aws:cloudformation:us-west-2:000000000000:stack/Deleted-Test-Lamp-Stack/23801r22-906h-53a0-pao3-74yre1420836",
"LogicalResourceId": "WebServerSecurityGroup",
"PhysicalResourceId": "Test-Lamp-Stack-WebServerSecurityGroup-RA2RW6FRBYXX",
"ResourceType": "AWS::EC2::SecurityGroup",
"Timestamp": "2018-12-26T18:54:39.981Z",
"ResourceStatus": "CREATE_COMPLETE",
"DriftInformation": {
"StackResourceDriftStatus": "NOT_CHECKED"
}
}
]
}

We can see here that an EC2 instance and an EC2 security group were created, so we can assume the role attached to this stack at least has access to do those two things. To then take advantage of these permissions and escalate our own privileges, we can use the UpdateStack command. This allows us to update/change the template associated with the stack we are targeting, allowing us to add/remove resources to the list. To cause less of a disturbance in the environment, we could pull the existing template from the stack and then just add resources to it, to cause as little disruption as possible. This is because existing resources that have not been changed will not be modified, so we won't cause a denial of service.

At this point, the next steps depend quite a bit on the situation. If you find out that a stack has IAM permissions, add some IAM resources to the template that allow you to escalate your access, or if you find out that a stack has EC2 permissions, like we did here, add a bunch of EC2 instances with your own SSH key or something like that. If we went ahead and added some more EC2 instances to our demo stack, we could possibly gain access to the internal side of the VPC that they are using for these resources, which then could possibly grant us further, more-privileged access to the environment.

An example command to perform this attack might look like this:

aws cloudformation update-stack --stack-name Test-Lamp-Stack --region us-west-2 --template-body file://template.json --parameters file://params.json

The template.json file would include your updated CloudFormation template and params.json would include something that instructs the stack to use all of the already supplied parameters, instead of new ones:

[
{
"ParameterKey": "KeyName",
"UsePreviousValue": true
},
{
"ParameterKey": "DBPassword",
"UsePreviousValue": true
},
{
"ParameterKey": "DBUser",
"UsePreviousValue": true
},
{
"ParameterKey": "DBRootPassword",
"UsePreviousValue": true
}
]

Now the stack will update and create your new resources, and you will have successfully used the passed roles' permissions to perform an API action in AWS, effectively escalating your own privileges.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.144.243.184