Previous: login functions, Up: login Analyzer



7.19.4 login event handlers

The standard login script handles the following events:

login_failure (c: connection, user: string, client_user: string, password: string, line: string)
Invoked when the event engine has seen a failed attempt to authenticate as user with password on the given connection c. client_user is the user's username on the client side of the connection. For Telnet connections, this is an empty string, but for Rlogin connections, it is the client name passed in the initial authentication information (to check against .rhosts). line is the line of text that led the analyzer to conclude that the authentication had failed.

The analyzer first generates an account_tried event to facilitate detection of password guessing, and then checks for a sensitive username or password. If the username was not sensitive and the password is empty, then no further analysis is applied, since clearly the attempt was half-hearted and aborted. Otherwise, the analyzer annotates the connection's addl field with fail/<username> to mark the authentication failure, and also checks the client_user to see if it is sensitive. If we then find that the connection is hot, the analyzer logs a message to that effect.

login_success (c: connection, user: string, client_user: string, password: string, line: string)
Invoked when the event engine has seen a successful attempt to authenticate. The parameters are the same as for login_failure.

The analyzer invokes check_hot with mode APPL_ESTABLISHED since the application session has now been established. It generates an account_tried event to facilitate detection of password guessing, and then checks for a sensitive username or password. The event engine uses the special password "<none>" to indicate that no password was exposed, and this mitigates the sensitivity of logins using particular usernames per rlogin_id_okay_if_no_password_exposed.

The analyzer annotates the connection's addl field with "<username>" to mark the successful authentication. Finally, if we then find that the connection is hot, the analyzer logs a message to that effect.

login_input_line (c: connection, line: string)
Invoked for every line of text sent by the client side of the login session to the server side. The analyzer matches the text against input_trouble and edited_input_trouble and invokes hot_login with a tag of "trb" if it sees a match, which will log an alert concerning the connection. However, this invocation is only done while the connection's hot field count is <= 2, to avoid cascaded alerts when an attacker gets really busy and steps on a lot of sensitive patterns.
login_output_line (c: connection, line: string)
Invoked for every line of text sent by the server side of the login session to the client side. The analyzer checks backdoor_prompts and any pending input alerts that were waiting on the server output, per edited_input_trouble. These last are then logged unless the output matched the pattern:
              /No such file or directory/
     

Deficiency: Clearly, this pattern should not be hardwired but instead specified by a redefinable variable.

Finally, if the line is not too long and the text matches output_trouble and the connection's hot field count is <= 2 (to avoid cascaded alerts), the analyzer invokes hot_login with a tag of "trb". Deficiency: “Too long” is hardwired to be a length $\ge 256$ bytes. It, too, should be specifiable via a redefinable variable. Note: We might wonder if not checking overly long lines presents an evasion threat: the attacker can bury their access to a sensitive string in an excessive line and thus avoid detection. While this is true, it doesn't appear to cost much. First, some of the sensitive patterns are generated in server output that will be hard to manipulate into being overly long. Second, if the attacker is trying to avoid detection, there are easier ways, such as passing their output through a filter that alters it a good deal.

login_confused (c: connection, msg: string, line: string)
Invoked when the event engine's heuristics have concluded that they have become confused and can no longer correctly track the authentication dialog (See: login analyzer confusion). msg gives the particular problem the heuristics detected (for example, multiple_login_prompts means that the engine saw several login prompts in a row, without the type-ahead from the client side presumed necessary to cause them) and line the line of text that caused the heuristics to conclude they were confused.

Once declaring that it's confused, the event engine will no longer attempt to follow the authentication dialog. In particular, it will not generate subsequent login_failure or login_success events.

Upon this event, the standard login script invokes check_hot with mode APPL_ESTABLISHED since it could well be that the application session is now established (it can't know for sure, of course, because the event engine has given up). It annotates the connection's addl field with confused<line> to mark the confused state, and then logs to the wierd file the particulars of the connection and the type of confusion (msg). Deficiency: This should be done by generating a weird-related event instead.

Finally, the analyzer invokes set_record_packets to specify that all of the packets associated with this connection should be recorded to the trace file. Note: For the current login analyzer, this call is not needed—it records every packet of every login session anyway, because the generally philosophy is that Bro should record whatever it analyzes, so that the analysis may be repeated or examined in detail. Since the current analyzer looks at every input and output line via login_input and login_output, it records all of the packets of every such analyzed session. There is commented-out text in login_success to be used if login_input and login_output are not being used; it turns off recording of a session's packets after the user has successfully logged in (assuming the connection is not considered hot).

login_confused_text (c: connection, line: string)
Invoked for every line the user types after the event engine has entered the confused state. If the connection is not already considered hot, then the analyzer checks for the presence of sensitive usernames in the line using edit_and_check_line, and, if present, annotates the connection's addl field with confused<line>, logs that the connection has become hot, and invokes set_record_packets to record to the trace file all of the packets associated with the connection.
login_terminal (c: connection, terminal: string)
Invoked when the client transmits a terminal type to the server. The mechanism by which the client transmits the type depends on the underlying protocol (Rlogin or Telnet).

The handler checks the terminal type against hot_terminal_types and if it finds a match invokes hot_login with a tag of "trb".


excessive_line (c: connection)
Invoked when the event engine observes a very long line sent by either the client or the server. Such long lines are seen as potential attempts by an attacker to evade the login analyzer; or, possibly, as a Login session carrying an unusual application. Note: One example we have observed occurs when a high-bandwidth binary payload protocol such as Napster is sent over the Telnet or Rlogin well-known port in an attempt to either evade detection or tunnel through a firewall.

This event is actually generic to any TCP connection carrying an application that uses the “Network Virtual Terminal” (NVT) abstraction, which presently comprises Telnet and FTP. But the only handler defined in the demonstration Bro policy is for Telnet, hence we discuss it here. For this reason, the handler first invokes is_login_conn to check whether the connection is in fact a login session. If so, then if the connection is not hot, and if the analyzer finds the server listed in non_ACSII_HOSTS, then it presumes the long line is due to use of a non-ASCII character set; the analyzer invokes set_login_state and set_record_packets to avoid further analysis or recording of the connection.

Otherwise, if the connection is still in the authentication dialog, then the handler generates a event with a confusion-type of "excessive_line", and changes the connection's state to confused.

Deficiency: The event engine is currently hardwired to consider a line of >= 1024 bytes as “excessive”; clearly this should be user-redefinable.


inconsistent_option (c: connection)
NVT options are specified by the client and server stating which options they are willing to support vs. which they are not, and then instructing one another which in fact they should or should not use for the current connection. If the event engine sees a peer violate either what the other peer has instructed it to do, or what it itself offered in terms of options in the past, then the engine generates an inconsistent_option event.

The handler for this event simply records an entry about it to the file. Deficiency: The event handler invocation does not include enough information to determine what option was inconsistently specified; in addition, it would be convenient to integrate the handling of problems like this within the general “weird” framework.

Note: As for excessive_line above, this event is actually a generic one applicable to any NVT-based protocol. It is handled here because the problem most often crops up for Telnet sessions. Note: Also, the handler does not check to see whether the connection is a login session (as it does for excessive_line); it serves as the handler for any NVT session with an excessive line.

Note: Finally, note that this event can be generated if the session contains a stream of binary data. One way this can occur is when the session is encrypted but Bro fails to recognize this fact.

bad_option (c: connection)
If an NVT option is either ill-formed (e.g., a bad length field) or unrecognized, then the analyzer generates this event.

The processing of this event (recording information to the file) and the various notes and deficiencies associated with it are the same as those for inconsistent_option above.


bad_option_termination (c: connection)
If an NVT option fails to be terminated correctly (for example, a character is seen within the option that is disallowed for use in the option), then the analyzer generates this event.

The processing of this event (recording information to the file) and the various notes and deficiencies associated with it are the same as those for inconsistent_option above.


authentication_accepted (name: string, c: connection)
The NVT framework includes options for negotiating authentication. When such an option is sent from client to server and the server replies that it accepts the authentication, then the event engine generates this event.

The handler annotates the connection's addl field with auth<name>, unless that annotation is already present.


authentication_rejected (name: string, c: connection)
The same as authentication_accepted, except invoked when the server replies that it rejects the attempted authentication.

The handler annotates the connection's addl field with auth-failed<name>.


authentication_skipped (c: connection)
Invoked when the event engine sees a line in the authentication dialog that matches .

The handler annotates the connection's addl field with “ skipped” to mark that authentication was skipped, and then invokes skip_further_processing and (unless the connection is hot) set_record_packets to skip any further analysis of the connection, and to stop recording its packets to the trace file.

connection_established (c: connection)
connection_established is a generic event generated for all TCP connections; however, the login analyzer defines an additional handler for it.

The handler first checks (via is_login_conn) whether this is a Telnet or Rlogin connection. If so, it generates an authentication_skipped event if the server's address occurs in skip_logins_to, and also (for Telnet) checks whether the client's port occurs in hot_telnet_orig_ports, invoking hot_login with the tag "orig" if it does.

For SSH connections, it likewise checks the client's port, but in hot_ssh_orig_ports, marking the connection as hot and logging a real-time alert if it is.

partial_connection (c: connection)
As noted earlier, partial_connection is a generic event generated for all TCP connections. The login analyzer also defines a handler for it, one which (if it's a Telnet/Rlogin connection) sets the connection's state to confused and checks for hot_telnet_orig_ports.


activating_encryption (c: connection)
The NVT framework includes options for negotiating encryption. When such a series of options is successfully negotiated, the event engine generates this event. Note: The negotiation sequence is complex and can fail at a number of points. The event engine does not attempt to generate events for each possible failure, but instead only looks for the option sent after a successful negotiation sequence.

The handler annotates the connection's addl field with “(encrypted)” to mark that authentication was encrypted. Note: The event engine itself marks the connection as requiring no further processing. This is done by the event engine rather than the handler because the event engine cannot do its job (regardless of the policy the handler might desire) in the face of encryption.