The analyzer uses a capture filter of ``port ftp'' (§
The main data structure managed by the ftp analyzer is a collection of ftp_session_info records, where the record type is shown in Figure 7.16.1. The corresponding fields are:
[user] The username associated with this session (from the initial FTP authentication dialog), or an empty string if not yet determined.
[request] The pending request, if the client has issued any. Ordinarily there would be at most one pending request, but a client can in fact send multiple requests to the server all at once, and an attacker could do so attempting to confuse the analyzer into mismatching responses with requests, or simply forgetting about previous requests.
[num_requests] A count of how many requests are currently pending.
[request_t] The time at which the pending request was issued.
[log_if_not_denied] If true, then when the reply to the current request comes in, Bro should log it, unless the reply code is 530 (``denied'').
[log_if_not_unavail] If true, then when the reply to the current request comes in, Bro should log it, unless the reply code is 550 (``unavail'').
[log_it] If true, then when the reply to the current request comes in, Bro should log it.
The standard script defines the following redefinable variables:
Default: { "anonymous", "ftp", "guest", }.
[ftp_skip_hot : set[addr, addr, string]] Entries indicate that a connection from the first given address to the second given address, using the given string username, should not be treated as hot even if the username is sensitive.
Default: empty.
Example: redefining ftp_skip_hot using
redef ftp_skip_hot: set[addr, addr, string] += { [[bob1.dsl.home.net, bob2.dsl.home.net], bob.work.com, "root"], };would result in Bro not alerting on FTP connections as user "root" from either bob1.dsl.home.net or bob2.dsl.home.net to the server running on bob.work.com.
[ftp_hot_files : pattern] Bro matches the argument given in each FTP file manipulation request (RETR, STOR, etc.) against this pattern to see if the file is sensitive. If so, and if the request succeeds, then the access is logged.
eggdrop Default: a pattern that matches various flavors of password files, plus any string with eggdrop in it. Note: Eggdrop is an IRC management tool often installed by certain attackers upon a successful break-in.
[ftp_not_actually_hot_files : pattern] A pattern giving exceptions to ftp_hot_files. It turns out that a pattern like /passwd/ generates a lot of false hits, such as from passwd.c (source for the passwd utility; this can turn up in FTP sessions that fetch entire sets of utility sources using MGET) or passwd.html (a Web page explaining how to enter a password for accessing a particular page).
Default: /(passwd|shadow).*\.
(c|gif|htm|pl|rpm|tar|zip)/ .
[ftp_hot_guest_files : pattern] Files that guests should not attempt to access.
Default: .rhosts and .forward .
[skip_unexpected : set[addr]] If a new host (address) unexpectedly connects to the endpoint specified in a PORT or PASV directive, then if either the original host or the new host is in this set, no message is generated. The idea is that you can specify multi-homed hosts that frequently show up in your FTP traffic, as these can generate innocuous warnings about connections from unexpected hosts.
Default: some hp.com hosts, as an example. Most are specified as raw IP addresses rather than hostnames, since the hostnames don't always consistently resolve.
[skip_unexpected_net : set[addr]] The same as skip_unexpected, except addresses are masked to /24 and /16 before looked up in this set.
Default: empty.
In addition, ftp_log holds the name of the FTP log file to which Bro writes FTP session summaries. It defaults to open_log_file("ftp").
Figure 7.16.2 shows an example of what entries in this file look like. Here we see a transcript of the 26th FTP session seen since Bro started running. The first line gives its start time and the participating hosts and ports. The next line (split across two lines above for clarity) gives the server's welcome banner. The client then logged in as user ``anonymous'', and because this is one of the guest usernames, Bro recorded their password too, which in this case was ``IEUser@'' (a useless string supplied by their Web browser). The server accepted this authentication, so the status on the line is ``(logged in)''.
The client then issues a request for the Image file type, to which the server agreed. Next they issued a PASV directive, and received a response instructing them to connect to the server on port 2427/tcp for the next transfer. At this point, after issuing a SIZE directive (to which the server returned 1,675,597 bytes), they send RETR to fetch the file /pub/OB/4.0/JOB-4.0.3.zip. However, before the transfer completed, they issued ABOR, but the transfer finished before the server processed the abort, so the log shows a status of (completed). Furthermore, because the client issued two commands without waiting for an intervening response, these are shown together in the log file, and the line marked with a ``*'' so it draws the eye. Finally, because Bro paired up the (completed) with the multi-request line, it then treats the response to the ABOR command as a reply by itself, showing in the last line that the server reported it successfully carried out the abort.
The corresponding lines in the red file look like:
972499885.784104 565.836 ftp 118 427 131.243.70.68 64.55.26.206 RSTO L #26 anonymous/IEUser@ 972499888.984116 165.098 ftp-data ? 1675597 131.243.70.68 64.55.26.206 RSTO LThe first line summarizes the FTP control session (over which the client sends its requests and receives the server's responses). It includes an addl annotation of ``#26 anonymous/IEUser@'', summarizing the session number (so you can find the corresponding records in the ftp log file) and the authentication information.
The second line summarizes the single FTP data transfer, of 1,675,597 bytes. The amount of data sent by the client for this connection is shown as unknown because the client aborted the connection with a RST (hence the state RSTO). For connections that Bro does not look inside (such as FTP data transfers), it learns the amount of data transferred from the sequence numbers of the SYN and FIN connection control packets, and can't (reliably) learn them for the sender of a RST. (It can for the receiver of the RST.)
They also aborted the control session (again, state RSTO), but in this case, Bro captured all of the packets of the session, so it could still assign sizes to both directions.
The standard ftp script provides one function for external use:
Also returns true if the source port is 20/tcp and there's currently an FTP session active between the originator and responder, in case for some reason Bro's bookkeeping is inconsistent.
The standard script handles the following events:
The processing depends on the particular command:
The analyzer also updates the connection's addl field with the username.
If the password is empty and the username appears in forbidden_ids_if_no_password (also from the hot-ids analyzer), then the analyzer terminates the connection.
If the username corresponds to a guest account (ftp_guest_ids), then the analyzer updates the connection's addl field with the password as additional account information. Otherwise, it generates an account_tried event to facilitate detection of password guessing.
[ftp_reply (c: connection, code: count, msg: string, cont_resp: bool)] Invoked upon the server side of connection c having replied to a request using the given status code and text message. cont_resp is true if the reply line is tagged as being continued to the next line. The analyzer only processes requests when the last line of a continued reply is received.
The analyzer checks the reply against any expected for the connection (for example, ``log_if_not_denied'') and generates alerts accordingly. If the reply corresponds to a PASV directive, then it parses the address/port specification in the reply and generates alerts in an analogous fashion as done by the ftp_request handler for PORT directives.
Finally, if the reply is not one that the analyzer is hardwired to skip
(code 150, used at the beginning of a data transfer, and code
331, used to prompt for a password),
then it writes a summary of the request and reply to the FTP log file
(§
The standard ftp script defines one other handler, an instance of connection_finished used to flush FTP session information in case the session terminates abnormally and no reply is seen to the pending request(s).