COMMAND

    kernel (IP Masquerading)

SYSTEMS AFFECTED

    Linux 2.2.x

PROBLEM

    H  D  Moore  found  following.    Due  to  lax  checking  in   the
    masquerading kernel code, an attacker  is able to rewrite a  linux
    masq gateway's UDP  masquerading entries so  that the remote  host
    and port are whatever they choose.  This creates a tunnel  between
    whatever host  and port  they want  and a  UDP port  on an  inside
    machine.  The attacker is  unable to tell what local  inside ports
    and addresses are  being used, but  they can determine  the number
    of currently masqueraded connections  and the number of  different
    hosts using those  connections behind the  firewall.  Any  network
    where UDP traffic is masqueraded  to the outside is vulnerable  to
    this,  including  DNS,  TFTP,  NetBIOS,  and  a multitude of other
    applications  which  rely  on  UDP  transport.   Since  UDP  is  a
    connectionless  protocol,  the  only  way  to  determine  that   a
    masqueraded connection  is no  longer being  used is  by timing it
    out due to lack of activity or receiving ICMP messages  indication
    the  port  is  closed.   The  result  is  that there is a 5 minute
    time-out by default for all masqueraded UDP sessions, allowing  an
    attacker enough time to find and exploit the connection with  some
    of the methods outlined in the Examples section below.

    For  those  familiar  with  the  linux masquerading system, please
    jump to the next paragraph.  IP masquerading is an  implementation
    of NAT (Network Address Translation) for the linux OS.  It  allows
    you to connect an internal  network using private addresses to  an
    external  network  (internet)  in  a  fairly  secure  manner.  All
    packets  coming  from  the  internal  network and destined for the
    external network are rewritten so  the source of those packets  is
    the masquerading  gateway's external  address and  the source port
    is the gateway's source port.  This only requires one external  IP
    address  to  enable  internet  access  for  hundreds/thousands  of
    internal  machines  and  is  therefore  a  popular method for many
    businesses and  home users  with broadband  connections.   The TCP
    and UDP  protocols require  both source  and destination  ports as
    well as  source and  destination addresses  to work.   The  source
    port for outgoing UDP/TCP  connections is usually picked  from the
    first available  port between  1024 and  65535 on  the originating
    host, so how does the masq gateway relay these connections AND  be
    able to use  these protocols for  its own networking?   The kernel
    sets aside the  ports 61000 to  65096 by default  for handling the
    masqueaded connection entries, allowing for a theoretical  maximum
    of 4096 of both UDP and  TCP connections at a time.   These values
    can be changed in the code or through the /proc file system.   Now
    when connection request from internal  host A comes in from  local
    port 1035 and  its destination is  the external DNS  server Host Z
    on  port  53,  the  masquerading  machine  adds a new entry to the
    masquerading table that looks like this:

        Host A:1035 (651001) -> Host Z:53

    The port  in paranthesis  is the  local port  the gateway  uses to
    send the  forwarded UDP  datagrams from  and the  port it  uses to
    receive responses back from Host Z.  The next paragraph  describes
    how  the  vulnerability  found  allows  an  attacker to modify the
    right side of the above  connection to allow traffic to  come from
    thier host  back into  the internal  network to  the local port on
    the inside host.

    The  UDP  masquerading  code  only  checks the DESTINATION PORT to
    determine if a  packet coming from  the external network  is to be
    forwarded inside.  It  then sets the remote  HOST and PORT to  the
    source address and  source port of  the incoming packet.   This is
    due to a number of  hosts/services returning UDP from an  IP other
    than that which the original UDP  packet went to - for example  it
    is frequently the case that NFS servers just use the interface  ip
    address "closest" to that which the NFS op came from.

    An attacker only needs to  determine  the  local  port on the masq
    gateway  to  be  able  to  rewrite  the  masq table with thier own
    address  and  port,  which  is  trivial considering the relatively
    small port range set by default for use by masqueraded conenctions
    (65100 -  65096).   Now how  do you  determine which  one of these
    ports is the  local port on  the gateway for  the masq connection?
    Easy, we send a probe packet to each of these hosts and watch  the
    IP ID field  in the responses.   The IP ID  field is  sequentially
    incremented on each host's TCP/IP stack for each packet they  send
    out, so the masq'd port ICMP  response will have the IP ID  of the
    INTERNAL host, which is almost always at least 1000 away from  the
    current IP ID  of the gateway  machine.  See  the Examples section
    below for packet traces of a complete scan/attack.

    Examples.   We  know  that  example.com  has  a linux masquerading
    gateway and that thier DNS server is outside of this firewall.  We
    can come to the conclusion that internal machines must be able  to
    contact  the  external  DNS  server  to  be  able  to  access  the
    internet.  We start sending our probe packets:

        Host A is our internal workstation (192.168.1.100)
        Host B is our masq gateway (192.168.1.1 / 10.0.0.1)
        Host C is the DNS server (10.0.0.25)
        Host X is the attacker (10.10.187.13)

    ipchains -L -M -n on the masq gateway BEFORE the probes

        > UDP 03:39.21 192.168.1.100  10.0.0.25   1035 (63767) -> 53

    [ tcpdump from attacker's machine ]
    ( we picked source  port 12345 for our  packets just so the  trace
    would be easier to follow)

    [ snip -- this starts at port 61000 ]

        10.0.0.1 > 10.10.187.13: icmp: 10.0.0.1 udp port 63762 unreachable [tos
        0xd8] (ttl 245, id 13135)
        10.10.187.13.12345 > 10.0.0.1.63763: udp 0 (DF) [tos 0x18] (ttl 254, id
        23069)
        10.0.0.1 > 10.10.187.13: icmp: 10.0.0.1 udp port 63763 unreachable [tos
        0xd8] (ttl 245, id 13136)
        10.10.187.13.12345 > 10.0.0.1.63764: udp 0 (DF) [tos 0x18] (ttl 254, id
        23070)
        10.0.0.1 > 10.10.187.13: icmp: 10.0.0.1 udp port 63764 unreachable [tos
        0xd8] (ttl 245, id 13137)
        10.10.187.13.12345 > 10.0.0.1.63765: udp 0 (DF) [tos 0x18] (ttl 254, id
        23071)
        10.0.0.1 > 10.10.187.13: icmp: 10.0.0.1 udp port 63765 unreachable [tos
        0xd8] (ttl 245, id 13138)
        10.10.187.13.12345 > 10.0.0.1.63766: udp 0 (DF) [tos 0x18] (ttl 254, id
        23074)
        10.0.0.1 > 10.10.187.13: icmp: 10.0.0.1 udp port 63766 unreachable [tos
        0xd8] (ttl 245, id 13139)
        10.10.187.13.12345 > 10.0.0.1.63767: udp 0 (DF) [tos 0x18] (ttl 254, id
        23083)

        10.0.0.1 > 10.10.187.13: icmp: 10.0.0.1 udp port 63767 unreachable [tos
        0xd8] (ttl 244, id 17205)
        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

    The  above  packet's  ID  is  substantially different, we may have
    found a masq'd connection !!!

        10.10.187.13.12345 > 10.0.0.1.63768: udp 0 (DF) [tos 0x18] (ttl 254, id
        23084)
        10.0.0.1 > 10.10.187.13: icmp: 10.0.0.1 udp port 63768 unreachable [tos
        0xd8] (ttl 245, id 13140)
        10.10.187.13.12345 > 10.0.0.1.63769: udp 0 (DF) [tos 0x18] (ttl 254, id
        23088)
        10.0.0.1 > 10.10.187.13: icmp: 10.0.0.1 udp port 63769 unreachable [tos
        0xd8] (ttl 245, id 13141)
        10.10.187.13.12345 > 10.0.0.1.63770: udp 0 (DF) [tos 0x18] (ttl 254, id
        23090)
        10.0.0.1 > 10.10.187.13: icmp: 10.0.0.1 udp port 63770 unreachable [tos
        0xd8] (ttl 245, id 13142)
        10.10.187.13.12345 > 10.0.0.1.63771: udp 0 (DF) [tos 0x18] (ttl 254, id
        23091)
        10.0.0.1 > 10.10.187.13: icmp: 10.0.0.1 udp port 63771 unreachable [tos
        0xd8] (ttl 245, id 13143)
        10.10.187.13.12345 > 10.0.0.1.63771: udp 0 (DF) [tos 0x18] (ttl 254, id
        23092)
        10.0.0.1 > 10.10.187.13: icmp: 10.0.0.1 udp port 63772 unreachable [tos
        0xd8] (ttl 245, id 13144)

        [ snip -- all the way to the upper end of our masq ports ]

        ipchains -L -M -n on the masq gateway AFTER the probes
        > UDP 04:35.12 192.168.1.100  10.10.187.13   1035 (63767) -> 12345
        ^-------[ expiration of the udp tunnel has been updated ;)

    We now have  a working tunnel  from our host  to port 1035  on the
    inside machine!

    We have demonstrated  that it is  possible for us  to 'hijack' the
    enternal side of a masqueraded connection, so now what?  There  is
    not a  whole lot  we can  do to  the closed  local udp port on the
    inside    machine,    so    its    time    to    examine     other
    applications/protocols  that  use  UDP  for  transport  and   what
    security risks there are in allowing unrestricted external  access
    to thier  source ports.   We leave  this as  an excercise  to  the
    reader...

    Following the "NetBIOS Info"  thread on Incidents mailing  list at
    SF, Robert Graham  mentioned a utility  he wrote to  automatically
    respond  to  netbios  port  137  name  probes  with a netbios name
    lookup back to the originating  host.  He mentioned that  it seems
    to  cut  right  through  state-based  firewalls  and  NAT  systems
    because the response probe looks  like a response to the  outgoing
    probe.  Assuming that a host  on an inside network is sending  out
    these netbios name  queries, an attacker  could exploit the  linux
    2.2.x vulnerability and be   able to query the  netbios  names  of
    internal machines.  More info:

        http://www.robertgraham.com/pubs/firewall-seen.html#netbios

SOLUTION

    In  general  it  is  not  advisable  the  use  of  UDP  masq for a
    firewalling  gateway  -  since  the  only  thing  that  people are
    normally putting through the UDP side is DNS, you are much  better
    advised to  put a  decent caching  name server  on the gateway box
    and block UDP through completely.

    The core problem  is precisely not  being able to  actually _know_
    when internal box has closed the  port.  You can easily revert  to
    good"old" way (1 tunnel/pair) by commenting out

        #define CONFIG_IP_MASQ_LOOSE_DEFAULT 1

    at  ip_masq.c:418  (stupid  patch  attached).   This  should  drop
    hijack'ing...  Of  course, if we  change the default,  some way to
    enable  it  back  perhaps  on  a  per-application  basis  (ip_masq
    module) MUST be done.

    --- net/ipv4/ip_masq.c.dloose	Thu Mar 30 14:51:06 2000
    +++ net/ipv4/ip_masq.c	Thu Mar 30 14:57:24 2000
    @@ -415,7 +415,7 @@
     /*
      *	By default enable dest loose semantics
      */
    -#define CONFIG_IP_MASQ_LOOSE_DEFAULT 1
    +/* #define CONFIG_IP_MASQ_LOOSE_DEFAULT 1 */


     /*

    The issues causing  this DoS are  apparently more complex  than it
    may appear according to the discussion in the Linux kernel mailing
    list.  There is a patch for the exploit in 2.2.15pre-16 and it  is
    a noteworthy amount of code.

    If you downloaded pre-patch-2.2.15pre-16 you'll see following:

    diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla
    /net/unix/af_unix.c linux.15pre16/net/unix/af_unix.c
    --- linux.vanilla/net/unix/af_unix.c   Sat Aug 14 02:27:46 1999
    +++ linux.15pre16/net/unix/af_unix.c   Tue Mar 28 17:27:52 2000
    @@ -969,6 +969,10 @@
             return -ENOTCONN;
       }

    +  err = -EMSGSIZE;
    +  if (len > sk->sndbuf)
    +     goto out;
    +
       if (sock->passcred && !sk->protinfo.af_unix.addr)
          unix_autobind(sock);

    This isn't so different from  above (except the fact that  the one
    above checks  len >  sk->sndbuff -  16, thus  limiting the sending
    buffer).

    Solution for SuSE Linux (they  provide a patched 2.2.14 kernel  to
    ensure stability and not the 2.2.15 kernel):

        ftp://ftp.suse.com/pub/suse/i386/update/6.4/kernel/k_deflt.rpm
        ftp://ftp.suse.com/pub/suse/i386/update/6.4/kernel/k_eide.rpm
        ftp://ftp.suse.com/pub/suse/i386/update/6.4/kernel/k_i386.rpm
        ftp://ftp.suse.com/pub/suse/i386/update/6.4/d1/lx_suse-2.2.14.SuSE-24.i386.rpm