Firewall Wizards mailing list archives

Re: recent telnet vulnerability


From: Balazs Scheidler <bazsi () balabit hu>
Date: Sat, 11 Aug 2001 14:51:10 +0200

On Sat, Aug 11, 2001 at 04:21:12PM +0400, ark () eltex ru wrote:
nuqneH,

It does stop script kiddie's exploits, but is it really able to prevent the 
attack?

tn-gw (fwtk and old Gauntlet, don't have current source now) does stop
the _exploit_ too, because it does handle options sent while _initial_
handshake, but it does nothing with options sent later when session is
already estabilished (well, not actually nothing but nothing that can stop
the attacker).

The proxy interprets telnet negotiation options during the whole session.
Known options are also parsed, unknown ones are rejected by default, but can
be enabled explicitly by the administrator. (known ones are: terminal_type
(alphanumeric + '-'), terminal speed (digits + ','), x display (alphanumeric
+ ':' + '.'), environment (can be selected which variables are valid),
+ naws). Other options are not parsed, only their consistency with the protocol
is enforced.

Here's the default configuration:

class TelnetProxy(Proxy):
  ...
  def config(self):
          """Configuration for TelnetProxy

          It enables all options needed for a usable Telnet session.
          """
          self.policy["*"]                            = (TELNET_OPTION_DENY)
          self.policy[TELNET_TERMINAL_TYPE]           = (TELNET_OPTION_ACCEPT)
          self.policy[TELNET_TERMINAL_TYPE, "*"]      = (TELNET_OPTION_ACCEPT)
          self.policy[TELNET_TERMINAL_SPEED]          = (TELNET_OPTION_ACCEPT)
          self.policy[TELNET_TERMINAL_SPEED, "*"]     = (TELNET_OPTION_ACCEPT)
          self.policy[TELNET_X_DISPLAY_LOCATION]      = (TELNET_OPTION_ACCEPT)
          self.policy[TELNET_X_DISPLAY_LOCATION, "*"] = (TELNET_OPTION_ACCEPT)
          self.policy[TELNET_ENVIRONMENT]             = (TELNET_OPTION_ACCEPT)
          self.policy[TELNET_ENVIRONMENT, "*"]        = (TELNET_OPTION_ACCEPT)
          self.policy[TELNET_NAWS]                    = (TELNET_OPTION_ACCEPT)
          self.policy[TELNET_NAWS, "*"]               = (TELNET_OPTION_ACCEPT)
          self.policy[TELNET_SUPPRESS_GO_AHEAD]       = (TELNET_OPTION_ACCEPT)
          self.policy[TELNET_ECHO]                    = (TELNET_OPTION_ACCEPT)


To fully understand the possibilities I attach the documentation, which is
quite short:

        TelnetProxy is a wrapper class for the built-in Telnet proxy in
        Zorp. It implements the Telnet protocol, as described in RFC 854,
        and most common extensions. Although not all possible options are
        checked at the low level proxy, the administrator has the
        possibility to filter any option and suboption negotiation sequence
        using policy callbacks.

        Usage

          Default policy

            The low level Telnet proxy denies every option and suboption
            negotiation sequences by default, and provides the administrator
            with methods to change this default behaviour. As the low level
            implementation denies everything, the default policy of the
            TelnetProxy class has been set so that all important options
            (which are necessary to use Telnet to log in to other machines)
            and their suboption negotiation sequences are allowed. These
            are: Telnet Terminal Type, Telnet X Display Location, Telnet
            Environment, Telnet Suppress Go Ahead, Telnet NAWS (Negotiation
            About Window Size), and Telnet Echo.

          Setting policy in general

            As Telnet is a symmetrical protocol, there is no point in
            dividing the data stream into requests and responses. Instead of
            this, the administrator can define which options the Telnet
            session may use, and can filter the suboption negotiation
            sequences of these options. Changing the default policy can be
            done using the multi-dimensional hash (DimHash) 'policy'. It is
            indexed with one or two values: the first is the option, and the
            optional second one is the suboption which you want to filter.

          Setting policy for option negotiation

            To determine which options to enable in the session, the low
            level Telnet proxy consults the 'policy' hash: the proxy looks
            up the hash value corresponding the option number as a key. If
            the hash contains no entry for that number, the default policy
            '*' is looked instead. If there is no default policy defined, the
            option negotiation is denied: the option won't be used in the
            session.

            If a match is found, the corresponding tuple is used to
            determine the action to take. This tuple consists of one or two
            elements. The first is an integer, the second is optional: if
            the first value is TELNET_OPTION_POLICY, the second must be the
            name of the callback function):

              TELNET_OPTION_ACCEPT -- allow option

              TELNET_OPTION_DENY   -- deny option

              TELNET_OPTION_ABORT  -- deny option and terminate the Telnet session

              TELNET_OPTION_POLICY -- call the function given in the second tuple item
                                      This second item must be a callable Python function,
                                      taking exactly two parameters: self and option (option
                                      is an integer). The function must return one of these
                                      action codes, excluding TELNET_OPTION_POLICY.

              Example (Sample for disabling Telnet X Display Location option)

                class MyTelnetProxy(TelnetProxy):
                  def config(self):
                    TelnetProxy.config(self)
                    self.policy[TELNET_X_DISPLAY_LOCATION] = (TELNET_OPTION_DENY)

       Setting policy for suboption negotiation

         To change the default processing (deny) of suboption negotiation
         sequences, you must enable the suboption negotiation subcommands
         for each option. You can do this by adding tuples to the 'policy'
         hash, indexed by two values: the option and the suboption
         negotiation subcommand. For example, if the low level
         implementation detects that a suboption negotiation sequence
         follows, it looks up the tuple corresponding the indexes (option
         number, subcommand). If a match is not found, the subcommand is
         substituted with '*', and the lookup is repeated. If there is still
         no match, the subcommand is restored and the option is substituted
         with '*'. The last combination of index values looked up is ('*',
         '*'). For example, for the SEND subcommand of Telnet Terminal Type
         option, the following lookups are made (in this order):
 
           1. "24", "1"      (24 is the code of Telnet Terminal Type option)
           2. "24", "*"
           3. "*",  "1"
           4. "*",  "*"

         If a match is found, the corresponding tuple is used to determine
         the necessary action. This tuple has one or two elements: the first
         one defines the action, the second may be the name of a function,
         used only if the first one is TELNET_OPTION_POLICY. Possible values
         for the first value:

           TELNET_OPTION_ACCEPT -- allow suboption negotiation sequence

           TELNET_OPTION_DENY   -- deny suboption negotiation sequence

           TELNET_OPTION_ABORT  -- deny suboption negotiation, and terminate session

           TELNET_OPTION_POLICY -- call the function given in the second tuple item
                                   This second item must be a callable Python function,
                                   taking exactly four parameters: self, option, name
                                   and value. The function must return one of these
                                   action codes, excluding TELNET_OPTION_POLICY.

         Policy callback functions can be used to make decisions based on
         the conent of the suboption negotiation sequence. For example, the
         Telnet Environment option's suboption negotiation sequences
         transfer environment variables. The low level proxy implementation
         parses these variables, and passes their name and value to the
         callback function, one at a time. These values van be also changed
         during transfer, by changing the var_name and var_value attributes
         of the proxy class.

            Example (Rewriting the DISPLAY environment variable):

              class MyRewritingTelnetProxy(TelnetProxy):

                def config(self):
                  TelnetProxy.config()
                  self.policy[TELNET_ENVIRONMENT, TELNET_SB_IS] = (TELNET_OPTION_POLICY, self.rewriteVar)

                def rewriteVar(self, option, name, value):
                  if name == "DISPLAY"
                        self.var_value = "rewritten_value:0"
                  return TELNET_OPTION_ACCEPT

-- 
Bazsi
PGP info: KeyID 9AF8D0A9 Fingerprint CD27 CFB0 802C 0944 9CFD 804E C82C 8EB1
_______________________________________________
firewall-wizards mailing list
firewall-wizards () nfr com
http://list.nfr.com/mailman/listinfo/firewall-wizards


Current thread: