Some time ago I have done some research on possible Man-in-the-Middle threats in AWS. This blog post describes the results of this research and shows an interesting way of escalating the IAM privileges in the AWS VPC.

Let’s start with the prerequisites that the attacker has taken over the IAM role which allows to make modifications to Route53 and issue the certificates signed by private CA from ACM-PCA.

The minimum IAM permissions that the role must have to do the same exploitation are:

route53:CreateHostedZone
route53:ChangeResourceRecordSets
acm-pca:IssueCertificate
acm-pca:GetCertificate

The other IAM permissions which can be useful in enumeration but are not mandatory to exploit:

route53:GetHostedZone
route53:ListHostedZones
acm-pca:ListCertificateAuthorities
ec2:DescribeVpcs

Once the attacker has minimum IAM permissions on route53 and acm-pca, he or she would be able to hijack the calls to AWS API and successfully escalate the IAM privileges in AWS deployment - by forwarding the hijack AWS API calls to relevant VPC Endpoints and reading the responses e.g. secretsmanager:GetSecretValue call.

I was amazed that this is possible, because of my false assumption that: 1) AWS SDK uses a sort of certificate pinning, 2) Both route53 and acm-pca would not allow controlling the AWS internal domain names.

All of those assumptions are not true. The AWS Security has been consulted but it turned out it is not a security bug. There are use cases where the clients want to set up the proxy or custom routing for the traffic to AWS APIs. I have decided to document and share this behavior as it might be useful for other cloud pen-testers.

Discovery

The discovery started with playing the route53, by first creating the hosted zone for amazonaws.com, which failed:

aws_hijack

I have tried the same for us-east-1.amazonaws.com, which gave the same results:

aws_hijack

But to my surprise the secretsmanager.us-east-1.amazonaws.com worked:

aws_hijack

Now, one can create A record for the secretsmanager.us-east-1.amazonaws.com pointing to some internal IP inside the VPC:

aws_hijack

Simulating the victim listing secrets in the victim machine and in the attacker’s machine we receive the connection which is TLS encrypted traffic:

aws_hijack

The communication is TLS encrypted but if the applications in the VPC trust the private CA managed by the ACM-PCA and the attacker has IAM permissions to control that private CA in ACM-PCA, it would be possible to do full Man-In-The-Middle and escalate IAM privileges.

Exploitation

You can watch the whole exploitation here:

https://youtu.be/I-IakgPyEtk

If you prefer to read and go through the screenshot, please carry on.

For the purpose of demonstration let’s assume that the attacker compromised one of ec2 with the following IAM role assumed:

aws_hijack

In the real world, the ec2 should not have such broad permissions but you may encounter some developer or DevOps role having so.

The compromised ec2 with the privileged IAM role has the internal IP 10.0.0.87, the victim application runs on the ec2 with IP 10.0.0.224.

Now on the attacker’s owned machine, we create the hosted zone for secretsmanager.us-east-1.amazonaws.com:

aws_hijack

Then set the A record for secretsmanager.us-east-1.amazonaws.com pointing to the 10.0.0.87:

aws_hijack

aws_hijack

We know that there is a Private CA defined in the ACM-PCA:

aws_hijack

The Java Application running on the victim machine (10.0.0.224) trusts this Private CA to sign the web service certificate. The Private CA is in the Java TrustStore.

aws_hijack

Now on the attacker’s machine, we generate the private key and CSR. Then, we call the acm-ca to issue a certificate signed by the private CA. The API responds with the signed certificate ARN: aws_hijack aws_hijack

Then, the attacker retrieves the signed certificate from the ACM-PCA:

aws_hijack

To simulate the Java Application calls to Secrets Manager from the victim’s machine, I have run the JUnit tests through maven, in the below screenshot you can see that there are no exceptions, which means that the certificate is trusted: aws_hijack

Finally, in the ncat listener, we can see the HTTP request sent by the AWS SDK from Java Application. aws_hijack

How to escalate the IAM privileges using that? We do not have the permissions to do s3:GetObject on any s3 object or to do secretsmanager:GetSecretValue, but if we sniff the traffic to either S3 or secretsmanager with those calls, we can forward the requests to the respective VPCE and obtain access to Objects stored in S3 or secrets stored in secretsmanager.

Conclusions

It is recommended to avoid broad route53 IAM permissions with regards to the creation of a private hosted zone or unrestricted route53:ChangeResourceRecordSets. Since ACM-PCA does not allow to apply restrictions on which domain’s certificate can be signed by the private CA, it is also recommended to pay special attention to the acm-pca:IssueCertificate IAM permissions.