aerissecure / nse

Nmap NSE scripts
28 stars 13 forks source link

FTP Check #8

Open freb opened 7 years ago

freb commented 7 years ago

Nessus has this plugin (https://www.tenable.com/plugins/index.php?view=single&id=34324) that doesn't always fire. It would be nice to have a plugin for nmap to double check. FTP has a few different modes. There is FTPS which runs over an always encrypted connection. There is normal unencrypted connections over 20/21 and then there is the AUTH TLS which upgrades the connection. It would be nice to tease out exactly what is supported.

freb commented 5 years ago

If you look at the [FTP library[(https://nmap.org/nsedoc/lib/ftp.html) for nmap, it is super simple. Just a few functions wrapping the lower level comm library. It should be easy to add this functionality.

freb commented 5 years ago

Content of ftp_clear_text_credentials.nasl:

#
# (C) Tenable Network Security, Inc.
#

include("compat.inc");

if (description)
{
 script_id(34324);
 script_version("$Revision: 1.25 $");
 script_cvs_date("$Date: 2016/12/08 20:42:13 $");

 script_name(english:"FTP Supports Cleartext Authentication");
 script_summary(english:"Check if the FTP server accepts passwords in cleartext.");

 script_set_attribute(attribute:"synopsis", value:"Authentication credentials might be intercepted.");
 script_set_attribute(attribute:"description", value:
"The remote FTP server allows the user's name and password to be
transmitted in cleartext, which could be intercepted by a network
sniffer or a man-in-the-middle attack.");
 script_set_attribute(attribute:"solution", value:
"Switch to SFTP (part of the SSH suite) or FTPS (FTP over SSL/TLS). In
the latter case, configure the server so that control connections are
encrypted.");
 script_set_cvss_base_vector("CVSS2#AV:N/AC:H/Au:N/C:P/I:N/A:N");
 script_cwe_id(
   522, # Insufficiently Protected Credentials
   523, # Unprotected Transport of Credentials
   928, # Weaknesses in OWASP Top Ten 2013
   930  # OWASP Top Ten 2013 Category A2 - Broken Authentication and Session Management
 );

 script_set_attribute(attribute:"plugin_publication_date", value:"2008/10/01");

 script_set_attribute(attribute:"plugin_type", value:"remote");
 script_end_attributes();

 script_category(ACT_GATHER_INFO);

 script_copyright(english:"This script is Copyright (C) 2008-2016 Tenable Network Security, Inc.");
 script_family(english:"FTP");

 script_dependencies("ftpserver_detect_type_nd_version.nasl", "ftp_starttls.nasl");
 script_require_ports("Services/ftp", 21);

 exit(0);
}

include("audit.inc");
include("global_settings.inc");
include("misc_func.inc");
include("ftp_func.inc");

user = get_kb_item('ftp/login');
if (strlen(user) == 0 || user == 'anonymous' || user == 'ftp')
{
  if (supplied_logins_only)  audit(AUDIT_SUPPLIED_LOGINS_ONLY);

  user = rand_str(length:8, charset:'abcdefghijklmnopqrstuvwxyz');
}
pass = get_kb_item('ftp/password');
if (strlen(pass) == 0) pass = 'root@example.com';

port = get_ftp_port(default: 21);

banner = get_ftp_banner(port: port);
if (strlen(banner) == 0) exit(1, "No FTP banner on port "+port+".");
if (banner =~ '^[45][0-9][0-9][ -]')
 exit(1, "The FTP server on port "+port+" rejects our connections.");

trp = get_port_transport(port);
if (trp > ENCAPS_IP)
 exit(0, "The FTP server on port "+port+" is running through SSL/TLS.");

soc = open_sock_tcp(port);
if (! soc) audit(AUDIT_SOCK_FAIL, port);

b = ftp_recv_line(socket: soc);
if (b =~ '^2[0-9][0-9][ -]')
{
 u = ftp_send_cmd(socket: soc, cmd: 'USER '+user);
 if (u =~ '^3[0-9][0-9][ -]')
 {
  if (report_verbosity < 1)
  {
    if ( get_kb_item("Settings/PCI_DSS") ) set_kb_item(name:"PCI/ClearTextCreds/" + port,
                        value:"The remote FTP server allows the credentials to be transmitted in clear text.");
    security_note(port);
  }
  else
  {
   if (get_kb_item("ftp/"+port+"/starttls")) report =
'\nAlthough this FTP server supports \'AUTH TLS\', it is not mandatory
and USER and PASS may be sent without switching to TLS.';
   else report = '\nThis FTP server does not support \'AUTH TLS\'.';

   if ( get_kb_item("Settings/PCI_DSS") ) set_kb_item(name:"PCI/ClearTextCreds/" + port, value:report);
   security_note(port:port, extra:report);
  }

  # Make FTPD happy
  b = ftp_send_cmd(socket: soc, cmd: 'PASS '+pass);
 }
}
ftp_close(socket: soc);
freb commented 5 years ago

There are also servers which support Auth TLS but don't mandate it. See example in .nmap-commands.

freb commented 5 years ago

Accepting USER and PASS without upgrading connection means plaintext support:

220 ProFTPD Server (ProFTPD) [x.x.x.41]
USER pentest
331 Password required for pentest
PASS pentest
530 Login incorrect.
quit
221 Goodbye.
freb commented 5 years ago

Supporting pltainext connection, but not login:

telnet x.x.x.177 1`
Trying x.x.x.177...
Connected to x.x.x.177.
Escape character is '^]'.
220 FTP Server Ready
USER asdf
550 SSL/TLS required on the control channel
quit
221 Goodbye.
Connection closed by foreign host.

You should use the Auth command over the plain control connection initialize a secure connection. Something like:

Trying x.x.x.177...
Connected to x.x.x.177.
Escape character is '^]'.
220 FTP Server Ready
AUTH
504 AUTH requires at least one argument
AUTH TLS
234 AUTH TLS successful
USER asdf
550 TLS handshake failed
Connection closed by foreign host.
freb commented 5 years ago

There is also the ftp_starttls.nasl, FTP Service AUTH TLS Command Support which will attempt the actual connection. It will report on whether it was able to establish an encrypted connection and whether they are likely supported:

The remote FTP service responded to the 'AUTH TLS' command with a
'234' response code, suggesting that it supports that command.  However,
we failed to negotiate a TLS connection or get the associated SSL
certificate, perhaps because of a network connectivity problem or the
service requires a peer certificate as part of the negotiation.
freb commented 4 years ago

One more wrinkle. Just encountered a server that will let connect over plaintext, but then when you attempt USER asdf, it drops the connection with:

Connected to x.x.x.x
Escape character is '^]'.
220 (vsFTPd 3.0.2)
USER asdf
530 Non-anonymous sessions must use encryption.
Connection closed by foreign host.

In order of severity, you have:

  1. plaintext ftp, no support for AUTH TLS, permits logins
  2. plaintext ftp, supports AUTH TLS, permits logins
  3. plaintext ftp for anon only, supports AUTH TLS, permits logins only after AUTH TLS
  4. no plaintext ftp
freb commented 4 years ago

Another response:

USER asdf
530 This server does not allow plain FTP. You have to use FTP over TLS.