mirror of
https://github.com/zeek/zeek.git
synced 2025-10-14 04:28:20 +00:00
FileAnalysis: replace script-layer FTP file analysis.
The notable difference here is that ftp.log now logs by default the PORT, PASV, EPRT, EPSV commands as well as a separate line for ftp-data channels in which file extraction was requested. This difference isn't a direct result of now doing the file extraction through the file analysis framework, it's just because I noticed even the old way of tracking extracted-file name didn't work right and this was the way I came up with so that a locally extracted file can be associated with a data channel and then that data channel associated with a control channel.
This commit is contained in:
parent
621fe51c82
commit
7e895a3a2f
13 changed files with 227 additions and 67 deletions
|
@ -16,7 +16,8 @@ export {
|
|||
|
||||
## List of commands that should have their command/response pairs logged.
|
||||
const logged_commands = {
|
||||
"APPE", "DELE", "RETR", "STOR", "STOU", "ACCT"
|
||||
"APPE", "DELE", "RETR", "STOR", "STOU", "ACCT", "PORT", "PASV", "EPRT",
|
||||
"EPSV"
|
||||
} &redef;
|
||||
|
||||
## This setting changes if passwords used in FTP sessions are captured or not.
|
||||
|
@ -24,6 +25,18 @@ export {
|
|||
|
||||
## User IDs that can be considered "anonymous".
|
||||
const guest_ids = { "anonymous", "ftp", "ftpuser", "guest" } &redef;
|
||||
|
||||
## The expected endpoints of an FTP data channel.
|
||||
type ExpectedDataChannel: record {
|
||||
## Whether PASV mode is toggled for control channel.
|
||||
passive: bool &log;
|
||||
## The host that will be initiating the data connection.
|
||||
orig_h: addr &log;
|
||||
## The host that will be accepting the data connection.
|
||||
resp_h: addr &log;
|
||||
## The port at which the acceptor is listening for the data connection.
|
||||
resp_p: port &log;
|
||||
};
|
||||
|
||||
type Info: record {
|
||||
## Time when the command was sent.
|
||||
|
@ -54,7 +67,10 @@ export {
|
|||
reply_msg: string &log &optional;
|
||||
## Arbitrary tags that may indicate a particular attribute of this command.
|
||||
tags: set[string] &log &default=set();
|
||||
|
||||
|
||||
## Expected FTP data channel.
|
||||
data_channel: ExpectedDataChannel &log &optional;
|
||||
|
||||
## Current working directory that this session is in. By making
|
||||
## the default value '/.', we can indicate that unless something
|
||||
## more concrete is discovered that the existing but unknown
|
||||
|
@ -103,7 +119,7 @@ redef dpd_config += { [ANALYZER_FTP] = [$ports = ports] };
|
|||
redef likely_server_ports += { 21/tcp, 2811/tcp };
|
||||
|
||||
# Establish the variable for tracking expected connections.
|
||||
global ftp_data_expected: table[addr, port] of Info &create_expire=5mins;
|
||||
global ftp_data_expected: table[addr, port] of Info &read_expire=5mins;
|
||||
|
||||
event bro_init() &priority=5
|
||||
{
|
||||
|
@ -180,7 +196,7 @@ function ftp_message(s: Info)
|
|||
delete s$arg;
|
||||
else
|
||||
s$arg=arg;
|
||||
|
||||
|
||||
Log::write(FTP::LOG, s);
|
||||
}
|
||||
|
||||
|
@ -190,8 +206,19 @@ function ftp_message(s: Info)
|
|||
delete s$mime_type;
|
||||
delete s$mime_desc;
|
||||
delete s$file_size;
|
||||
# Same with data channel.
|
||||
delete s$data_channel;
|
||||
# Tags are cleared everytime too.
|
||||
delete s$tags;
|
||||
s$tags = set();
|
||||
}
|
||||
|
||||
function add_expected_data_channel(s: Info, chan: ExpectedDataChannel)
|
||||
{
|
||||
s$passive = chan$passive;
|
||||
s$data_channel = chan;
|
||||
ftp_data_expected[chan$resp_h, chan$resp_p] = s;
|
||||
expect_connection(chan$orig_h, chan$resp_h, chan$resp_p, ANALYZER_FTP_DATA,
|
||||
5mins);
|
||||
}
|
||||
|
||||
event ftp_request(c: connection, command: string, arg: string) &priority=5
|
||||
|
@ -226,10 +253,8 @@ event ftp_request(c: connection, command: string, arg: string) &priority=5
|
|||
|
||||
if ( data$valid )
|
||||
{
|
||||
c$ftp$passive=F;
|
||||
ftp_data_expected[data$h, data$p] = c$ftp;
|
||||
expect_connection(id$resp_h, data$h, data$p, ANALYZER_FTP_DATA,
|
||||
5mins);
|
||||
add_expected_data_channel(c$ftp, [$passive=F, $orig_h=id$resp_h,
|
||||
$resp_h=data$h, $resp_p=data$p]);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -280,10 +305,9 @@ event ftp_reply(c: connection, code: count, msg: string, cont_resp: bool) &prior
|
|||
|
||||
if ( code == 229 && data$h == [::] )
|
||||
data$h = id$resp_h;
|
||||
|
||||
ftp_data_expected[data$h, data$p] = c$ftp;
|
||||
expect_connection(id$orig_h, data$h, data$p, ANALYZER_FTP_DATA,
|
||||
5mins);
|
||||
|
||||
add_expected_data_channel(c$ftp, [$passive=T, $orig_h=id$orig_h,
|
||||
$resp_h=data$h, $resp_p=data$p]);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -333,14 +357,13 @@ event file_transferred(c: connection, prefix: string, descr: string,
|
|||
}
|
||||
}
|
||||
|
||||
event file_transferred(c: connection, prefix: string, descr: string,
|
||||
mime_type: string) &priority=-5
|
||||
event connection_state_remove(c: connection) &priority=-5
|
||||
{
|
||||
local id = c$id;
|
||||
if ( [id$resp_h, id$resp_p] in ftp_data_expected )
|
||||
delete ftp_data_expected[id$resp_h, id$resp_p];
|
||||
}
|
||||
|
||||
|
||||
# Use state remove event to cover connections terminated by RST.
|
||||
event connection_state_remove(c: connection) &priority=-5
|
||||
{
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue