The ftp Analyzer
Keywords: doc-html

Next: The http Analyzer Up: Analyzers and Events Previous: The hot-ids Module Contents Index
Subsections

- The `ftp_session_info` record
- `ftp` variables
- `ftp` functions
- `ftp` event handlers

#
The `ftp` Analyzer

The `ftp` analyzer processes traffic associated with the FTP file transfer service [RFC959]. Bro instantiates an `ftp` analyzer for any connection with service port `21/tcp`, providing you have loaded the `ftp` analyzer, or defined a handler for `ftp_request` or `ftp_reply`.

The analyzer uses a capture filter of ```port ftp`'' (§ ). It generates summaries of FTP sessions; looks for sensitive usernames, access to sensitive files, and possible FTP ``bounce'' attacks, in which the host specified in a ```PORT`'' or ```PASV`'' directive does not correspond to the host sending the directive; or in which a different host than the server (client) connects to the endpoint specified in a `PORT` (`PASV`) directive.

##
The `ftp_session_info` record

Figure 7.6: Definition of the `ftp_session_info` record.

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:

  [`id`] The unique session identifier assigned to this session. Sessions are numbered starting at `1` and incrementing with each new session.

  [`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.

##
`ftp` variables

The standard script defines the following redefinable variables:

  [``ftp_guest_ids : set[string]``] A set of usernames associated with publicly accessible ``guest'' services. Bro interprets guest usernames as indicating Bro should use the authentication password as the effective username.

  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.

Figure 7.7: Example of FTP log file entries for a single FTP session.

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 L

The 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.

##
`ftp` functions

The standard `ftp` script provides one function for external use:

  [``is_ftp_data_conn`(c: connection): bool``` ] Returns true if the given connection matches one we're expecting as the data connection half of an FTP session. Note: This function is not idempotent: if the connection matches an expected one, then Bro updates its state such that that connection is no longer expected. It also logs a discrepancy if the connection appears to be usurping another one that generated either a ```PORT`'' or a ```PASV`'' directive.

  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.

##
`ftp` event handlers

The standard script handles the following events:

  [``ftp_request (c: connection, command: string, arg: string)``] Invoked upon the client side of connection `c` having made the request `command` with the argument `arg`.

  The processing depends on the particular command:

  `USER`
    Specifies the username that the client wishes to use for authentication. If it is sensitive--in `hot_ids` (which the `ftp` analyzer accesses via a `@load` of `hot-ids`)--then the analyzer flags the FTP session as log-worthy. In addition, if the username is in `forbidden_ids`, then the analyzer terminates the session.

    The analyzer also updates the connection's `addl` field with the username.

  `PASS`
    Specifies the password to use for authentication.

    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.

  `PORT`
    Instructs the FTP server to connect to the given IP address and port for delivery of the next FTP data item. The analyzer first checks the address/port specifier for validity. If valid, it will generate an alert if either the address specified in the directive does not match that of the client, or if the port corresponds to a ``privileged'' port, i.e., one in the range 0-1023. Finally, it establishes state so that `is_ftp_data_conn` can identify a subsequent connection corresponding to this directive as belonging to this FTP session.

  `ACCT`
    Specifies additional accounting information associated with a session, which the analyzer simply adds to the connection's `addl` field.

  `APPE`, `CWD`, `DELE`, `MKD`, `RETR`, `RMD`, `RNFR`, `RNTO`, `STOR`, `STOU`
    All of these manipulate files (and directories). The analyzer checks the filename against the policies to see if it is sensitive in the context of the given username (i.e., guest or non-guest), and, if so, marks the connection to generate an alert unless the operation fails. The analyzer also checks for an excessively long filename, currently by checking its length against a Deficiency: hardwired maximum of 250 bytes.

  [``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 (§ ). Also, if the reply is an ``orphan'' (there was no corresponding request, perhaps because Bro started up after the request was made), then the reply is summarized in the log file by itself.

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).

Next: The http Analyzer Up: Analyzers and Events Previous: The hot-ids Module Contents Index