Merge remote-tracking branch 'origin/topic/johanna/gh-4463'

* origin/topic/johanna/gh-4463:
  Add explicit TLS support for FTP
This commit is contained in:
Johanna Amann 2025-05-27 17:46:35 +01:00
commit 8ce741a7a8
12 changed files with 84 additions and 2 deletions

View file

@ -1,3 +1,10 @@
8.0.0-dev.229 | 2025-05-27 17:46:35 +0100
* Add explicit TLS support for FTP (Johanna Amann, Corelight)
This is defined in RFC 4217; TLS is initialized by the client sending an
`AUTH TLS` command.
8.0.0-dev.227 | 2025-05-27 10:18:49 -0400 8.0.0-dev.227 | 2025-05-27 10:18:49 -0400
* spicy-redis: Separate error replies from success (Evan Typanski, Corelight) * spicy-redis: Separate error replies from success (Evan Typanski, Corelight)

2
NEWS
View file

@ -53,6 +53,8 @@ New Functionality
Analyzer::ANALYZER_REDIS, Analyzer::ANALYZER_REDIS,
}; };
- The FTP analyzer now supports explicit TLS via AUTH TLS.
Changed Functionality Changed Functionality
--------------------- ---------------------

View file

@ -1 +1 @@
8.0.0-dev.227 8.0.0-dev.229

View file

