Instance Metadata Service Version 2 (IMDSv2): Work memo for setting and behavior confirmation of Instance Metadata Service v2
https://docs.aws.amazon.com/ja_jp/AWSEC2/latest/UserGuide/ec2-instance-metadata.html
Instance metadata is data about an instance and is used to configure or manage a running instance. Instance metadata is divided into categories such as host name, event, and security group.
https://docs.aws.amazon.com/ja_jp/AWSEC2/latest/UserGuide/configuring-instance-metadata-service.html
You can access the instance metadata from a running instance using one of the following methods:
--Instance Metadata Service Version 1 (IMDSv1) – Request / Response Method --Instance Metadata Service Version 2 (IMDSv2) – Session-Oriented Methods
How Instance Metadata Service Version 2 Works
IMDSv2 uses session-oriented requests. Use session-oriented requests to create a session token that defines the session duration (1 second to 6 hours). You can use the same session token for subsequent requests during the specified time period. After the specified time period expires, you need to create a new session token to use for future requests.
On July 29, 2019, personal information of more than 100 million people was leaked due to unauthorized access at Capital One, a major US financial company.
Information on the Capital One Cyber Incident https://www.capitalone.com/facts2019/
The causes of information leakage are as follows
--An attacker accesses EC2 instance metadata via WAF and obtains IAM Role credentials (access to S3). --IMDSv1 does not authenticate to connect to metadata. --Using the acquired IAM Role authentication information, access S3 of Capital One and acquire the information.
On the other hand, IMDSv2 requires a Token obtained in advance to access the metadata. The usage of IMDSv2 and the advantages in terms of security are as follows.
--Create a 6 hour (21,600 second) session token using a PUT request --Store the session token header in a variable named TOKEN --Request top-level metadata items using tokens
--Since most WAFs do not allow PUT requests, it is unlikely that external access via the WAF will succeed. --The hop limit of the metadata response can be shortened to prevent acquisition via multiple hosts. (If set to 1, you can prevent the acquisition of metadata via WAF as it occurred in Capital One) --PUT request is rejected if it contains an X-Forwarded-For header. (On proxy servers, usually add an X-Forwarded-For header)
Prepare an instance (cli_instance) for AWS-CLI execution to issue an instance build / configuration change command
cli_instance environment(AWS-CLI publisher environmental information)
[root@ip-10-0-0-74 ~]# cat /etc/system-release
Amazon Linux release 2 (Karoo)
[root@ip-10-0-0-74 ~]#
[root@ip-10-0-0-74 ~]# uname -a
Linux ip-10-0-0-74.ap-northeast-1.compute.internal 4.14.193-149.317.amzn2.x86_64 #1 SMP Thu Sep 3 19:04:44 UTC 2020 x86_64 x86_64 x86_64 GNU/Linux
[root@ip-10-0-0-74 ~]#
[root@ip-10-0-0-74 ~]# aws --version
aws-cli/1.18.107 Python/2.7.18 Linux/4.14.193-149.317.amzn2.x86_64 botocore/1.17.31
[root@ip-10-0-0-74 ~]#
[root@ip-10-0-0-74 ~]# curl http://169.254.169.254/latest/meta-data/instance-type/
t3.small
[root@ip-10-0-0-74 ~]#
IMDSv2 operation confirmation instance "test_instance" construction
cli_instance environment(run-Instance execution)
[root@ip-10-0-0-74 ~]# aws ec2 run-instances \
> --image-id ami-0ce107ae7af2e92b5 \
> --instance-type t2.nano \
> --key-name key_file \
> --monitoring Enabled=false \
> --placement AvailabilityZone=ap-northeast-1a \
> --subnet-id subnet-03d74b8d6ab6c39f2 \
> --associate-public-ip-address \
> --security-group-ids sg-0a00ecb871bb15fb3 \
> --tag-specifications 'ResourceType=instance,Tags=[{Key=Name,Value=test_instance}]'
Constructed instance (test_instance) Check default instance metadata settings
cli_instance environment(describe-Instance execution)
[root@ip-10-0-0-74 ~]# aws ec2 describe-instances \
> --filters "Name=tag:Name,Values=test_instance" \
> --query Reservations[*].Instances[*].[MetadataOptions]
[
[
[
{
"State": "applied",
"HttpEndpoint": "enabled",
"HttpTokens": "optional",
"HttpPutResponseHopLimit": 1
}
]
]
]
[root@ip-10-0-0-74 ~]#
" HttpTokens ":" optional "-> IMDSv1 / IMDSv2 are both available
" HttpTokens ":" required "-> IMDSv2 only available (IMDSv2 enforcement)
The following is executed on the newly constructed" test_instance "environment
test_instance environment (IMDSv1 execution)
[root@ip-10-0-0-68 ~]# curl http://169.254.169.254/latest/meta-data/
ami-id
ami-launch-index
ami-manifest-path
block-device-mapping/
events/
hostname
identity-credentials/
instance-action
instance-id
instance-life-cycle
instance-type
local-hostname
local-ipv4
mac
metrics/
network/
placement/
profile
public-hostname
public-ipv4
public-keys/
reservation-id
security-groups
services/
[root@ip-10-0-0-68 ~]#
test_instance environment (IMDSv2 execution)
[root@ip-10-0-0-68 ~]# TOKEN=`curl -X PUT "http://169.254.169.254/latest/api/token" -H "X-aws-ec2-metadata-token-ttl-seconds: 21600"` && curl -H "X-aws-ec2-metadata-token: $TOKEN" -v http://169.254.169.254/latest/meta-data/
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 56 100 56 0 0 9333 0 --:--:-- --:--:-- --:--:-- 11200
* Trying 169.254.169.254...
* TCP_NODELAY set
* Connected to 169.254.169.254 (169.254.169.254) port 80 (#0)
> GET /latest/meta-data/ HTTP/1.1
> Host: 169.254.169.254
> User-Agent: curl/7.61.1
> Accept: */*
> X-aws-ec2-metadata-token: AQAAAO6n081baEIWdrfpILhc9Egt4kTm0HSpUftcYqvJSR-NKewL6A==
>
* HTTP 1.0, assume close after body
< HTTP/1.0 200 OK
< Accept-Ranges: bytes
< Content-Length: 313
< Content-Type: text/plain
< Date: Sat, 26 Sep 2020 14:45:29 GMT
< Last-Modified: Sat, 26 Sep 2020 14:28:58 GMT
< X-Aws-Ec2-Metadata-Token-Ttl-Seconds: 21600
< Connection: close
< Server: EC2ws
<
ami-id
ami-launch-index
ami-manifest-path
block-device-mapping/
events/
hostname
identity-credentials/
instance-action
instance-id
instance-life-cycle
instance-type
local-hostname
local-ipv4
mac
metrics/
network/
placement/
profile
public-hostname
public-ipv4
public-keys/
reservation-id
security-groups
* Closing connection 0
services/
[root@ip-10-0-0-68 ~]#
The following is executed on the AWS-CLI execution environment" cli_instance "environment
cli_instance environment
[root@ip-10-0-0-74 ~]# # test_Get instance ID of instance
[root@ip-10-0-0-74 ~]# aws ec2 describe-instances \
> --filters "Name=tag:Name,Values=test_instance" \
> --query Reservations[*].Instances[*].[InstanceId]
[
[
[
"i-034109c70aaa4b055"
]
]
]
[root@ip-10-0-0-74 ~]#
[root@ip-10-0-0-74 ~]# #Execution of IMDSv2 forced setting("HttpTokens": "required")
[root@ip-10-0-0-74 ~]# aws ec2 modify-instance-metadata-options \
> --instance-id i-034109c70aaa4b055 \
> --http-tokens required \
> --http-put-response-hop-limit 1 \
> --http-endpoint enabled
{
"InstanceId": "i-034109c70aaa4b055",
"InstanceMetadataOptions": {
"State": "pending",
"HttpEndpoint": "enabled",
"HttpTokens": "required",
"HttpPutResponseHopLimit": 1
}
}
[root@ip-10-0-0-74 ~]#
The following is executed on the newly constructed" test_instance "environment
test_instance environment (IMDSv1 execution)
[root@ip-10-0-0-68 ~]# curl http://169.254.169.254/latest/meta-data/
<?xml version="1.0" encoding="iso-8859-1"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<title>401 - Unauthorized</title>
</head>
<body>
<h1>401 - Unauthorized</h1>
</body>
</html>
[root@ip-10-0-0-68 ~]#
ʻIMDSv2 is forced and cannot be obtained by the IMDSv1 method`
test_instance environment (IMDSv2 execution)
[root@ip-10-0-0-68 ~]# TOKEN=`curl -X PUT "http://169.254.169.254/latest/api/token" -H "X-aws-ec2-metadata-token-ttl-seconds: 21600"` && curl -H "X-aws-ec2-metadata-token: $TOKEN" -v http://169.254.169.254/latest/meta-data/
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 56 100 56 0 0 9333 0 --:--:-- --:--:-- --:--:-- 11200
* Trying 169.254.169.254...
* TCP_NODELAY set
* Connected to 169.254.169.254 (169.254.169.254) port 80 (#0)
> GET /latest/meta-data/ HTTP/1.1
> Host: 169.254.169.254
> User-Agent: curl/7.61.1
> Accept: */*
> X-aws-ec2-metadata-token: AQAAAO6n081aj7u-yzdFHoD8zll2ZKiNfVS79OXp1qJDwgzw7-96gA==
>
* HTTP 1.0, assume close after body
< HTTP/1.0 200 OK
< Accept-Ranges: bytes
< Content-Length: 313
< Content-Type: text/plain
< Date: Sat, 26 Sep 2020 15:01:45 GMT
< Last-Modified: Sat, 26 Sep 2020 14:28:58 GMT
< X-Aws-Ec2-Metadata-Token-Ttl-Seconds: 21600
< Connection: close
< Server: EC2ws
<
ami-id
ami-launch-index
ami-manifest-path
block-device-mapping/
events/
hostname
identity-credentials/
instance-action
instance-id
instance-life-cycle
instance-type
local-hostname
local-ipv4
mac
metrics/
network/
placement/
profile
public-hostname
public-ipv4
public-keys/
reservation-id
security-groups
* Closing connection 0
services/
[root@ip-10-0-0-68 ~]#