COMMAND

    Netscape

SYSTEMS AFFECTED

    Netscape 3.0...4.73

PROBLEM

    Solar  Designer  found  following.    This  advisory  explains   a
    vulnerability in Netscape browsers present since at least  version
    3.0 and up  to Netscape 4.73  and Mozilla M15.   The vulnerability
    is fixed in Netscape 4.74 and Mozilla M16.

    It may be possible, although  hard to do reliably in  a real-world
    attack, for  a malicious  web site  to execute  arbitrary assembly
    code in the context of the  web browser.  In the case  of Netscape
    Mail or News, the attack may be performed via a mail message or  a
    news article, as well.

    JPEG interchange format streams  consist of an ordered  collection
    of markers,  parameters, and  entropy-coded data  segments.   Many
    markers  start  marker  segments,  which  consist  of  the  marker
    followed by a sequence of related parameters.  Marker segments are
    of a variable length, with the first parameter being the  two-byte
    length.   The  encoded  length  includes  the  size  of the length
    parameter  itself.   Thus,  lengths  smaller  than  2  are  always
    invalid.

    Netscape browsers use the Independent JPEG Group's decoder library
    for  JPEG  File  Interchange  Format  (JFIF) files.  However, they
    install a custom handler  for processing the COM  (comment) marker
    that stores the  comment in memory  rather than just  skip it like
    the  library  would  do.   Unfortunately,  the new handler doesn't
    check whether the length field is valid, and subtracts 2 from  the
    encoded length to calculate the length of the comment itself.   It
    then allocates memory  for the comment  (with one additional  byte
    for its NUL termination) and goes into a loop to read the  comment
    into that memory.

    By setting the  length field to  1, it is  possible to ensure  the
    memory  allocation  call  (of  0  bytes)  will  succeed.   As  the
    calculated comment length is declared unsigned, it will be a  huge
    positive value rather than a small negative one, so the loop won't
    terminate until the  end of JPEG  stream.  It  will read the  JPEG
    stream  onto  the  heap,  possibly  overwriting  other dynamically
    allocated buffers of Netscape,  as well as structures  internal to
    the malloc(3) implementation.  Exploiting this vulnerability  into
    executing  arbitrary  code  is  non-trivial,  but possible on some
    platforms.

    Is  this  problem  in  the  lack  of  error  checking in the code?
    Indeed.  A programmer's fault.   Is this a problem because of  the
    choice  of  a  programming  language  that  doesn't offer overflow
    checking and with compilers  that traditionally don't offer  bound
    checking?  Partially.

    However, let's see how many different file formats, languages, and
    protocols a modern web  browser has to support.   Have all of  the
    file parsers been initially  implemented with intent to  be robust
    against untrusted and possibly malicious  data?  If not, have  all
    possible cases  been covered  with additional  checks now?   Do we
    have a reason  to believe there're  no bugs in  the implementation
    of any of those, or do we have reasons to suspect the opposite?

    The vulnerability lets us overwrite heap locations beyond the  end
    of allocated area.   We're limited to  printable characters,  NUL,
    and LF.  Thus, the ability to exploit this into doing more than  a
    crash will depend on locale settings on some platforms.

    First,  we  need  to  decide  on  what  we  overwrite.  Structures
    internal  to  the  dynamic  memory  implementation  are  the  most
    promising target: they're always there and they typically  contain
    pointers.  For the example  below, we'll assume Doug Lea's  malloc
    (which is used by most Linux  systems, both libc 5 and glibc)  and
    locale for an 8-bit character set (such as most locales that  come
    with glibc, including en_US, or ru_RU.KOI8-R).

    The following fields  are kept for  every free chunk  on the list:
    size  of  the  previous  chunk  (if  free), this chunk's size, and
    pointers to next and previous chunks.  Additionally, bit 0 of  the
    chunk size is  used to indicate  whether the previous  chunk is in
    use (LSB of actual chunk size is always zero due to the  structure
    size and alignment).

    By playing with  these fields carefully,  it is possible  to trick
    calls to free(3) into overwriting arbitrary memory locations  with
    our data.   free(3) checks if  a chunk adjacent  to the one  being
    freed  is  in  use  and,  if  not,  consolidates the two chunks by
    unlinking the  adjacent chunk  from the  list.   Unlinking a chunk
    involves setting the previous chunk's "next" pointer and the  next
    chunk's  "previous"  pointer,  where  both  of  these  chunks  are
    addressed via pointers  from the chunk  being unlinked.   Thus, in
    order  to  get  control  over  these  memory  writes,  we  need to
    overwrite  the  two  pointers  within  a chunk (or maybe allocated
    memory at the  time) and preferably  reset the PREV_INUSE  flag of
    the next chunk.   This takes 13 bytes  on a 32-bit little  endian,
    such  as  Linux/x86  (8  bytes  for  the  two pointers, four bytes
    placeholder for the previous size  field, and 1 byte to  reset the
    flag).  In practice, we  would want to repeat the  desired 16-byte
    pattern (of which only 9  bytes matter) at least several  times to
    increase our chances in case of larger allocated chunks.

    The overwritten pointers  each serve as  both the address  and the
    data being stored, which limits our choice of data: it has to be a
    valid  address  as  well,  and  memory  at  that address should be
    writable.

    Now we need to decide  what pointer we want to  overwrite (there's
    not that much use in  overwriting a non-pointer with an  address).
    A good candidate would be any  return address on the stack.   That
    would work, but not be very  reliable as the location of a  return
    address depends on how much other data is on the stack,  including
    program arguments, and  that is generally  not known for  a remote
    attack.  A better  target would be a  function pointer.  We  don't
    want to guess exact locations on the stack and we can't get to the
    ELF sections  on x86  (BS isn't  a printable  character), so we're
    effectively limited to pointers  within shared libraries.   A nice
    one we can use is __free_hook, so that the second call to  free(3)
    will give us the control.  The debugging hooks are always compiled
    in when Doug Lea's code is a part of GNU libc.

    Our next decision is about where we want the control  transferred.
    We would definitely prefer to have our "shellcode" within the JFIF
    file itself.  However, the character set restriction might prevent
    us from passing heap  addresses.  We have  to settle on the  stack
    and place our code in there  via other parts of the browser  prior
    to the overflow.   We can use  a bunch of  NOP's or equivalent  to
    avoid having to  provide an exact  stack location.   A compiler to
    produce JFIF files implementing the above approach is included  in
    the accompanying archive.

    Please note that this is by  no means limited to Linux/x86.   It's
    just that one platform had to be chosen for the example.  So  far,
    this is known to be exploitable on at least one Win32 installation
    in a very similar way (via ntdll!RtlFreeHeap).

    Additional  programs  and  example  JFIF  files  mentioned in this
    advisory are provided  in the accompanying  archive, which can  be
    downloaded via one of these links:

        http://www.openwall.com/advisories/OW-002-netscape-jpeg-r1.tar.gz
        http://www.openwall.com/advisories/OW-002-1.zip

    JPEG  interchange  format  is  documented  in  ISO   International
    Standard 10918-1 and CCITT (now ITU-T) Recommendation T.81.   JFIF
    specification and the IJG library are available at:

        ftp://ftp.uu.net/graphics/jpeg/

SOLUTION

    Solutions?  There's little  an end user can  do, but you can  take
    this advisory as yet another  reminder to run the web  browser you
    use  to  access  untrusted  content  in  a restricted environment,
    without access to  your most critical  data.  Unfortunately,  this
    isn't easy to do in the Win32 world, yet.

    Upgrade to Netscape 4.74 or Mozilla M16, or newer.  Alternatively,
    Mozilla users can apply the following patch (against Milestone 15)
    and rebuild the sources:

    --- mozilla/modules/libimg/jpgcom/jpeg.cpp.orig	Tue Mar 28 02:08:15 2000
    +++ mozilla/modules/libimg/jpgcom/jpeg.cpp	Wed May 24 17:24:03 2000
    @@ -469,6 +469,10 @@

         /* Get 16-bit comment length word. */
         INPUT_2BYTES(cinfo, length, return FALSE);
    +    if (length < 2) {
    +	cinfo->err->msg_code = JERR_BAD_LENGTH;
    +	il_error_exit((j_common_ptr)cinfo);
    +    }
         length -= 2;            /* discount the length word itself */

         PR_FREEIF(ic->comment);

    For Red Hat:

        i386: ftp://updates.redhat.com/5.2/i386/netscape-common-4.74-0.5.2.i386.rpm
              ftp://updates.redhat.com/5.2/i386/netscape-communicator-4.74-0.5.2.i386.rpm
              ftp://updates.redhat.com/5.2/i386/netscape-navigator-4.74-0.5.2.i386.rpm
              ftp://updates.redhat.com/6.2/i386/netscape-common-4.74-0.6.2.i386.rpm
              ftp://updates.redhat.com/6.2/i386/netscape-communicator-4.74-0.6.2.i386.rpm
              ftp://updates.redhat.com/6.2/i386/netscape-navigator-4.74-0.6.2.i386.rpm

     sources: ftp://updates.redhat.com/5.2/SRPMS/netscape-4.74-0.5.2.src.rpm
              ftp://updates.redhat.com/6.2/SRPMS/netscape-alpha-4.74-1.src.rpm
              ftp://updates.redhat.com/6.2/SRPMS/netscape-4.74-0.6.2.src.rpm

       alpha: ftp://updates.redhat.com/6.2/alpha/netscape-common-4.74-1.alpha.rpm
              ftp://updates.redhat.com/6.2/alpha/netscape-communicator-4.74-1.alpha.rpm
              ftp://updates.redhat.com/6.2/alpha/netscape-navigator-4.74-1.alpha.rpm

    For Linux-Mandrake:

        6.0/RPMS/netscape-common-4.74-2mdk.i586.rpm
        6.0/RPMS/netscape-communicator-4.74-2mdk.i586.rpm
        6.0/RPMS/netscape-navigator-4.74-2mdk.i586.rpm
        6.0/SRPMS/netscape-4.74-2mdk.src.rpm

        6.1/RPMS/netscape-common-4.74-2mdk.i586.rpm
        6.1/RPMS/netscape-communicator-4.74-2mdk.i586.rpm
        6.1/RPMS/netscape-navigator-4.74-2mdk.i586.rpm
        6.1/SRPMS/netscape-4.74-2mdk.src.rpm

        7.0/RPMS/netscape-castellano-4.74-1mdk.noarch.rpm
        7.0/RPMS/netscape-common-4.74-2mdk.i586.rpm
        7.0/RPMS/netscape-communicator-4.74-2mdk.i586.rpm
        7.0/RPMS/netscape-francais-4.74-2mdk.noarch.rpm
        7.0/RPMS/netscape-navigator-4.74-2mdk.i586.rpm
        7.0/RPMS/netscape-walon-4.74-1mdk.noarch.rpm
        7.0/SRPMS/netscape-4.74-2mdk.src.rpm
        7.0/SRPMS/netscape-castellano-4.74-1mdk.src.rpm
        7.0/SRPMS/netscape-francais-4.74-2mdk.src.rpm
        7.0/SRPMS/netscape-walon-4.74-1mdk.src.rpm

        7.1/RPMS/netscape-castellano-4.74-1mdk.noarch.rpm
        7.1/RPMS/netscape-catalan-4.74-1mdk.noarch.rpm
        7.1/RPMS/netscape-common-4.74-2mdk.i586.rpm
        7.1/RPMS/netscape-communicator-4.74-2mdk.i586.rpm
        7.1/RPMS/netscape-euskara-4.74-1mdk.noarch.rpm
        7.1/RPMS/netscape-francais-4.74-2mdk.noarch.rpm
        7.1/RPMS/netscape-navigator-4.74-2mdk.i586.rpm
        7.1/RPMS/netscape-walon-4.74-1mdk.noarch.rpm
        7.1/SRPMS/netscape-4.74-2mdk.src.rpm
        7.1/SRPMS/netscape-castellano-4.74-1mdk.src.rpm
        7.1/SRPMS/netscape-catalan-4.74-1mdk.src.rpm
        7.1/SRPMS/netscape-euskara-4.74-1mdk.src.rpm
        7.1/SRPMS/netscape-francais-4.74-2mdk.src.rpm
        7.1/SRPMS/netscape-walon-4.74-1mdk.src.rpm

    For TurboLinux:

        netscape-communicator-4.74-2.i386.rpm
        netscape-communicator-4.74-2.src.rpm

    SuSE  provides  an  updated  package  for the vulnerable software.
    The update package introduces Netscape version 4.75, including the
    SuSE-specific libraries  that fix  some of  Netscape's "irregular"
    behaviour.  Please  note that Netscape-4.75  is not available  for
    the glibc-2.0-based  SuSE Distributions  SuSE-6.0 and  6.1 because
    Netscape doesn't provide  any files for  this glibc version.   For
    these  distributions,  SuSE  provides  Netscape Version 4.74 which
    fixes problem.   Alternatively, the  package for  the  libc5-based
    SuSE-5.3 distribution can be used as well if the package 'shlibs5'
    is installed.  This is  recommended, since the 5.3 package  may be
    faster and more reliable:

        ftp://ftp.gwdg.de/pub/linux/suse/6.4_update_de/xap1/netscape.rpm

    As  for  NetBSD  versions  of  Netscape Communicator and Navigator
    older than version 4.74 are  vulnerable.  To find out  the version
    of Communicator or Navigator installed on your NetBSD system,  you
    can use pkg_info(1):

        # pkg_info -e communicator-\*
        # pkg_info -e navigator-\*

    If Communicator or Navigator is  not installed on your system,  no
    output will  be generated,  and your  system is  not vulnerable to
    this problem.  If you have  a version older than 4.74, you  should
    upgrade  to  version  4.74  (or  newer)  of  Netscape Communicator
    and/or Navigator.  A corrected version has been part of the NetBSD
    packages collection since 25th July 2000.  If a vulnerable version
    of  Communicator  or  Navigator  is  installed,  then  you  should
    immediately remove the vulnerability by deleting the package.   As
    root, type:

        # pkg_delete -v communicator-\*
        # pkg_delete -v navigator-\*

    If  you  continue  to  need  Communicator or Navigator, you should
    install a  new version  of the  package.   You can  use the pkgsrc
    infrastructure to download the precompiled binaries directly  from
    their home site.  First, make sure that you have a version of  the
    pkgsrc  hierarchy  from  25th  July  2000  or later.  You can then
    install the new version of the packages:

        cd pkgsrc/www/communicator; make clean; make install

    and/or

        cd pkgsrc/www/navigator; make clean; make install

    For Conectiva Linux:

        ftp://atualizacoes.conectiva.com.br/4.0/i386/netscape-common-4.74-1cl.i386.rpm
        ftp://atualizacoes.conectiva.com.br/4.0/i386/netscape-communicator-4.74-1cl.i386.rpm
        ftp://atualizacoes.conectiva.com.br/4.0/i386/netscape-navigator-4.74-1cl.i386.rpm
        ftp://atualizacoes.conectiva.com.br/4.0es/i386/netscape-common-4.74-1cl.i386.rpm
        ftp://atualizacoes.conectiva.com.br/4.0es/i386/netscape-communicator-4.74-1cl.i386.rpm
        ftp://atualizacoes.conectiva.com.br/4.0es/i386/netscape-navigator-4.74-1cl.i386.rpm
        ftp://atualizacoes.conectiva.com.br/4.1/i386/netscape-common-4.74-1cl.i386.rpm
        ftp://atualizacoes.conectiva.com.br/4.1/i386/netscape-communicator-4.74-1cl.i386.rpm
        ftp://atualizacoes.conectiva.com.br/4.1/i386/netscape-navigator-4.74-1cl.i386.rpm
        ftp://atualizacoes.conectiva.com.br/4.2/i386/netscape-common-4.74-1cl.i386.rpm
        ftp://atualizacoes.conectiva.com.br/4.2/i386/netscape-communicator-4.74-1cl.i386.rpm
        ftp://atualizacoes.conectiva.com.br/4.2/i386/netscape-navigator-4.74-1cl.i386.rpm
        ftp://atualizacoes.conectiva.com.br/5.0/i386/netscape-common-4.74-1cl.i386.rpm
        ftp://atualizacoes.conectiva.com.br/5.0/i386/netscape-communicator-4.74-1cl.i386.rpm
        ftp://atualizacoes.conectiva.com.br/5.0/i386/netscape-navigator-4.74-1cl.i386.rpm
        ftp://atualizacoes.conectiva.com.br/5.1/i386/netscape-common-4.74-1cl.i386.rpm
        ftp://atualizacoes.conectiva.com.br/5.1/i386/netscape-communicator-4.74-1cl.i386.rpm
        ftp://atualizacoes.conectiva.com.br/5.1/i386/netscape-navigator-4.74-1cl.i386.rpm
        ftp://atualizacoes.conectiva.com.br/ferramentas/ecommerce/i386/netscape-common-4.74-1cl.i386.rpm
        ftp://atualizacoes.conectiva.com.br/ferramentas/ecommerce/i386/netscape-communicator-4.74-1cl.i386.rpm
        ftp://atualizacoes.conectiva.com.br/ferramentas/ecommerce/i386/netscape-navigator-4.74-1cl.i386.rpm
        ftp://atualizacoes.conectiva.com.br/ferramentas/graficas/i386/netscape-common-4.74-1cl.i386.rpm
        ftp://atualizacoes.conectiva.com.br/ferramentas/graficas/i386/netscape-communicator-4.74-1cl.i386.rpm
        ftp://atualizacoes.conectiva.com.br/ferramentas/graficas/i386/netscape-navigator-4.74-1cl.i386.rpm

    For FreeBSD deinstall the  netscape port/package, if you  you have
    installed it.  Solution is one of the following:

    1) Upgrade your entire  ports collection and rebuild  the relevant
       netscape port.
    2) Deinstall  the  old  package  and  install a new package  dated
       after  the  correction  date,   obtained  from  the   following
       directories:
        ftp://ftp.FreeBSD.org/pub/FreeBSD/ports/i386/packages-3-stable/www/
        ftp://ftp.FreeBSD.org/pub/FreeBSD/ports/i386/packages-4-stable/www/
        ftp://ftp.FreeBSD.org/pub/FreeBSD/ports/alpha/packages-4-stable/www/
        ftp://ftp.FreeBSD.org/pub/FreeBSD/ports/i386/packages-5-current/www/
        ftp://ftp.FreeBSD.org/pub/FreeBSD/ports/alpha/packages-5-current/www/
    3) download a new port skeleton for the netscape port from:
        http://www.freebsd.org/ports/
       and use it to rebuild the port.