@ -65,6 +65,11 @@ static bool is_ftp_cmd(int len, const char* s) {
void FTP_Analyzer::DeliverStream(int length, const u_char* data, bool orig) { void FTP_Analyzer::DeliverStream(int length, const u_char* data, bool orig) {
analyzer::tcp::TCP_ApplicationAnalyzer::DeliverStream(length, data, orig); analyzer::tcp::TCP_ApplicationAnalyzer::DeliverStream(length, data, orig);
if ( tls_active ) {
ForwardStream(length, data, orig);
return;
}
if ( (orig && ! ftp_request) || (! orig && ! ftp_reply) ) if ( (orig && ! ftp_request) || (! orig && ! ftp_reply) )
return; return;
@ -172,6 +177,17 @@ void FTP_Analyzer::DeliverStream(int length, const u_char* data, bool orig) {
} }
} }
if ( reply_code == 234 && auth_requested.size() > 0 && auth_requested == "TLS" ) {
EnqueueConnEvent(ftp_starttls, ConnVal());
Analyzer* ssl = analyzer_mgr->InstantiateAnalyzer("SSL", Conn());
if ( ssl ) {
AddChildAnalyzer(ssl);
RemoveSupportAnalyzer(nvt_orig);
RemoveSupportAnalyzer(nvt_resp);
tls_active = true;
}
}
if ( reply_code == 334 && auth_requested.size() > 0 && auth_requested == "GSSAPI" ) { if ( reply_code == 334 && auth_requested.size() > 0 && auth_requested == "GSSAPI" ) {
// Server wants to proceed with an ADAT exchange and we // Server wants to proceed with an ADAT exchange and we
// know how to analyze the GSI mechanism, so attach analyzer // know how to analyze the GSI mechanism, so attach analyzer
@ -192,7 +208,8 @@ void FTP_Analyzer::DeliverStream(int length, const u_char* data, bool orig) {
EnqueueConnEvent(f, std::move(vl)); EnqueueConnEvent(f, std::move(vl));
ForwardStream(length, data, orig); if ( ! tls_active )
ForwardStream(length, data, orig);
} }
void FTP_ADAT_Analyzer::DeliverStream(int len, const u_char* data, bool orig) { void FTP_ADAT_Analyzer::DeliverStream(int len, const u_char* data, bool orig) {

View file

@ -24,6 +24,7 @@ protected:
analyzer::login::NVT_Analyzer* nvt_resp; analyzer::login::NVT_Analyzer* nvt_resp;
uint32_t pending_reply; // code associated with multi-line reply, or 0 uint32_t pending_reply; // code associated with multi-line reply, or 0
std::string auth_requested; // AUTH method requested std::string auth_requested; // AUTH method requested
bool tls_active = false; // starttls active
}; };
/** /**

View file

@ -33,3 +33,9 @@ event ftp_request%(c: connection, command: string, arg: string%);
## parse_ftp_epsv parse_ftp_pasv parse_ftp_port ## parse_ftp_epsv parse_ftp_pasv parse_ftp_port
event ftp_reply%(c: connection, code: count, msg: string, cont_resp: bool%); event ftp_reply%(c: connection, code: count, msg: string, cont_resp: bool%);
## Generated if an FTP connection switched to TLS using AUTH TLS. After this
## event no more FTP events will be raised for the connection. See the SSL
## analyzer for related SSL events, which will now be generated.
##
## c: The connection.
event ftp_starttls%(c: connection%);

View file

@ -0,0 +1,2 @@
### BTest baseline data generated by btest-diff. Do not edit. Use "btest -U/-u" to update. Requires BTest >= 0.63.
starttls, [orig_h=127.0.0.1, orig_p=40284/tcp, resp_h=127.0.0.1, resp_p=21/tcp, proto=6]

View file

@ -0,0 +1,11 @@
### BTest baseline data generated by btest-diff. Do not edit. Use "btest -U/-u" to update. Requires BTest >= 0.63.
#separator \x09
#set_separator ,
#empty_field (empty)
#unset_field -
#path conn
#open XXXX-XX-XX-XX-XX-XX
#fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p proto service duration orig_bytes resp_bytes conn_state local_orig local_resp missed_bytes history orig_pkts orig_ip_bytes resp_pkts resp_ip_bytes tunnel_parents ip_proto
#types time string addr port addr port enum string interval count count string bool bool count string count count count count set[string] count
XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 127.0.0.1 40284 127.0.0.1 21 tcp ftp,ssl 23.881319 1133 3314 RSTR T T 0 ShAdDafr 40 3221 44 5598 - 6
#close XXXX-XX-XX-XX-XX-XX

View file

@ -0,0 +1,12 @@
### BTest baseline data generated by btest-diff. Do not edit. Use "btest -U/-u" to update. Requires BTest >= 0.63.
#separator \x09
#set_separator ,
#empty_field (empty)
#unset_field -
#path ftp
#open XXXX-XX-XX-XX-XX-XX
#fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p user password command arg mime_type file_size reply_code reply_msg data_channel.passive data_channel.orig_h data_channel.resp_h data_channel.resp_p fuid
#types time string addr port addr port string string string string string count count string bool addr addr port string
XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 127.0.0.1 40284 127.0.0.1 21 <unknown> - <init> - - - 220 (vsFTPd 3.0.5) - - - - -
XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 127.0.0.1 40284 127.0.0.1 21 <unknown> - AUTH TLS - - 234 Proceed with negotiation. - - - - -
#close XXXX-XX-XX-XX-XX-XX

View file

@ -0,0 +1,11 @@
### BTest baseline data generated by btest-diff. Do not edit. Use "btest -U/-u" to update. Requires BTest >= 0.63.
#separator \x09
#set_separator ,
#empty_field (empty)
#unset_field -
#path ssl
#open XXXX-XX-XX-XX-XX-XX
#fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p version cipher curve server_name resumed last_alert next_protocol established ssl_history cert_chain_fps client_cert_chain_fps sni_matches_cert
#types time string addr port addr port string string string string bool string string bool string vector[string] vector[string] bool
XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 127.0.0.1 40284 127.0.0.1 21 TLSv13 TLS_AES_256_GCM_SHA384 secp256r1 127.0.0.1 F - - T CsiI - - -
#close XXXX-XX-XX-XX-XX-XX

Binary file not shown.

View file

@ -0,0 +1,13 @@
# This tests explicit TLS.
#
# @TEST-EXEC: zeek -r $TRACES/ftp/ftp-auth-tls.pcap %INPUT
# @TEST-EXEC: btest-diff conn.log
# @TEST-EXEC: btest-diff ftp.log
# @TEST-EXEC: btest-diff ssl.log
# @TEST-EXEC: btest-diff .stdout
redef FTP::logged_commands += { "<init>", "AUTH" };
event ftp_starttls(c: connection) {
print "starttls", c$id;
}