diff --git a/scripts/base/frameworks/notice/weird.zeek b/scripts/base/frameworks/notice/weird.zeek index 9d9a3dfbdd..aa7a412bbd 100644 --- a/scripts/base/frameworks/notice/weird.zeek +++ b/scripts/base/frameworks/notice/weird.zeek @@ -136,6 +136,7 @@ export { ["FIN_advanced_last_seq"] = ACTION_LOG, ["FIN_after_reset"] = ACTION_IGNORE, ["FIN_storm"] = ACTION_NOTICE_PER_ORIG, + ["FTP_max_command_length_exceeded"] = ACTION_LOG_PER_CONN, ["FTP_too_many_pending_commands"] = ACTION_LOG_PER_CONN, ["HTTP_bad_chunk_size"] = ACTION_LOG, ["HTTP_chunked_transfer_for_multipart_message"] = ACTION_LOG, diff --git a/scripts/base/init-bare.zeek b/scripts/base/init-bare.zeek index c1f73949cc..63bbd532ad 100644 --- a/scripts/base/init-bare.zeek +++ b/scripts/base/init-bare.zeek @@ -337,6 +337,15 @@ type ftp_port: record { valid: bool; ##< True if format was right. Only then are *h* and *p* valid. }; + +module FTP; + +## Limits the size of commands accepted by the FTP analyzer. Longer commands +## raise a FTP_max_command_length_exceeded weird and are discarded. +const max_command_length = 100 &redef; + +module GLOBAL; + ## Statistics about what a TCP endpoint sent. ## ## .. zeek:see:: conn_stats diff --git a/src/analyzer/protocol/ftp/FTP.cc b/src/analyzer/protocol/ftp/FTP.cc index 1142e092ff..bfdd42da34 100644 --- a/src/analyzer/protocol/ftp/FTP.cc +++ b/src/analyzer/protocol/ftp/FTP.cc @@ -96,6 +96,17 @@ void FTP_Analyzer::DeliverStream(int length, const u_char* data, bool orig) // Weird("FTP command missing", end_of_line - orig_line, orig_line); cmd_str = new StringVal(""); } + else if ( BifConst::FTP::max_command_length > 0 && + static_cast(cmd_len) > BifConst::FTP::max_command_length ) + { + // If the FTP command is unusually long, log a weird if the analyzer + // has previously been confirmed, but otherwise just ignore the whole + // line and move on to the next. + if ( AnalyzerConfirmed() ) + Weird("FTP_max_command_length_exceeded", util::fmt("%d", cmd_len)); + + return; + } else cmd_str = (new StringVal(cmd_len, cmd))->ToUpper(); diff --git a/src/const.bif b/src/const.bif index 2658376817..f28429b33c 100644 --- a/src/const.bif +++ b/src/const.bif @@ -11,6 +11,8 @@ const exit_only_after_terminate: bool; const digest_salt: string; const max_analyzer_violations: count; +const FTP::max_command_length: count; + const NFS3::return_data: bool; const NFS3::return_data_max: count; const NFS3::return_data_first_only: bool; diff --git a/testing/btest/Baseline/scripts.base.protocols.ftp.ftp-max-command-length/conn.log b/testing/btest/Baseline/scripts.base.protocols.ftp.ftp-max-command-length/conn.log new file mode 100644 index 0000000000..c7fb619584 --- /dev/null +++ b/testing/btest/Baseline/scripts.base.protocols.ftp.ftp-max-command-length/conn.log @@ -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 +#types time string addr port addr port enum string interval count count string bool bool count string count count count count set[string] +XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 127.0.0.1 58634 127.0.0.1 21 tcp ftp 0.213412 358 313 SF - - 0 ShAdDaFf 23 1562 17 1205 - +#close XXXX-XX-XX-XX-XX-XX diff --git a/testing/btest/Baseline/scripts.base.protocols.ftp.ftp-max-command-length/dpd.log b/testing/btest/Baseline/scripts.base.protocols.ftp.ftp-max-command-length/dpd.log new file mode 100644 index 0000000000..55429f6c38 --- /dev/null +++ b/testing/btest/Baseline/scripts.base.protocols.ftp.ftp-max-command-length/dpd.log @@ -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 dpd +#open XXXX-XX-XX-XX-XX-XX +#fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p proto analyzer failure_reason +#types time string addr port addr port enum string string +XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 127.0.0.1 58634 127.0.0.1 21 tcp FTP FTP::max_command_length exceeded +#close XXXX-XX-XX-XX-XX-XX diff --git a/testing/btest/Baseline/scripts.base.protocols.ftp.ftp-max-command-length/ftp.log b/testing/btest/Baseline/scripts.base.protocols.ftp.ftp-max-command-length/ftp.log new file mode 100644 index 0000000000..4a2c02d8c2 --- /dev/null +++ b/testing/btest/Baseline/scripts.base.protocols.ftp.ftp-max-command-length/ftp.log @@ -0,0 +1,15 @@ +### 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 58634 127.0.0.1 21 anonymous - USER anonymous - - 230 Response to USER command - - - - - +XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 127.0.0.1 58634 127.0.0.1 21 anonymous anonymous@zeek.org SYST - - - 200 Response to TYPEEEEEEEEEEEEE command - - - - - +XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 127.0.0.1 58634 127.0.0.1 21 anonymous anonymous@zeek.org PASV - - - 215 Response to SYSTTTTTTTTTTTTT command - - - - - +XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 127.0.0.1 58634 127.0.0.1 21 anonymous anonymous@zeek.org RETR ftp://127.0.0.1/./robots.txt - - 225 Response to RETR command - - - - - +XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 127.0.0.1 58634 127.0.0.1 21 anonymous anonymous@zeek.org PORT 114,115 - - 200 Response to PORT command - - - - - +#close XXXX-XX-XX-XX-XX-XX diff --git a/testing/btest/Baseline/scripts.base.protocols.ftp.ftp-max-command-length/weird.log b/testing/btest/Baseline/scripts.base.protocols.ftp.ftp-max-command-length/weird.log new file mode 100644 index 0000000000..49022db073 --- /dev/null +++ b/testing/btest/Baseline/scripts.base.protocols.ftp.ftp-max-command-length/weird.log @@ -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 weird +#open XXXX-XX-XX-XX-XX-XX +#fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p name addl notice peer source +#types time string addr port addr port string string bool string string +XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 127.0.0.1 58634 127.0.0.1 21 FTP_max_command_length_exceeded 132 F zeek FTP +#close XXXX-XX-XX-XX-XX-XX diff --git a/testing/btest/Traces/ftp/fake-long-commands.pcap b/testing/btest/Traces/ftp/fake-long-commands.pcap new file mode 100644 index 0000000000..8a31502e8a Binary files /dev/null and b/testing/btest/Traces/ftp/fake-long-commands.pcap differ diff --git a/testing/btest/scripts/base/protocols/ftp/ftp-max-command-length.zeek b/testing/btest/scripts/base/protocols/ftp/ftp-max-command-length.zeek new file mode 100644 index 0000000000..39f0bcca1f --- /dev/null +++ b/testing/btest/scripts/base/protocols/ftp/ftp-max-command-length.zeek @@ -0,0 +1,12 @@ +# @TEST-DOC: Artificially generated pcap with FTP commands of length > 100. Verify generation of the involved logs. +# +# @TEST-EXEC: zeek -b -r $TRACES/ftp/fake-long-commands.pcap %INPUT +# @TEST-EXEC: btest-diff conn.log +# @TEST-EXEC: btest-diff ftp.log +# @TEST-EXEC: btest-diff weird.log +# @TEST-EXEC: test ! -f reporter.log + +@load base/protocols/conn +@load base/protocols/ftp + +redef FTP::logged_commands += { "USER", "SYST" };