IAM Roles vs. Instance Profiles: Misconfigurations, Security Gaps, and Hardening Strategies
Manish Kumar
Cloud & IT Infrastructure Consultant | Architecting Secure, Scalable Solutions for Digital Transformation
IAM (Identity and Access Management) roles are a cornerstone of secure AWS deployments. They allow you to grant temporary permissions to services and applications running on AWS resources, without embedding long-term credentials. One common and powerful use case is attaching an IAM role to an EC2 instance via an?instance profile. However, misconfigurations in these areas can create significant security vulnerabilities. This post will explore the risks of overly permissive roles, IMDS vulnerabilities, and provide concrete command-line solutions to implement best practices.
What are IAM Roles and Instance Profiles?
Risks of Overly Permissive Roles Attached to EC2 Instance Profiles
The most common, and potentially devastating, misconfiguration is assigning an IAM role with overly broad permissions to an EC2 instance. If an attacker gains access to the instance (through a vulnerable application, compromised SSH keys, or other means), they inherit?all?the permissions granted by the attached role.
Scenario:?Let's say you grant an EC2 instance the?AdministratorAccess?managed policy to simplify development. While convenient, this grants the instance (and anyone who compromises it) full control over your entire AWS account.
The Danger Zone:?An attacker who compromises this instance can:
Mitigation: Principle of Least Privilege (POLP)
The Principle of Least Privilege (POLP) is the golden rule of security. Grant only the minimum permissions necessary for a resource to perform its intended function.
Command-Line Instructions (AWS CLI):
aws iam list-roles
Pay close attention to roles with names like "AdminRole", "DevRole", or roles attached to EC2 instance profiles in your development/staging environments.
aws iam list-attached-role-policies --role-name <role-name>
If you see?AdministratorAccess,?PowerUserAccess, or similar broad-managed policies, your role is likely overly permissive.
First, create a JSON file (e.g.,?limited-policy.json) with the following content, replacing?<your-bucket-name>?and?<your-region>?with the appropriate values:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"s3:GetObject",
"s3:ListBucket"
],
"Resource": [
"arn:aws:s3:::<your-bucket-name>",
"arn:aws:s3:::<your-bucket-name>/*"
]
},
{
"Effect": "Allow",
"Action": [
"logs:CreateLogGroup",
"logs:CreateLogStream",
"logs:PutLogEvents",
"logs:DescribeLogGroups",
"logs:DescribeLogStreams"
],
"Resource": "arn:aws:logs:<your-region>:<your-account-id>:*"
}
]
}
Remember to replace?<your-account-id>?with your AWS account ID. You can get this from the AWS Console or by running?aws sts get-caller-identity.
Then, create the IAM policy:
aws iam create-policy --policy-name LimitedEC2Access --policy-document file://limited-policy.json --description "Policy granting limited S3 read and CloudWatch Logs write access"
This command will output the ARN (Amazon Resource Name) of the newly created policy. Copy this ARN; you'll need it in the next step.
aws iam detach-role-policy --role-name <role-name> --policy-arn arn:aws:iam::aws:policy/AdministratorAccess
Replace?<role-name>?with the actual name of the IAM role. Replace?arn:aws:iam::aws:policy/AdministratorAccess?with the ARN of the managed policy you want to detach.
2. Attach the new, limited policy:
aws iam attach-role-policy --role-name <role-name> --policy-arn <arn-of-limited-policy>
Replace?<role-name>?with the IAM role name and?<arn-of-limited-policy>?with the ARN of the policy you created in step 3.
3. Test thoroughly:?Verify that your application still functions correctly with the new, limited permissions. This is crucial to avoid breaking your application. Increase permissions incrementally if needed.
How Attackers Can Abuse Instance Metadata Service (IMDSv1 vs. IMDSv2)
EC2 instances have access to metadata about themselves through the Instance Metadata Service (IMDS). This service is accessible via HTTP at?https://169.254.169.254/latest/meta-data/. Among other things, IMDS provides access to the temporary security credentials associated with the IAM role attached to the instance.
IMDSv1 (Legacy):
Example SSRF Payload (in a GET request parameter):
https://example.com/?url=https://169.254.169.254/latest/meta-data/iam/security-credentials/<role-name>/?
IMDSv2 (Latest):
Mitigation: Enforce IMDSv2
Disabling IMDSv1 and requiring IMDSv2 is a critical security measure.
Command-Line Instructions:
Launch a new EC2 instance with IMDSv2 enforced:?When launching an instance, specify the?MetadataOptions?parameter.
aws ec2 run-instances \
--image-id ami-xxxxxxxxxxxxxxxxx \
--instance-type t2.micro \
--subnet-id subnet-xxxxxxxxxxxxxxxxx \
--iam-instance-profile Arn=arn:aws:iam::<your-account-id>:instance-profile/<instance-profile-name> \
--metadata-options "HttpTokens=required,HttpPutResponseHopLimit=1,HttpEndpoint=enabled"
?
Replace the?ami-xxxxxxxxxxxxxxxxx,?subnet-xxxxxxxxxxxxxxxxx,?<your-account-id>, and?<instance-profile-name>?with your actual values.
Update existing instances to require IMDSv2:
aws ec2 modify-instance-metadata-options \
--instance-id <instance-id> \
--http-tokens required \
--http-put-response-hop-limit 1 \
--http-endpoint enabled
Replace?<instance-id>?with the ID of the EC2 instance you want to update.
Verify IMDSv2 is enforced:?SSH into the instance and try to access the instance metadata without a token. You should receive an error.
Attempt to access instance metadata using IMDSv1 (This should fail):
curl https://169.254.169.254/latest/meta-data/iam/security-credentials/<role-name>/
Get the IMDSv2 token:
TOKEN=`curl -X PUT "https://169.254.169.254/latest/api/token" -H "X-aws-ec2-metadata-token-ttl-seconds: 21600"`
Now, use the token to access the metadata:
curl -H "X-aws-ec2-metadata-token: $TOKEN" https://169.254.169.254/latest/meta-data/iam/security-credentials/<role-name>/?
This last command should succeed.
Further Hardening Tips:
Conclusion:
Securing your AWS environment requires a proactive and layered approach. Properly configuring IAM roles and instance profiles, combined with enforcing IMDSv2 (or IMDSv3) and implementing the Principle of Least Privilege, significantly reduces your attack surface and protects your data from unauthorized access. Regular auditing and monitoring are crucial for maintaining a secure posture in the ever-evolving cloud landscape. Remember that security is a journey, not a destination!
?
#AWS #CloudSecurity #IAM #DevSecOps #CyberSecurity #AWSIAM #CloudComputing #SecurityBestPractices #DevOps