Restrict Ec2 Metadata to Root

October 9, 2018

Lock down the EC2 Metadata Service

I recently read an article about how someone had exploited an EC2 instance running bad code and dumped the metadata service including API keys and token to console so they could then gain access to the full AWS account. The thing that strikes me initially is that wow thats some bad code, but also there is a real problem with the IAM role associated witht hat instance. Every IAM role should work on the rule of least privilage, if they did this is really a none issue. Let me explain more.

Least privilage

What do I mean by this, well first lets give an example of a simple web app that needs to write to S3. Now if I’m not doing this correctly I’d grant S3:* to the IAM role allowing that app to do anything with S3 including create and delete objects and buckets! Even worse there are examples of people giving admin rights to the IAM role which means that instance could create other users or spin up lots of EC2/Bitcoin mining resource. We don’t want that, so be careful to only grant access to the service and the fine grained controls you need. For example my simple web app just needs to write objects to one bucket, so it should look like this.

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "Stmt1539076578803",
      "Action": [
        "s3:PutObject",
        "s3:PutObjectTagging",
        "s3:PutObjectVersionTagging"
      ],
      "Effect": "Allow",
      "Resource": "arn:aws:s3:::<bucket_name>/*"
    }
  ]
}

Even if someone exploits your instance they dont have access in your account to do much, they can simply put objects in one bucket.

Locking down the EC2 Metadata Service

Lets take this one step further. Most web services run as another user and not root. So it may be www-data, apache or nginx depending on your distribution. This means we could use IPTables to stop anyone other than root getting access to the EC2 metadata. Its pretty simple, the foloowing command will prevent other users getting access. This means that they can never use the web app to get the STS keys (which btw are only valid for ~5 mins).

iptables -A OUTPUT -m owner ! --uid-owner root -d 169.254.169.254 -j DROP

This really starts to lock down your instance and hardens it against an attack. Even if you have some bad code which was the real issue in the article I read, you have limited and restricted what can be done. These are things your ops team should be considering on every instance or even function you create.

Further reading

I’d highly recommend reading the Security Pillar of the Well Architected Framework, for further insights. Also make sure you understand the Shared Responsibility Model of AWS.